{"version":3,"sources":["../src/context/BeninPaymentContext.tsx","../src/utils/scriptLoader.ts","../src/utils/logger.ts","../src/utils/analytics.ts","../src/utils/errors.ts","../src/utils/verifyTransaction.ts","../src/core/createPaymentEngine.ts","../src/core/usePaymentEngine.ts","../src/utils/keyValidator.ts","../src/utils/currency.ts","../src/core/validateCommonConfig.ts","../src/providers/fedapay.ts","../src/utils/environment.ts","../src/hooks/mergeI18nOptions.ts","../src/hooks/useFedaPay.ts","../src/hooks/usePaymentStatus.ts","../src/hooks/usePaymentHistory.ts","../src/hooks/useRetryPayment.ts","../src/components/FedaPayButton.tsx","../src/components/FedaPayConsumer.tsx","../src/components/icons/FedaPayLogo.tsx","../src/components/PaymentStatusBadge.tsx"],"names":["validationError","useMemo","useRef","useState","useEffect","useCallback","jsx"],"mappings":"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","file":"fedapay.mjs","sourcesContent":["\"use client\";\r\n\r\nimport {\r\n  createContext,\r\n  useContext,\r\n  useMemo,\r\n  type ReactNode,\r\n} from \"react\";\r\nimport type { Currency } from \"../types\";\r\nimport type { BeninPaymentAnalyticsHandler } from \"../utils/analytics\";\r\nimport type { ErrorMessageResolver, PaymentMessageOverrides } from \"../types/validation\";\r\nimport type { EnvironmentWarningMessages } from \"../utils/keyValidator\";\r\n\r\n/**\r\n * Global configuration for Benin Payment providers.\r\n */\r\nexport interface BeninPaymentConfig {\r\n  /** \r\n   * Default FedaPay public key.\r\n   * Will be used if no key is provided at the component level.\r\n   * @example \"pk_live_xxxxxxxxxxxx\"\r\n   */\r\n  fedaPayPublicKey?: string;\r\n  /** \r\n   * Default KKiaPay public key.\r\n   * Will be used if no key is provided at the component level.\r\n   * @example \"pk_xxxxxxxxxxxx\"\r\n   */\r\n  kkiaPayPublicKey?: string;\r\n  /** \r\n   * Default currency for all transactions.\r\n   * @default \"XOF\"\r\n   */\r\n  defaultCurrency?: Currency;\r\n  /** \r\n   * Force sandbox/test mode globally.\r\n   * When true, all transactions will be in test mode.\r\n   * @default false\r\n   */\r\n  isTestMode?: boolean;\r\n  /** \r\n   * Enable debug mode globally.\r\n   * Shows console logs for all payment operations.\r\n   * @default false\r\n   */\r\n  debug?: boolean;\r\n  /**\r\n   * Global analytics callback for standardized payment events.\r\n   */\r\n  onAnalyticsEvent?: BeninPaymentAnalyticsHandler;\r\n  /**\r\n   * Overrides the wording of built-in validation error messages\r\n   * (missing key, invalid amount, SDK not loaded...) for every hook.\r\n   * Can be refined per-hook via `useFedaPay`/`useKkiaPay` options.\r\n   */\r\n  messages?: PaymentMessageOverrides;\r\n  /**\r\n   * Resolves the message for arbitrary caught errors (SDK load failures,\r\n   * network errors...) surfaced via a hook's `error` state. Falls back to\r\n   * the built-in French translations when it returns `undefined`.\r\n   */\r\n  resolveErrorMessage?: ErrorMessageResolver;\r\n  /**\r\n   * Overrides the wording of dev-time console warnings (live key used in\r\n   * sandbox mode, etc.) for every hook. Can be refined per-hook via\r\n   * `useFedaPay`/`useKkiaPay` options.\r\n   */\r\n  environmentWarnings?: EnvironmentWarningMessages;\r\n}\r\n\r\n/**\r\n * Internal context value with resolved defaults.\r\n */\r\ninterface BeninPaymentContextValue {\r\n  fedaPayPublicKey: string | undefined;\r\n  kkiaPayPublicKey: string | undefined;\r\n  defaultCurrency: Currency;\r\n  isTestMode: boolean;\r\n  debug: boolean;\r\n  onAnalyticsEvent?: BeninPaymentAnalyticsHandler;\r\n  messages?: PaymentMessageOverrides;\r\n  resolveErrorMessage?: ErrorMessageResolver;\r\n  environmentWarnings?: EnvironmentWarningMessages;\r\n  isProviderMounted: boolean;\r\n}\r\n\r\nconst BeninPaymentContext = createContext<BeninPaymentContextValue | null>(null);\r\n\r\n/**\r\n * Props for the BeninPaymentProvider component.\r\n */\r\nexport interface BeninPaymentProviderProps extends BeninPaymentConfig {\r\n  /** Child components that will have access to the payment context */\r\n  children: ReactNode;\r\n}\r\n\r\n/**\r\n * Global provider for Benin Payment configuration.\r\n * \r\n * Wrap your application (or a section of it) with this provider to set\r\n * default values for all FedaPay and KKiaPay hooks and components.\r\n * \r\n * @example\r\n * ```tsx\r\n * import { BeninPaymentProvider } from \"react-benin-payments\";\r\n * \r\n * function App() {\r\n *   return (\r\n *     <BeninPaymentProvider\r\n *       fedaPayPublicKey=\"pk_live_xxxxxxxxxxxx\"\r\n *       kkiaPayPublicKey=\"pk_xxxxxxxxxxxx\"\r\n *       defaultCurrency=\"XOF\"\r\n *       isTestMode={process.env.NODE_ENV === \"development\"}\r\n *       debug={true}\r\n *     >\r\n *       <YourApp />\r\n *     </BeninPaymentProvider>\r\n *   );\r\n * }\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Components inside the provider can now use hooks without passing keys\r\n * function PaymentButton() {\r\n *   const { openDialog, loading } = useFedaPay({\r\n *     transaction: { amount: 5000 }\r\n *     // No need for public_key - it's taken from the provider!\r\n *   });\r\n * \r\n *   return <button onClick={openDialog}>Pay</button>;\r\n * }\r\n * ```\r\n */\r\nexport function BeninPaymentProvider({\r\n  fedaPayPublicKey,\r\n  kkiaPayPublicKey,\r\n  defaultCurrency = \"XOF\",\r\n  isTestMode = false,\r\n  debug = false,\r\n  onAnalyticsEvent,\r\n  messages,\r\n  resolveErrorMessage,\r\n  environmentWarnings,\r\n  children,\r\n}: BeninPaymentProviderProps) {\r\n  const value = useMemo<BeninPaymentContextValue>(\r\n    () => ({\r\n      fedaPayPublicKey,\r\n      kkiaPayPublicKey,\r\n      defaultCurrency,\r\n      isTestMode,\r\n      debug,\r\n      onAnalyticsEvent,\r\n      messages,\r\n      resolveErrorMessage,\r\n      environmentWarnings,\r\n      isProviderMounted: true,\r\n    }),\r\n    [\r\n      fedaPayPublicKey,\r\n      kkiaPayPublicKey,\r\n      defaultCurrency,\r\n      isTestMode,\r\n      debug,\r\n      onAnalyticsEvent,\r\n      messages,\r\n      resolveErrorMessage,\r\n      environmentWarnings,\r\n    ]\r\n  );\r\n\r\n  return (\r\n    <BeninPaymentContext.Provider value={value}>\r\n      {children}\r\n    </BeninPaymentContext.Provider>\r\n  );\r\n}\r\n\r\n/**\r\n * Hook to access the global Benin Payment configuration.\r\n * \r\n * Returns the configuration from the nearest BeninPaymentProvider,\r\n * or default values if no provider is found.\r\n * \r\n * @returns The current payment configuration\r\n * \r\n * @example\r\n * ```tsx\r\n * function PaymentStatus() {\r\n *   const { isTestMode, defaultCurrency, debug } = useBeninConfig();\r\n *   \r\n *   return (\r\n *     <div>\r\n *       Mode: {isTestMode ? \"Test\" : \"Production\"}\r\n *       Currency: {defaultCurrency}\r\n *     </div>\r\n *   );\r\n * }\r\n * ```\r\n */\r\nexport function useBeninConfig(): BeninPaymentContextValue {\r\n  const context = useContext(BeninPaymentContext);\r\n  \r\n  if (!context) {\r\n    return {\r\n      fedaPayPublicKey: undefined,\r\n      kkiaPayPublicKey: undefined,\r\n      defaultCurrency: \"XOF\",\r\n      isTestMode: false,\r\n      debug: false,\r\n      onAnalyticsEvent: undefined,\r\n      isProviderMounted: false,\r\n    };\r\n  }\r\n  \r\n  return context;\r\n}\r\n\r\n/**\r\n * Hook to check if the app is wrapped with BeninPaymentProvider.\r\n * \r\n * @returns true if provider is mounted, false otherwise\r\n */\r\nexport function useIsBeninProviderMounted(): boolean {\r\n  const context = useContext(BeninPaymentContext);\r\n  return context?.isProviderMounted ?? false;\r\n}\r\n","/**\r\n * Loads an external JavaScript script dynamically.\r\n * \r\n * Checks if a script with the given ID already exists to prevent duplicates.\r\n * Scripts are loaded asynchronously to avoid blocking page rendering.\r\n * \r\n * @param src - The URL of the script to load\r\n * @param id - Unique ID for the script element (used for deduplication)\r\n * @returns Promise that resolves to `true` when loaded, or rejects on error\r\n * \r\n * @example\r\n * ```ts\r\n * await loadScript(\"https://cdn.example.com/sdk.js\", \"example-sdk\");\r\n * // SDK is now available on window\r\n * ```\r\n */\r\nexport function loadScript(src: string, id: string): Promise<boolean> {\r\n  // Guard for SSR environments (Next.js server components, Node.js)\r\n  if (typeof document === \"undefined\") {\r\n    return Promise.resolve(false);\r\n  }\r\n\r\n  return new Promise((resolve, reject) => {\r\n    const existingScript = document.getElementById(id) as HTMLScriptElement | null;\r\n\r\n    if (existingScript) {\r\n      // Script already in the DOM — resolve immediately to avoid duplicates.\r\n      // We trust the existing element is either loaded or being loaded elsewhere.\r\n      resolve(true);\r\n      return;\r\n    }\r\n\r\n    const script = document.createElement(\"script\");\r\n    script.id = id;\r\n    script.src = src;\r\n    script.async = true;\r\n\r\n    script.onload = () => {\r\n      script.dataset.loaded = \"true\";\r\n      resolve(true);\r\n    };\r\n\r\n    script.onerror = () => {\r\n      reject(new Error(`Failed to load script: ${src}`));\r\n    };\r\n\r\n    document.body.appendChild(script);\r\n  });\r\n}\r\n","const PREFIX = \"[react-benin-payments]\";\r\n\r\nconst STYLES = {\r\n  info: \"color: #4E6BFF; font-weight: bold;\",\r\n  success: \"color: #0AB67A; font-weight: bold;\",\r\n  error: \"color: #EF4444; font-weight: bold;\",\r\n  warn: \"color: #F59E0B; font-weight: bold;\",\r\n};\r\n\r\n/**\r\n * Creates a styled logger for debug mode.\r\n * \r\n * When enabled, logs are color-coded by level:\r\n * - Info: Blue (#4E6BFF)\r\n * - Success: Green (#0AB67A)\r\n * - Error: Red (#EF4444)\r\n * - Warn: Orange (#F59E0B)\r\n * \r\n * @param enabled - Whether logging is enabled\r\n * @returns Logger object with info, success, error, and warn methods\r\n * \r\n * @example\r\n * ```ts\r\n * const log = createLogger(true);\r\n * log.info(\"Loading SDK...\");\r\n * log.success(\"SDK loaded!\");\r\n * log.error(\"Failed to load\", error);\r\n * ```\r\n */\r\nexport function createLogger(enabled: boolean): Logger {\r\n  return {\r\n    info: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.log(`%c${PREFIX} ${message}`, STYLES.info, ...args);\r\n      }\r\n    },\r\n    success: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.log(`%c${PREFIX} ${message}`, STYLES.success, ...args);\r\n      }\r\n    },\r\n    error: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.error(`%c${PREFIX} ${message}`, STYLES.error, ...args);\r\n      }\r\n    },\r\n    warn: (message: string, ...args: unknown[]) => {\r\n      if (enabled) {\r\n        console.warn(`%c${PREFIX} ${message}`, STYLES.warn, ...args);\r\n      }\r\n    },\r\n  };\r\n}\r\n\r\n/**\r\n * Logger interface with color-coded methods.\r\n */\r\nexport interface Logger {\r\n  /** Log informational message (blue) */\r\n  info: (message: string, ...args: unknown[]) => void;\r\n  /** Log success message (green) */\r\n  success: (message: string, ...args: unknown[]) => void;\r\n  /** Log error message (red) */\r\n  error: (message: string, ...args: unknown[]) => void;\r\n  /** Log warning message (orange) */\r\n  warn: (message: string, ...args: unknown[]) => void;\r\n}\r\n","import type { PaymentProviderId } from \"../core/types\";\r\n\r\nexport type BeninPaymentAnalyticsEventName =\r\n  | \"sdk_load_started\"\r\n  | \"sdk_load_succeeded\"\r\n  | \"sdk_load_failed\"\r\n  | \"payment_validation_failed\"\r\n  | \"payment_pre_validation_started\"\r\n  | \"payment_pre_validation_succeeded\"\r\n  | \"payment_pre_validation_cancelled\"\r\n  | \"payment_pre_validation_failed\"\r\n  | \"payment_open_attempted\"\r\n  | \"payment_opened\"\r\n  | \"payment_completed\"\r\n  | \"payment_failed\"\r\n  | \"payment_closed\"\r\n  | \"payment_verification_started\"\r\n  | \"payment_verification_succeeded\"\r\n  | \"payment_verification_failed\";\r\n\r\nexport interface BeninPaymentAnalyticsEvent {\r\n  name: BeninPaymentAnalyticsEventName;\r\n  /** `\"fedapay\"` / `\"kkiapay\"`, or a custom provider identifier for a driver you wrote yourself. */\r\n  provider: PaymentProviderId;\r\n  amount?: number;\r\n  currency?: string;\r\n  mode: \"mock\" | \"live\";\r\n  transactionId?: string;\r\n  status?: string;\r\n  errorCode?: string;\r\n  errorMessage?: string;\r\n  timestamp: string;\r\n  metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport type BeninPaymentAnalyticsHandler = (\r\n  event: BeninPaymentAnalyticsEvent\r\n) => void | Promise<void>;\r\n\r\nexport function createAnalyticsEmitter(\r\n  handlers: Array<BeninPaymentAnalyticsHandler | undefined>,\r\n  debugLog?: (message: string, ...args: unknown[]) => void\r\n): (event: Omit<BeninPaymentAnalyticsEvent, \"timestamp\">) => void {\r\n  return (event) => {\r\n    const fullEvent: BeninPaymentAnalyticsEvent = {\r\n      ...event,\r\n      timestamp: new Date().toISOString(),\r\n    };\r\n\r\n    handlers.forEach((handler) => {\r\n      if (!handler) return;\r\n\r\n      try {\r\n        void Promise.resolve(handler(fullEvent)).catch((error) => {\r\n          debugLog?.(\"Analytics handler failed\", error);\r\n        });\r\n      } catch (error) {\r\n        debugLog?.(\"Analytics handler failed\", error);\r\n      }\r\n    });\r\n  };\r\n}\r\n","/**\n * A pattern matched against a raw error message, with the user-facing\n * message to show when it matches.\n */\nexport interface ErrorPattern {\n  pattern: RegExp;\n  message: string;\n}\n\n/**\n * Options to fully control `parseError`'s output — pass your own patterns\n * and/or fallback message to translate or reword the built-in French\n * defaults, instead of being stuck with them.\n */\nexport interface ParseErrorOptions {\n  /**\n   * Patterns checked in order; the first match wins. Defaults to\n   * `DEFAULT_ERROR_PATTERNS`. Spread the defaults in if you only want to\n   * add or reorder a few: `{ patterns: [...myPatterns, ...DEFAULT_ERROR_PATTERNS] }`.\n   */\n  patterns?: ErrorPattern[];\n  /** Returned when nothing matches and the error has no usable message. */\n  fallbackMessage?: string;\n}\n\n/**\n * Default error patterns and their French, user-friendly translations.\n * Exported so you can extend rather than fully replace them — see\n * `ParseErrorOptions.patterns`.\n */\nexport const DEFAULT_ERROR_PATTERNS: ErrorPattern[] = [\n  { pattern: /closed|dismissed|cancel/i, message: \"Paiement annulé.\" },\n  { pattern: /insufficient.*(fund|balance)/i, message: \"Solde insuffisant sur votre compte.\" },\n  { pattern: /network|connection|offline/i, message: \"Problème de connexion internet.\" },\n  { pattern: /timeout/i, message: \"La requête a expiré. Veuillez réessayer.\" },\n  { pattern: /invalid.*key/i, message: \"Clé API invalide.\" },\n  { pattern: /invalid.*amount/i, message: \"Montant invalide.\" },\n  { pattern: /unauthorized|401/i, message: \"Accès non autorisé.\" },\n  { pattern: /not.*found|404/i, message: \"Ressource introuvable.\" },\n  { pattern: /server.*error|500/i, message: \"Erreur serveur. Veuillez réessayer.\" },\n];\n\nconst DEFAULT_FALLBACK_MESSAGE = \"Une erreur inconnue est survenue.\";\n\n/**\n * Parses an error and returns a user-friendly message.\n *\n * Defaults to French translations (`DEFAULT_ERROR_PATTERNS`), but you're\n * never stuck with them — pass your own `patterns` and/or `fallbackMessage`\n * to translate or reword every message this library can produce.\n *\n * @param error - The error to parse (can be any type)\n * @param options - Optional custom patterns / fallback message\n * @returns A clean, user-friendly error message\n *\n * @example\n * ```ts\n * parseError(new Error(\"Network connection failed\"));\n * // Returns: \"Problème de connexion internet.\"\n *\n * // Full control — e.g. an English-speaking product:\n * parseError(err, {\n *   patterns: [\n *     { pattern: /closed|dismissed|cancel/i, message: \"Payment cancelled.\" },\n *     { pattern: /network|connection|offline/i, message: \"No internet connection.\" },\n *   ],\n *   fallbackMessage: \"Something went wrong.\",\n * });\n * ```\n */\nexport function parseError(error: unknown, options: ParseErrorOptions = {}): string {\n  const patterns = options.patterns ?? DEFAULT_ERROR_PATTERNS;\n  const fallbackMessage = options.fallbackMessage ?? DEFAULT_FALLBACK_MESSAGE;\n\n  if (!error) {\n    return fallbackMessage;\n  }\n\n  let errorMessage: string;\n\n  if (typeof error === \"string\") {\n    errorMessage = error;\n  } else if (error instanceof Error) {\n    errorMessage = error.message;\n  } else if (typeof error === \"object\" && error !== null) {\n    const errorObj = error as Record<string, unknown>;\n    errorMessage =\n      (errorObj.message as string) ||\n      (errorObj.error as string) ||\n      (errorObj.msg as string) ||\n      JSON.stringify(error);\n  } else {\n    return fallbackMessage;\n  }\n\n  for (const { pattern, message } of patterns) {\n    if (pattern.test(errorMessage)) {\n      return message;\n    }\n  }\n\n  return errorMessage || fallbackMessage;\n}\n\n/**\n * Creates a standardized error object with parsed message.\n *\n * @param error - The raw error\n * @param options - Optional custom patterns / fallback message, forwarded to `parseError`\n * @returns An Error object with a user-friendly message\n */\nexport function createParsedError(error: unknown, options?: ParseErrorOptions): Error {\n  return new Error(parseError(error, options));\n}\n","import type { VerificationConfig, VerificationResponse, VerifyMethod } from \"../types\";\r\nimport type { PaymentProviderId } from \"../core/types\";\r\n\r\n/**\r\n * Payload sent to the verification endpoint.\r\n */\r\nexport interface VerifyPayload {\r\n  /** Transaction ID from the payment provider */\r\n  transactionId: string;\r\n  /** Amount that was charged */\r\n  amount: number;\r\n  /** Payment provider used — `\"fedapay\"` / `\"kkiapay\"`, or a custom driver's identifier */\r\n  provider: PaymentProviderId;\r\n  /** Additional metadata */\r\n  metadata?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Thrown when backend verification fails. `isBackendMessage` tells callers\r\n * whether `message` is text your own `verifyUrl` endpoint returned (and\r\n * should therefore be shown to the user exactly as written) or a generic\r\n * fallback/network message that's safe to run through further translation.\r\n */\r\nexport class VerificationError extends Error {\r\n  constructor(message: string, public readonly isBackendMessage: boolean) {\r\n    super(message);\r\n    this.name = \"VerificationError\";\r\n  }\r\n}\r\n\r\n/**\r\n * Verifies a transaction with the backend.\r\n *\r\n * @param config - Verification configuration\r\n * @param payload - Transaction data to verify\r\n * @returns Verification response from the backend\r\n * @throws {VerificationError} if verification fails or network error occurs\r\n *\r\n * @example\r\n * ```ts\r\n * const result = await verifyTransaction(\r\n *   { verifyUrl: \"/api/verify\", verifyMethod: \"POST\" },\r\n *   { transactionId: \"tx_123\", amount: 5000, provider: \"fedapay\" }\r\n * );\r\n * ```\r\n */\r\nexport async function verifyTransaction(\r\n  config: VerificationConfig,\r\n  payload: VerifyPayload\r\n): Promise<VerificationResponse> {\r\n  if (!config.verifyUrl) {\r\n    throw new Error(\"verifyUrl is required for transaction verification\");\r\n  }\r\n\r\n  const method: VerifyMethod = config.verifyMethod ?? \"POST\";\r\n  const headers: Record<string, string> = {\r\n    \"Content-Type\": \"application/json\",\r\n    ...config.customVerifyHeaders,\r\n  };\r\n\r\n  let url = config.verifyUrl;\r\n  const fetchOptions: RequestInit = {\r\n    method,\r\n    headers,\r\n  };\r\n\r\n  if (method === \"POST\") {\r\n    fetchOptions.body = JSON.stringify(payload);\r\n  } else {\r\n    const params = new URLSearchParams({\r\n      transactionId: payload.transactionId,\r\n      amount: payload.amount.toString(),\r\n      provider: payload.provider,\r\n    });\r\n    url = `${config.verifyUrl}?${params.toString()}`;\r\n  }\r\n\r\n  const response = await fetch(url, fetchOptions);\r\n\r\n  if (!response.ok) {\r\n    let errorMessage = `Verification failed with status ${response.status}`;\r\n    let isBackendMessage = false;\r\n\r\n    try {\r\n      const errorData = await response.json();\r\n      if (errorData.message) {\r\n        errorMessage = errorData.message;\r\n        isBackendMessage = true;\r\n      }\r\n    } catch {\r\n      // Response is not JSON, use default message\r\n    }\r\n\r\n    throw new VerificationError(errorMessage, isBackendMessage);\r\n  }\r\n\r\n  const data = await response.json();\r\n  \r\n  return {\r\n    success: data.success ?? true,\r\n    message: data.message,\r\n    data: data.data ?? data,\r\n  };\r\n}\r\n","import { loadScript } from \"../utils/scriptLoader\";\nimport { createLogger } from \"../utils/logger\";\nimport { createAnalyticsEmitter, type BeninPaymentAnalyticsEvent } from \"../utils/analytics\";\nimport { parseError } from \"../utils/errors\";\nimport { verifyTransaction, VerificationError } from \"../utils/verifyTransaction\";\nimport type { PaymentValidationError } from \"../types/validation\";\nimport type {\n  PaymentDriver,\n  PaymentEngine,\n  PaymentEngineOptions,\n  PaymentEngineState,\n} from \"./types\";\n\ntype AnalyticsEventInput = Omit<BeninPaymentAnalyticsEvent, \"timestamp\" | \"provider\">;\n\n/**\n * Creates a framework-agnostic payment flow controller for a given provider\n * driver. Handles script loading, validation, mock simulation, the optional\n * `onBeforePayment` hook, backend verification and standardized analytics —\n * identically for every provider that implements `PaymentDriver`.\n *\n * This has no dependency on React: `subscribe`/`getState` can be wired into\n * any UI layer. `usePaymentEngine` is the thin React binding used internally\n * by `useFedaPay` / `useKkiaPay`.\n */\nexport function createPaymentEngine<TConfig, TRaw>(\n  driver: PaymentDriver<TConfig, TRaw>,\n  getOptions: () => PaymentEngineOptions<TConfig, TRaw>\n): PaymentEngine<TConfig> {\n  const initialMock = getOptions().isMockMode;\n\n  let state: PaymentEngineState = {\n    loading: !initialMock,\n    scriptLoaded: initialMock,\n    error: null,\n    isVerifying: false,\n    isPreparing: false,\n  };\n  let lastConfig: TConfig | null = null;\n  let destroyed = false;\n  const listeners = new Set<() => void>();\n\n  function getState() {\n    return state;\n  }\n\n  function subscribe(listener: () => void) {\n    listeners.add(listener);\n    return () => listeners.delete(listener);\n  }\n\n  function setState(patch: Partial<PaymentEngineState>) {\n    state = { ...state, ...patch };\n    // The `destroyed` guard is what makes it safe for usePaymentEngine to\n    // swap in a new engine (e.g. when `isMockMode` changes) without\n    // explicitly cancelling this one first: React runs this engine's\n    // `start()` cleanup (which sets `destroyed = true`) before the new\n    // engine's effect runs, so any in-flight promise/timer that resolves\n    // late just updates dead internal state instead of notifying React.\n    if (!destroyed) listeners.forEach((listener) => listener());\n  }\n\n  function getLog() {\n    return createLogger(getOptions().debug ?? false);\n  }\n\n  function emit(event: AnalyticsEventInput, configForExtras: TConfig | undefined) {\n    const options = getOptions();\n    const emitter = createAnalyticsEmitter(\n      [options.globalAnalyticsHandler, options.onAnalyticsEvent],\n      getLog().warn\n    );\n    const extras = driver.getAnalyticsExtras?.(configForExtras) ?? {};\n    emitter({ ...extras, ...event, provider: driver.name });\n  }\n\n  /** Applies a per-code message override (`options.messages`), if configured. */\n  function applyMessageOverride(error: PaymentValidationError): PaymentValidationError {\n    const override = getOptions().messages?.[error.code];\n    return override ? { ...error, message: override } : error;\n  }\n\n  /**\n   * Resolves a user-facing message for a caught technical error (SDK load\n   * failure, network error, thrown SDK exception...). Tries the caller's\n   * `resolveErrorMessage` first, then falls back to `parseError`'s built-in\n   * translations.\n   */\n  function resolveGenericErrorMessage(error: unknown): string {\n    const custom = getOptions().resolveErrorMessage?.(error);\n    return custom !== undefined ? custom : parseError(error);\n  }\n\n  function handleSuccess(raw: TRaw, config?: TConfig) {\n    const options = getOptions();\n    const log = getLog();\n    const resolvedConfig = config ?? (lastConfig as TConfig);\n    const mode: \"mock\" | \"live\" = options.isMockMode ? \"mock\" : \"live\";\n\n    log.success(\"Payment completed by provider\", raw);\n\n    const payload = driver.toVerifyPayload(raw, resolvedConfig);\n    const status = driver.getStatus?.(raw);\n    const verifyUrl = options.verification?.verifyUrl;\n\n    if (!verifyUrl) {\n      emit(\n        { name: \"payment_completed\", amount: payload.amount, mode, transactionId: payload.transactionId, status },\n        resolvedConfig\n      );\n      options.onRawSuccess?.(raw);\n      return;\n    }\n\n    setState({ isVerifying: true });\n    log.info(\"🔐 Verifying transaction with backend...\", { url: verifyUrl });\n    emit(\n      { name: \"payment_verification_started\", amount: payload.amount, mode, transactionId: payload.transactionId },\n      resolvedConfig\n    );\n\n    verifyTransaction(\n      {\n        verifyUrl,\n        verifyMethod: options.verification?.verifyMethod,\n        customVerifyHeaders: options.verification?.customVerifyHeaders,\n      },\n      {\n        transactionId: payload.transactionId,\n        amount: payload.amount,\n        provider: driver.name,\n        metadata: payload.metadata,\n      }\n    )\n      .then((verifyResult) => {\n        setState({ isVerifying: false });\n        log.success(\"🔐 Backend verification successful\", verifyResult);\n        emit(\n          { name: \"payment_verification_succeeded\", amount: payload.amount, mode, transactionId: payload.transactionId },\n          resolvedConfig\n        );\n        emit(\n          { name: \"payment_completed\", amount: payload.amount, mode, transactionId: payload.transactionId, status },\n          resolvedConfig\n        );\n        options.onRawSuccess?.(raw);\n      })\n      .catch((err) => {\n        setState({ isVerifying: false });\n        const verifyError = err instanceof Error ? err : new Error(\"Verification failed\");\n        log.error(\"🔐 Backend verification failed\", verifyError);\n        emit(\n          {\n            name: \"payment_verification_failed\",\n            amount: payload.amount,\n            mode,\n            transactionId: payload.transactionId,\n            errorMessage: verifyError.message,\n          },\n          resolvedConfig\n        );\n        // A message your own verifyUrl endpoint wrote is shown exactly as you\n        // wrote it — only messages WE generated (network failures, a bare\n        // HTTP status with no body) go through translation/resolution.\n        const userMessage =\n          verifyError instanceof VerificationError && verifyError.isBackendMessage\n            ? verifyError.message\n            : resolveGenericErrorMessage(verifyError);\n        options.onValidationError?.(applyMessageOverride({ code: \"SDK_ERROR\", message: userMessage }));\n      });\n  }\n\n  function start(): () => void {\n    const options = getOptions();\n    const log = getLog();\n\n    if (options.isMockMode) {\n      log.info(\"🧪 Running in Mock Mode - No real SDK loaded\");\n      setState({ scriptLoaded: true, loading: false });\n      return () => {\n        destroyed = true;\n      };\n    }\n\n    let cancelled = false;\n    const analyticsConfig = options.getAnalyticsConfig?.();\n\n    log.info(`Loading ${driver.name} SDK...`);\n    emit({ name: \"sdk_load_started\", mode: \"live\", amount: driver.getAmount(analyticsConfig) }, analyticsConfig);\n\n    loadScript(driver.scriptUrl, driver.scriptId)\n      .then(() => {\n        if (cancelled) return;\n        setState({ scriptLoaded: true, loading: false });\n        log.success(`${driver.name} SDK loaded successfully`);\n        emit(\n          { name: \"sdk_load_succeeded\", mode: \"live\", amount: driver.getAmount(analyticsConfig) },\n          analyticsConfig\n        );\n      })\n      .catch((err) => {\n        if (cancelled) return;\n        const friendlyMessage = resolveGenericErrorMessage(err);\n        setState({ error: new Error(friendlyMessage), loading: false });\n        log.error(`Failed to load ${driver.name} SDK`, err);\n        emit(\n          {\n            name: \"sdk_load_failed\",\n            mode: \"live\",\n            amount: driver.getAmount(analyticsConfig),\n            errorMessage: friendlyMessage,\n          },\n          analyticsConfig\n        );\n      });\n\n    return () => {\n      cancelled = true;\n      destroyed = true;\n    };\n  }\n\n  async function runOpen(config: TConfig) {\n    const options = getOptions();\n    const log = getLog();\n    const isMockMode = options.isMockMode;\n    const mode: \"mock\" | \"live\" = isMockMode ? \"mock\" : \"live\";\n\n    if (state.isPreparing) {\n      log.warn(\"Payment pre-validation already in progress\");\n      return;\n    }\n\n    log.info(`Opening ${driver.name} dialog...`, { config, isMockMode });\n\n    driver.logEnvironmentWarnings?.(config, { isMockMode, environmentWarnings: options.environmentWarnings });\n\n    const validationError = driver.validate(config, { isMockMode });\n    if (validationError) {\n      log.error(`Validation failed: ${validationError.message}`);\n      emit(\n        {\n          name: \"payment_validation_failed\",\n          amount: driver.getAmount(config),\n          mode,\n          errorCode: validationError.code,\n          errorMessage: validationError.message,\n        },\n        config\n      );\n      options.onValidationError?.(applyMessageOverride(validationError));\n      return;\n    }\n\n    emit({ name: \"payment_open_attempted\", amount: driver.getAmount(config), mode }, config);\n\n    if (options.onBeforePayment) {\n      try {\n        setState({ isPreparing: true });\n        emit({ name: \"payment_pre_validation_started\", amount: driver.getAmount(config), mode }, config);\n        const shouldContinue = await options.onBeforePayment();\n        if (shouldContinue === false) {\n          log.info(\"Payment opening cancelled by onBeforePayment\");\n          emit({ name: \"payment_pre_validation_cancelled\", amount: driver.getAmount(config), mode }, config);\n          return;\n        }\n        emit({ name: \"payment_pre_validation_succeeded\", amount: driver.getAmount(config), mode }, config);\n      } catch (err) {\n        const preValidationError = err instanceof Error ? err : new Error(\"Payment pre-validation failed\");\n        setState({ error: preValidationError });\n        log.error(\"onBeforePayment failed\", preValidationError);\n        emit(\n          {\n            name: \"payment_pre_validation_failed\",\n            amount: driver.getAmount(config),\n            mode,\n            errorMessage: preValidationError.message,\n          },\n          config\n        );\n        options.onValidationError?.(\n          applyMessageOverride({ code: \"PRE_VALIDATION_FAILED\", message: preValidationError.message })\n        );\n        return;\n      } finally {\n        setState({ isPreparing: false });\n      }\n    }\n\n    if (isMockMode) {\n      log.info(\"🧪 Simulating payment...\");\n      emit({ name: \"payment_opened\", amount: driver.getAmount(config), mode: \"mock\" }, config);\n      setTimeout(() => {\n        const mockResponse = driver.buildMockSuccess(config);\n        log.success(\"🧪 Mock Payment Successful\", mockResponse);\n        handleSuccess(mockResponse, config);\n      }, 1000);\n      return;\n    }\n\n    if (!state.scriptLoaded || !driver.isSdkReady()) {\n      const validationError = {\n        code: \"SDK_NOT_LOADED\" as const,\n        message: `${driver.name} SDK not loaded. Please wait for the script to load.`,\n      };\n      log.error(\"SDK not loaded. Cannot open dialog.\");\n      emit(\n        {\n          name: \"payment_validation_failed\",\n          amount: driver.getAmount(config),\n          mode: \"live\",\n          errorCode: validationError.code,\n          errorMessage: validationError.message,\n        },\n        config\n      );\n      options.onValidationError?.(applyMessageOverride(validationError));\n      return;\n    }\n\n    try {\n      driver.open(\n        config,\n        {\n          onSuccess: (raw) => handleSuccess(raw, config),\n          onFailure: (raw) => getOptions().onRawFailure?.(raw),\n          onClose: () => getOptions().onClose?.(),\n        },\n        {\n          log,\n          isMockMode,\n          emit: (partial) => emit({ amount: driver.getAmount(config), mode: \"live\", ...partial }, config),\n        }\n      );\n\n      log.success(`${driver.name} dialog opened successfully`);\n      emit({ name: \"payment_opened\", amount: driver.getAmount(config), mode: \"live\" }, config);\n    } catch (err) {\n      log.error(`Failed to open ${driver.name} dialog`, err);\n      const sdkError = err instanceof Error ? err : new Error(`Failed to open ${driver.name} dialog`);\n      setState({ error: sdkError });\n      emit(\n        {\n          name: \"payment_failed\",\n          amount: driver.getAmount(config),\n          mode: \"live\",\n          errorCode: \"SDK_ERROR\",\n          errorMessage: sdkError.message,\n        },\n        config\n      );\n      options.onValidationError?.(\n        applyMessageOverride({ code: \"SDK_ERROR\", message: resolveGenericErrorMessage(sdkError) })\n      );\n    }\n  }\n\n  function open(config: TConfig) {\n    lastConfig = config;\n    void runOpen(config);\n  }\n\n  return { getState, subscribe, start, open };\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPaymentEngine } from \"./createPaymentEngine\";\nimport type { PaymentDriver, PaymentEngineOptions, PaymentEngineState } from \"./types\";\n\n/**\n * React binding for `createPaymentEngine`. Owns one engine instance per\n * hook call (recreated only if the driver or mock-mode flag changes),\n * subscribes to its state, and starts its background lifecycle\n * (script loading, persistent SDK listeners) for the component's lifetime.\n *\n * `getOptions` is called fresh on every render, so callbacks and config\n * values it returns are always up to date without needing to be listed in\n * any dependency array.\n */\nexport function usePaymentEngine<TConfig, TRaw>(\n  driver: PaymentDriver<TConfig, TRaw>,\n  getOptions: () => PaymentEngineOptions<TConfig, TRaw>\n): [PaymentEngineState, (config: TConfig) => void] {\n  const getOptionsRef = useRef(getOptions);\n  getOptionsRef.current = getOptions;\n\n  const isMockMode = getOptions().isMockMode;\n\n  const engine = useMemo(\n    () => createPaymentEngine(driver, () => getOptionsRef.current()),\n    // Recreated only when the driver identity or the mock flag changes —\n    // mirrors the original hooks re-running their script-loading effect then.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [driver, isMockMode]\n  );\n\n  const [state, setState] = useState<PaymentEngineState>(() => engine.getState());\n\n  useEffect(() => {\n    setState(engine.getState());\n    const unsubscribe = engine.subscribe(() => setState(engine.getState()));\n    const stop = engine.start();\n    return () => {\n      unsubscribe();\n      stop();\n    };\n  }, [engine]);\n\n  return [state, engine.open];\n}\n","/**\n * Overrides the wording of the dev-time console warnings emitted by\n * `validateKeyEnvironment`/`logSandboxMode`. Every field is optional — any\n * warning you don't override keeps its default English text.\n */\nexport interface EnvironmentWarningMessages {\n  /** Shown when a live key is used while sandbox mode is on. Receives the provider name (e.g. \"FedaPay\"). */\n  liveKeyInSandbox?: (provider: string) => string;\n  /** Shown when a test/sandbox key is used while sandbox mode is off. Receives the provider name. */\n  testKeyInProduction?: (provider: string) => string;\n  /** Shown once whenever sandbox mode is active. Receives the provider name. */\n  sandboxModeActive?: (provider: string) => string;\n}\n\n/**\n * Validates API key consistency with sandbox mode.\n * Warns developers about potential misconfigurations.\n *\n * @param key - The API public key\n * @param sandbox - Whether sandbox mode is enabled\n * @param provider - The payment provider name (for logging)\n * @param messages - Optional overrides for the warning text\n */\nexport function validateKeyEnvironment(\n  key: string,\n  sandbox: boolean,\n  provider: \"FedaPay\" | \"KKiaPay\",\n  messages?: EnvironmentWarningMessages\n): void {\n  if (!key) return;\n\n  const isLiveKey = key.startsWith(\"pk_live_\") || key.startsWith(\"pk_live\");\n  const isTestKey =\n    key.startsWith(\"pk_test_\") ||\n    key.startsWith(\"pk_sandbox_\") ||\n    key.startsWith(\"pk_sandbox\");\n\n  if (sandbox && isLiveKey) {\n    console.warn(\n      messages?.liveKeyInSandbox?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: You are in Sandbox mode but using a LIVE key! This may cause unexpected charges.`\n    );\n  }\n\n  if (!sandbox && isTestKey) {\n    console.warn(\n      messages?.testKeyInProduction?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: You are in Production mode but using a TEST key! Payments will not be processed.`\n    );\n  }\n}\n\n/**\n * Logs sandbox mode warning if enabled.\n *\n * @param sandbox - Whether sandbox mode is enabled\n * @param provider - The payment provider name\n * @param messages - Optional overrides for the warning text\n */\nexport function logSandboxMode(\n  sandbox: boolean,\n  provider: \"FedaPay\" | \"KKiaPay\",\n  messages?: EnvironmentWarningMessages\n): void {\n  if (sandbox) {\n    console.log(\n      messages?.sandboxModeActive?.(provider) ??\n        `⚠️ [react-benin-payments] ${provider}: Running in Sandbox Mode - No real transactions will be processed.`\n    );\n  }\n}\n","import type { Currency } from \"../types\";\r\n\r\n/**\r\n * Formats an amount in XOF (West African CFA Franc).\r\n * \r\n * @param amount - The amount to format\r\n * @returns Formatted string with FCFA suffix (e.g., \"5 000 FCFA\")\r\n * \r\n * @example\r\n * ```ts\r\n * formatXOF(5000);    // \"5 000 FCFA\"\r\n * formatXOF(1500000); // \"1 500 000 FCFA\"\r\n * formatXOF(0);       // \"0 FCFA\"\r\n * ```\r\n */\r\nexport function formatXOF(amount: number): string {\r\n  const formatted = new Intl.NumberFormat(\"fr-FR\", {\r\n    style: \"decimal\",\r\n    minimumFractionDigits: 0,\r\n    maximumFractionDigits: 0,\r\n  }).format(amount);\r\n\r\n  return `${formatted} FCFA`;\r\n}\r\n\r\n/**\r\n * Formats an amount in the specified currency.\r\n * \r\n * @param amount - The amount to format\r\n * @param currency - The currency code (XOF, USD, EUR)\r\n * @returns Formatted string with currency symbol\r\n * \r\n * @example\r\n * ```ts\r\n * formatCurrency(5000, \"XOF\");  // \"5 000 FCFA\"\r\n * formatCurrency(100, \"USD\");   // \"$100.00\"\r\n * formatCurrency(100, \"EUR\");   // \"100,00 €\"\r\n * ```\r\n */\r\nexport function formatCurrency(amount: number, currency: Currency): string {\r\n  switch (currency) {\r\n    case \"XOF\":\r\n      return formatXOF(amount);\r\n    case \"USD\":\r\n      return new Intl.NumberFormat(\"en-US\", {\r\n        style: \"currency\",\r\n        currency: \"USD\",\r\n      }).format(amount);\r\n    case \"EUR\":\r\n      return new Intl.NumberFormat(\"fr-FR\", {\r\n        style: \"currency\",\r\n        currency: \"EUR\",\r\n      }).format(amount);\r\n    default:\r\n      return `${amount} ${currency}`;\r\n  }\r\n}\r\n\r\n/**\r\n * Generates a mock transaction ID for testing.\r\n * \r\n * @returns A unique mock transaction ID\r\n */\r\nexport function generateMockTransactionId(): string {\r\n  const timestamp = Date.now().toString(36);\r\n  const random = Math.random().toString(36).substring(2, 8);\r\n  return `mock_tx_${timestamp}_${random}`;\r\n}\r\n","import type { PaymentValidationError } from \"../types/validation\";\n\n/**\n * The most common `PaymentDriver.validate` shape: a required public key\n * (unless in mock mode) and a positive amount. Both built-in drivers\n * (FedaPay, KKiaPay) use this — reach for it in a custom driver too instead\n * of re-implementing the same two checks.\n *\n * @example\n * ```ts\n * validate: (config, { isMockMode }) =>\n *   validatePublicKeyAndAmount(config.apiKey, config.amount, isMockMode),\n * ```\n */\nexport function validatePublicKeyAndAmount(\n  publicKey: string | undefined,\n  amount: number | undefined,\n  isMockMode: boolean\n): PaymentValidationError | null {\n  if (!isMockMode && (!publicKey || publicKey.trim() === \"\")) {\n    return {\n      code: \"MISSING_PUBLIC_KEY\",\n      message: \"Missing Public Key. Provide it via config or BeninPaymentProvider.\",\n    };\n  }\n  if (!amount || amount <= 0) {\n    return { code: \"INVALID_AMOUNT\", message: \"Invalid amount. Amount must be greater than 0.\" };\n  }\n  return null;\n}\n","import { validateKeyEnvironment, logSandboxMode } from \"../utils/keyValidator\";\nimport { generateMockTransactionId } from \"../utils/currency\";\nimport { validatePublicKeyAndAmount } from \"../core/validateCommonConfig\";\nimport type { PaymentDriver } from \"../core/types\";\nimport type { FedaPayConfig, FedaPayCallbackResponse } from \"../types\";\n\nconst FEDAPAY_SCRIPT_URL = \"https://cdn.fedapay.com/checkout.js?v=1.1.7\";\nconst FEDAPAY_SCRIPT_ID = \"fedapay-checkout-script\";\n\n/**\n * FedaPay adapter for `createPaymentEngine`. FedaPay's SDK takes inline\n * `onComplete`/`onClose` callbacks per call (`window.FedaPay.init(...).open()`),\n * so `open()` wires the engine's handlers directly into that call.\n */\nexport function createFedaPayDriver(): PaymentDriver<FedaPayConfig, FedaPayCallbackResponse> {\n  return {\n    name: \"fedapay\",\n    scriptUrl: FEDAPAY_SCRIPT_URL,\n    scriptId: FEDAPAY_SCRIPT_ID,\n\n    isSdkReady: () => typeof window !== \"undefined\" && !!window.FedaPay,\n\n    logEnvironmentWarnings(config, { isMockMode, environmentWarnings }) {\n      if (isMockMode) return;\n      if (config.public_key) {\n        validateKeyEnvironment(config.public_key, !!config.sandbox, \"FedaPay\", environmentWarnings);\n      }\n      logSandboxMode(!!config.sandbox, \"FedaPay\", environmentWarnings);\n    },\n\n    validate: (config, { isMockMode }) =>\n      validatePublicKeyAndAmount(config.public_key, config.transaction?.amount, isMockMode),\n\n    getAmount: (config) => config?.transaction?.amount,\n\n    getAnalyticsExtras: (config) => ({ currency: config?.currency?.iso }),\n\n    buildMockSuccess: (config) => ({\n      reason: \"mock_transaction_completed\",\n      transaction: {\n        id: Math.floor(Math.random() * 1000000),\n        reference: generateMockTransactionId(),\n        amount: config.transaction.amount,\n        status: \"approved\",\n      },\n    }),\n\n    toVerifyPayload: (raw, config) => ({\n      transactionId: raw.transaction.reference,\n      amount: raw.transaction.amount,\n      metadata: config.metadata,\n    }),\n\n    getStatus: (raw) => raw.transaction.status,\n\n    open(config, handlers, ctx) {\n      const transactionWithMetadata = {\n        ...config.transaction,\n        custom_metadata: {\n          ...config.transaction.custom_metadata,\n          ...config.metadata,\n        },\n      };\n\n      const widget = window.FedaPay!.init({\n        public_key: config.public_key,\n        transaction: transactionWithMetadata,\n        customer: config.customer,\n        currency: config.currency,\n        onComplete: (response: FedaPayCallbackResponse) => handlers.onSuccess(response),\n        onClose: () => {\n          ctx.log.info(\"Payment dialog closed by user\");\n          ctx.emit({ name: \"payment_closed\" });\n          handlers.onClose();\n        },\n      });\n\n      widget.open();\n    },\n  };\n}\n","/**\r\n * Checks if the current environment is a test environment.\r\n * Safe to use in browser and Node.js contexts.\r\n * \r\n * @returns true if running in test mode\r\n */\r\nexport function isTestEnvironment(): boolean {\r\n  // Safe check for Node.js environment\r\n  if (typeof process === \"undefined\") {\r\n    return false;\r\n  }\r\n  \r\n  if (!process.env) {\r\n    return false;\r\n  }\r\n  \r\n  return process.env.NODE_ENV === \"test\";\r\n}\r\n","import type { ErrorMessageResolver, PaymentMessageOverrides } from \"../types/validation\";\nimport type { EnvironmentWarningMessages } from \"../utils/keyValidator\";\n\ninterface I18nConfig {\n  messages?: PaymentMessageOverrides;\n  resolveErrorMessage?: ErrorMessageResolver;\n  environmentWarnings?: EnvironmentWarningMessages;\n}\n\n/**\n * Merges a hook's local `messages`/`resolveErrorMessage`/`environmentWarnings`\n * with `BeninPaymentProvider`'s global config — local wins per validation\n * code, and `resolveErrorMessage` tries local first, then global. Shared by\n * `useFedaPay`/`useKkiaPay`/`useBeninPay` so the precedence rule lives in one place.\n */\nexport function mergeI18nOptions(\n  global: I18nConfig,\n  local: I18nConfig\n): Required<Pick<I18nConfig, \"messages\" | \"environmentWarnings\">> &\n  Pick<I18nConfig, \"resolveErrorMessage\"> {\n  return {\n    messages: { ...global.messages, ...local.messages },\n    resolveErrorMessage: (error) => local.resolveErrorMessage?.(error) ?? global.resolveErrorMessage?.(error),\n    environmentWarnings: { ...global.environmentWarnings, ...local.environmentWarnings },\n  };\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { usePaymentEngine } from \"../core/usePaymentEngine\";\nimport { createFedaPayDriver } from \"../providers/fedapay\";\nimport { isTestEnvironment } from \"../utils/environment\";\nimport { useBeninConfig } from \"../context\";\nimport { mergeI18nOptions } from \"./mergeI18nOptions\";\nimport type { FedaPayConfig, FedaPayCallbackResponse, Currency } from \"../types\";\nimport type {\n  ErrorMessageResolver,\n  PaymentMessageOverrides,\n  PaymentValidationError,\n} from \"../types/validation\";\nimport type { EnvironmentWarningMessages } from \"../utils/keyValidator\";\nimport type { BeninPaymentAnalyticsHandler } from \"../utils/analytics\";\n\nconst fedaPayDriver = createFedaPayDriver();\n\n/**\n * Options for the useFedaPay hook.\n */\nexport interface UseFedaPayOptions {\n  /**\n   * Enable debug mode with styled console logs.\n   * If not provided, uses the value from BeninPaymentProvider.\n   * @default false\n   */\n  debug?: boolean;\n  /**\n   * Enable mock mode for testing.\n   * When true, no real SDK is loaded and payments are simulated.\n   * Automatically enabled when process.env.NODE_ENV === 'test'.\n   * @default false\n   */\n  mock?: boolean;\n  /**\n   * Runs before opening the payment modal.\n   * Return `false` to cancel opening without throwing an error.\n   */\n  onBeforePayment?: () => void | boolean | Promise<void | boolean>;\n  /**\n   * Receives standardized analytics events for the payment lifecycle.\n   */\n  onAnalyticsEvent?: BeninPaymentAnalyticsHandler;\n  /**\n   * Callback fired when validation fails or SDK errors occur.\n   * @param error - The validation error with code and message\n   */\n  onError?: (error: PaymentValidationError) => void;\n  /**\n   * Overrides the wording of validation error messages for this hook only\n   * (takes precedence over `BeninPaymentProvider`'s `messages`).\n   */\n  messages?: PaymentMessageOverrides;\n  /**\n   * Resolves the message for arbitrary caught errors (SDK load failures...)\n   * for this hook only. Falls back to the provider's `resolveErrorMessage`,\n   * then to the built-in translations.\n   */\n  resolveErrorMessage?: ErrorMessageResolver;\n  /**\n   * Overrides the wording of dev-time console warnings for this hook only\n   * (takes precedence over `BeninPaymentProvider`'s `environmentWarnings`).\n   */\n  environmentWarnings?: EnvironmentWarningMessages;\n}\n\n/**\n * Return type for the useFedaPay hook.\n */\nexport interface UseFedaPayReturn {\n  /** Function to open the FedaPay payment dialog */\n  openDialog: () => void;\n  /** Whether the SDK is currently loading */\n  loading: boolean;\n  /** Error object if SDK loading failed */\n  error: Error | null;\n  /** Whether the SDK script has been successfully loaded */\n  scriptLoaded: boolean;\n  /** Whether running in mock mode */\n  isMockMode: boolean;\n  /** Whether backend verification is in progress */\n  isVerifying: boolean;\n  /** Whether async pre-validation is in progress */\n  isPreparing: boolean;\n}\n\n/**\n * Configuration for useFedaPay that supports optional public_key.\n * When used inside BeninPaymentProvider, public_key can be omitted.\n */\nexport type UseFedaPayConfig = Omit<FedaPayConfig, \"public_key\"> & {\n  /**\n   * Your FedaPay public key.\n   * Optional if using BeninPaymentProvider with fedaPayPublicKey set.\n   */\n  public_key?: string;\n};\n\n/**\n * React hook for integrating FedaPay payments.\n *\n * Handles script loading, validation, payment dialog, and backend verification.\n * Supports mock mode for testing without loading the actual SDK.\n *\n * Internally this is a thin binding over the framework-agnostic payment\n * engine (see `src/core`) configured with the FedaPay driver — the same\n * engine that powers `useKkiaPay`.\n *\n * @param config - FedaPay configuration (public_key optional if using Provider)\n * @param options - Optional settings for debug mode, mock mode, and error handling\n * @returns Object with `openDialog` function, loading states, and `isVerifying`\n *\n * @example\n * ```tsx\n * // With automatic backend verification\n * const { openDialog, loading, isVerifying } = useFedaPay({\n *   transaction: { amount: 5000 },\n *   verifyUrl: \"/api/payments/verify\",\n *   customVerifyHeaders: { \"Authorization\": \"Bearer xxx\" },\n *   onComplete: (response) => {\n *     // Called AFTER backend verification succeeds\n *     console.log(\"Payment verified!\", response.transaction.id);\n *   }\n * });\n * ```\n */\nexport function useFedaPay(\n  config: UseFedaPayConfig,\n  options: UseFedaPayOptions = {}\n): UseFedaPayReturn {\n  const globalConfig = useBeninConfig();\n\n  const resolvedPublicKey = config.public_key || globalConfig.fedaPayPublicKey || \"\";\n  const resolvedSandbox = config.sandbox ?? globalConfig.isTestMode;\n  const resolvedCurrency: Currency = config.currency?.iso || globalConfig.defaultCurrency;\n  const isMockMode = options.mock ?? isTestEnvironment();\n\n  // Fully-resolved config handed to the driver/engine — it never needs to\n  // know about BeninPaymentProvider defaults.\n  const resolvedConfig: FedaPayConfig = useMemo(\n    () => ({\n      ...config,\n      public_key: resolvedPublicKey,\n      sandbox: resolvedSandbox,\n      currency: { iso: resolvedCurrency },\n    }),\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [config, resolvedPublicKey, resolvedSandbox, resolvedCurrency]\n  );\n\n  const configRef = useRef(resolvedConfig);\n  configRef.current = resolvedConfig;\n\n  const { onError, onBeforePayment, onAnalyticsEvent, messages, resolveErrorMessage, environmentWarnings } =\n    options;\n\n  const [state, open] = usePaymentEngine(fedaPayDriver, () => ({\n    debug: options.debug ?? globalConfig.debug,\n    isMockMode,\n    verification: {\n      verifyUrl: config.verifyUrl,\n      verifyMethod: config.verifyMethod,\n      customVerifyHeaders: config.customVerifyHeaders,\n    },\n    onBeforePayment,\n    onAnalyticsEvent,\n    globalAnalyticsHandler: globalConfig.onAnalyticsEvent,\n    onRawSuccess: (response: FedaPayCallbackResponse) => config.onComplete?.(response),\n    onClose: config.onClose,\n    onValidationError: onError,\n    getAnalyticsConfig: () => configRef.current,\n    ...mergeI18nOptions(globalConfig, { messages, resolveErrorMessage, environmentWarnings }),\n  }));\n\n  const openDialog = useCallback(() => {\n    open(configRef.current);\n  }, [open]);\n\n  return {\n    openDialog,\n    loading: state.loading,\n    error: state.error,\n    scriptLoaded: state.scriptLoaded,\n    isMockMode,\n    isVerifying: state.isVerifying,\n    isPreparing: state.isPreparing,\n  };\n}\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useMemo, useRef, useState, type MutableRefObject } from \"react\";\r\nimport { createLogger } from \"../utils/logger\";\r\nimport { useBeninConfig } from \"../context\";\r\n\r\n/**\r\n * Possible statuses for a transaction returned by your backend.\r\n */\r\nexport type TransactionStatus =\r\n  | \"pending\"\r\n  | \"approved\"\r\n  | \"declined\"\r\n  | \"cancelled\"\r\n  | \"unknown\";\r\n\r\nconst TERMINAL_STATUSES: TransactionStatus[] = [\r\n  \"approved\",\r\n  \"declined\",\r\n  \"cancelled\",\r\n];\r\n\r\nexport type PaymentStatusTransport = \"polling\" | \"websocket\";\r\n\r\nexport interface PaymentStatusWebSocketLike {\r\n  close: () => void;\r\n  onopen: ((event: Event) => void) | null;\r\n  onmessage: ((event: MessageEvent) => void) | null;\r\n  onerror: ((event: Event) => void) | null;\r\n  onclose: ((event: CloseEvent) => void) | null;\r\n}\r\n\r\nexport interface UsePaymentStatusWebSocketMessage {\r\n  status?: TransactionStatus;\r\n}\r\n\r\n/**\r\n * Options for the usePaymentStatus hook.\r\n */\r\nexport interface UsePaymentStatusOptions {\r\n  /**\r\n   * URL of your backend endpoint that returns the transaction status.\r\n   * The hook sends: GET `checkUrl?transactionId=xxx&provider=yyy`\r\n   * Expected response: `{ status: TransactionStatus }`\r\n   * @example \"/api/payments/status\"\r\n   */\r\n  checkUrl?: string;\r\n  /**\r\n   * Transaction ID returned by FedaPay or KKiaPay after payment.\r\n   */\r\n  transactionId: string;\r\n  /**\r\n   * The payment provider used for this transaction.\r\n   */\r\n  provider: \"fedapay\" | \"kkiapay\";\r\n  /**\r\n   * How often to poll in milliseconds.\r\n   * @default 3000\r\n   */\r\n  pollInterval?: number;\r\n  /**\r\n   * Transport used to follow status updates.\r\n   * @default \"polling\"\r\n   */\r\n  transport?: PaymentStatusTransport;\r\n  /**\r\n   * WebSocket endpoint used when `transport` is `\"websocket\"`.\r\n   * @example \"wss://api.example.com/payments/status\"\r\n   */\r\n  websocketUrl?: string;\r\n  /**\r\n   * Optional WebSocket protocols.\r\n   */\r\n  websocketProtocols?: string | string[];\r\n  /**\r\n   * Optional factory used to create the WebSocket instance.\r\n   * Useful for tests or custom runtimes.\r\n   */\r\n  websocketFactory?: (\r\n    url: string,\r\n    protocols?: string | string[]\r\n  ) => PaymentStatusWebSocketLike;\r\n  /**\r\n   * Parses incoming WebSocket messages into a transaction status.\r\n   * By default expects either a raw status string or `{ status: ... }`.\r\n   */\r\n  parseWebSocketMessage?: (\r\n    event: MessageEvent\r\n  ) => TransactionStatus | UsePaymentStatusWebSocketMessage | null | undefined;\r\n  /**\r\n   * Maximum number of polling attempts before stopping.\r\n   * Prevents infinite loops if the backend never returns a terminal status.\r\n   * @default 10\r\n   */\r\n  maxAttempts?: number;\r\n  /**\r\n   * Custom headers to include in every status check request.\r\n   * @example { \"Authorization\": \"Bearer xxx\" }\r\n   */\r\n  customHeaders?: Record<string, string>;\r\n  /**\r\n   * Called every time the status changes.\r\n   * @param status - The new transaction status\r\n   */\r\n  onStatusChange?: (status: TransactionStatus) => void;\r\n  /**\r\n   * Whether to start polling immediately when the hook mounts.\r\n   * Set to false to delay polling until you call startPolling().\r\n   * @default true\r\n   */\r\n  enabled?: boolean;\r\n  /**\r\n   * Enable debug logs.\r\n   * If not provided, uses the value from BeninPaymentProvider.\r\n   * @default false\r\n   */\r\n  debug?: boolean;\r\n}\r\n\r\n/**\r\n * Return type for the usePaymentStatus hook.\r\n */\r\nexport interface UsePaymentStatusReturn {\r\n  /** Current transaction status returned by your backend */\r\n  status: TransactionStatus;\r\n  /** Whether a status check is currently in progress */\r\n  loading: boolean;\r\n  /** Error from the last failed check */\r\n  error: Error | null;\r\n  /** Total number of polling attempts made */\r\n  attempts: number;\r\n  /** Whether the polling loop is currently active */\r\n  isPolling: boolean;\r\n  /** Stop the polling loop */\r\n  stopPolling: () => void;\r\n  /** Resume polling (resets attempt counter and status to pending) */\r\n  startPolling: () => void;\r\n  /** Trigger a single immediate check without affecting the polling loop */\r\n  refetch: () => void;\r\n}\r\n\r\n/**\r\n * Hook to poll your backend for a transaction status after payment.\r\n *\r\n * Automatically stops polling when a terminal status is reached\r\n * (approved, declined, cancelled) or when maxAttempts is exceeded.\r\n *\r\n * @example\r\n * ```tsx\r\n * // After a FedaPay payment completes:\r\n * const { status, isPolling, attempts } = usePaymentStatus({\r\n *   checkUrl: \"/api/payments/status\",\r\n *   transactionId: response.transaction.reference,\r\n *   provider: \"fedapay\",\r\n *   pollInterval: 3000,\r\n *   maxAttempts: 10,\r\n *   onStatusChange: (status) => {\r\n *     if (status === \"approved\") router.push(\"/success\");\r\n *     if (status === \"declined\") router.push(\"/failed\");\r\n *   },\r\n * });\r\n *\r\n * return (\r\n *   <div>\r\n *     {isPolling && <p>Vérification en cours... (tentative {attempts}/10)</p>}\r\n *     {status === \"approved\" && <p>Paiement confirmé !</p>}\r\n *     {status === \"declined\" && <p>Paiement refusé.</p>}\r\n *   </div>\r\n * );\r\n * ```\r\n */\r\nexport function usePaymentStatus(\r\n  options: UsePaymentStatusOptions\r\n): UsePaymentStatusReturn {\r\n  const {\r\n    checkUrl,\r\n    transactionId,\r\n    provider,\r\n    pollInterval = 3000,\r\n    transport = \"polling\",\r\n    websocketUrl,\r\n    websocketProtocols,\r\n    websocketFactory,\r\n    parseWebSocketMessage,\r\n    maxAttempts = 10,\r\n    customHeaders,\r\n    onStatusChange,\r\n    enabled = true,\r\n    debug,\r\n  } = options;\r\n\r\n  const globalConfig = useBeninConfig();\r\n  const resolvedDebug = debug ?? globalConfig.debug;\r\n  const log = useMemo(() => createLogger(resolvedDebug), [resolvedDebug]);\r\n\r\n  const [status, setStatus] = useState<TransactionStatus>(\"pending\");\r\n  const [loading, setLoading] = useState(false);\r\n  const [error, setError] = useState<Error | null>(null);\r\n  const [attempts, setAttempts] = useState(0);\r\n  const [isPolling, setIsPolling] = useState(enabled);\r\n\r\n  // Refs to avoid stale closures inside the async checkStatus callback\r\n  const statusRef = useRef<TransactionStatus>(\"pending\");\r\n  const attemptsRef = useRef(0);\r\n  const isPollingRef = useRef(enabled);\r\n  const webSocketRef = useRef<PaymentStatusWebSocketLike | null>(null);\r\n\r\n  // Stabilise les callbacks passés en props pour éviter des re-runs d'effet inutiles\r\n  // lorsque l'appelant crée des fonctions inline (nouvelle référence à chaque render).\r\n  const websocketFactoryRef = useRef(websocketFactory) as MutableRefObject<typeof websocketFactory>;\r\n  websocketFactoryRef.current = websocketFactory;\r\n  const parseWebSocketMessageRef = useRef(parseWebSocketMessage) as MutableRefObject<typeof parseWebSocketMessage>;\r\n  parseWebSocketMessageRef.current = parseWebSocketMessage;\r\n\r\n  useEffect(() => {\r\n    isPollingRef.current = isPolling;\r\n  }, [isPolling]);\r\n\r\n  const applyStatus = useCallback(\r\n    (newStatus: TransactionStatus) => {\r\n      if (newStatus !== statusRef.current) {\r\n        statusRef.current = newStatus;\r\n        setStatus(newStatus);\r\n        log.info(`Transaction status: ${newStatus}`);\r\n        onStatusChange?.(newStatus);\r\n      }\r\n\r\n      if (TERMINAL_STATUSES.includes(newStatus)) {\r\n        log.success(`Terminal status reached: ${newStatus}`);\r\n        setIsPolling(false);\r\n        webSocketRef.current?.close();\r\n        webSocketRef.current = null;\r\n      }\r\n    },\r\n    [log, onStatusChange]\r\n  );\r\n\r\n  const checkStatus = useCallback(async () => {\r\n    if (!transactionId || !checkUrl) return;\r\n\r\n    setLoading(true);\r\n    setError(null);\r\n    attemptsRef.current += 1;\r\n    setAttempts(attemptsRef.current);\r\n\r\n    try {\r\n      const params = new URLSearchParams({ transactionId, provider });\r\n      const fullUrl = `${checkUrl}?${params.toString()}`;\r\n\r\n      const response = await fetch(fullUrl, {\r\n        method: \"GET\",\r\n        headers: {\r\n          \"Content-Type\": \"application/json\",\r\n          ...customHeaders,\r\n        },\r\n      });\r\n\r\n      if (!response.ok) {\r\n        let errorMessage = `Status check failed with HTTP ${response.status}`;\r\n        try {\r\n          const errorData = await response.json();\r\n          if (errorData.message) errorMessage = errorData.message;\r\n        } catch {\r\n          // Response is not JSON — use default message\r\n        }\r\n        throw new Error(errorMessage);\r\n      }\r\n\r\n      const data = await response.json();\r\n      const newStatus: TransactionStatus = data.status ?? \"unknown\";\r\n\r\n      applyStatus(newStatus);\r\n\r\n      if (TERMINAL_STATUSES.includes(newStatus)) {\r\n        return;\r\n      }\r\n\r\n      // Stop polling after maxAttempts\r\n      if (attemptsRef.current >= maxAttempts) {\r\n        log.warn(`Max polling attempts (${maxAttempts}) reached`);\r\n        setIsPolling(false);\r\n      }\r\n    } catch (err) {\r\n      const checkError =\r\n        err instanceof Error ? err : new Error(\"Status check failed\");\r\n      setError(checkError);\r\n      log.error(\"Status check failed\", checkError);\r\n\r\n      if (attemptsRef.current >= maxAttempts) {\r\n        log.warn(`Max polling attempts (${maxAttempts}) reached after errors`);\r\n        setIsPolling(false);\r\n      }\r\n    } finally {\r\n      setLoading(false);\r\n    }\r\n  }, [checkUrl, transactionId, provider, customHeaders, maxAttempts, log, applyStatus]);\r\n\r\n  const resolveWebSocketStatus = useCallback(\r\n    (event: MessageEvent): TransactionStatus | null => {\r\n      // Lit depuis le ref pour éviter de recréer ce callback quand parseWebSocketMessage change.\r\n      const parsed = parseWebSocketMessageRef.current?.(event);\r\n\r\n      if (typeof parsed === \"string\") {\r\n        return parsed;\r\n      }\r\n\r\n      if (parsed && typeof parsed === \"object\" && \"status\" in parsed) {\r\n        return parsed.status ?? null;\r\n      }\r\n\r\n      if (typeof event.data === \"string\") {\r\n        try {\r\n          const data = JSON.parse(event.data) as\r\n            | UsePaymentStatusWebSocketMessage\r\n            | TransactionStatus;\r\n\r\n          if (typeof data === \"string\") {\r\n            return data;\r\n          }\r\n\r\n          return data.status ?? null;\r\n        } catch {\r\n          return null;\r\n        }\r\n      }\r\n\r\n      return null;\r\n    },\r\n    // parseWebSocketMessageRef est stable — pas besoin de l'ajouter ici.\r\n    // eslint-disable-next-line react-hooks/exhaustive-deps\r\n    []\r\n  );\r\n\r\n  useEffect(() => {\r\n    if (!isPolling || !transactionId) return;\r\n\r\n    if (transport === \"websocket\") {\r\n      if (!websocketUrl) return;\r\n\r\n      // Lit depuis le ref pour éviter de recréer la socket quand le callback change de référence.\r\n      const createSocket =\r\n        websocketFactoryRef.current ??\r\n        ((url: string, protocols?: string | string[]) =>\r\n          new WebSocket(url, protocols) as unknown as PaymentStatusWebSocketLike);\r\n\r\n      setLoading(true);\r\n      setError(null);\r\n\r\n      const socket = createSocket(websocketUrl, websocketProtocols);\r\n      webSocketRef.current = socket;\r\n\r\n      socket.onopen = () => {\r\n        setLoading(false);\r\n        log.info(\"WebSocket status tracking connected\");\r\n      };\r\n\r\n      socket.onmessage = (event) => {\r\n        attemptsRef.current += 1;\r\n        setAttempts(attemptsRef.current);\r\n\r\n        const nextStatus = resolveWebSocketStatus(event);\r\n        if (!nextStatus) return;\r\n        applyStatus(nextStatus);\r\n      };\r\n\r\n      socket.onerror = () => {\r\n        setLoading(false);\r\n        setError(new Error(\"WebSocket status tracking failed\"));\r\n        log.error(\"WebSocket status tracking failed\");\r\n      };\r\n\r\n      socket.onclose = () => {\r\n        webSocketRef.current = null;\r\n        setLoading(false);\r\n      };\r\n\r\n      return () => {\r\n        socket.close();\r\n        if (webSocketRef.current === socket) {\r\n          webSocketRef.current = null;\r\n        }\r\n      };\r\n    }\r\n\r\n    if (!checkUrl) return;\r\n\r\n    // Différer la première vérification via setTimeout pour que les appels\r\n    // synchrones (ex: startPolling dans act()) voient attempts=0 avant le premier check.\r\n    const immediateId = setTimeout(() => {\r\n      if (isPollingRef.current) void checkStatus();\r\n    }, 0);\r\n\r\n    const intervalId = setInterval(() => {\r\n      if (!isPollingRef.current) {\r\n        clearInterval(intervalId);\r\n        return;\r\n      }\r\n      void checkStatus();\r\n    }, pollInterval);\r\n\r\n    return () => {\r\n      clearTimeout(immediateId);\r\n      clearInterval(intervalId);\r\n    };\r\n  }, [\r\n    isPolling,\r\n    transactionId,\r\n    checkUrl,\r\n    pollInterval,\r\n    checkStatus,\r\n    transport,\r\n    websocketUrl,\r\n    // websocketFactory et parseWebSocketMessage sont lus via refs — pas dans les deps.\r\n    websocketProtocols,\r\n    resolveWebSocketStatus,\r\n    applyStatus,\r\n    log,\r\n  ]);\r\n\r\n  const stopPolling = useCallback(() => {\r\n    log.info(\"Polling stopped manually\");\r\n    webSocketRef.current?.close();\r\n    webSocketRef.current = null;\r\n    setIsPolling(false);\r\n  }, [log]);\r\n\r\n  const startPolling = useCallback(() => {\r\n    log.info(\"Polling restarted\");\r\n    attemptsRef.current = 0;\r\n    statusRef.current = \"pending\";\r\n    setAttempts(0);\r\n    setStatus(\"pending\");\r\n    setError(null);\r\n    setIsPolling(true);\r\n  }, [log]);\r\n\r\n  const refetch = useCallback(() => {\r\n    checkStatus();\r\n  }, [checkStatus]);\r\n\r\n  return {\r\n    status,\r\n    loading,\r\n    error,\r\n    attempts,\r\n    isPolling,\r\n    stopPolling,\r\n    startPolling,\r\n    refetch,\r\n  };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\nimport type { UnifiedPaymentResult } from \"./useBeninPay\";\r\nimport type { PaymentProvider } from \"./useBeninPay\";\r\n\r\n/**\r\n * Storage strategy for payment history.\r\n *\r\n * - `\"memory\"` — In-memory only. Cleared when the component unmounts or the\r\n *   page is refreshed. Best for ephemeral UX flows (default).\r\n * - `\"session\"` — Persisted in `sessionStorage`. Survives page reloads within\r\n *   the same browser tab, cleared when the tab/browser closes.\r\n * - `\"local\"` — Persisted in `localStorage`. Survives full browser restarts.\r\n *   Use when you want cross-session history (e.g. a receipts page).\r\n */\r\nexport type PaymentHistoryStorage = \"memory\" | \"session\" | \"local\";\r\n\r\n/**\r\n * A single entry in the payment history.\r\n * Extends UnifiedPaymentResult with audit fields.\r\n */\r\nexport interface PaymentHistoryEntry extends UnifiedPaymentResult {\r\n  /** ISO 8601 timestamp of when the payment was recorded */\r\n  recordedAt: string;\r\n  /** The payment provider used for this transaction */\r\n  provider?: PaymentProvider;\r\n}\r\n\r\n/**\r\n * Options for the usePaymentHistory hook.\r\n */\r\nexport interface UsePaymentHistoryOptions {\r\n  /**\r\n   * Storage strategy for persisting history.\r\n   * @default \"memory\"\r\n   */\r\n  storage?: PaymentHistoryStorage;\r\n  /**\r\n   * Key to use in sessionStorage or localStorage.\r\n   * Change this if you have multiple independent payment flows.\r\n   * @default \"rbp_payment_history\"\r\n   */\r\n  storageKey?: string;\r\n  /**\r\n   * Maximum number of entries to keep.\r\n   * When exceeded, the oldest entries are dropped.\r\n   * @default 50\r\n   */\r\n  maxEntries?: number;\r\n}\r\n\r\n/**\r\n * Return type for the usePaymentHistory hook.\r\n */\r\nexport interface UsePaymentHistoryReturn {\r\n  /** Full list of recorded payments, ordered from most recent to oldest */\r\n  history: PaymentHistoryEntry[];\r\n  /** The most recently recorded payment, or `null` if history is empty */\r\n  lastTransaction: PaymentHistoryEntry | null;\r\n  /** Sum of all `amount` values across the recorded transactions */\r\n  totalPaid: number;\r\n  /** Number of entries in history */\r\n  count: number;\r\n  /**\r\n   * Add a payment result to history.\r\n   *\r\n   * Automatically called by `useBeninPay` when integrated, but can be called\r\n   * manually for advanced use-cases (e.g. recording a server-confirmed payment).\r\n   *\r\n   * Duplicate `transactionId` values are silently ignored.\r\n   *\r\n   * @param result - The UnifiedPaymentResult returned by useBeninPay's onSuccess\r\n   * @param provider - The provider that processed the payment\r\n   */\r\n  addToHistory: (result: UnifiedPaymentResult, provider?: PaymentProvider) => void;\r\n  /**\r\n   * Remove a specific entry from history by its `transactionId`.\r\n   * No-op if the ID is not found.\r\n   */\r\n  removeFromHistory: (transactionId: string) => void;\r\n  /** Clear all entries from history (and from storage if applicable) */\r\n  clearHistory: () => void;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\nconst DEFAULT_STORAGE_KEY = \"rbp_payment_history\";\r\nconst DEFAULT_MAX_ENTRIES = 50;\r\n\r\n/** Returns the relevant Web Storage instance, or null for memory/SSR. */\r\nfunction getWebStorage(type: PaymentHistoryStorage): Storage | null {\r\n  if (typeof window === \"undefined\") return null; // SSR guard\r\n  if (type === \"session\") return window.sessionStorage;\r\n  if (type === \"local\") return window.localStorage;\r\n  return null; // \"memory\"\r\n}\r\n\r\n/** Safely reads and parses entries from Web Storage. */\r\nfunction readFromStorage(\r\n  storage: Storage | null,\r\n  key: string\r\n): PaymentHistoryEntry[] {\r\n  if (!storage) return [];\r\n  try {\r\n    const raw = storage.getItem(key);\r\n    if (!raw) return [];\r\n    const parsed = JSON.parse(raw);\r\n    return Array.isArray(parsed) ? parsed : [];\r\n  } catch {\r\n    return [];\r\n  }\r\n}\r\n\r\n/** Safely serialises entries to Web Storage. Fails silently on quota errors. */\r\nfunction writeToStorage(\r\n  storage: Storage | null,\r\n  key: string,\r\n  entries: PaymentHistoryEntry[]\r\n): void {\r\n  if (!storage) return;\r\n  try {\r\n    storage.setItem(key, JSON.stringify(entries));\r\n  } catch {\r\n    // Storage quota exceeded or access denied — degrade gracefully.\r\n  }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Hook\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Hook for tracking payment history within a session or across sessions.\r\n *\r\n * Supports three storage strategies: in-memory (default), sessionStorage, and\r\n * localStorage. Automatically deduplicates entries by `transactionId` and\r\n * enforces a configurable `maxEntries` limit.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic in-memory usage\r\n * const { history, lastTransaction, totalPaid, clearHistory } = usePaymentHistory();\r\n *\r\n * // Persist across page reloads within the tab\r\n * const { history } = usePaymentHistory({ storage: \"session\" });\r\n *\r\n * // Integrated with useBeninPay\r\n * const { addToHistory } = usePaymentHistory({ storage: \"session\" });\r\n *\r\n * const { pay } = useBeninPay(config, {\r\n *   onSuccess: (result) => addToHistory(result, \"fedapay\"),\r\n * });\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // Display a receipt list\r\n * const { history, totalPaid, count } = usePaymentHistory({ storage: \"session\" });\r\n *\r\n * return (\r\n *   <div>\r\n *     <p>{count} paiement(s) — Total : {formatXOF(totalPaid)}</p>\r\n *     <ul>\r\n *       {history.map((entry) => (\r\n *         <li key={entry.transactionId}>\r\n *           {entry.transactionId} — {formatXOF(entry.amount)} ({entry.status})\r\n *         </li>\r\n *       ))}\r\n *     </ul>\r\n *   </div>\r\n * );\r\n * ```\r\n */\r\nexport function usePaymentHistory(\r\n  options: UsePaymentHistoryOptions = {}\r\n): UsePaymentHistoryReturn {\r\n  const {\r\n    storage = \"memory\",\r\n    storageKey = DEFAULT_STORAGE_KEY,\r\n    maxEntries = DEFAULT_MAX_ENTRIES,\r\n  } = options;\r\n\r\n  // Lazy initializer: read from web storage on first render (SSR-safe — the\r\n  // function only runs client-side, after hydration).\r\n  const [history, setHistory] = useState<PaymentHistoryEntry[]>(() => {\r\n    const webStorage = getWebStorage(storage);\r\n    return readFromStorage(webStorage, storageKey);\r\n  });\r\n\r\n  // Keep a stable ref to the current web storage so effects don't stale-close.\r\n  const webStorageRef = useRef<Storage | null>(null);\r\n  useEffect(() => {\r\n    webStorageRef.current = getWebStorage(storage);\r\n  }, [storage]);\r\n\r\n  useEffect(() => {\r\n    const nextStorage = getWebStorage(storage);\r\n    webStorageRef.current = nextStorage;\r\n    setHistory(readFromStorage(nextStorage, storageKey));\r\n  }, [storage, storageKey]);\r\n\r\n  // Sync history to web storage whenever it changes.\r\n  useEffect(() => {\r\n    if (history.length === 0) {\r\n      try {\r\n        webStorageRef.current?.removeItem(storageKey);\r\n      } catch {\r\n        // fail silently if storage access is denied\r\n      }\r\n    } else {\r\n      writeToStorage(webStorageRef.current, storageKey, history);\r\n    }\r\n  }, [history, storageKey]);\r\n\r\n  const addToHistory = useCallback(\r\n    (result: UnifiedPaymentResult, provider?: PaymentProvider) => {\r\n      setHistory((prev) => {\r\n        // Deduplicate: silently ignore already-recorded transaction IDs.\r\n        const alreadyExists = prev.some(\r\n          (e) => e.transactionId === result.transactionId\r\n        );\r\n        if (alreadyExists) return prev;\r\n\r\n        const entry: PaymentHistoryEntry = {\r\n          ...result,\r\n          provider,\r\n          recordedAt: new Date().toISOString(),\r\n        };\r\n\r\n        const updated = [entry, ...prev];\r\n\r\n        // Enforce the maxEntries cap by trimming the oldest entries.\r\n        return updated.length > maxEntries\r\n          ? updated.slice(0, maxEntries)\r\n          : updated;\r\n      });\r\n    },\r\n    [maxEntries]\r\n  );\r\n\r\n  const removeFromHistory = useCallback((transactionId: string) => {\r\n    setHistory((prev) =>\r\n      prev.filter((e) => e.transactionId !== transactionId)\r\n    );\r\n  }, []);\r\n\r\n  const clearHistory = useCallback(() => {\r\n    setHistory([]);\r\n  }, []);\r\n\r\n  const lastTransaction = history.length > 0 ? history[0] : null;\r\n  const totalPaid = history.reduce((sum, e) => sum + e.amount, 0);\r\n\r\n  return {\r\n    history,\r\n    lastTransaction,\r\n    totalPaid,\r\n    count: history.length,\r\n    addToHistory,\r\n    removeFromHistory,\r\n    clearHistory,\r\n  };\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useCallback, useRef, useEffect } from \"react\";\r\n\r\nexport interface UseRetryPaymentOptions<TResult = unknown> {\r\n  /**\r\n   * Nombre maximum de tentatives après le premier échec.\r\n   * @default 3\r\n   */\r\n  maxRetries?: number;\r\n  /**\r\n   * Délai de base en millisecondes avant la première tentative de retry.\r\n   * @default 1000\r\n   */\r\n  baseDelay?: number;\r\n  /**\r\n   * Facteur multiplicateur exponentiel pour le délai après chaque échec.\r\n   * Exemple pour factor = 2, delay = 1000: 1000ms, 2000ms, 4000ms...\r\n   * @default 2\r\n   */\r\n  backoffFactor?: number;\r\n  /** Callback appelé avant chaque nouvelle tentative */\r\n  onRetry?: (attempt: number, delayMs: number, error: unknown) => void;\r\n  /** Callback appelé en cas de succès final */\r\n  onSuccess?: (data: TResult) => void;\r\n  /** Callback appelé quand toutes les tentatives sont épuisées */\r\n  onFail?: (error: unknown) => void;\r\n}\r\n\r\nexport interface UseRetryPaymentReturn<TArgs extends unknown[], TResult> {\r\n  /** Déclenche l'action asynchrone avec backoff en cas d'échec */\r\n  execute: (...args: TArgs) => Promise<TResult | undefined>;\r\n  /** Annule la tentative en cours et stoppe le retry */\r\n  cancel: () => void;\r\n  /** Indique si l'action (ou ses retrys) est en cours d'exécution */\r\n  isPending: boolean;\r\n  /** L'erreur du dernier échec rencontré */\r\n  error: unknown | null;\r\n  /** Le nombre de retrys effectués jusqu'à présent (0 si premier essai) */\r\n  attemptCount: number;\r\n}\r\n\r\n/**\r\n * Hook utilitaire pour retenter automatiquement une action de paiement\r\n * (ex: vérification de statut API, initialisation asynchrone) avec\r\n * un système de délai exponentiel (exponential backoff).\r\n *\r\n * @example\r\n * ```tsx\r\n * const { execute, isPending, error, attemptCount } = useRetryPayment(\r\n *   async (transactionId) => {\r\n *     return await verifyOnMyBackend(transactionId);\r\n *   },\r\n *   {\r\n *     maxRetries: 3,\r\n *     baseDelay: 2000,\r\n *     onSuccess: (data) => console.log(\"Paiement validé !\", data),\r\n *     onFail: (err) => console.error(\"Échec définitif\", err),\r\n *     onRetry: (attempt, delay) => console.log(`Essai ${attempt} dans ${delay}ms`)\r\n *   }\r\n * );\r\n * ```\r\n */\r\nexport function useRetryPayment<TArgs extends unknown[], TResult>(\r\n  action: (...args: TArgs) => Promise<TResult>,\r\n  options: UseRetryPaymentOptions<TResult> = {}\r\n): UseRetryPaymentReturn<TArgs, TResult> {\r\n  const {\r\n    maxRetries = 3,\r\n    baseDelay = 1000,\r\n    backoffFactor = 2,\r\n  } = options;\r\n\r\n  const [isPending, setIsPending] = useState(false);\r\n  const [error, setError] = useState<unknown | null>(null);\r\n  const [attemptCount, setAttemptCount] = useState(0);\r\n\r\n  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n  const isCancelledRef = useRef(false);\r\n\r\n  // Utilisation de refs pour l'action et les options afin d'éviter\r\n  // de redéclencher les useEffect/useCallback à chaque rendu.\r\n  const actionRef = useRef(action);\r\n  const optionsRef = useRef(options);\r\n\r\n  useEffect(() => {\r\n    actionRef.current = action;\r\n    optionsRef.current = options;\r\n  });\r\n\r\n  const cancel = useCallback(() => {\r\n    isCancelledRef.current = true;\r\n    if (timeoutRef.current) {\r\n      clearTimeout(timeoutRef.current);\r\n      timeoutRef.current = null;\r\n    }\r\n    setIsPending(false);\r\n  }, []);\r\n\r\n  const execute = useCallback(\r\n    async (...args: TArgs): Promise<TResult | undefined> => {\r\n      cancel(); // Annule toute exécution précédente en cours\r\n      isCancelledRef.current = false;\r\n      setIsPending(true);\r\n      setError(null);\r\n      setAttemptCount(0);\r\n\r\n      let currentAttempt = 0;\r\n\r\n      const attempt = async (): Promise<TResult | undefined> => {\r\n        if (isCancelledRef.current) return undefined;\r\n\r\n        try {\r\n          const result = await actionRef.current(...args);\r\n          if (isCancelledRef.current) return undefined;\r\n\r\n          setIsPending(false);\r\n          optionsRef.current.onSuccess?.(result);\r\n          return result;\r\n        } catch (err) {\r\n          if (isCancelledRef.current) return undefined;\r\n\r\n          setError(err);\r\n\r\n          if (currentAttempt < maxRetries) {\r\n            currentAttempt++;\r\n            setAttemptCount(currentAttempt);\r\n\r\n            const delayMs = baseDelay * Math.pow(backoffFactor, currentAttempt - 1);\r\n            optionsRef.current.onRetry?.(currentAttempt, delayMs, err);\r\n\r\n            return new Promise<TResult | undefined>((resolve) => {\r\n              timeoutRef.current = setTimeout(() => {\r\n                resolve(attempt());\r\n              }, delayMs);\r\n            });\r\n          } else {\r\n            setIsPending(false);\r\n            optionsRef.current.onFail?.(err);\r\n            throw err;\r\n          }\r\n        }\r\n      };\r\n\r\n      return attempt();\r\n    },\r\n    [baseDelay, backoffFactor, maxRetries, cancel]\r\n  );\r\n\r\n  // Nettoyage lors du démontage du composant\r\n  useEffect(() => {\r\n    return () => cancel();\r\n  }, [cancel]);\r\n\r\n  return {\r\n    execute,\r\n    cancel,\r\n    isPending,\r\n    error,\r\n    attemptCount,\r\n  };\r\n}\r\n","\"use client\";\r\n\r\nimport React, { forwardRef } from \"react\";\r\nimport { useFedaPay } from \"../hooks/useFedaPay\";\r\nimport type { UseFedaPayConfig } from \"../hooks/useFedaPay\";\r\nimport type { PaymentValidationError } from \"../types/validation\";\r\nimport type { BeninPaymentAnalyticsHandler } from \"../utils/analytics\";\r\n\r\nexport interface FedaPayButtonProps\r\n  extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n  config: UseFedaPayConfig;\r\n  /** @default \"Payer\" */\r\n  text?: string;\r\n  /** @default \"Chargement...\" */\r\n  loadingText?: string;\r\n  /** @default \"Vérification...\" */\r\n  verifyingText?: string;\r\n  /** @default false */\r\n  debug?: boolean;\r\n  onBeforePayment?: () => void | boolean | Promise<void | boolean>;\r\n  onAnalyticsEvent?: BeninPaymentAnalyticsHandler;\r\n  onPaymentError?: (error: PaymentValidationError) => void;\r\n}\r\n\r\nexport const FedaPayButton = forwardRef<HTMLButtonElement, FedaPayButtonProps>(\r\n  (\r\n    {\r\n      config,\r\n      text = \"Payer\",\r\n      loadingText = \"Chargement...\",\r\n      verifyingText = \"Vérification...\",\r\n      debug = false,\r\n      onBeforePayment,\r\n      onAnalyticsEvent,\r\n      onPaymentError,\r\n      children,\r\n      disabled,\r\n      style,\r\n      ...props\r\n    },\r\n    ref\r\n  ) => {\r\n    const { openDialog, loading, scriptLoaded, isVerifying, isPreparing } = useFedaPay(config, {\r\n      debug,\r\n      onBeforePayment,\r\n      onAnalyticsEvent,\r\n      onError: onPaymentError,\r\n    });\r\n\r\n    const isDisabled = disabled || loading || !scriptLoaded || isVerifying || isPreparing;\r\n\r\n    const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\r\n      if (isDisabled) {\r\n        e.preventDefault();\r\n        return;\r\n      }\r\n      openDialog();\r\n      props.onClick?.(e);\r\n    };\r\n\r\n    const getButtonText = () => {\r\n      if (loading || isPreparing) return loadingText;\r\n      if (isVerifying) return verifyingText;\r\n      return children ?? text;\r\n    };\r\n\r\n    return (\r\n      <button\r\n        ref={ref}\r\n        type=\"button\"\r\n        disabled={isDisabled}\r\n        aria-busy={loading || isVerifying || isPreparing}\r\n        onClick={handleClick}\r\n        style={{ cursor: isDisabled ? \"not-allowed\" : \"pointer\", ...style }}\r\n        {...props}\r\n      >\r\n        {getButtonText()}\r\n      </button>\r\n    );\r\n  }\r\n);\r\n\r\nFedaPayButton.displayName = \"FedaPayButton\";\r\n","\"use client\";\r\n\r\nimport { useFedaPay } from \"../hooks/useFedaPay\";\r\nimport type { UseFedaPayConfig } from \"../hooks/useFedaPay\";\r\nimport type { PaymentValidationError } from \"../types/validation\";\r\nimport type { ReactNode } from \"react\";\r\nimport type { BeninPaymentAnalyticsHandler } from \"../utils/analytics\";\r\n\r\nexport interface FedaPayRenderProps {\r\n  open: () => void;\r\n  loading: boolean;\r\n  error: Error | null;\r\n  scriptLoaded: boolean;\r\n  isVerifying: boolean;\r\n  isPreparing: boolean;\r\n}\r\n\r\nexport interface FedaPayConsumerProps {\r\n  config: UseFedaPayConfig;\r\n  debug?: boolean;\r\n  onBeforePayment?: () => void | boolean | Promise<void | boolean>;\r\n  onAnalyticsEvent?: BeninPaymentAnalyticsHandler;\r\n  onPaymentError?: (error: PaymentValidationError) => void;\r\n  children: (props: FedaPayRenderProps) => ReactNode;\r\n}\r\n\r\nexport function FedaPayConsumer({\r\n  config,\r\n  debug = false,\r\n  onBeforePayment,\r\n  onAnalyticsEvent,\r\n  onPaymentError,\r\n  children,\r\n}: FedaPayConsumerProps): ReactNode {\r\n  const { openDialog, loading, error, scriptLoaded, isVerifying, isPreparing } = useFedaPay(config, {\r\n    debug,\r\n    onBeforePayment,\r\n    onAnalyticsEvent,\r\n    onError: onPaymentError,\r\n  });\r\n\r\n  return children({\r\n    open: openDialog,\r\n    loading,\r\n    error,\r\n    scriptLoaded,\r\n    isVerifying,\r\n    isPreparing,\r\n  });\r\n}\r\n","\r\n\r\n\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\n/**\r\n * FedaPay logo SVG component.\r\n * \r\n * Customizable via standard SVG props (width, height, fill, className, etc.)\r\n * Uses `currentColor` for text, allowing color inheritance from parent.\r\n * \r\n * @example\r\n * ```tsx\r\n * import { FedaPayLogo } from \"react-benin-payments\";\r\n * \r\n * // Default size\r\n * <FedaPayLogo />\r\n * \r\n * // Custom size and color\r\n * <FedaPayLogo width={80} height={28} className=\"text-green-600\" />\r\n * ```\r\n */\r\nexport function FedaPayLogo(props: React.SVGProps<SVGSVGElement>) {\r\n  return (\r\n    <svg\r\n      xmlns=\"http://www.w3.org/2000/svg\"\r\n      viewBox=\"0 0 120 40\"\r\n      width=\"120\"\r\n      height=\"40\"\r\n      fill=\"currentColor\"\r\n      aria-label=\"FedaPay\"\r\n      role=\"img\"\r\n      {...props}\r\n    >\r\n      <rect x=\"2\" y=\"8\" width=\"24\" height=\"24\" rx=\"4\" fill=\"#0AB67A\" />\r\n      <path\r\n        d=\"M8 16h12M8 20h8M8 24h10\"\r\n        stroke=\"white\"\r\n        strokeWidth=\"2\"\r\n        strokeLinecap=\"round\"\r\n      />\r\n      <text\r\n        x=\"32\"\r\n        y=\"26\"\r\n        fontFamily=\"Arial, sans-serif\"\r\n        fontSize=\"16\"\r\n        fontWeight=\"bold\"\r\n        fill=\"currentColor\"\r\n      >\r\n        FedaPay\r\n      </text>\r\n    </svg>\r\n  );\r\n}\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\nimport type { TransactionStatus } from \"../hooks/usePaymentStatus\";\r\n\r\nexport interface PaymentStatusBadgeProps\r\n  extends React.HTMLAttributes<HTMLSpanElement> {\r\n  /** Le statut de la transaction à afficher */\r\n  status: TransactionStatus;\r\n  /** Surcharge des libellés par défaut pour chaque statut */\r\n  labels?: Partial<Record<TransactionStatus, React.ReactNode>>;\r\n  /** Surcharge des classes CSS spécifiques par statut (ex: Tailwind) */\r\n  statusClasses?: Partial<Record<TransactionStatus, string>>;\r\n  /** Si true, aucun style en ligne par défaut ne sera appliqué (Headless) */\r\n  unstyled?: boolean;\r\n}\r\n\r\nconst DEFAULT_LABELS: Record<TransactionStatus, string> = {\r\n  pending: \"En attente\",\r\n  approved: \"Approuvé\",\r\n  declined: \"Refusé\",\r\n  cancelled: \"Annulé\",\r\n  unknown: \"Inconnu\",\r\n};\r\n\r\nconst DEFAULT_STYLES: Record<TransactionStatus, React.CSSProperties> = {\r\n  pending: { backgroundColor: \"#fef3c7\", color: \"#d97706\" }, // Amber\r\n  approved: { backgroundColor: \"#d1fae5\", color: \"#059669\" }, // Emerald\r\n  declined: { backgroundColor: \"#fee2e2\", color: \"#dc2626\" }, // Red\r\n  cancelled: { backgroundColor: \"#f3f4f6\", color: \"#4b5563\" }, // Gray\r\n  unknown: { backgroundColor: \"#e5e7eb\", color: \"#374151\" }, // Gray\r\n};\r\n\r\nconst BASE_STYLE: React.CSSProperties = {\r\n  display: \"inline-flex\",\r\n  alignItems: \"center\",\r\n  padding: \"0.25rem 0.75rem\",\r\n  borderRadius: \"9999px\",\r\n  fontSize: \"0.875rem\",\r\n  fontWeight: 500,\r\n  lineHeight: 1,\r\n};\r\n\r\n/**\r\n * Composant visuel permettant d'afficher le statut d'un paiement.\r\n * \r\n * Il intègre des couleurs et libellés par défaut (en français) pour chaque statut.\r\n * Peut être utilisé en mode \"Headless\" (`unstyled={true}`) pour laisser \r\n * votre propre framework CSS (comme Tailwind) gérer le visuel via `statusClasses`.\r\n * \r\n * @example\r\n * // Mode par défaut (styles en ligne injectés)\r\n * <PaymentStatusBadge status=\"approved\" />\r\n * \r\n * @example\r\n * // Mode Headless avec Tailwind CSS\r\n * <PaymentStatusBadge \r\n *   status=\"pending\" \r\n *   unstyled \r\n *   className=\"px-3 py-1 rounded-full text-sm font-medium\"\r\n *   statusClasses={{\r\n *     pending: \"bg-yellow-100 text-yellow-800\",\r\n *     approved: \"bg-green-100 text-green-800\"\r\n *   }}\r\n * />\r\n */\r\nexport const PaymentStatusBadge: React.FC<PaymentStatusBadgeProps> = ({\r\n  status,\r\n  labels,\r\n  statusClasses,\r\n  unstyled = false,\r\n  className,\r\n  style,\r\n  ...rest\r\n}) => {\r\n  const label = labels?.[status] ?? DEFAULT_LABELS[status];\r\n\r\n  const computedStyle: React.CSSProperties = unstyled\r\n    ? { ...style }\r\n    : { ...BASE_STYLE, ...DEFAULT_STYLES[status], ...style };\r\n\r\n  const combinedClassName =\r\n    [className, statusClasses?.[status]].filter(Boolean).join(\" \") || undefined;\r\n\r\n  return (\r\n    <span\r\n      className={combinedClassName}\r\n      style={Object.keys(computedStyle).length > 0 ? computedStyle : undefined}\r\n      data-status={status}\r\n      data-testid=\"payment-status-badge\"\r\n      {...rest}\r\n    >\r\n      {label}\r\n    </span>\r\n  );\r\n};\r\n"]}