ynkap-payment
Version:
Module de paiement Y-Nkap pour Angular - Intégration simple des paiements mobiles (Orange Money, MTN Mobile Money)
1,560 lines • 214 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, Optional, Inject, Input, NgModule, Pipe, EventEmitter, Output, HostListener } from '@angular/core';
import { BehaviorSubject, throwError, timer, switchMap, tap, catchError, of, map, interval } from 'rxjs';
import * as i7 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i1 from '@angular/common/http';
import { HttpHeaders, HttpClientModule } from '@angular/common/http';
import * as i1$1 from '@angular/forms';
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { mergeMap } from 'rxjs/operators';
import { trigger, transition, style, animate } from '@angular/animations';
class YnkapService {
constructor() { }
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class ConfigurationService {
/**
* Get the current API configuration
*/
get config$() {
return this.configSubject.asObservable();
}
/**
* Get the current API configuration synchronously
*/
get currentConfig() {
return this.configSubject.getValue();
}
get apiUrl() {
return this._apiUrl;
}
set apiUrl(url) {
this._apiUrl = url;
}
constructor() {
this.defaultApiBaseUrl = 'https://api.ynkap.com/v1';
this.sandboxApiBaseUrl = 'https://sandbox.api.ynkap.com/v1';
this.configSubject = new BehaviorSubject(null);
this.initialized = false;
this._apiUrl = 'https://api.ynkap.com/v1';
}
/**
* Initialize the module with API configuration
* @param config The API configuration
* @returns True if initialization was successful, false otherwise
*/
initialize(config) {
if (!this.validateConfig(config)) {
console.error('Y-Nkap: Invalid configuration provided');
return false;
}
// Set defaults if not provided
const completeConfig = {
...config,
environment: config.environment || 'production',
apiBaseUrl: config.apiBaseUrl || (config.environment === 'sandbox' ? this.sandboxApiBaseUrl : this.defaultApiBaseUrl)
};
this.configSubject.next(completeConfig);
this.initialized = true;
return true;
}
/**
* Check if the module has been initialized
*/
isInitialized() {
return this.initialized;
}
/**
* Reset the configuration
*/
reset() {
this.configSubject.next(null);
this.initialized = false;
}
/**
* Update part of the configuration
* @param partialConfig Partial configuration to update
* @returns True if update was successful, false otherwise
*/
updateConfig(partialConfig) {
const currentConfig = this.currentConfig;
if (!currentConfig) {
console.error('Y-Nkap: Cannot update config before initialization');
return false;
}
const updatedConfig = { ...currentConfig, ...partialConfig };
if (!this.validateConfig(updatedConfig)) {
console.error('Y-Nkap: Invalid configuration update');
return false;
}
this.configSubject.next(updatedConfig);
return true;
}
/**
* Validate API configuration
* @param config The API configuration to validate
* @returns True if configuration is valid, false otherwise
*/
validateConfig(config) {
// Check if required fields are present and not empty
if (!config.apiKey || config.apiKey.trim() === '') {
console.error('Y-Nkap: API Key is required');
return false;
}
if (!config.apiSecret || config.apiSecret.trim() === '') {
console.error('Y-Nkap: API Secret is required');
return false;
}
if (!config.merchantId || config.merchantId.trim() === '') {
console.error('Y-Nkap: Merchant ID is required');
return false;
}
// Validate environment if provided
if (config.environment && !['production', 'sandbox'].includes(config.environment)) {
console.error('Y-Nkap: Environment must be either "production" or "sandbox"');
return false;
}
return true;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class YnkapComponent {
constructor(configService, moduleConfig) {
this.configService = configService;
this.moduleConfig = moduleConfig;
/**
* Version actuelle du module Y-Nkap
*/
this.version = '1.0.0-dev';
/**
* Indique si le module est correctement initialisé
*/
this.isInitialized = false;
}
ngOnInit() {
// Vérifie si le service est déjà initialisé
this.isInitialized = this.configService.isInitialized();
// Si non initialisé mais config disponible, initialiser
if (!this.isInitialized) {
// Priorité à la config fournie par input, puis celle du module
const config = this.config || this.moduleConfig;
if (config) {
this.isInitialized = this.configService.initialize(config);
}
}
}
/**
* Initialise manuellement le module Y-Nkap avec une configuration
* @param config Configuration de l'API Y-Nkap
* @returns true si l'initialisation a réussi, false sinon
*/
initialize(config) {
this.isInitialized = this.configService.initialize(config);
return this.isInitialized;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapComponent, deps: [{ token: ConfigurationService }, { token: 'Y_NKAP_CONFIG', optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: YnkapComponent, selector: "lib-ynkap", inputs: { config: "config" }, ngImport: i0, template: `
<div class="ynkap-container">
<!-- Message d'accueil ou d'erreur -->
<div *ngIf="!isInitialized" class="ynkap-error-message">
Y-Nkap n'est pas initialisé. Veuillez fournir une configuration valide avec vos clés d'API.
</div>
<!-- Message de bienvenue si initialisé -->
<div *ngIf="isInitialized" class="ynkap-welcome">
<div class="ynkap-logo">
<img src="https://placeholder-for-ynkap-logo.svg" alt="Y-Nkap" />
</div>
<h2 class="ynkap-title">Y-Nkap - La passerelle de paiement sécurisée</h2>
<p class="ynkap-description">
Intégrez facilement les paiements en ligne dans votre application avec Y-Nkap.
Utilisez les composants spécifiques pour accéder aux fonctionnalités :
</p>
<ul class="ynkap-components-list">
<li><code><lib-ynkap-payment></code> - Module de paiement</li>
<li><code><lib-configuration></code> - Configuration de l'API</li>
</ul>
<div class="ynkap-version">Version: {{version}}</div>
</div>
</div>
`, isInline: true, styles: [".ynkap-container{font-family:Roboto,Segoe UI,Arial,sans-serif;padding:20px;border-radius:8px;background-color:#f9f9f9;color:#333;max-width:600px;margin:0 auto}.ynkap-error-message{background-color:#ffeaea;border-left:4px solid #f44336;padding:12px 15px;border-radius:4px;color:#d32f2f;font-size:.9rem}.ynkap-welcome{text-align:center}.ynkap-logo{margin:0 auto 20px;width:80px;height:80px;background-color:#007bff;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:1.5rem}.ynkap-title{font-size:1.5rem;color:#2c3e50;margin-bottom:15px}.ynkap-description{font-size:1rem;line-height:1.5;color:#666;margin-bottom:20px}.ynkap-components-list{text-align:left;width:max-content;margin:0 auto 20px;padding-left:20px}.ynkap-components-list li{margin-bottom:8px}.ynkap-components-list code{background-color:#e9ecef;padding:2px 6px;border-radius:4px;color:#007bff;font-family:monospace}.ynkap-version{font-size:.8rem;color:#999;margin-top:20px}\n"], dependencies: [{ kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-ynkap', template: `
<div class="ynkap-container">
<!-- Message d'accueil ou d'erreur -->
<div *ngIf="!isInitialized" class="ynkap-error-message">
Y-Nkap n'est pas initialisé. Veuillez fournir une configuration valide avec vos clés d'API.
</div>
<!-- Message de bienvenue si initialisé -->
<div *ngIf="isInitialized" class="ynkap-welcome">
<div class="ynkap-logo">
<img src="https://placeholder-for-ynkap-logo.svg" alt="Y-Nkap" />
</div>
<h2 class="ynkap-title">Y-Nkap - La passerelle de paiement sécurisée</h2>
<p class="ynkap-description">
Intégrez facilement les paiements en ligne dans votre application avec Y-Nkap.
Utilisez les composants spécifiques pour accéder aux fonctionnalités :
</p>
<ul class="ynkap-components-list">
<li><code><lib-ynkap-payment></code> - Module de paiement</li>
<li><code><lib-configuration></code> - Configuration de l'API</li>
</ul>
<div class="ynkap-version">Version: {{version}}</div>
</div>
</div>
`, styles: [".ynkap-container{font-family:Roboto,Segoe UI,Arial,sans-serif;padding:20px;border-radius:8px;background-color:#f9f9f9;color:#333;max-width:600px;margin:0 auto}.ynkap-error-message{background-color:#ffeaea;border-left:4px solid #f44336;padding:12px 15px;border-radius:4px;color:#d32f2f;font-size:.9rem}.ynkap-welcome{text-align:center}.ynkap-logo{margin:0 auto 20px;width:80px;height:80px;background-color:#007bff;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:1.5rem}.ynkap-title{font-size:1.5rem;color:#2c3e50;margin-bottom:15px}.ynkap-description{font-size:1rem;line-height:1.5;color:#666;margin-bottom:20px}.ynkap-components-list{text-align:left;width:max-content;margin:0 auto 20px;padding-left:20px}.ynkap-components-list li{margin-bottom:8px}.ynkap-components-list code{background-color:#e9ecef;padding:2px 6px;border-radius:4px;color:#007bff;font-family:monospace}.ynkap-version{font-size:.8rem;color:#999;margin-top:20px}\n"] }]
}], ctorParameters: function () { return [{ type: ConfigurationService }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: ['Y_NKAP_CONFIG']
}] }]; }, propDecorators: { config: [{
type: Input
}] } });
/**
* Enum for error categories
*/
var ErrorCategory;
(function (ErrorCategory) {
ErrorCategory["NETWORK"] = "NETWORK";
ErrorCategory["AUTHENTICATION"] = "AUTHENTICATION";
ErrorCategory["AUTHORIZATION"] = "AUTHORIZATION";
ErrorCategory["VALIDATION"] = "VALIDATION";
ErrorCategory["PAYMENT_PROCESSING"] = "PAYMENT_PROCESSING";
ErrorCategory["SERVER"] = "SERVER";
ErrorCategory["UNKNOWN"] = "UNKNOWN";
})(ErrorCategory || (ErrorCategory = {}));
class YnkapError extends Error {
constructor(code, message, details) {
super(message);
this.code = code;
this.message = message;
this.details = details;
this.name = 'YnkapError';
Object.setPrototypeOf(this, YnkapError.prototype);
}
}
class ErrorHandlingService {
constructor() {
this.errorSubject = new BehaviorSubject(null);
// Default retry options
this.defaultRetryOptions = {
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 10000,
nonRetryableErrors: [
ErrorCategory.AUTHENTICATION,
ErrorCategory.AUTHORIZATION,
ErrorCategory.VALIDATION
]
};
}
handleError(error) {
let ynkapError;
if (error instanceof YnkapError) {
ynkapError = error;
}
else {
ynkapError = new YnkapError(error.code || 'UNKNOWN_ERROR', error.message || 'Une erreur inattendue est survenue', error.details);
}
this.errorSubject.next(ynkapError);
console.error('Y-Nkap Error:', ynkapError);
}
getError() {
return this.errorSubject.asObservable();
}
clearError() {
this.errorSubject.next(null);
}
/**
* Apply retry logic with exponential backoff for failed operations
* @param error The error that occurred
* @param retryFn Function to retry
* @param options Retry options
* @returns An observable that will retry the operation
*/
retryWithBackoff(error, retryFn, options) {
const retryOpts = { ...this.defaultRetryOptions, ...options };
// Check if error is retryable
if (!error.retryable) {
return throwError(() => error);
}
// Check if the error type is in the non-retryable list
if (retryOpts.nonRetryableErrors?.includes(error.code)) {
return throwError(() => error);
}
// Check if we've exceeded max retries
const attemptNumber = (error.details?.attemptNumber || 0) + 1;
if (attemptNumber > retryOpts.maxRetries) {
return throwError(() => error);
}
// Calculate backoff delay with exponential increase
const delayMs = Math.min(retryOpts.baseDelayMs * Math.pow(2, attemptNumber - 1), retryOpts.maxDelayMs);
// Call the onRetry callback if provided
if (retryOpts.onRetry) {
retryOpts.onRetry(error, attemptNumber);
}
// Update attempt number in error details
error.details = { ...error.details, attemptNumber };
// Wait for the delay then retry
return timer(delayMs).pipe(mergeMap(() => retryFn()));
}
/**
* Convert any error to a standardized YnkapError
* @param error The error to convert
* @param context Optional context information
* @returns A standardized YnkapError
*/
convertToYnkapError(error, context) {
const timestamp = new Date();
// HTTP errors
if (error && error.status) {
const httpStatus = error.status;
const errorBody = error.error || {};
let category;
let retryable = false;
switch (true) {
case httpStatus === 401:
category = ErrorCategory.AUTHENTICATION;
retryable = false;
break;
case httpStatus === 403:
category = ErrorCategory.AUTHORIZATION;
retryable = false;
break;
case httpStatus >= 400 && httpStatus < 500:
category = ErrorCategory.VALIDATION;
retryable = false;
break;
case httpStatus >= 500:
category = ErrorCategory.SERVER;
retryable = true;
break;
default:
category = ErrorCategory.UNKNOWN;
retryable = true;
}
return new YnkapError(errorBody.code || category, errorBody.message || `Error ${httpStatus}: ${error.statusText || 'Unknown HTTP error'}`, {
details: errorBody.details || {},
originalError: error,
httpStatus,
retryable,
timestamp
});
}
// Network errors
else if (error instanceof TypeError && error.message.includes('network')) {
return new YnkapError(ErrorCategory.NETWORK, 'Network error: Could not connect to Y-Nkap API', {
originalError: error,
retryable: true,
retryAfterMs: 3000,
timestamp
});
}
// Other errors
else {
return new YnkapError(ErrorCategory.UNKNOWN, error?.message || 'An unknown error occurred', {
originalError: error,
retryable: true,
details: { context },
timestamp
});
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class AuthService {
constructor() {
this.apiKeySubject = new BehaviorSubject(null);
this.isAuthenticatedSubject = new BehaviorSubject(false);
// Vérifier si une clé API existe dans le localStorage
const savedApiKey = localStorage.getItem('ynkap_api_key');
if (savedApiKey) {
this.setApiKey(savedApiKey);
}
}
/**
* Définit la clé API Y-Nkap
* @param apiKey La clé API à utiliser
*/
setApiKey(apiKey) {
if (!this.validateApiKey(apiKey)) {
throw new Error('Clé API invalide');
}
localStorage.setItem('ynkap_api_key', apiKey);
this.apiKeySubject.next(apiKey);
this.isAuthenticatedSubject.next(true);
}
/**
* Récupère la clé API actuelle
* @returns Observable de la clé API
*/
getApiKey() {
return this.apiKeySubject.asObservable();
}
/**
* Vérifie si l'utilisateur est authentifié
* @returns Observable de l'état d'authentification
*/
isAuthenticated() {
return this.isAuthenticatedSubject.asObservable();
}
/**
* Déconnecte l'utilisateur
*/
logout() {
localStorage.removeItem('ynkap_api_key');
this.apiKeySubject.next(null);
this.isAuthenticatedSubject.next(false);
}
/**
* Valide le format de la clé API
* @param apiKey La clé API à valider
* @returns true si la clé est valide
*/
validateApiKey(apiKey) {
// Format attendu : ykap_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
const apiKeyRegex = /^ynkap_[a-zA-Z0-9]{32}$/;
return apiKeyRegex.test(apiKey);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
class RetryService {
constructor() {
this.retryStates = new Map();
this.defaultRetryOptions = {
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 30000,
nonRetryableErrors: [
ErrorCategory.AUTHENTICATION,
ErrorCategory.AUTHORIZATION,
ErrorCategory.VALIDATION
]
};
}
/**
* Initialize retry state for a transaction
*/
initializeRetryState(transactionId, options) {
const retryOptions = { ...this.defaultRetryOptions, ...options };
const state = {
attemptNumber: 0,
maxRetries: retryOptions.maxRetries,
nextRetryDelayMs: retryOptions.baseDelayMs,
canRetry: true,
transactionId
};
this.retryStates.set(transactionId, state);
return state;
}
/**
* Get retry state for a transaction
*/
getRetryState(transactionId) {
return this.retryStates.get(transactionId) || null;
}
/**
* Check if an error is retryable
*/
isRetryable(error, options) {
const retryOptions = { ...this.defaultRetryOptions, ...options };
// Check if error explicitly says it's not retryable
if (error.retryable === false) {
return false;
}
// Check if error category is in non-retryable list
if (retryOptions.nonRetryableErrors?.includes(error.code)) {
return false;
}
// Network errors are usually retryable
if (error.code === ErrorCategory.NETWORK) {
return true;
}
// Server errors (5xx) are retryable
if (error.httpStatus && error.httpStatus >= 500) {
return true;
}
// Payment processing errors might be retryable
if (error.code === ErrorCategory.PAYMENT_PROCESSING) {
return true;
}
// Default to retryable if not explicitly set to false
return error.retryable === undefined || error.retryable === true;
}
/**
* Calculate next retry delay with exponential backoff
*/
calculateRetryDelay(attemptNumber, options) {
const retryOptions = { ...this.defaultRetryOptions, ...options };
// Exponential backoff: baseDelay * 2^(attempt-1)
const delay = retryOptions.baseDelayMs * Math.pow(2, attemptNumber - 1);
// Add some jitter to avoid thundering herd
const jitter = Math.random() * 0.1 * delay;
return Math.min(delay + jitter, retryOptions.maxDelayMs);
}
/**
* Update retry state after an attempt
*/
updateRetryState(transactionId, error) {
const state = this.retryStates.get(transactionId);
if (!state)
return null;
state.attemptNumber++;
state.lastError = error;
state.canRetry = state.attemptNumber < state.maxRetries && this.isRetryable(error);
if (state.canRetry) {
state.nextRetryDelayMs = this.calculateRetryDelay(state.attemptNumber);
}
return state;
}
/**
* Execute retry with proper delay and state management
*/
executeRetry(transactionId, retryFn, options) {
const state = this.getRetryState(transactionId);
if (!state || !state.canRetry) {
return throwError(() => state?.lastError || new YnkapError('RETRY_EXHAUSTED', 'Maximum retry attempts reached'));
}
const retryOptions = { ...this.defaultRetryOptions, ...options };
// Call onRetry callback if provided
if (retryOptions.onRetry && state.lastError) {
retryOptions.onRetry(state.lastError, state.attemptNumber + 1);
}
// Wait for the calculated delay, then execute retry
return timer(state.nextRetryDelayMs).pipe(switchMap(() => retryFn()), tap({
error: (error) => {
this.updateRetryState(transactionId, error);
}
}));
}
/**
* Clear retry state for a transaction
*/
clearRetryState(transactionId) {
this.retryStates.delete(transactionId);
}
/**
* Get human-readable retry information
*/
getRetryInfo(transactionId) {
const state = this.getRetryState(transactionId);
if (!state)
return '';
if (!state.canRetry) {
return 'Nombre maximum de tentatives atteint';
}
const remainingAttempts = state.maxRetries - state.attemptNumber;
const nextRetrySeconds = Math.ceil(state.nextRetryDelayMs / 1000);
return `${remainingAttempts} tentative(s) restante(s). Prochaine tentative dans ${nextRetrySeconds}s`;
}
/**
* Check if automatic retry should be attempted
*/
shouldAutoRetry(error) {
// Auto-retry only for network errors and server errors
return error.code === ErrorCategory.NETWORK ||
(error.httpStatus !== undefined && error.httpStatus >= 500);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RetryService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
/**
* Logos en base64 générés automatiquement
* Générés le: 2025-06-27T14:26:54.389Z
*/
const LOGOS_BASE64 = {
ynkap: 'data:image/jpeg;base64,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',
mtn: 'data:image/jpeg;base64,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REREREREREREREREREREREREREREREREREREUIiIilEREREREREREREREREREREREREREREREREREREREUL/2Q==',
orange: 'data:image/png;base64,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'
};
const LOGOS_INFO = {
ynkap: { size: '15 KB', type: 'image/jpeg' },
mtn: { size: '4 KB', type: 'image/jpeg' },
orange: { size: '4 KB', type: 'image/png' }
};
class LogoService {
/**
* Obtient l'URL du logo pour un opérateur donné
* Utilise les vraies images converties en base64
*/
getOperatorLogoUrl(operatorId) {
switch (operatorId) {
case 'mtn-momo':
return LOGOS_BASE64.mtn;
case 'orange-money':
return LOGOS_BASE64.orange;
case 'ynkap':
return LOGOS_BASE64.ynkap;
default:
return LOGOS_BASE64.ynkap;
}
}
/**
* Obtient les informations sur un logo (taille, type)
*/
getLogoInfo(operatorId) {
const logos = {
'mtn-momo': { size: '4 KB', type: 'image/jpeg' },
'orange-money': { size: '4 KB', type: 'image/png' },
'ynkap': { size: '15 KB', type: 'image/jpeg' }
};
return logos[operatorId] || logos['ynkap'];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LogoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LogoService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LogoService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class PaymentService {
/**
* Observable of available payment methods
*/
get availablePaymentMethods$() {
return this.availablePaymentMethodsSubject.asObservable();
}
/**
* Observable of the current transaction
*/
get currentTransaction$() {
return this.currentTransactionSubject.asObservable();
}
/**
* Observable of transaction history
*/
get transactionHistory$() {
return this.transactionHistorySubject.asObservable();
}
getMockPaymentMethods() {
return [
{
id: 'mtn-momo',
name: 'MTN Mobile Money',
provider: 'MTN',
iconUrl: this.logoService.getOperatorLogoUrl('mtn-momo'),
status: 'enabled'
},
{
id: 'orange-money',
name: 'Orange Money',
provider: 'Orange',
iconUrl: this.logoService.getOperatorLogoUrl('orange-money'),
status: 'enabled'
}
];
}
constructor(http, configService, errorHandlingService, authService, retryService, logoService) {
this.http = http;
this.configService = configService;
this.errorHandlingService = errorHandlingService;
this.authService = authService;
this.retryService = retryService;
this.logoService = logoService;
this.availablePaymentMethodsSubject = new BehaviorSubject([]);
this.currentTransactionSubject = new BehaviorSubject(null);
this.transactionHistorySubject = new BehaviorSubject([]);
this.loadPaymentMethods();
}
/**
* Load available payment methods
*/
loadPaymentMethods() {
this.authService.getApiKey().subscribe(apiKey => {
if (!apiKey) {
// Mode démo : on affiche les méthodes mockées sans erreur
this.availablePaymentMethodsSubject.next(this.getMockPaymentMethods());
return;
}
const headers = new HttpHeaders().set('Authorization', `Bearer ${apiKey}`);
this.http.get(`${this.configService.apiUrl}/payment-methods`, { headers })
.pipe(catchError(error => {
this.errorHandlingService.handleError(error);
return of(this.getMockPaymentMethods());
}))
.subscribe(methods => {
this.availablePaymentMethodsSubject.next(methods);
});
});
}
/**
* Initiate a payment transaction
* @param paymentRequest The payment request details
* @returns Observable of the payment response
*/
initiatePayment(request) {
// Generate a unique transaction ID for retry tracking
const transactionId = this.generateTransactionId();
return this.authService.getApiKey().pipe(map(apiKey => {
if (!apiKey) {
throw new YnkapError('AUTH_ERROR', 'Clé API non configurée', 'Veuillez configurer votre clé API Y-Nkap');
}
return apiKey;
}), switchMap(apiKey => {
// Initialize retry state for this transaction
this.retryService.initializeRetryState(transactionId);
const headers = new HttpHeaders().set('Authorization', `Bearer ${apiKey}`);
const paymentRequest = { ...request, transactionId };
return this.http.post(`${this.configService.apiUrl}/payments`, paymentRequest, { headers }).pipe(catchError(error => {
// Convert error to YnkapError
let ynkapError;
if (error instanceof YnkapError) {
ynkapError = error;
}
else {
ynkapError = new YnkapError(error.code || 'PAYMENT_ERROR', error.message || 'Erreur lors du paiement', { originalError: error, retryable: true });
}
// Update retry state
this.retryService.updateRetryState(transactionId, ynkapError);
// Check if we should auto-retry
if (this.retryService.shouldAutoRetry(ynkapError)) {
const retryState = this.retryService.getRetryState(transactionId);
if (retryState?.canRetry) {
// Auto-retry with delay
return this.retryService.executeRetry(transactionId, () => this.http.post(`${this.configService.apiUrl}/payments`, paymentRequest, { headers }));
}
}
this.errorHandlingService.handleError(ynkapError);
return throwError(() => ynkapError);
}), tap(response => {
if (response.status === 'success' && response.transaction) {
this.currentTransactionSubject.next(response.transaction);
const history = this.transactionHistorySubject.value;
this.transactionHistorySubject.next([...history, response.transaction]);
// Clear retry state on success
this.retryService.clearRetryState(transactionId);
}
}));
}));
}
/**
* Retry a payment after an error or failure
* @param transactionId ID of the failed transaction
* @returns Observable of the payment response
*/
retryPayment(transactionId) {
return this.authService.getApiKey().pipe(map(apiKey => {
if (!apiKey) {
throw new YnkapError('AUTH_ERROR', 'Clé API non configurée', 'Veuillez configurer votre clé API Y-Nkap');
}
return apiKey;
}), switchMap(apiKey => {
const headers = new HttpHeaders().set('Authorization', `Bearer ${apiKey}`);
return this.http.post(`${this.configService.apiUrl}/payments/${transactionId}/retry`, {}, { headers }).pipe(catchError(error => {
this.errorHandlingService.handleError(error);
return throwError(() => error);
}), tap(response => {
if (response.status === 'success' && response.transaction) {
this.currentTransactionSubject.next(response.transaction);
const history = this.transactionHistorySubject.value;
this.transactionHistorySubject.next([...history, response.transaction]);
}
}));
}));
}
/**
* Generate a unique transaction ID for retry tracking
*/
generateTransactionId() {
return `txn_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
}
/**
* Create authentication headers for API requests
* @param apiKey The API key from configuration
* @param apiSecret The API secret from configuration
* @returns Object with authorization headers
*/
getAuthHeaders(apiKey, apiSecret) {
// In a real implementation, you might want to use a more secure
// authentication method like OAuth or JWT
const timestamp = Date.now().toString();
// This is a simple example of creating an authorization header
// In a production environment, you would use a more secure approach
const authToken = btoa(`${apiKey}:${apiSecret}:${timestamp}`);
return {
'Authorization': `Bearer ${authToken}`,
'X-Api-Key': apiKey,
'X-Timestamp': timestamp,
'Content-Type': 'application/json'
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentService, deps: [{ token: i1.HttpClient }, { token: ConfigurationService }, { token: ErrorHandlingService }, { token: AuthService }, { token: RetryService }, { token: LogoService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: ConfigurationService }, { type: ErrorHandlingService }, { type: AuthService }, { type: RetryService }, { type: LogoService }]; } });
class ConfigurationComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ConfigurationComponent, selector: "lib-configuration", ngImport: i0, template: "<p>configuration works!</p>\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-configuration', template: "<p>configuration works!</p>\n" }]
}] });
class ConfigurationModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationModule, declarations: [ConfigurationComponent], imports: [CommonModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConfigurationModule, decorators: [{
type: NgModule,
args: [{
declarations: [
ConfigurationComponent
],
imports: [
CommonModule
]
}]
}] });
const fadeInOut = trigger('fadeInOut', [
transition(':enter', [
style({ opacity: 0 }),
animate('120ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 1 }))
]),
transition(':leave', [
animate('120ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 }))
])
]);
const scaleIn = trigger('scaleIn', [
transition(':enter', [
style({
transform: 'scale(0.95)',
opacity: 0
}),
animate('120ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({
transform: 'scale(1)',
opacity: 1
}))
])
]);
/**
* Pipe pour formater les montants en FCFA avec le bon ordre
* Exemple: 1000 → "1 000 FCFA"
*/
class FcfaPipe {
/**
* Transforme un montant en format FCFA lisible
* @param value Le montant à formater
* @param currency La devise (par défaut 'FCFA')
* @returns Le montant formaté avec séparateurs de milliers
*/
transform(value, currency = 'FCFA') {
if (value == null || isNaN(value)) {
return '0 ' + currency;
}
// Formatage avec séparateurs de milliers selon la locale française
const formatted = new Intl.NumberFormat('fr-FR', {
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(value);
return `${formatted} ${currency}`;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FcfaPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FcfaPipe, name: "fcfa" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FcfaPipe, decorators: [{
type: Pipe,
args: [{
name: 'fcfa'
}]
}] });
class PaymentComponent {
constructor(fb, paymentService, authService, errorHandlingService, retryService, logoService) {
this.fb = fb;
this.paymentService = paymentService;
this.authService = authService;
this.errorHandlingService = errorHandlingService;
this.retryService = retryService;
this.logoService = logoService;
this.currency = 'XAF';
this.theme = 'light';
this.paymentSuccess = new EventEmitter();
this.paymentError = new EventEmitter();
this.cancelled = new EventEmitter();
this.currentStep = 'methods';
this.processing = false;
this.error = null;
this.selectedMethod = null;
this.paymentMethods = [];
this.retryEnabled = false;
this.lastTransactionId = null;
this.retryInfo = '';
this.retryCountdown = 0;
this.paymentForm = this.fb.group({
phoneNumber: ['', [Validators.required, this.phoneNumberValidator()]]
});
}
ngOnInit() {
this.authService.isAuthenticated().subscribe(isAuthenticated => {
this.loadPaymentMethods();
});
}
ngOnDestroy() {
if (this.retryCountdownSubscription) {
this.retryCountdownSubscription.unsubscribe();
}
}
loadPaymentMethods() {
this.paymentService.availablePaymentMethods$.subscribe(methods => {
this.paymentMethods = methods;
if (!methods || methods.length === 0) {
this.error = 'Aucune méthode de paiement disponible. Veuillez configurer votre clé API Y-Nkap.';
}
else {
const enabledMethods = methods.filter(m => m.status === 'enabled');
if (enabledMethods.length === 0) {
this.error = 'Toutes les méthodes de paiement sont actuellement désactivées.';
}
else {
this.error = null;
}
}
}, error => {
this.errorHandlingService.handleError(error);
this.error = 'Erreur lors du chargement des méthodes de paiement.';
});
}
selectMethod(method) {
if (method.status === 'disabled') {
return;
}
this.selectedMethod = method;
this.currentStep = 'form';
this.error = null;
this.retryEnabled = false;
// Reset form with new validator based on selected method
this.paymentForm.patchValue({ phoneNumber: '' });
this.paymentForm.get('phoneNumber')?.updateValueAndValidity();
}
getPhonePlaceholder() {
if (this.selectedMethod?.id === 'mtn-momo') {
return 'Ex: 67XXXXXXX, 68XXXXXXX, 65XXXXXXX';
}
return 'Ex: 66XXXXXXX, 655XXXXXX, 656XXXXXX';
}
phoneNumberValidator() {
return (control) => {
const value = control.value;
if (!value)
return null;
const mtnRegex = /^(67|68|65)\d{7}$/;
const orangeRegex = /^(66|69)\d{7}$|^(655|656)\d{6}$/;
if (this.selectedMethod?.id === 'mtn-momo' && !mtnRegex.test(value)) {
return { invalidMtnNumber: true };
}
if (this.selectedMethod?.id === 'orange-money' && !orangeRegex.test(value)) {
return { invalidOrangeNumber: true };
}
return null;
};
}
getPhoneError() {
const control = this.paymentForm.get('phoneNumber');
if (!control?.errors || !control.touched)
return '';
if (control.errors['required']) {
return 'Le numéro de téléphone est requis';
}
if (control.errors['invalidMtnNumber']) {
return 'Numéro MTN invalide (ex: 67XXXXXXX, 68XXXXXXX, 65XXXXXXX)';
}
if (control.errors['invalidOrangeNumber']) {
return 'Numéro Orange invalide (ex: 66XXXXXXX, 655XXXXXX, 656XXXXXX)';
}
return 'Numéro de téléphone invalide';
}
/**
* Check if there are any enabled payment methods
*/
hasEnabledMethods() {
return this.paymentMethods.some(method => method.status === 'enabled');
}
/**
* Get the count of enabled payment methods
*/
getEnabledMethodsCount() {
return this.paymentMethods.filter(method => method.status === 'enabled').length;
}
/**
* Get Y-Nkap logo URL
*/
getYnkapLogoUrl() {
return this.logoService.getOperatorLogoUrl('ynkap');
}
/**
* Start countdown for retry button
*/
startRetryCountdown(seconds) {
this.retryCountdown = seconds;
if (this.retryCountdownSubscription) {
this.retryCountdownSubscription.unsubscribe();
}
this.retryCountdownSubscription = interval(1000).subscribe(() => {
this.retryCountdown--;
if (this.retryCountdown <= 0) {
this.retryCountdownSubscription?.unsubscribe();
this.retryCountdown = 0;
}
});
}
goBack() {
this.currentStep = 'methods';
this.selectedMethod = null;
this.paymentForm.reset();
this.error = null;
}
cancel() {
this.cancelled.emit();
}
processPayment() {
if (!this.paymentForm.valid || !this.selectedMethod)
return;
this.processing = true;
this.error = null;
const paymentRequest = {
amount: this.amount,
currency: this.currency,
merchantReference: this.merchantReference,
description: this.description,
successUrl: this.successUrl,
cancelUrl: this.cancelUrl,
webhookUrl: this.webhookUrl,
customer: {
phone: this.paymentForm.get('phoneNumber')?.value
}
};
this.paymentService.initiatePayment(paymentRequest).subscribe({
next: (response) => {
this.processing = false;
if (response.status === 'success') {
this.paymentSuccess.emit(response);
}
else {
setTimeout(() => {
this.handlePaymentError(response.error);
this.processing = false;
}, 1500);
}
},
error: (error) => {
setTimeout(() => {
this.handlePaymentError(error);
this.processing = false;
}, 1500);
}
});
}
retryPayment() {
if (!this.lastTransactionId) {
this.currentStep = 'methods';
this.selectedMethod = null;
this.paymentForm.reset();
this.error = null;
this.retryEnabled = false;
this.processing = false;
return;
}
this.processing = true;
this.error = null;
this.paymentService.retryPayment(this.lastTransactionId).subscribe({
next: (response) => {
if (response.status === 'success') {
this.processing = false;
this.paymentSuccess.emit(response);
this.retryEnabled = false;
}
else {
setTimeout(() => {
this.handlePaymentError(response.error);
this.processing = false;
}, 1500);
}
},
error: (error) => {
setTimeout(() => {
this.handlePaymentError(error);
this.processing = false;
}, 1500);
}
});
}
handlePaymentError(error) {
this.error = error.message || 'Une erreur est survenue lors du paiement';
this.paymentError.emit(error);
// Check if we have a transaction ID for retry
if (error.transactionId) {
this.lastTransactionId = error.transactionId;
// Get retry state information
const retryState = this.retryService.getRetryState(error.transactionId);
if (retryState) {
this.retryEnabled = retryState.canRetry;
this.retryInfo = this.retryService.getRetryInfo(error.transactionId);
// Start countdown if retry is available
if (retryState.canRetry && retryState.nextRetryDelayMs) {
this.startRetryCountdown(Math.ceil(retryState.nextRetryDelayMs / 1000));
}
}
else {
this.retryEnabled = this.retryService.isRetryable(error);
}
}
else {
this.retryEnabled = this.retryService.isRetryable(error);
}
}
onMouseMove(event) {
const items = document.querySelectorAll('.ynkap-method-item');
items.forEach((element) => {
const item = element;
const rect = item.getBoundingClientRect();
const x = ((event.clientX - rect.left) / rect.width) * 100;
const y = ((event.clientY - rect.top) / rect.height) * 100;
item.style.setProperty('--mouse-x', `${x}%`);
item.style.setProperty('--y', `${y}%`);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentComponent, deps: [{ token: i1$1.FormBuilder }, { token: PaymentService }, { token: AuthService }, { token: ErrorHandlingService }, { token: RetryService }, { token: LogoService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PaymentComponent, selector: "lib-ynkap-payment", inputs: { amount: "amount", currency: "currency", merchantReference: "merchantReference", theme: "theme", description: "description", successUrl: "successUrl", cancelUrl: "cancelUrl", webhookUrl: "webhookUrl", logoUrl: "logoUrl", primaryColor: "primaryColor", payButtonText: "payButtonText" }, outputs: { paymentSuccess: "paymentSuccess", paymentError: "paymentError", cancelled: "cancelled" }, host: { listeners: { "mousemove": "onMouseMove($event)" } }, ngImport: i0, template: "<div class=\"ynkap-payment\" [class.ynkap-dark]=\"theme === 'dark'\">\n \n\n <!-- Liste des m\u00E9thodes de paiement -->\n <div *ngIf=\"currentStep === 'methods'\" class=\"ynkap-methods\">\n <div class=\"ynkap-header-cool\">\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Logo Y-NKAP\" class=\"ynkap-logo-cool\" />\n <div class=\"ynkap-header-title\">\n <span class=\"ynkap-header-brand\">Y-NKAP</span>\n <span class=\"ynkap-header-pay\">Paiement s\u00E9curis\u00E9</span>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"ynkap-error-container\" [@fadeInOut] role=\"alert\" aria-live=\"assertive\">\n <div class=\"ynkap-error\">\n <span class=\"ynkap-error-icon-message\">\n <svg class=\"ynkap-error-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n <span class=\"ynkap-error-message\">{{ error }}</span>\n </span>\n <div *ngIf=\"retryInfo\" class=\"ynkap-retry-info\">\n <small>{{ retryInfo }}</small>\n </div>\n <button *ngIf=\"retryEnabled\"\n class=\"ynkap-button ynkap-button-secondary ynkap-retry-button ynkap-animated-border\"\n (click)=\"retryPayment()\"\n [disabled]=\"processing || retryCountdown > 0\"\n [attr.aria-label]=\"retryCountdown > 0 ? 'R\u00E9essayer dans ' + retryCountdown + ' secondes' : 'R\u00E9essayer le paiement'\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>\n </svg>\n <span *ngIf=\"retryCountdown > 0\">R\u00E9essayer ({{ retryCountdown }}s)</span>\n <span *ngIf=\"retryCountdown === 0\">R\u00E9essayer</span>\n </button>\n </div>\n </div>\n <div class=\"ynkap-payment-summary\" [@scaleIn]>\n <div class=\"ynkap-amount\">{{ amount | fcfa:currency }}</div>\n <div class=\"ynkap-description\">{{ description || 'S\u00E9lectionnez votre mode de paiement pr\u00E9f\u00E9r\u00E9' }}</div>\n </div>\n\n <div class=\"ynkap-methods-list\">\n <button *ngFor=\"let method of paymentMethods\" \n type=\"button\"\n class=\"ynkap-method-item\" \n [class.selected]=\"selectedMethod?.id === method.id\"\n [class.disabled]=\"method.status === 'disabled'\"\n (click)=\"method.status === 'enabled' && selectMethod(method)\"\n [attr.aria-pressed]=\"selectedMethod?.id === method.id\"\n [attr.aria-disabled]=\"method.status === 'disabled'\"\n [@scaleIn]\n [tabindex]=\"method.status === 'enabled' ? 0 : -1\"\n [attr.aria-label]=\"'S\u00E9lectionner ' + method.name\">\n <div class=\"ynkap-method-logo\">\n <img [src]=\"method.iconUrl\" [alt]=\"method.name\">\n </div>\n <div class=\"ynkap-method-info\">\n <div class=\"ynkap-method-name\">{{ method.name }}</div>\n <div class=\"ynkap-method-provider\">{{ method.provider }}</div>\n <div *ngIf=\"method.feePercentage || method.fixedFee\" class=\"ynkap-method-fee\">\n Frais: {{ method.feePercentage ? (method.feePercentage + '%') : (method.fixedFee | fcfa:currency) }}\n </div>\n </div>\n <svg class=\"ynkap-method-arrow\" viewBox=\"0 0 24 24\">\n <path d=\"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ynkap-actions\">\n <button type=\"button\" class=\"ynkap-button ynkap-button-secondary ynkap-animated-border\" (click)=\"cancel()\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>\n </svg>\n <span>Annuler</span>\n </button>\n </div>\n </div>\n\n <!-- Formulaire de paiement -->\n <div *ngIf=\"currentStep === 'form'\" class=\"ynkap-form\">\n <div class=\"ynkap-header-cool\">\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Logo Y-NKAP\" class=\"ynkap-logo-cool\" />\n <div class=\"ynkap-header-title\">\n <span class=\"ynkap-header-brand\">Y-NKAP</span>\n <span class=\"ynkap-header-pay\">Paiement s\u00E9curis\u00E9</span>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"ynkap-error-container\" [@fadeInOut] role=\"alert\" aria-live=\"assertive\">\n <div class=\"ynkap-error\">\n <span class=\"ynkap-error-icon-message\">\n <svg class=\"ynkap-error-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n <span class=\"ynkap-error-message\">{{ error }}</span>\n </span>\n <div *ngIf=\"retryInfo\" class=\"ynkap-retry-info\">\n <small>{{ retryInfo }}</small>\n </div>\n <button *ngIf=\"retryEnabled\"\n class=\"ynkap-button ynkap-button-secondary ynkap-retry-button ynkap-animated-border\"\n (click)=\"retryPayment()\"\n [disabled]=\"processing || retryCountdown > 0\"\n [attr.aria-label]=\"retryCountdown > 0 ? 'R\u00E9essayer dans ' + retryCountdown + ' secondes' : 'R\u00E9essayer le paiement'\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>\n </svg>\n <span *ngIf=\"retryCountdown > 0\">R\u00E9essayer ({{ retryCountdown }}s)</span>\n <span *ngIf=\"retryCountdown === 0\">R\u00E9essayer</span>\n </button>\n </div>\n </div>\n\n <div class=\"ynkap-payment-summary\" [@scaleIn]>\n <div class=\"summary-logo-container\">\n <img [src]=\"selectedMethod?.iconUrl\" [alt]=\"selectedMethod?.name\" class=\"ynkap-method-mini-logo\">\n </div>\n <div class=\"summary-details-container\">\n <div class=\"ynkap-amount\">{{ amount | fcfa:currency }}</div>\n <div class=\"ynkap-description\" *ngIf=\"description\">{{ description }}</div>\n </div>\n </div>\n\n <form [formGroup]=\"paymentForm\" (ngSubmit)=\"processPayment()\" class=\"ynkap-payment-form\">\n <div class=\"ynkap-form-group\">\n <label for=\"phoneNumber\" class=\"ynkap-label\">\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z\"/>\n </svg>\n <span>Num\u00E9ro de t\u00E9l\u00E9phone</span>\n </label>\n <div class=\"ynkap-input-group\">\n <input \n type=\"tel\" \n id=\"phoneNumber\" \n formControlName=\"phoneNumber\" \n class=\"ynkap-input\" \n [class.ynkap-input-error]=\"paymentForm.get('phoneNumber')?.errors && paymentForm.get('phoneNumber')?.touched\"\n [placeholder]=\"getPhonePlaceholder()\"\n aria-required=\"true\"\n [attr.aria-invalid]=\"paymentForm.get('phoneNumber')?.invalid\"\n aria-describedby=\"phoneNumberError\"\n >\n <div class=\"ynkap-input-icon\">\n <svg *ngIf=\"!paymentForm.get('phoneNumber')?.errors\" class=\"ynkap-icon success\" viewBox=\"0 0 24 24\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n <svg *ngIf=\"paymentForm.get('phoneNumber')?.errors\" class=\"ynkap-icon error\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n </div>\n </div>\n <div class=\"ynkap-error-message\" *ngIf=\"paymentForm.get('phoneNumber')?.errors && paymentForm.get('phoneNumber')?.touched\" [@fadeInOut] id=\"phoneNumberError\" role=\"alert\">\n {{ getPhoneError() }}\n </div>\n </div>\n\n <div class=\"ynkap-actions\">\n <button type=\"button\" class=\"ynkap-button ynkap-button-secondary ynkap-animated-border\" (click)=\"goBack()\" aria-label=\"Retour \u00E0 la s\u00E9lection de m\u00E9thode\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z\"/>\n </svg>\n <span>Retour</span>\n </button>\n <button \n type=\"submit\" \n class=\"ynkap-button ynkap-button-primary\" \n [disabled]=\"!paymentForm.valid || processing\"\n [ngStyle]=\"primaryColor ? {'background': primaryColor, 'border-color': primaryColor} : {}\"\n [attr.aria-label]=\"'Payer ' + (amount | currency:currency:'symbol':'1.0-0')\"\n >\n <svg *ngIf=\"!processing\" class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z\"/>\n </svg>\n <svg *ngIf=\"processing\" class=\"ynkap-icon spinner\" viewBox=\"0 0 24 24\">\n <path d=\"M12 6v3l4-4-4-4v-3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z\"/>\n </svg>\n <span *ngIf=\"!processing\">{{ payButtonText || ('Payer ' + (amount | fcfa:currency)) }}</span>\n <span *ngIf=\"processing\">Traitement en cours...</span>\n </button>\n </div>\n </form>\n </div>\n</div>\n\n<style>\n.ynkap-payment {\n max-width: 500px;\n margin: 0 auto;\n padding: 20px;\n font-family: system-ui, -apple-system, sans-serif;\n background: rgba(255,255,255,0.85);\n border-radius: 22px;\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.18), 0 1.5px 8px 0 rgba(0,123,255,0.10);\n backdrop-filter: blur(8px);\n border: 1.5px solid rgba(0,123,255,0.08);\n}\n\n.ynkap-header {\n display: flex;\n align-items: center;\n gap: 15px;\n margin-bottom: 30px;\n}\n\n.ynkap-logo {\n width: 40px;\n height: 40px;\n}\n\nh2, h3 {\n margin: 0;\n color: #333;\n}\n\nh2 {\n font-size: 20px;\n}\n\nh3 {\n margin-bottom: 20px;\n font-size: 18px;\n}\n\n.ynkap-payment-details {\n background: #f8f9fa;\n padding: 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-method-selected {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 10px;\n color: #666;\n}\n\n.ynkap-methods-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 20px;\n}\n\n.ynkap-method-item {\n display: flex;\n align-items: center;\n padding: 15px;\n border: 2px solid #e0e7ef;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: linear-gradient(90deg, #fff 80%, #f8fafc 100%);\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n position: relative;\n overflow: hidden;\n}\n\n.ynkap-method-item:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 16px 0 rgba(25,118,210,0.15);\n transform: translateY(-2px);\n}\n\n.ynkap-method-item.selected {\n border-color: #1976d2;\n background: linear-gradient(90deg, #e3f2fd 60%, #bbdefb 100%);\n box-shadow: 0 4px 20px 0 rgba(25,118,210,0.25);\n}\n\n.ynkap-method-item.selected::after {\n content: '\u2713';\n position: absolute;\n top: 8px;\n right: 12px;\n color: #1976d2;\n font-weight: bold;\n font-size: 16px;\n}\n\n.ynkap-method-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.ynkap-method-item.disabled:hover {\n transform: none;\n border-color: #e0e7ef;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n}\n\n.ynkap-method-logo {\n margin-right: 15px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-logo img {\n width: 48px;\n height: 48px;\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n padding: 4px;\n box-shadow: 0 2px 8px 0 rgba(0,0,0,0.1);\n}\n\n.mtn-badge,\n.orange-badge {\n display: inline-block;\n padding: 5px 10px;\n border-radius: 4px;\n font-weight: bold;\n font-size: 14px;\n}\n\n.mtn-badge {\n background: #ffd700;\n color: #000;\n}\n\n.orange-badge {\n background: #ff7900;\n color: white;\n}\n\n.ynkap-method-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ynkap-method-name {\n font-weight: 600;\n font-size: 16px;\n color: #2c3e50;\n margin-bottom: 2px;\n}\n\n.ynkap-method-provider {\n font-size: 14px;\n color: #64748b;\n font-weight: 500;\n}\n\n.ynkap-method-fee {\n font-size: 12px;\n color: #1976d2;\n font-weight: 500;\n margin-top: 4px;\n background: rgba(25,118,210,0.1);\n padding: 2px 8px;\n border-radius: 12px;\n display: inline-block;\n width: fit-content;\n}\n\n.ynkap-method-arrow {\n width: 20px;\n height: 20px;\n color: #64748b;\n transition: all 0.3s ease;\n flex-shrink: 0;\n}\n\n.ynkap-method-arrow path {\n fill: currentColor;\n}\n\n.ynkap-method-item:hover .ynkap-method-arrow {\n color: #1976d2;\n transform: translateX(4px);\n}\n\n.ynkap-method-item.selected .ynkap-method-arrow {\n color: #1976d2;\n}\n\n.ynkap-form-group {\n margin-bottom: 20px;\n}\n\n.ynkap-form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n}\n\n.ynkap-form-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 16px;\n}\n\n.ynkap-form-group input:focus {\n border-color: #007bff;\n outline: none;\n}\n\n.ynkap-error {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.ynkap-error-icon-message {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ynkap-actions {\n display: flex;\n gap: 10px;\n margin-top: 30px;\n}\n\n.ynkap-button-primary,\n.ynkap-button-secondary {\n padding: 12px 24px;\n border-radius: 4px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.ynkap-button-primary {\n background: #007bff;\n color: white;\n border: none;\n flex: 1;\n}\n\n.ynkap-button-primary:hover:not(:disabled) {\n background: #0056b3;\n}\n\n.ynkap-button-primary:disabled {\n background: #b3d7ff;\n cursor: not-allowed;\n}\n\n.ynkap-button-secondary {\n position: relative;\n background: linear-gradient(90deg, #fff 80%, #f4f8fc 100%);\n color: #222;\n border: 1.5px solid #e0e7ef;\n border-radius: 12px;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n font-weight: 600;\n letter-spacing: 0.5px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 10px 22px;\n overflow: hidden;\n z-index: 1;\n}\n\n.ynkap-button-secondary::before {\n content: '';\n position: absolute;\n top: -2px; left: -2px; right: -2px; bottom: -2px;\n border-radius: 14px;\n padding: 0;\n z-index: 2;\n pointer-events: none;\n background: \n linear-gradient(270deg, \n #1976d2 0%, \n #b3d1f7 20%, \n transparent 40%, \n transparent 60%, \n #b3d1f7 80%, \n #1976d2 100%);\n background-size: 400% 400%;\n background-repeat: no-repeat;\n filter: blur(0.5px);\n animation: border-trace 2.5s linear infinite;\n}\n\n@keyframes border-trace {\n 0% {\n background-position: 100% 0;\n }\n 25% {\n background-position: 100% 100%;\n }\n 50% {\n background-position: 0 100%;\n }\n 75% {\n background-position: 0 0;\n }\n 100% {\n background-position: 100% 0;\n }\n}\n\n.ynkap-button-secondary:hover {\n background: #f8f9fa;\n}\n\n.ynkap-method-item:focus {\n outline: 2px solid #1976d2;\n outline-offset: 2px;\n z-index: 2;\n}\n\n.ynkap-payment-summary {\n display: flex;\n align-items: center;\n gap: 18px;\n background: linear-gradient(90deg, #f8fafc 60%, #e3f0ff 100%);\n border-radius: 16px;\n box-shadow: 0 2px 12px 0 rgba(0,123,255,0.07);\n padding: 18px 18px 12px 18px;\n margin-bottom: 18px;\n}\n\n.summary-logo-container {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-mini-logo {\n height: 54px; /* Agrandit le logo */\n width: 54px; /* Garde le logo carr\u00E9 */\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.08);\n}\n\n.summary-details-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 4px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-animated-border {\n position: relative;\n overflow: visible;\n z-index: 1;\n}\n\n.ynkap-border-svg {\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 2;\n}\n\n.ynkap-border-svg rect {\n fill: none;\n stroke: #1976d2;\n stroke-width: 2.5;\n stroke-dasharray: 180 400;\n stroke-dashoffset: 0;\n filter: drop-shadow(0 0 6px #1976d2cc);\n animation: border-shine-svg 2.5s linear infinite;\n rx: 12;\n ry: 12;\n}\n\n@keyframes border-shine-svg {\n 0% {\n stroke-dashoffset: 580;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n 60% {\n stroke: #b3d1f7;\n filter: drop-shadow(0 0 12px #b3d1f7cc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n}\n\n.ynkap-header-brand {\n font-size: 1.7rem; /* Plus grand qu'avant */\n font-weight: bold;\n letter-spacing: 1px;\n}\n\n.ynkap-header-pay {\n font-size: 1.1rem;\n color: #4a6fa1;\n font-weight: 500;\n}\n\n/* --- Dark Theme Overrides for Method Items --- */\n.ynkap-dark .ynkap-method-item {\n background: linear-gradient(90deg, #2a2a3a 80%, #1e1e2d 100%);\n border-color: rgba(255,255,255,0.1);\n box-shadow: 0 2px 12px 0 rgba(0,0,0,0.4);\n}\n\n.ynkap-dark .ynkap-method-item:hover {\n background: linear-gradient(90deg, #3c3c4c 60%, #2a2a3a 100%);\n border-color: rgba(255,255,255,0.3);\n box-shadow: 0 4px 20px 0 rgba(0,123,255,0.2);\n}\n\n.ynkap-dark .ynkap-method-item.selected {\n background: linear-gradient(90deg, #1e3a8a 60%, #1e40af 100%);\n border-color: #3b82f6;\n box-shadow: 0 4px 24px 0 rgba(59,130,246,0.3);\n}\n\n.ynkap-dark .ynkap-method-item.selected::after {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-name {\n color: #f1f5f9;\n}\n\n.ynkap-dark .ynkap-method-provider {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-fee {\n color: #60a5fa;\n background: rgba(96,165,250,0.2);\n}\n\n.ynkap-dark .ynkap-method-arrow {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-item:hover .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-item.selected .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n/* --- Retry Information Styles --- */\n.ynkap-retry-info {\n margin-top: 8px;\n padding: 8px 12px;\n background: rgba(59, 130, 246, 0.1);\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n}\n\n.ynkap-retry-info small {\n color: #1e40af;\n font-size: 12px;\n font-weight: 500;\n}\n\n.ynkap-dark .ynkap-retry-info {\n background: rgba(96, 165, 250, 0.15);\n border-left-color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-retry-info small {\n color: #93c5fd;\n}\n\n/* --- Retry Button Disabled State --- */\n.ynkap-retry-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ynkap-retry-button:disabled .ynkap-border-svg rect {\n animation: none;\n stroke: #94a3b8;\n filter: none;\n}\n\n/* --- Dark Theme Overrides for Layout --- */\n.ynkap-dark .ynkap-header-cool,\n.ynkap-dark .ynkap-payment-summary {\n background: linear-gradient(135deg, #2b2b40, #1e1e2d);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n}\n\n/* Text colors */\n.ynkap-dark .ynkap-header-brand,\n.ynkap-dark .ynkap-amount {\n color: #ffffff;\n}\n\n.ynkap-dark .ynkap-header-pay,\n.ynkap-dark .ynkap-description {\n color: #a0a0b0;\n}\n\n/* Secondary Button (Cancel) */\n.ynkap-dark .ynkap-button-secondary {\n background: transparent;\n color: #e0e0e0;\n border-color: rgba(255, 255, 255, 0.2);\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #e0e0e0;\n}\n\n/* --- Styles complets pour le th\u00E8me sombre --- */\n\n/* Rend le fond du formulaire transparent pour h\u00E9riter de celui de la modale */\n.ynkap-dark .ynkap-payment {\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n border: none;\n}\n\n/* --- Boutons Secondaires (Annuler/Retour) --- */\n.ynkap-dark .ynkap-button-secondary {\n background: rgba(57, 53, 53, 0.938);\n color: #ffffff;\n /* border-color: rgb(255, 255, 255); */\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: linear-gradient(90deg, #2f2f3a 80%, #2e2e3c 100%);\n /* border-color: rgba(255, 255, 255, 0.4); */\n}\n\n/* Ic\u00F4nes des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #fffeff;\n}\n\n/* Bordure anim\u00E9e des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-border-svg rect {\n animation-name: border-shine-svg-dark;\n}\n\n@keyframes border-shine-svg-dark {\n 0% {\n stroke-dashoffset: 580;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n 60% {\n stroke: rgba(255, 255, 255, 0.9);\n filter: drop-shadow(0 0 12px #a8b2ffcc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n}\n</style>\n", styles: [":host{display:block;--primary-color: #007bff;--primary-hover: #0056b3;--error-color: #dc3545;--success-color: #28a745;--text-color: #2c3e50;--text-secondary: #6c757d;--border-color: #e0e0e0;--background-color: #ffffff;--background-secondary: #f8f9fa;--shadow-color: rgba(0, 0, 0, .1);--input-background: #ffffff;--primary-rgb: 0, 123, 255;position:relative;overflow:hidden;width:100%;height:100%}.ynkap-dark{--primary-color: #3699ff;--primary-hover: #187de4;--text-color: #ffffff;--text-secondary: #b5b5c3;--border-color: #2b2b40;--background-color: #1e1e2d;--background-secondary: #151521;--shadow-color: rgba(0, 0, 0, .3);--input-background: #151521;--primary-rgb: 54, 153, 255}.ynkap-payment{max-width:500px;margin:0 auto;padding:20px;font-family:system-ui,-apple-system,sans-serif;background:#ffffffd9;border-radius:22px;box-shadow:0 8px 32px #1f26872e,0 1.5px 8px #007bff1a;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1.5px solid rgba(0,123,255,.08)}@keyframes gradientFlow{0%{background-position:0% 50%;opacity:.4}50%{background-position:100% 50%;opacity:.7}to{background-position:0% 50%;opacity:.4}}.ynkap-payment:before{content:\"\";position:absolute;inset:-50%;background:linear-gradient(135deg,rgba(var(--primary-rgb),.08),rgba(var(--primary-rgb),.03),#ffffff0d,rgba(var(--primary-rgb),.03),rgba(var(--primary-rgb),.08));background-size:400% 400%;animation:gradientFlow 8s ease infinite;z-index:-3;transform:scale(1.5)}@keyframes waveEffect{0%{transform:translate(-100%) translateY(-50%) rotate(-45deg)}50%{transform:translate(0) translateY(-50%) rotate(-45deg)}to{transform:translate(100%) translateY(-50%) rotate(-45deg)}}.ynkap-payment:after{content:\"\";position:absolute;left:0;top:50%;width:200%;height:200%;background:linear-gradient(90deg,transparent 0%,rgba(var(--primary-rgb),.1) 50%,transparent 100%);animation:waveEffect 4s ease-in-out infinite;z-index:-2}.ynkap-payment .gradient-layer{content:\"\";position:absolute;inset:0;background:linear-gradient(135deg,var(--background-color) 0%,rgba(var(--primary-rgb),.05) 100%);z-index:-1;opacity:.7}@keyframes floatingDot1{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(-20px,-30px) scale(1.2);opacity:.6}75%{transform:translate(20px,-60px) scale(.8);opacity:.4}}@keyframes floatingDot2{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(30px,-40px) scale(1.4);opacity:.5}75%{transform:translate(-10px,-50px) scale(.9);opacity:.3}}@keyframes floatingDot3{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(-15px,-45px) scale(1.3);opacity:.7}75%{transform:translate(25px,-35px) scale(.7);opacity:.4}}.floating-dot{position:absolute;width:6px;height:6px;border-radius:50%;background:rgba(var(--primary-rgb),.6);box-shadow:0 0 10px 2px rgba(var(--primary-rgb),.3),0 0 20px 4px rgba(var(--primary-rgb),.1);pointer-events:none;z-index:1}.floating-dot:nth-child(1){bottom:20%;left:20%;animation:floatingDot1 6s ease-in-out infinite}.floating-dot:nth-child(2){bottom:30%;right:25%;animation:floatingDot2 8s ease-in-out infinite}.floating-dot:nth-child(3){bottom:25%;left:40%;animation:floatingDot3 7s ease-in-out infinite}.ynkap-dark .ynkap-payment{background:linear-gradient(135deg,#1e1e2df2,#141423fa);box-shadow:0 10px 30px -10px #0006,0 0 0 1px #ffffff1a inset}.ynkap-dark .gradient-layer{background:linear-gradient(135deg,rgba(var(--primary-rgb),.15),rgba(var(--primary-rgb),.05));opacity:.3}@keyframes sparkle{0%,to{transform:scale(0) rotate(0);opacity:0}50%{transform:scale(1) rotate(180deg);opacity:.8}}.sparkle{position:absolute;width:3px;height:3px;background:rgba(var(--primary-rgb),.8);clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%);pointer-events:none;z-index:1}.sparkle:nth-child(1){top:20%;left:30%;animation:sparkle 4s infinite}.sparkle:nth-child(2){top:40%;right:20%;animation:sparkle 5s infinite 1s}.sparkle:nth-child(3){bottom:30%;left:40%;animation:sparkle 4.5s infinite .5s}@media (max-width: 480px){.sparkle{display:none}.floating-dot{width:4px;height:4px}}.ynkap-header{display:flex;align-items:center;gap:8px;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border-color)}.ynkap-logo-container{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:var(--background-secondary);border-radius:8px;padding:4px}.ynkap-logo{width:100%;height:auto}.ynkap-title{font-size:1rem;font-weight:600;margin:0;color:var(--text-color)}.ynkap-error-container{margin-bottom:20px}.ynkap-error{display:flex;justify-content:space-between;align-items:center;gap:12px;background:#dc35451a;border-left:4px solid var(--error-color);padding:12px 16px;border-radius:8px}.ynkap-error-icon{width:24px;height:24px;fill:var(--error-color);flex-shrink:0}.ynkap-error-message{color:var(--error-color);font-size:.9rem;line-height:1.5}.ynkap-payment-summary{background:linear-gradient(90deg,#f8fafc 60%,#e3f0ff);border-radius:16px;box-shadow:0 2px 12px #007bff12;padding:18px 18px 12px;margin-bottom:18px}.ynkap-amount{font-size:1.5rem;font-weight:700;margin-bottom:2px;background:linear-gradient(135deg,var(--text-color) 0%,rgba(var(--primary-rgb),.8) 100%);-webkit-background-clip:text;background-clip:text;color:transparent}.ynkap-description{font-size:.8rem;color:var(--text-secondary)}.ynkap-methods-list{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.ynkap-method-item{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(135deg,var(--background-secondary) 0%,rgba(var(--primary-rgb),.03) 100%);border:1px solid var(--border-color);border-radius:14px;cursor:pointer;transition:box-shadow .2s,transform .2s,background .2s;position:relative;overflow:hidden;box-shadow:0 1.5px 8px #007bff12;background:linear-gradient(90deg,#fff 80%,#f0f6ff)}.ynkap-method-item:hover{box-shadow:0 4px 16px #007bff21;background:linear-gradient(90deg,#e3f0ff 60%,#fff);transform:translateY(-2px) scale(1.03)}.ynkap-method-item:after{content:\"\";position:absolute;inset:0;background:radial-gradient(circle at var(--x, 50%) var(--y, 50%),rgba(var(--primary-rgb),.1) 0%,transparent 50%);opacity:0;transition:opacity .3s}.ynkap-method-item:hover:after{opacity:1}.ynkap-method-item.selected{border-color:var(--primary-color);background:#007bff0d}.ynkap-method-logo{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:#fff;border-radius:6px;padding:4px;composes:shine-hover}.ynkap-method-logo img{width:100%;height:auto}.ynkap-method-info{flex:1;text-align:left}.ynkap-method-name{font-size:.9rem;font-weight:600;margin-bottom:1px;color:var(--text-color);text-align:left}.ynkap-method-provider{font-size:.75rem;color:var(--text-secondary);text-align:left}.ynkap-method-arrow{width:24px;height:24px;fill:var(--text-secondary);flex-shrink:0}.ynkap-selected-method{display:flex;align-items:center;gap:12px;font-size:16px;font-weight:500}.ynkap-method-mini-logo{height:32px;width:auto;border-radius:4px}.ynkap-payment-form{margin-top:20px}.ynkap-form-group{margin-bottom:20px}.ynkap-label{display:block;margin-bottom:8px;color:var(--text-secondary);font-size:.9rem}.ynkap-label i{margin-right:8px}.ynkap-input-group{position:relative;overflow:hidden}.ynkap-input-group:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.2) 40%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 60%,rgba(255,255,255,0) 80%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.ynkap-input-group:focus-within:before{animation:shineRight 1s ease-in-out forwards}.ynkap-input-group:not(:focus-within):before{animation:shineLeft 1s ease-in-out forwards}.ynkap-input{width:100%;padding:16px 40px 16px 16px;font-size:1rem;border:1px solid var(--border-color);border-radius:12px;background:linear-gradient(135deg,var(--input-background) 0%,rgba(var(--primary-rgb),.02) 100%);color:var(--text-color);transition:all .3s cubic-bezier(.4,0,.2,1)}.ynkap-input::placeholder{color:var(--text-secondary);opacity:.7;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ynkap-input:focus{outline:none;border-color:rgba(var(--primary-rgb),.3);box-shadow:0 5px 15px -5px rgba(var(--primary-rgb),.2),0 0 0 1px rgba(var(--primary-rgb),.1) inset;background:linear-gradient(135deg,var(--input-background) 0%,rgba(var(--primary-rgb),.05) 100%)}.ynkap-input-error{border-color:var(--error-color)}.ynkap-input-error:focus{box-shadow:0 0 0 3px #dc35451a}.ynkap-input-icon{position:absolute;right:12px;top:50%;transform:translateY(-50%);width:20px;height:20px;display:flex;align-items:center;justify-content:center;pointer-events:none}.ynkap-input-icon .success{fill:var(--success-color)}.ynkap-input-icon .error{fill:var(--error-color)}.ynkap-actions{display:flex;gap:6px;margin-top:12px}.ynkap-button{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:8px 16px;font-size:.85rem;font-weight:500;border-radius:8px;cursor:pointer;border:none;outline:none;position:relative;overflow:hidden;transition:all .2s ease-out}.ynkap-button i{font-size:1rem}@keyframes shineRight{0%{transform:translate(-100%) skew(-15deg);opacity:0}50%{opacity:.5}to{transform:translate(100%) skew(-15deg);opacity:0}}@keyframes shineLeft{0%{transform:translate(100%) skew(-15deg);opacity:0}50%{opacity:.5}to{transform:translate(-100%) skew(-15deg);opacity:0}}.shine-hover{position:relative;overflow:hidden}.shine-hover:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 25%,rgba(var(--primary-rgb),.2) 45%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 55%,rgba(255,255,255,0) 75%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.shine-hover:hover:before{animation:shineRight .8s ease-out forwards}.shine-hover:not(:hover):before{animation:shineLeft .8s ease-out forwards}.ynkap-button:before{display:none}.ynkap-button-primary{background:linear-gradient(135deg,var(--primary-color) 0%,rgba(var(--primary-rgb),.8) 100%);color:#fff;box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 0 1px #ffffff1a inset;position:relative;z-index:1}@keyframes pulse{0%{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 rgba(var(--primary-rgb),.4)}70%{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 0 15px rgba(var(--primary-rgb),0)}to{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 rgba(var(--primary-rgb),0)}}@keyframes particleAnimation{0%{transform:translate(0) rotate(0);opacity:0}50%{opacity:.5}to{transform:translate(100px,-100px) rotate(360deg);opacity:0}}.ynkap-button-primary:after{content:\"\";position:absolute;inset:-50%;background:radial-gradient(circle at center,#fffc,#fff0 50%);opacity:0;transition:opacity .3s;transform:scale(.5);filter:blur(20px)}.ynkap-button-primary:hover{transform:translateY(-2px);background:linear-gradient(135deg,var(--primary-hover) 0%,rgba(var(--primary-rgb),.9) 100%);animation:pulse 2s infinite}.ynkap-button-primary:hover:after{opacity:.5;transform:scale(1)}.ynkap-button-primary:active{transform:translateY(0)}.ynkap-button-primary:hover:before{content:\"\";position:absolute;width:4px;height:4px;border-radius:50%;background:#fff;box-shadow:0 0 10px 2px #fffc,0 0 20px 4px rgba(var(--primary-rgb),.4);animation:particleAnimation 1s ease-out infinite}.ynkap-button-primary:disabled{opacity:.7;cursor:not-allowed;animation:none;transform:none}.ynkap-button-primary:disabled:before,.ynkap-button-primary:disabled:after{display:none}.ynkap-button-secondary{background:linear-gradient(90deg,#fff 80%,#f4f8fc);color:#222;border:1.5px solid #e0e7ef;border-radius:12px;box-shadow:0 2px 8px #007bff0f;font-weight:600;letter-spacing:.5px;transition:all .3s cubic-bezier(.4,0,.2,1);padding:10px 22px}.ynkap-button-secondary:focus{outline:2px solid #1976d2;outline-offset:2px;box-shadow:0 0 0 3px #1976d226}.ynkap-icon{width:16px;height:16px;fill:currentColor}.spinner{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.ynkap-methods,.ynkap-form{width:100%;position:relative}.ynkap-methods.active,.ynkap-form.active{display:block}.ynkap-methods.inactive,.ynkap-form.inactive{display:none}@media (max-width: 480px){:host{position:fixed;inset:0;width:100vw;height:100vh}.ynkap-payment{border-radius:0;padding:10px}.ynkap-header{margin-bottom:12px;padding-bottom:8px}.ynkap-logo-container{width:28px;height:28px;padding:4px}.ynkap-title{font-size:1rem}.ynkap-amount{font-size:1.4rem}.ynkap-payment-summary{padding:12px;margin-bottom:12px}.ynkap-method-item{padding:8px 10px;gap:8px}.ynkap-method-logo{width:28px;height:28px;padding:4px}.ynkap-method-name{font-size:.9rem}.ynkap-method-provider{font-size:.75rem}.ynkap-form,.ynkap-payment-form{flex:1;display:flex;flex-direction:column}.ynkap-actions{margin-top:auto;padding-top:12px}.ynkap-button{padding:8px 12px;font-size:.8rem}.ynkap-button-primary:hover{transform:none;animation:pulse 2.5s infinite}.ynkap-input{padding:12px 32px 12px 12px;font-size:.9rem}.ynkap-input::placeholder{font-size:.75rem}.ynkap-input-icon{right:8px;width:16px;height:16px}.ynkap-error-message{font-size:.8rem}.ynkap-selected-method{gap:8px}.ynkap-method-mini-logo{width:20px;height:20px}.ynkap-methods,.ynkap-form{height:auto;min-height:calc(100vh - 180px);overflow-y:auto;-webkit-overflow-scrolling:touch}}.ynkap-dark .shine-hover:before{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 25%,rgba(var(--primary-rgb),.1) 45%,rgba(255,255,255,.15) 50%,rgba(var(--primary-rgb),.1) 55%,rgba(255,255,255,0) 75%,transparent 100%)}.ynkap-button:disabled:before,.ynkap-input-group.disabled:before{display:none}.ynkap-payment-summary,.ynkap-selected-method,.ynkap-method-logo{composes:shine-hover}.ynkap-method-item:hover,.ynkap-button-primary:hover:not(:disabled),.ynkap-button-secondary:hover{transform:translateY(-1px);transition:transform .2s ease}.ynkap-method-item:active,.ynkap-button-primary:active:not(:disabled),.ynkap-button-secondary:active{transform:translateY(0)}.ynkap-method-item:before,.ynkap-button:before,.ynkap-input-group:before,.ynkap-logo-container:before,.ynkap-method-logo:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.2) 40%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 60%,rgba(255,255,255,0) 80%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.ynkap-method-item:hover:before,.ynkap-button:hover:before,.ynkap-input-group:hover:before,.ynkap-logo-container:hover:before,.ynkap-method-logo:hover:before{animation:shineRight .7s ease-out forwards}.ynkap-method-item:not(:hover):before,.ynkap-button:not(:hover):before,.ynkap-input-group:not(:hover):before,.ynkap-logo-container:not(:hover):before,.ynkap-method-logo:not(:hover):before{animation:shineLeft .7s ease-out forwards}.ynkap-dark .ynkap-method-item:before,.ynkap-dark .ynkap-button:before,.ynkap-dark .ynkap-input-group:before,.ynkap-dark .ynkap-logo-container:before,.ynkap-dark .ynkap-method-logo:before{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.15) 40%,rgba(255,255,255,.2) 50%,rgba(var(--primary-rgb),.15) 60%,rgba(255,255,255,0) 80%,transparent 100%)}@media (hover: hover){.ynkap-method-item:hover{--x: var(--mouse-x, 50%);--y: var(--mouse-y, 50%)}}.ynkap-dark .ynkap-button-secondary{background:#ffffff0d;border-color:#ffffff1a}.ynkap-dark .ynkap-button-secondary:hover{background:#ffffff14;border-color:#fff3}.ynkap-dark .ynkap-button-primary:after{background:radial-gradient(circle at center,#fff9,#fff0 50%)}.ynkap-method-item.disabled{opacity:.5;cursor:not-allowed;background:var(--background-secondary)}.ynkap-method-item.disabled:hover{transform:none;box-shadow:none}.ynkap-method-fee{font-size:.75rem;color:var(--text-secondary);margin-top:4px}.ynkap-retry-button{margin-top:8px;background:var(--background-secondary);border:1px solid var(--border-color);padding:6px 12px;font-size:.8rem}.ynkap-retry-button:hover:not(:disabled){background:linear-gradient(135deg,var(--background-secondary) 0%,rgba(var(--primary-rgb),.05) 100%);transform:translateY(-1px);box-shadow:0 4px 12px -2px rgba(var(--primary-rgb),.15)}.ynkap-retry-button:disabled{opacity:.5;cursor:not-allowed}.ynkap-header-cool{display:flex;align-items:center;justify-content:center;gap:18px;background:linear-gradient(90deg,#f8fafc 60%,#e3f0ff);border-radius:14px;box-shadow:0 2px 12px #007bff12;padding:18px 0 14px;margin-bottom:18px;position:relative;overflow:hidden}.ynkap-logo-cool{width:54px;height:54px;border-radius:12px;box-shadow:0 2px 8px #00000012;background:#fff;object-fit:contain}.ynkap-header-title{display:flex;flex-direction:column;align-items:flex-start;gap:2px}.ynkap-header-brand{font-size:1.35rem;font-weight:700;letter-spacing:2px;color:#1976d2;text-shadow:0 1px 2px #fff,0 2px 8px #e3f0ff}.ynkap-header-pay{font-size:.95rem;color:#2c3e50;opacity:.85;font-weight:500;letter-spacing:1px}\n", "\n.ynkap-payment {\n max-width: 500px;\n margin: 0 auto;\n padding: 20px;\n font-family: system-ui, -apple-system, sans-serif;\n background: rgba(255,255,255,0.85);\n border-radius: 22px;\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.18), 0 1.5px 8px 0 rgba(0,123,255,0.10);\n backdrop-filter: blur(8px);\n border: 1.5px solid rgba(0,123,255,0.08);\n}\n\n.ynkap-header {\n display: flex;\n align-items: center;\n gap: 15px;\n margin-bottom: 30px;\n}\n\n.ynkap-logo {\n width: 40px;\n height: 40px;\n}\n\nh2, h3 {\n margin: 0;\n color: #333;\n}\n\nh2 {\n font-size: 20px;\n}\n\nh3 {\n margin-bottom: 20px;\n font-size: 18px;\n}\n\n.ynkap-payment-details {\n background: #f8f9fa;\n padding: 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-method-selected {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 10px;\n color: #666;\n}\n\n.ynkap-methods-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 20px;\n}\n\n.ynkap-method-item {\n display: flex;\n align-items: center;\n padding: 15px;\n border: 2px solid #e0e7ef;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: linear-gradient(90deg, #fff 80%, #f8fafc 100%);\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n position: relative;\n overflow: hidden;\n}\n\n.ynkap-method-item:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 16px 0 rgba(25,118,210,0.15);\n transform: translateY(-2px);\n}\n\n.ynkap-method-item.selected {\n border-color: #1976d2;\n background: linear-gradient(90deg, #e3f2fd 60%, #bbdefb 100%);\n box-shadow: 0 4px 20px 0 rgba(25,118,210,0.25);\n}\n\n.ynkap-method-item.selected::after {\n content: '\u2713';\n position: absolute;\n top: 8px;\n right: 12px;\n color: #1976d2;\n font-weight: bold;\n font-size: 16px;\n}\n\n.ynkap-method-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.ynkap-method-item.disabled:hover {\n transform: none;\n border-color: #e0e7ef;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n}\n\n.ynkap-method-logo {\n margin-right: 15px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-logo img {\n width: 48px;\n height: 48px;\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n padding: 4px;\n box-shadow: 0 2px 8px 0 rgba(0,0,0,0.1);\n}\n\n.mtn-badge,\n.orange-badge {\n display: inline-block;\n padding: 5px 10px;\n border-radius: 4px;\n font-weight: bold;\n font-size: 14px;\n}\n\n.mtn-badge {\n background: #ffd700;\n color: #000;\n}\n\n.orange-badge {\n background: #ff7900;\n color: white;\n}\n\n.ynkap-method-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ynkap-method-name {\n font-weight: 600;\n font-size: 16px;\n color: #2c3e50;\n margin-bottom: 2px;\n}\n\n.ynkap-method-provider {\n font-size: 14px;\n color: #64748b;\n font-weight: 500;\n}\n\n.ynkap-method-fee {\n font-size: 12px;\n color: #1976d2;\n font-weight: 500;\n margin-top: 4px;\n background: rgba(25,118,210,0.1);\n padding: 2px 8px;\n border-radius: 12px;\n display: inline-block;\n width: fit-content;\n}\n\n.ynkap-method-arrow {\n width: 20px;\n height: 20px;\n color: #64748b;\n transition: all 0.3s ease;\n flex-shrink: 0;\n}\n\n.ynkap-method-arrow path {\n fill: currentColor;\n}\n\n.ynkap-method-item:hover .ynkap-method-arrow {\n color: #1976d2;\n transform: translateX(4px);\n}\n\n.ynkap-method-item.selected .ynkap-method-arrow {\n color: #1976d2;\n}\n\n.ynkap-form-group {\n margin-bottom: 20px;\n}\n\n.ynkap-form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n}\n\n.ynkap-form-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 16px;\n}\n\n.ynkap-form-group input:focus {\n border-color: #007bff;\n outline: none;\n}\n\n.ynkap-error {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.ynkap-error-icon-message {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ynkap-actions {\n display: flex;\n gap: 10px;\n margin-top: 30px;\n}\n\n.ynkap-button-primary,\n.ynkap-button-secondary {\n padding: 12px 24px;\n border-radius: 4px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.ynkap-button-primary {\n background: #007bff;\n color: white;\n border: none;\n flex: 1;\n}\n\n.ynkap-button-primary:hover:not(:disabled) {\n background: #0056b3;\n}\n\n.ynkap-button-primary:disabled {\n background: #b3d7ff;\n cursor: not-allowed;\n}\n\n.ynkap-button-secondary {\n position: relative;\n background: linear-gradient(90deg, #fff 80%, #f4f8fc 100%);\n color: #222;\n border: 1.5px solid #e0e7ef;\n border-radius: 12px;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n font-weight: 600;\n letter-spacing: 0.5px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 10px 22px;\n overflow: hidden;\n z-index: 1;\n}\n\n.ynkap-button-secondary::before {\n content: '';\n position: absolute;\n top: -2px; left: -2px; right: -2px; bottom: -2px;\n border-radius: 14px;\n padding: 0;\n z-index: 2;\n pointer-events: none;\n background: \n linear-gradient(270deg, \n #1976d2 0%, \n #b3d1f7 20%, \n transparent 40%, \n transparent 60%, \n #b3d1f7 80%, \n #1976d2 100%);\n background-size: 400% 400%;\n background-repeat: no-repeat;\n filter: blur(0.5px);\n animation: border-trace 2.5s linear infinite;\n}\n\n@keyframes border-trace {\n 0% {\n background-position: 100% 0;\n }\n 25% {\n background-position: 100% 100%;\n }\n 50% {\n background-position: 0 100%;\n }\n 75% {\n background-position: 0 0;\n }\n 100% {\n background-position: 100% 0;\n }\n}\n\n.ynkap-button-secondary:hover {\n background: #f8f9fa;\n}\n\n.ynkap-method-item:focus {\n outline: 2px solid #1976d2;\n outline-offset: 2px;\n z-index: 2;\n}\n\n.ynkap-payment-summary {\n display: flex;\n align-items: center;\n gap: 18px;\n background: linear-gradient(90deg, #f8fafc 60%, #e3f0ff 100%);\n border-radius: 16px;\n box-shadow: 0 2px 12px 0 rgba(0,123,255,0.07);\n padding: 18px 18px 12px 18px;\n margin-bottom: 18px;\n}\n\n.summary-logo-container {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-mini-logo {\n height: 54px; /* Agrandit le logo */\n width: 54px; /* Garde le logo carr\u00E9 */\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.08);\n}\n\n.summary-details-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 4px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-animated-border {\n position: relative;\n overflow: visible;\n z-index: 1;\n}\n\n.ynkap-border-svg {\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 2;\n}\n\n.ynkap-border-svg rect {\n fill: none;\n stroke: #1976d2;\n stroke-width: 2.5;\n stroke-dasharray: 180 400;\n stroke-dashoffset: 0;\n filter: drop-shadow(0 0 6px #1976d2cc);\n animation: border-shine-svg 2.5s linear infinite;\n rx: 12;\n ry: 12;\n}\n\n@keyframes border-shine-svg {\n 0% {\n stroke-dashoffset: 580;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n 60% {\n stroke: #b3d1f7;\n filter: drop-shadow(0 0 12px #b3d1f7cc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n}\n\n.ynkap-header-brand {\n font-size: 1.7rem; /* Plus grand qu'avant */\n font-weight: bold;\n letter-spacing: 1px;\n}\n\n.ynkap-header-pay {\n font-size: 1.1rem;\n color: #4a6fa1;\n font-weight: 500;\n}\n\n/* --- Dark Theme Overrides for Method Items --- */\n.ynkap-dark .ynkap-method-item {\n background: linear-gradient(90deg, #2a2a3a 80%, #1e1e2d 100%);\n border-color: rgba(255,255,255,0.1);\n box-shadow: 0 2px 12px 0 rgba(0,0,0,0.4);\n}\n\n.ynkap-dark .ynkap-method-item:hover {\n background: linear-gradient(90deg, #3c3c4c 60%, #2a2a3a 100%);\n border-color: rgba(255,255,255,0.3);\n box-shadow: 0 4px 20px 0 rgba(0,123,255,0.2);\n}\n\n.ynkap-dark .ynkap-method-item.selected {\n background: linear-gradient(90deg, #1e3a8a 60%, #1e40af 100%);\n border-color: #3b82f6;\n box-shadow: 0 4px 24px 0 rgba(59,130,246,0.3);\n}\n\n.ynkap-dark .ynkap-method-item.selected::after {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-name {\n color: #f1f5f9;\n}\n\n.ynkap-dark .ynkap-method-provider {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-fee {\n color: #60a5fa;\n background: rgba(96,165,250,0.2);\n}\n\n.ynkap-dark .ynkap-method-arrow {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-item:hover .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-item.selected .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n/* --- Retry Information Styles --- */\n.ynkap-retry-info {\n margin-top: 8px;\n padding: 8px 12px;\n background: rgba(59, 130, 246, 0.1);\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n}\n\n.ynkap-retry-info small {\n color: #1e40af;\n font-size: 12px;\n font-weight: 500;\n}\n\n.ynkap-dark .ynkap-retry-info {\n background: rgba(96, 165, 250, 0.15);\n border-left-color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-retry-info small {\n color: #93c5fd;\n}\n\n/* --- Retry Button Disabled State --- */\n.ynkap-retry-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ynkap-retry-button:disabled .ynkap-border-svg rect {\n animation: none;\n stroke: #94a3b8;\n filter: none;\n}\n\n/* --- Dark Theme Overrides for Layout --- */\n.ynkap-dark .ynkap-header-cool,\n.ynkap-dark .ynkap-payment-summary {\n background: linear-gradient(135deg, #2b2b40, #1e1e2d);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n}\n\n/* Text colors */\n.ynkap-dark .ynkap-header-brand,\n.ynkap-dark .ynkap-amount {\n color: #ffffff;\n}\n\n.ynkap-dark .ynkap-header-pay,\n.ynkap-dark .ynkap-description {\n color: #a0a0b0;\n}\n\n/* Secondary Button (Cancel) */\n.ynkap-dark .ynkap-button-secondary {\n background: transparent;\n color: #e0e0e0;\n border-color: rgba(255, 255, 255, 0.2);\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #e0e0e0;\n}\n\n/* --- Styles complets pour le th\u00E8me sombre --- */\n\n/* Rend le fond du formulaire transparent pour h\u00E9riter de celui de la modale */\n.ynkap-dark .ynkap-payment {\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n border: none;\n}\n\n/* --- Boutons Secondaires (Annuler/Retour) --- */\n.ynkap-dark .ynkap-button-secondary {\n background: rgba(57, 53, 53, 0.938);\n color: #ffffff;\n /* border-color: rgb(255, 255, 255); */\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: linear-gradient(90deg, #2f2f3a 80%, #2e2e3c 100%);\n /* border-color: rgba(255, 255, 255, 0.4); */\n}\n\n/* Ic\u00F4nes des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #fffeff;\n}\n\n/* Bordure anim\u00E9e des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-border-svg rect {\n animation-name: border-shine-svg-dark;\n}\n\n@keyframes border-shine-svg-dark {\n 0% {\n stroke-dashoffset: 580;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n 60% {\n stroke: rgba(255, 255, 255, 0.9);\n filter: drop-shadow(0 0 12px #a8b2ffcc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n}\n"], dependencies: [{ kind: "directive", type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i7.CurrencyPipe, name: "currency" }, { kind: "pipe", type: FcfaPipe, name: "fcfa" }], animations: [fadeInOut, scaleIn] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-ynkap-payment', animations: [fadeInOut, scaleIn], template: "<div class=\"ynkap-payment\" [class.ynkap-dark]=\"theme === 'dark'\">\n \n\n <!-- Liste des m\u00E9thodes de paiement -->\n <div *ngIf=\"currentStep === 'methods'\" class=\"ynkap-methods\">\n <div class=\"ynkap-header-cool\">\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Logo Y-NKAP\" class=\"ynkap-logo-cool\" />\n <div class=\"ynkap-header-title\">\n <span class=\"ynkap-header-brand\">Y-NKAP</span>\n <span class=\"ynkap-header-pay\">Paiement s\u00E9curis\u00E9</span>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"ynkap-error-container\" [@fadeInOut] role=\"alert\" aria-live=\"assertive\">\n <div class=\"ynkap-error\">\n <span class=\"ynkap-error-icon-message\">\n <svg class=\"ynkap-error-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n <span class=\"ynkap-error-message\">{{ error }}</span>\n </span>\n <div *ngIf=\"retryInfo\" class=\"ynkap-retry-info\">\n <small>{{ retryInfo }}</small>\n </div>\n <button *ngIf=\"retryEnabled\"\n class=\"ynkap-button ynkap-button-secondary ynkap-retry-button ynkap-animated-border\"\n (click)=\"retryPayment()\"\n [disabled]=\"processing || retryCountdown > 0\"\n [attr.aria-label]=\"retryCountdown > 0 ? 'R\u00E9essayer dans ' + retryCountdown + ' secondes' : 'R\u00E9essayer le paiement'\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>\n </svg>\n <span *ngIf=\"retryCountdown > 0\">R\u00E9essayer ({{ retryCountdown }}s)</span>\n <span *ngIf=\"retryCountdown === 0\">R\u00E9essayer</span>\n </button>\n </div>\n </div>\n <div class=\"ynkap-payment-summary\" [@scaleIn]>\n <div class=\"ynkap-amount\">{{ amount | fcfa:currency }}</div>\n <div class=\"ynkap-description\">{{ description || 'S\u00E9lectionnez votre mode de paiement pr\u00E9f\u00E9r\u00E9' }}</div>\n </div>\n\n <div class=\"ynkap-methods-list\">\n <button *ngFor=\"let method of paymentMethods\" \n type=\"button\"\n class=\"ynkap-method-item\" \n [class.selected]=\"selectedMethod?.id === method.id\"\n [class.disabled]=\"method.status === 'disabled'\"\n (click)=\"method.status === 'enabled' && selectMethod(method)\"\n [attr.aria-pressed]=\"selectedMethod?.id === method.id\"\n [attr.aria-disabled]=\"method.status === 'disabled'\"\n [@scaleIn]\n [tabindex]=\"method.status === 'enabled' ? 0 : -1\"\n [attr.aria-label]=\"'S\u00E9lectionner ' + method.name\">\n <div class=\"ynkap-method-logo\">\n <img [src]=\"method.iconUrl\" [alt]=\"method.name\">\n </div>\n <div class=\"ynkap-method-info\">\n <div class=\"ynkap-method-name\">{{ method.name }}</div>\n <div class=\"ynkap-method-provider\">{{ method.provider }}</div>\n <div *ngIf=\"method.feePercentage || method.fixedFee\" class=\"ynkap-method-fee\">\n Frais: {{ method.feePercentage ? (method.feePercentage + '%') : (method.fixedFee | fcfa:currency) }}\n </div>\n </div>\n <svg class=\"ynkap-method-arrow\" viewBox=\"0 0 24 24\">\n <path d=\"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ynkap-actions\">\n <button type=\"button\" class=\"ynkap-button ynkap-button-secondary ynkap-animated-border\" (click)=\"cancel()\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>\n </svg>\n <span>Annuler</span>\n </button>\n </div>\n </div>\n\n <!-- Formulaire de paiement -->\n <div *ngIf=\"currentStep === 'form'\" class=\"ynkap-form\">\n <div class=\"ynkap-header-cool\">\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Logo Y-NKAP\" class=\"ynkap-logo-cool\" />\n <div class=\"ynkap-header-title\">\n <span class=\"ynkap-header-brand\">Y-NKAP</span>\n <span class=\"ynkap-header-pay\">Paiement s\u00E9curis\u00E9</span>\n </div>\n </div>\n <div *ngIf=\"error\" class=\"ynkap-error-container\" [@fadeInOut] role=\"alert\" aria-live=\"assertive\">\n <div class=\"ynkap-error\">\n <span class=\"ynkap-error-icon-message\">\n <svg class=\"ynkap-error-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n <span class=\"ynkap-error-message\">{{ error }}</span>\n </span>\n <div *ngIf=\"retryInfo\" class=\"ynkap-retry-info\">\n <small>{{ retryInfo }}</small>\n </div>\n <button *ngIf=\"retryEnabled\"\n class=\"ynkap-button ynkap-button-secondary ynkap-retry-button ynkap-animated-border\"\n (click)=\"retryPayment()\"\n [disabled]=\"processing || retryCountdown > 0\"\n [attr.aria-label]=\"retryCountdown > 0 ? 'R\u00E9essayer dans ' + retryCountdown + ' secondes' : 'R\u00E9essayer le paiement'\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>\n </svg>\n <span *ngIf=\"retryCountdown > 0\">R\u00E9essayer ({{ retryCountdown }}s)</span>\n <span *ngIf=\"retryCountdown === 0\">R\u00E9essayer</span>\n </button>\n </div>\n </div>\n\n <div class=\"ynkap-payment-summary\" [@scaleIn]>\n <div class=\"summary-logo-container\">\n <img [src]=\"selectedMethod?.iconUrl\" [alt]=\"selectedMethod?.name\" class=\"ynkap-method-mini-logo\">\n </div>\n <div class=\"summary-details-container\">\n <div class=\"ynkap-amount\">{{ amount | fcfa:currency }}</div>\n <div class=\"ynkap-description\" *ngIf=\"description\">{{ description }}</div>\n </div>\n </div>\n\n <form [formGroup]=\"paymentForm\" (ngSubmit)=\"processPayment()\" class=\"ynkap-payment-form\">\n <div class=\"ynkap-form-group\">\n <label for=\"phoneNumber\" class=\"ynkap-label\">\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z\"/>\n </svg>\n <span>Num\u00E9ro de t\u00E9l\u00E9phone</span>\n </label>\n <div class=\"ynkap-input-group\">\n <input \n type=\"tel\" \n id=\"phoneNumber\" \n formControlName=\"phoneNumber\" \n class=\"ynkap-input\" \n [class.ynkap-input-error]=\"paymentForm.get('phoneNumber')?.errors && paymentForm.get('phoneNumber')?.touched\"\n [placeholder]=\"getPhonePlaceholder()\"\n aria-required=\"true\"\n [attr.aria-invalid]=\"paymentForm.get('phoneNumber')?.invalid\"\n aria-describedby=\"phoneNumberError\"\n >\n <div class=\"ynkap-input-icon\">\n <svg *ngIf=\"!paymentForm.get('phoneNumber')?.errors\" class=\"ynkap-icon success\" viewBox=\"0 0 24 24\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n <svg *ngIf=\"paymentForm.get('phoneNumber')?.errors\" class=\"ynkap-icon error\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n </div>\n </div>\n <div class=\"ynkap-error-message\" *ngIf=\"paymentForm.get('phoneNumber')?.errors && paymentForm.get('phoneNumber')?.touched\" [@fadeInOut] id=\"phoneNumberError\" role=\"alert\">\n {{ getPhoneError() }}\n </div>\n </div>\n\n <div class=\"ynkap-actions\">\n <button type=\"button\" class=\"ynkap-button ynkap-button-secondary ynkap-animated-border\" (click)=\"goBack()\" aria-label=\"Retour \u00E0 la s\u00E9lection de m\u00E9thode\">\n <svg class=\"ynkap-border-svg\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" rx=\"12\" ry=\"12\"/>\n </svg>\n <svg class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z\"/>\n </svg>\n <span>Retour</span>\n </button>\n <button \n type=\"submit\" \n class=\"ynkap-button ynkap-button-primary\" \n [disabled]=\"!paymentForm.valid || processing\"\n [ngStyle]=\"primaryColor ? {'background': primaryColor, 'border-color': primaryColor} : {}\"\n [attr.aria-label]=\"'Payer ' + (amount | currency:currency:'symbol':'1.0-0')\"\n >\n <svg *ngIf=\"!processing\" class=\"ynkap-icon\" viewBox=\"0 0 24 24\">\n <path d=\"M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z\"/>\n </svg>\n <svg *ngIf=\"processing\" class=\"ynkap-icon spinner\" viewBox=\"0 0 24 24\">\n <path d=\"M12 6v3l4-4-4-4v-3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z\"/>\n </svg>\n <span *ngIf=\"!processing\">{{ payButtonText || ('Payer ' + (amount | fcfa:currency)) }}</span>\n <span *ngIf=\"processing\">Traitement en cours...</span>\n </button>\n </div>\n </form>\n </div>\n</div>\n\n<style>\n.ynkap-payment {\n max-width: 500px;\n margin: 0 auto;\n padding: 20px;\n font-family: system-ui, -apple-system, sans-serif;\n background: rgba(255,255,255,0.85);\n border-radius: 22px;\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.18), 0 1.5px 8px 0 rgba(0,123,255,0.10);\n backdrop-filter: blur(8px);\n border: 1.5px solid rgba(0,123,255,0.08);\n}\n\n.ynkap-header {\n display: flex;\n align-items: center;\n gap: 15px;\n margin-bottom: 30px;\n}\n\n.ynkap-logo {\n width: 40px;\n height: 40px;\n}\n\nh2, h3 {\n margin: 0;\n color: #333;\n}\n\nh2 {\n font-size: 20px;\n}\n\nh3 {\n margin-bottom: 20px;\n font-size: 18px;\n}\n\n.ynkap-payment-details {\n background: #f8f9fa;\n padding: 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-method-selected {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 10px;\n color: #666;\n}\n\n.ynkap-methods-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 20px;\n}\n\n.ynkap-method-item {\n display: flex;\n align-items: center;\n padding: 15px;\n border: 2px solid #e0e7ef;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: linear-gradient(90deg, #fff 80%, #f8fafc 100%);\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n position: relative;\n overflow: hidden;\n}\n\n.ynkap-method-item:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 16px 0 rgba(25,118,210,0.15);\n transform: translateY(-2px);\n}\n\n.ynkap-method-item.selected {\n border-color: #1976d2;\n background: linear-gradient(90deg, #e3f2fd 60%, #bbdefb 100%);\n box-shadow: 0 4px 20px 0 rgba(25,118,210,0.25);\n}\n\n.ynkap-method-item.selected::after {\n content: '\u2713';\n position: absolute;\n top: 8px;\n right: 12px;\n color: #1976d2;\n font-weight: bold;\n font-size: 16px;\n}\n\n.ynkap-method-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.ynkap-method-item.disabled:hover {\n transform: none;\n border-color: #e0e7ef;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n}\n\n.ynkap-method-logo {\n margin-right: 15px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-logo img {\n width: 48px;\n height: 48px;\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n padding: 4px;\n box-shadow: 0 2px 8px 0 rgba(0,0,0,0.1);\n}\n\n.mtn-badge,\n.orange-badge {\n display: inline-block;\n padding: 5px 10px;\n border-radius: 4px;\n font-weight: bold;\n font-size: 14px;\n}\n\n.mtn-badge {\n background: #ffd700;\n color: #000;\n}\n\n.orange-badge {\n background: #ff7900;\n color: white;\n}\n\n.ynkap-method-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ynkap-method-name {\n font-weight: 600;\n font-size: 16px;\n color: #2c3e50;\n margin-bottom: 2px;\n}\n\n.ynkap-method-provider {\n font-size: 14px;\n color: #64748b;\n font-weight: 500;\n}\n\n.ynkap-method-fee {\n font-size: 12px;\n color: #1976d2;\n font-weight: 500;\n margin-top: 4px;\n background: rgba(25,118,210,0.1);\n padding: 2px 8px;\n border-radius: 12px;\n display: inline-block;\n width: fit-content;\n}\n\n.ynkap-method-arrow {\n width: 20px;\n height: 20px;\n color: #64748b;\n transition: all 0.3s ease;\n flex-shrink: 0;\n}\n\n.ynkap-method-arrow path {\n fill: currentColor;\n}\n\n.ynkap-method-item:hover .ynkap-method-arrow {\n color: #1976d2;\n transform: translateX(4px);\n}\n\n.ynkap-method-item.selected .ynkap-method-arrow {\n color: #1976d2;\n}\n\n.ynkap-form-group {\n margin-bottom: 20px;\n}\n\n.ynkap-form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n}\n\n.ynkap-form-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 16px;\n}\n\n.ynkap-form-group input:focus {\n border-color: #007bff;\n outline: none;\n}\n\n.ynkap-error {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.ynkap-error-icon-message {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ynkap-actions {\n display: flex;\n gap: 10px;\n margin-top: 30px;\n}\n\n.ynkap-button-primary,\n.ynkap-button-secondary {\n padding: 12px 24px;\n border-radius: 4px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.ynkap-button-primary {\n background: #007bff;\n color: white;\n border: none;\n flex: 1;\n}\n\n.ynkap-button-primary:hover:not(:disabled) {\n background: #0056b3;\n}\n\n.ynkap-button-primary:disabled {\n background: #b3d7ff;\n cursor: not-allowed;\n}\n\n.ynkap-button-secondary {\n position: relative;\n background: linear-gradient(90deg, #fff 80%, #f4f8fc 100%);\n color: #222;\n border: 1.5px solid #e0e7ef;\n border-radius: 12px;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n font-weight: 600;\n letter-spacing: 0.5px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 10px 22px;\n overflow: hidden;\n z-index: 1;\n}\n\n.ynkap-button-secondary::before {\n content: '';\n position: absolute;\n top: -2px; left: -2px; right: -2px; bottom: -2px;\n border-radius: 14px;\n padding: 0;\n z-index: 2;\n pointer-events: none;\n background: \n linear-gradient(270deg, \n #1976d2 0%, \n #b3d1f7 20%, \n transparent 40%, \n transparent 60%, \n #b3d1f7 80%, \n #1976d2 100%);\n background-size: 400% 400%;\n background-repeat: no-repeat;\n filter: blur(0.5px);\n animation: border-trace 2.5s linear infinite;\n}\n\n@keyframes border-trace {\n 0% {\n background-position: 100% 0;\n }\n 25% {\n background-position: 100% 100%;\n }\n 50% {\n background-position: 0 100%;\n }\n 75% {\n background-position: 0 0;\n }\n 100% {\n background-position: 100% 0;\n }\n}\n\n.ynkap-button-secondary:hover {\n background: #f8f9fa;\n}\n\n.ynkap-method-item:focus {\n outline: 2px solid #1976d2;\n outline-offset: 2px;\n z-index: 2;\n}\n\n.ynkap-payment-summary {\n display: flex;\n align-items: center;\n gap: 18px;\n background: linear-gradient(90deg, #f8fafc 60%, #e3f0ff 100%);\n border-radius: 16px;\n box-shadow: 0 2px 12px 0 rgba(0,123,255,0.07);\n padding: 18px 18px 12px 18px;\n margin-bottom: 18px;\n}\n\n.summary-logo-container {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-mini-logo {\n height: 54px; /* Agrandit le logo */\n width: 54px; /* Garde le logo carr\u00E9 */\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.08);\n}\n\n.summary-details-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 4px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-animated-border {\n position: relative;\n overflow: visible;\n z-index: 1;\n}\n\n.ynkap-border-svg {\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 2;\n}\n\n.ynkap-border-svg rect {\n fill: none;\n stroke: #1976d2;\n stroke-width: 2.5;\n stroke-dasharray: 180 400;\n stroke-dashoffset: 0;\n filter: drop-shadow(0 0 6px #1976d2cc);\n animation: border-shine-svg 2.5s linear infinite;\n rx: 12;\n ry: 12;\n}\n\n@keyframes border-shine-svg {\n 0% {\n stroke-dashoffset: 580;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n 60% {\n stroke: #b3d1f7;\n filter: drop-shadow(0 0 12px #b3d1f7cc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n}\n\n.ynkap-header-brand {\n font-size: 1.7rem; /* Plus grand qu'avant */\n font-weight: bold;\n letter-spacing: 1px;\n}\n\n.ynkap-header-pay {\n font-size: 1.1rem;\n color: #4a6fa1;\n font-weight: 500;\n}\n\n/* --- Dark Theme Overrides for Method Items --- */\n.ynkap-dark .ynkap-method-item {\n background: linear-gradient(90deg, #2a2a3a 80%, #1e1e2d 100%);\n border-color: rgba(255,255,255,0.1);\n box-shadow: 0 2px 12px 0 rgba(0,0,0,0.4);\n}\n\n.ynkap-dark .ynkap-method-item:hover {\n background: linear-gradient(90deg, #3c3c4c 60%, #2a2a3a 100%);\n border-color: rgba(255,255,255,0.3);\n box-shadow: 0 4px 20px 0 rgba(0,123,255,0.2);\n}\n\n.ynkap-dark .ynkap-method-item.selected {\n background: linear-gradient(90deg, #1e3a8a 60%, #1e40af 100%);\n border-color: #3b82f6;\n box-shadow: 0 4px 24px 0 rgba(59,130,246,0.3);\n}\n\n.ynkap-dark .ynkap-method-item.selected::after {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-name {\n color: #f1f5f9;\n}\n\n.ynkap-dark .ynkap-method-provider {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-fee {\n color: #60a5fa;\n background: rgba(96,165,250,0.2);\n}\n\n.ynkap-dark .ynkap-method-arrow {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-item:hover .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-item.selected .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n/* --- Retry Information Styles --- */\n.ynkap-retry-info {\n margin-top: 8px;\n padding: 8px 12px;\n background: rgba(59, 130, 246, 0.1);\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n}\n\n.ynkap-retry-info small {\n color: #1e40af;\n font-size: 12px;\n font-weight: 500;\n}\n\n.ynkap-dark .ynkap-retry-info {\n background: rgba(96, 165, 250, 0.15);\n border-left-color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-retry-info small {\n color: #93c5fd;\n}\n\n/* --- Retry Button Disabled State --- */\n.ynkap-retry-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ynkap-retry-button:disabled .ynkap-border-svg rect {\n animation: none;\n stroke: #94a3b8;\n filter: none;\n}\n\n/* --- Dark Theme Overrides for Layout --- */\n.ynkap-dark .ynkap-header-cool,\n.ynkap-dark .ynkap-payment-summary {\n background: linear-gradient(135deg, #2b2b40, #1e1e2d);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n}\n\n/* Text colors */\n.ynkap-dark .ynkap-header-brand,\n.ynkap-dark .ynkap-amount {\n color: #ffffff;\n}\n\n.ynkap-dark .ynkap-header-pay,\n.ynkap-dark .ynkap-description {\n color: #a0a0b0;\n}\n\n/* Secondary Button (Cancel) */\n.ynkap-dark .ynkap-button-secondary {\n background: transparent;\n color: #e0e0e0;\n border-color: rgba(255, 255, 255, 0.2);\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #e0e0e0;\n}\n\n/* --- Styles complets pour le th\u00E8me sombre --- */\n\n/* Rend le fond du formulaire transparent pour h\u00E9riter de celui de la modale */\n.ynkap-dark .ynkap-payment {\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n border: none;\n}\n\n/* --- Boutons Secondaires (Annuler/Retour) --- */\n.ynkap-dark .ynkap-button-secondary {\n background: rgba(57, 53, 53, 0.938);\n color: #ffffff;\n /* border-color: rgb(255, 255, 255); */\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: linear-gradient(90deg, #2f2f3a 80%, #2e2e3c 100%);\n /* border-color: rgba(255, 255, 255, 0.4); */\n}\n\n/* Ic\u00F4nes des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #fffeff;\n}\n\n/* Bordure anim\u00E9e des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-border-svg rect {\n animation-name: border-shine-svg-dark;\n}\n\n@keyframes border-shine-svg-dark {\n 0% {\n stroke-dashoffset: 580;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n 60% {\n stroke: rgba(255, 255, 255, 0.9);\n filter: drop-shadow(0 0 12px #a8b2ffcc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n}\n</style>\n", styles: [":host{display:block;--primary-color: #007bff;--primary-hover: #0056b3;--error-color: #dc3545;--success-color: #28a745;--text-color: #2c3e50;--text-secondary: #6c757d;--border-color: #e0e0e0;--background-color: #ffffff;--background-secondary: #f8f9fa;--shadow-color: rgba(0, 0, 0, .1);--input-background: #ffffff;--primary-rgb: 0, 123, 255;position:relative;overflow:hidden;width:100%;height:100%}.ynkap-dark{--primary-color: #3699ff;--primary-hover: #187de4;--text-color: #ffffff;--text-secondary: #b5b5c3;--border-color: #2b2b40;--background-color: #1e1e2d;--background-secondary: #151521;--shadow-color: rgba(0, 0, 0, .3);--input-background: #151521;--primary-rgb: 54, 153, 255}.ynkap-payment{max-width:500px;margin:0 auto;padding:20px;font-family:system-ui,-apple-system,sans-serif;background:#ffffffd9;border-radius:22px;box-shadow:0 8px 32px #1f26872e,0 1.5px 8px #007bff1a;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1.5px solid rgba(0,123,255,.08)}@keyframes gradientFlow{0%{background-position:0% 50%;opacity:.4}50%{background-position:100% 50%;opacity:.7}to{background-position:0% 50%;opacity:.4}}.ynkap-payment:before{content:\"\";position:absolute;inset:-50%;background:linear-gradient(135deg,rgba(var(--primary-rgb),.08),rgba(var(--primary-rgb),.03),#ffffff0d,rgba(var(--primary-rgb),.03),rgba(var(--primary-rgb),.08));background-size:400% 400%;animation:gradientFlow 8s ease infinite;z-index:-3;transform:scale(1.5)}@keyframes waveEffect{0%{transform:translate(-100%) translateY(-50%) rotate(-45deg)}50%{transform:translate(0) translateY(-50%) rotate(-45deg)}to{transform:translate(100%) translateY(-50%) rotate(-45deg)}}.ynkap-payment:after{content:\"\";position:absolute;left:0;top:50%;width:200%;height:200%;background:linear-gradient(90deg,transparent 0%,rgba(var(--primary-rgb),.1) 50%,transparent 100%);animation:waveEffect 4s ease-in-out infinite;z-index:-2}.ynkap-payment .gradient-layer{content:\"\";position:absolute;inset:0;background:linear-gradient(135deg,var(--background-color) 0%,rgba(var(--primary-rgb),.05) 100%);z-index:-1;opacity:.7}@keyframes floatingDot1{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(-20px,-30px) scale(1.2);opacity:.6}75%{transform:translate(20px,-60px) scale(.8);opacity:.4}}@keyframes floatingDot2{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(30px,-40px) scale(1.4);opacity:.5}75%{transform:translate(-10px,-50px) scale(.9);opacity:.3}}@keyframes floatingDot3{0%,to{transform:translate(0) scale(1);opacity:0}25%{transform:translate(-15px,-45px) scale(1.3);opacity:.7}75%{transform:translate(25px,-35px) scale(.7);opacity:.4}}.floating-dot{position:absolute;width:6px;height:6px;border-radius:50%;background:rgba(var(--primary-rgb),.6);box-shadow:0 0 10px 2px rgba(var(--primary-rgb),.3),0 0 20px 4px rgba(var(--primary-rgb),.1);pointer-events:none;z-index:1}.floating-dot:nth-child(1){bottom:20%;left:20%;animation:floatingDot1 6s ease-in-out infinite}.floating-dot:nth-child(2){bottom:30%;right:25%;animation:floatingDot2 8s ease-in-out infinite}.floating-dot:nth-child(3){bottom:25%;left:40%;animation:floatingDot3 7s ease-in-out infinite}.ynkap-dark .ynkap-payment{background:linear-gradient(135deg,#1e1e2df2,#141423fa);box-shadow:0 10px 30px -10px #0006,0 0 0 1px #ffffff1a inset}.ynkap-dark .gradient-layer{background:linear-gradient(135deg,rgba(var(--primary-rgb),.15),rgba(var(--primary-rgb),.05));opacity:.3}@keyframes sparkle{0%,to{transform:scale(0) rotate(0);opacity:0}50%{transform:scale(1) rotate(180deg);opacity:.8}}.sparkle{position:absolute;width:3px;height:3px;background:rgba(var(--primary-rgb),.8);clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%);pointer-events:none;z-index:1}.sparkle:nth-child(1){top:20%;left:30%;animation:sparkle 4s infinite}.sparkle:nth-child(2){top:40%;right:20%;animation:sparkle 5s infinite 1s}.sparkle:nth-child(3){bottom:30%;left:40%;animation:sparkle 4.5s infinite .5s}@media (max-width: 480px){.sparkle{display:none}.floating-dot{width:4px;height:4px}}.ynkap-header{display:flex;align-items:center;gap:8px;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border-color)}.ynkap-logo-container{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:var(--background-secondary);border-radius:8px;padding:4px}.ynkap-logo{width:100%;height:auto}.ynkap-title{font-size:1rem;font-weight:600;margin:0;color:var(--text-color)}.ynkap-error-container{margin-bottom:20px}.ynkap-error{display:flex;justify-content:space-between;align-items:center;gap:12px;background:#dc35451a;border-left:4px solid var(--error-color);padding:12px 16px;border-radius:8px}.ynkap-error-icon{width:24px;height:24px;fill:var(--error-color);flex-shrink:0}.ynkap-error-message{color:var(--error-color);font-size:.9rem;line-height:1.5}.ynkap-payment-summary{background:linear-gradient(90deg,#f8fafc 60%,#e3f0ff);border-radius:16px;box-shadow:0 2px 12px #007bff12;padding:18px 18px 12px;margin-bottom:18px}.ynkap-amount{font-size:1.5rem;font-weight:700;margin-bottom:2px;background:linear-gradient(135deg,var(--text-color) 0%,rgba(var(--primary-rgb),.8) 100%);-webkit-background-clip:text;background-clip:text;color:transparent}.ynkap-description{font-size:.8rem;color:var(--text-secondary)}.ynkap-methods-list{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.ynkap-method-item{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(135deg,var(--background-secondary) 0%,rgba(var(--primary-rgb),.03) 100%);border:1px solid var(--border-color);border-radius:14px;cursor:pointer;transition:box-shadow .2s,transform .2s,background .2s;position:relative;overflow:hidden;box-shadow:0 1.5px 8px #007bff12;background:linear-gradient(90deg,#fff 80%,#f0f6ff)}.ynkap-method-item:hover{box-shadow:0 4px 16px #007bff21;background:linear-gradient(90deg,#e3f0ff 60%,#fff);transform:translateY(-2px) scale(1.03)}.ynkap-method-item:after{content:\"\";position:absolute;inset:0;background:radial-gradient(circle at var(--x, 50%) var(--y, 50%),rgba(var(--primary-rgb),.1) 0%,transparent 50%);opacity:0;transition:opacity .3s}.ynkap-method-item:hover:after{opacity:1}.ynkap-method-item.selected{border-color:var(--primary-color);background:#007bff0d}.ynkap-method-logo{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:#fff;border-radius:6px;padding:4px;composes:shine-hover}.ynkap-method-logo img{width:100%;height:auto}.ynkap-method-info{flex:1;text-align:left}.ynkap-method-name{font-size:.9rem;font-weight:600;margin-bottom:1px;color:var(--text-color);text-align:left}.ynkap-method-provider{font-size:.75rem;color:var(--text-secondary);text-align:left}.ynkap-method-arrow{width:24px;height:24px;fill:var(--text-secondary);flex-shrink:0}.ynkap-selected-method{display:flex;align-items:center;gap:12px;font-size:16px;font-weight:500}.ynkap-method-mini-logo{height:32px;width:auto;border-radius:4px}.ynkap-payment-form{margin-top:20px}.ynkap-form-group{margin-bottom:20px}.ynkap-label{display:block;margin-bottom:8px;color:var(--text-secondary);font-size:.9rem}.ynkap-label i{margin-right:8px}.ynkap-input-group{position:relative;overflow:hidden}.ynkap-input-group:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.2) 40%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 60%,rgba(255,255,255,0) 80%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.ynkap-input-group:focus-within:before{animation:shineRight 1s ease-in-out forwards}.ynkap-input-group:not(:focus-within):before{animation:shineLeft 1s ease-in-out forwards}.ynkap-input{width:100%;padding:16px 40px 16px 16px;font-size:1rem;border:1px solid var(--border-color);border-radius:12px;background:linear-gradient(135deg,var(--input-background) 0%,rgba(var(--primary-rgb),.02) 100%);color:var(--text-color);transition:all .3s cubic-bezier(.4,0,.2,1)}.ynkap-input::placeholder{color:var(--text-secondary);opacity:.7;font-size:.85rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ynkap-input:focus{outline:none;border-color:rgba(var(--primary-rgb),.3);box-shadow:0 5px 15px -5px rgba(var(--primary-rgb),.2),0 0 0 1px rgba(var(--primary-rgb),.1) inset;background:linear-gradient(135deg,var(--input-background) 0%,rgba(var(--primary-rgb),.05) 100%)}.ynkap-input-error{border-color:var(--error-color)}.ynkap-input-error:focus{box-shadow:0 0 0 3px #dc35451a}.ynkap-input-icon{position:absolute;right:12px;top:50%;transform:translateY(-50%);width:20px;height:20px;display:flex;align-items:center;justify-content:center;pointer-events:none}.ynkap-input-icon .success{fill:var(--success-color)}.ynkap-input-icon .error{fill:var(--error-color)}.ynkap-actions{display:flex;gap:6px;margin-top:12px}.ynkap-button{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:8px 16px;font-size:.85rem;font-weight:500;border-radius:8px;cursor:pointer;border:none;outline:none;position:relative;overflow:hidden;transition:all .2s ease-out}.ynkap-button i{font-size:1rem}@keyframes shineRight{0%{transform:translate(-100%) skew(-15deg);opacity:0}50%{opacity:.5}to{transform:translate(100%) skew(-15deg);opacity:0}}@keyframes shineLeft{0%{transform:translate(100%) skew(-15deg);opacity:0}50%{opacity:.5}to{transform:translate(-100%) skew(-15deg);opacity:0}}.shine-hover{position:relative;overflow:hidden}.shine-hover:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 25%,rgba(var(--primary-rgb),.2) 45%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 55%,rgba(255,255,255,0) 75%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.shine-hover:hover:before{animation:shineRight .8s ease-out forwards}.shine-hover:not(:hover):before{animation:shineLeft .8s ease-out forwards}.ynkap-button:before{display:none}.ynkap-button-primary{background:linear-gradient(135deg,var(--primary-color) 0%,rgba(var(--primary-rgb),.8) 100%);color:#fff;box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 0 1px #ffffff1a inset;position:relative;z-index:1}@keyframes pulse{0%{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 rgba(var(--primary-rgb),.4)}70%{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 0 15px rgba(var(--primary-rgb),0)}to{box-shadow:0 8px 16px -4px rgba(var(--primary-rgb),.3),0 0 rgba(var(--primary-rgb),0)}}@keyframes particleAnimation{0%{transform:translate(0) rotate(0);opacity:0}50%{opacity:.5}to{transform:translate(100px,-100px) rotate(360deg);opacity:0}}.ynkap-button-primary:after{content:\"\";position:absolute;inset:-50%;background:radial-gradient(circle at center,#fffc,#fff0 50%);opacity:0;transition:opacity .3s;transform:scale(.5);filter:blur(20px)}.ynkap-button-primary:hover{transform:translateY(-2px);background:linear-gradient(135deg,var(--primary-hover) 0%,rgba(var(--primary-rgb),.9) 100%);animation:pulse 2s infinite}.ynkap-button-primary:hover:after{opacity:.5;transform:scale(1)}.ynkap-button-primary:active{transform:translateY(0)}.ynkap-button-primary:hover:before{content:\"\";position:absolute;width:4px;height:4px;border-radius:50%;background:#fff;box-shadow:0 0 10px 2px #fffc,0 0 20px 4px rgba(var(--primary-rgb),.4);animation:particleAnimation 1s ease-out infinite}.ynkap-button-primary:disabled{opacity:.7;cursor:not-allowed;animation:none;transform:none}.ynkap-button-primary:disabled:before,.ynkap-button-primary:disabled:after{display:none}.ynkap-button-secondary{background:linear-gradient(90deg,#fff 80%,#f4f8fc);color:#222;border:1.5px solid #e0e7ef;border-radius:12px;box-shadow:0 2px 8px #007bff0f;font-weight:600;letter-spacing:.5px;transition:all .3s cubic-bezier(.4,0,.2,1);padding:10px 22px}.ynkap-button-secondary:focus{outline:2px solid #1976d2;outline-offset:2px;box-shadow:0 0 0 3px #1976d226}.ynkap-icon{width:16px;height:16px;fill:currentColor}.spinner{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.ynkap-methods,.ynkap-form{width:100%;position:relative}.ynkap-methods.active,.ynkap-form.active{display:block}.ynkap-methods.inactive,.ynkap-form.inactive{display:none}@media (max-width: 480px){:host{position:fixed;inset:0;width:100vw;height:100vh}.ynkap-payment{border-radius:0;padding:10px}.ynkap-header{margin-bottom:12px;padding-bottom:8px}.ynkap-logo-container{width:28px;height:28px;padding:4px}.ynkap-title{font-size:1rem}.ynkap-amount{font-size:1.4rem}.ynkap-payment-summary{padding:12px;margin-bottom:12px}.ynkap-method-item{padding:8px 10px;gap:8px}.ynkap-method-logo{width:28px;height:28px;padding:4px}.ynkap-method-name{font-size:.9rem}.ynkap-method-provider{font-size:.75rem}.ynkap-form,.ynkap-payment-form{flex:1;display:flex;flex-direction:column}.ynkap-actions{margin-top:auto;padding-top:12px}.ynkap-button{padding:8px 12px;font-size:.8rem}.ynkap-button-primary:hover{transform:none;animation:pulse 2.5s infinite}.ynkap-input{padding:12px 32px 12px 12px;font-size:.9rem}.ynkap-input::placeholder{font-size:.75rem}.ynkap-input-icon{right:8px;width:16px;height:16px}.ynkap-error-message{font-size:.8rem}.ynkap-selected-method{gap:8px}.ynkap-method-mini-logo{width:20px;height:20px}.ynkap-methods,.ynkap-form{height:auto;min-height:calc(100vh - 180px);overflow-y:auto;-webkit-overflow-scrolling:touch}}.ynkap-dark .shine-hover:before{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 25%,rgba(var(--primary-rgb),.1) 45%,rgba(255,255,255,.15) 50%,rgba(var(--primary-rgb),.1) 55%,rgba(255,255,255,0) 75%,transparent 100%)}.ynkap-button:disabled:before,.ynkap-input-group.disabled:before{display:none}.ynkap-payment-summary,.ynkap-selected-method,.ynkap-method-logo{composes:shine-hover}.ynkap-method-item:hover,.ynkap-button-primary:hover:not(:disabled),.ynkap-button-secondary:hover{transform:translateY(-1px);transition:transform .2s ease}.ynkap-method-item:active,.ynkap-button-primary:active:not(:disabled),.ynkap-button-secondary:active{transform:translateY(0)}.ynkap-method-item:before,.ynkap-button:before,.ynkap-input-group:before,.ynkap-logo-container:before,.ynkap-method-logo:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.2) 40%,rgba(255,255,255,.3) 50%,rgba(var(--primary-rgb),.2) 60%,rgba(255,255,255,0) 80%,transparent 100%);transform:translate(-100%) skew(-15deg);pointer-events:none;z-index:1}.ynkap-method-item:hover:before,.ynkap-button:hover:before,.ynkap-input-group:hover:before,.ynkap-logo-container:hover:before,.ynkap-method-logo:hover:before{animation:shineRight .7s ease-out forwards}.ynkap-method-item:not(:hover):before,.ynkap-button:not(:hover):before,.ynkap-input-group:not(:hover):before,.ynkap-logo-container:not(:hover):before,.ynkap-method-logo:not(:hover):before{animation:shineLeft .7s ease-out forwards}.ynkap-dark .ynkap-method-item:before,.ynkap-dark .ynkap-button:before,.ynkap-dark .ynkap-input-group:before,.ynkap-dark .ynkap-logo-container:before,.ynkap-dark .ynkap-method-logo:before{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,0) 20%,rgba(var(--primary-rgb),.15) 40%,rgba(255,255,255,.2) 50%,rgba(var(--primary-rgb),.15) 60%,rgba(255,255,255,0) 80%,transparent 100%)}@media (hover: hover){.ynkap-method-item:hover{--x: var(--mouse-x, 50%);--y: var(--mouse-y, 50%)}}.ynkap-dark .ynkap-button-secondary{background:#ffffff0d;border-color:#ffffff1a}.ynkap-dark .ynkap-button-secondary:hover{background:#ffffff14;border-color:#fff3}.ynkap-dark .ynkap-button-primary:after{background:radial-gradient(circle at center,#fff9,#fff0 50%)}.ynkap-method-item.disabled{opacity:.5;cursor:not-allowed;background:var(--background-secondary)}.ynkap-method-item.disabled:hover{transform:none;box-shadow:none}.ynkap-method-fee{font-size:.75rem;color:var(--text-secondary);margin-top:4px}.ynkap-retry-button{margin-top:8px;background:var(--background-secondary);border:1px solid var(--border-color);padding:6px 12px;font-size:.8rem}.ynkap-retry-button:hover:not(:disabled){background:linear-gradient(135deg,var(--background-secondary) 0%,rgba(var(--primary-rgb),.05) 100%);transform:translateY(-1px);box-shadow:0 4px 12px -2px rgba(var(--primary-rgb),.15)}.ynkap-retry-button:disabled{opacity:.5;cursor:not-allowed}.ynkap-header-cool{display:flex;align-items:center;justify-content:center;gap:18px;background:linear-gradient(90deg,#f8fafc 60%,#e3f0ff);border-radius:14px;box-shadow:0 2px 12px #007bff12;padding:18px 0 14px;margin-bottom:18px;position:relative;overflow:hidden}.ynkap-logo-cool{width:54px;height:54px;border-radius:12px;box-shadow:0 2px 8px #00000012;background:#fff;object-fit:contain}.ynkap-header-title{display:flex;flex-direction:column;align-items:flex-start;gap:2px}.ynkap-header-brand{font-size:1.35rem;font-weight:700;letter-spacing:2px;color:#1976d2;text-shadow:0 1px 2px #fff,0 2px 8px #e3f0ff}.ynkap-header-pay{font-size:.95rem;color:#2c3e50;opacity:.85;font-weight:500;letter-spacing:1px}\n", "\n.ynkap-payment {\n max-width: 500px;\n margin: 0 auto;\n padding: 20px;\n font-family: system-ui, -apple-system, sans-serif;\n background: rgba(255,255,255,0.85);\n border-radius: 22px;\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.18), 0 1.5px 8px 0 rgba(0,123,255,0.10);\n backdrop-filter: blur(8px);\n border: 1.5px solid rgba(0,123,255,0.08);\n}\n\n.ynkap-header {\n display: flex;\n align-items: center;\n gap: 15px;\n margin-bottom: 30px;\n}\n\n.ynkap-logo {\n width: 40px;\n height: 40px;\n}\n\nh2, h3 {\n margin: 0;\n color: #333;\n}\n\nh2 {\n font-size: 20px;\n}\n\nh3 {\n margin-bottom: 20px;\n font-size: 18px;\n}\n\n.ynkap-payment-details {\n background: #f8f9fa;\n padding: 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-method-selected {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 10px;\n color: #666;\n}\n\n.ynkap-methods-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-bottom: 20px;\n}\n\n.ynkap-method-item {\n display: flex;\n align-items: center;\n padding: 15px;\n border: 2px solid #e0e7ef;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: linear-gradient(90deg, #fff 80%, #f8fafc 100%);\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n position: relative;\n overflow: hidden;\n}\n\n.ynkap-method-item:hover {\n border-color: #1976d2;\n box-shadow: 0 4px 16px 0 rgba(25,118,210,0.15);\n transform: translateY(-2px);\n}\n\n.ynkap-method-item.selected {\n border-color: #1976d2;\n background: linear-gradient(90deg, #e3f2fd 60%, #bbdefb 100%);\n box-shadow: 0 4px 20px 0 rgba(25,118,210,0.25);\n}\n\n.ynkap-method-item.selected::after {\n content: '\u2713';\n position: absolute;\n top: 8px;\n right: 12px;\n color: #1976d2;\n font-weight: bold;\n font-size: 16px;\n}\n\n.ynkap-method-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: #f5f5f5;\n}\n\n.ynkap-method-item.disabled:hover {\n transform: none;\n border-color: #e0e7ef;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n}\n\n.ynkap-method-logo {\n margin-right: 15px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-logo img {\n width: 48px;\n height: 48px;\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n padding: 4px;\n box-shadow: 0 2px 8px 0 rgba(0,0,0,0.1);\n}\n\n.mtn-badge,\n.orange-badge {\n display: inline-block;\n padding: 5px 10px;\n border-radius: 4px;\n font-weight: bold;\n font-size: 14px;\n}\n\n.mtn-badge {\n background: #ffd700;\n color: #000;\n}\n\n.orange-badge {\n background: #ff7900;\n color: white;\n}\n\n.ynkap-method-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ynkap-method-name {\n font-weight: 600;\n font-size: 16px;\n color: #2c3e50;\n margin-bottom: 2px;\n}\n\n.ynkap-method-provider {\n font-size: 14px;\n color: #64748b;\n font-weight: 500;\n}\n\n.ynkap-method-fee {\n font-size: 12px;\n color: #1976d2;\n font-weight: 500;\n margin-top: 4px;\n background: rgba(25,118,210,0.1);\n padding: 2px 8px;\n border-radius: 12px;\n display: inline-block;\n width: fit-content;\n}\n\n.ynkap-method-arrow {\n width: 20px;\n height: 20px;\n color: #64748b;\n transition: all 0.3s ease;\n flex-shrink: 0;\n}\n\n.ynkap-method-arrow path {\n fill: currentColor;\n}\n\n.ynkap-method-item:hover .ynkap-method-arrow {\n color: #1976d2;\n transform: translateX(4px);\n}\n\n.ynkap-method-item.selected .ynkap-method-arrow {\n color: #1976d2;\n}\n\n.ynkap-form-group {\n margin-bottom: 20px;\n}\n\n.ynkap-form-group label {\n display: block;\n margin-bottom: 8px;\n color: #333;\n}\n\n.ynkap-form-group input {\n width: 100%;\n padding: 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 16px;\n}\n\n.ynkap-form-group input:focus {\n border-color: #007bff;\n outline: none;\n}\n\n.ynkap-error {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.ynkap-error-icon-message {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ynkap-actions {\n display: flex;\n gap: 10px;\n margin-top: 30px;\n}\n\n.ynkap-button-primary,\n.ynkap-button-secondary {\n padding: 12px 24px;\n border-radius: 4px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.ynkap-button-primary {\n background: #007bff;\n color: white;\n border: none;\n flex: 1;\n}\n\n.ynkap-button-primary:hover:not(:disabled) {\n background: #0056b3;\n}\n\n.ynkap-button-primary:disabled {\n background: #b3d7ff;\n cursor: not-allowed;\n}\n\n.ynkap-button-secondary {\n position: relative;\n background: linear-gradient(90deg, #fff 80%, #f4f8fc 100%);\n color: #222;\n border: 1.5px solid #e0e7ef;\n border-radius: 12px;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.06);\n font-weight: 600;\n letter-spacing: 0.5px;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 10px 22px;\n overflow: hidden;\n z-index: 1;\n}\n\n.ynkap-button-secondary::before {\n content: '';\n position: absolute;\n top: -2px; left: -2px; right: -2px; bottom: -2px;\n border-radius: 14px;\n padding: 0;\n z-index: 2;\n pointer-events: none;\n background: \n linear-gradient(270deg, \n #1976d2 0%, \n #b3d1f7 20%, \n transparent 40%, \n transparent 60%, \n #b3d1f7 80%, \n #1976d2 100%);\n background-size: 400% 400%;\n background-repeat: no-repeat;\n filter: blur(0.5px);\n animation: border-trace 2.5s linear infinite;\n}\n\n@keyframes border-trace {\n 0% {\n background-position: 100% 0;\n }\n 25% {\n background-position: 100% 100%;\n }\n 50% {\n background-position: 0 100%;\n }\n 75% {\n background-position: 0 0;\n }\n 100% {\n background-position: 100% 0;\n }\n}\n\n.ynkap-button-secondary:hover {\n background: #f8f9fa;\n}\n\n.ynkap-method-item:focus {\n outline: 2px solid #1976d2;\n outline-offset: 2px;\n z-index: 2;\n}\n\n.ynkap-payment-summary {\n display: flex;\n align-items: center;\n gap: 18px;\n background: linear-gradient(90deg, #f8fafc 60%, #e3f0ff 100%);\n border-radius: 16px;\n box-shadow: 0 2px 12px 0 rgba(0,123,255,0.07);\n padding: 18px 18px 12px 18px;\n margin-bottom: 18px;\n}\n\n.summary-logo-container {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.ynkap-method-mini-logo {\n height: 54px; /* Agrandit le logo */\n width: 54px; /* Garde le logo carr\u00E9 */\n object-fit: contain;\n border-radius: 8px;\n background: #fff;\n box-shadow: 0 2px 8px 0 rgba(0,123,255,0.08);\n}\n\n.summary-details-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 4px;\n}\n\n.ynkap-amount {\n font-size: 1.2rem;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 0;\n}\n\n.ynkap-description {\n color: #666;\n font-size: 0.95rem;\n}\n\n.ynkap-animated-border {\n position: relative;\n overflow: visible;\n z-index: 1;\n}\n\n.ynkap-border-svg {\n position: absolute;\n top: 0; left: 0;\n width: 100%; height: 100%;\n pointer-events: none;\n z-index: 2;\n}\n\n.ynkap-border-svg rect {\n fill: none;\n stroke: #1976d2;\n stroke-width: 2.5;\n stroke-dasharray: 180 400;\n stroke-dashoffset: 0;\n filter: drop-shadow(0 0 6px #1976d2cc);\n animation: border-shine-svg 2.5s linear infinite;\n rx: 12;\n ry: 12;\n}\n\n@keyframes border-shine-svg {\n 0% {\n stroke-dashoffset: 580;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n 60% {\n stroke: #b3d1f7;\n filter: drop-shadow(0 0 12px #b3d1f7cc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: #1976d2;\n filter: drop-shadow(0 0 6px #1976d2cc);\n }\n}\n\n.ynkap-header-brand {\n font-size: 1.7rem; /* Plus grand qu'avant */\n font-weight: bold;\n letter-spacing: 1px;\n}\n\n.ynkap-header-pay {\n font-size: 1.1rem;\n color: #4a6fa1;\n font-weight: 500;\n}\n\n/* --- Dark Theme Overrides for Method Items --- */\n.ynkap-dark .ynkap-method-item {\n background: linear-gradient(90deg, #2a2a3a 80%, #1e1e2d 100%);\n border-color: rgba(255,255,255,0.1);\n box-shadow: 0 2px 12px 0 rgba(0,0,0,0.4);\n}\n\n.ynkap-dark .ynkap-method-item:hover {\n background: linear-gradient(90deg, #3c3c4c 60%, #2a2a3a 100%);\n border-color: rgba(255,255,255,0.3);\n box-shadow: 0 4px 20px 0 rgba(0,123,255,0.2);\n}\n\n.ynkap-dark .ynkap-method-item.selected {\n background: linear-gradient(90deg, #1e3a8a 60%, #1e40af 100%);\n border-color: #3b82f6;\n box-shadow: 0 4px 24px 0 rgba(59,130,246,0.3);\n}\n\n.ynkap-dark .ynkap-method-item.selected::after {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-name {\n color: #f1f5f9;\n}\n\n.ynkap-dark .ynkap-method-provider {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-fee {\n color: #60a5fa;\n background: rgba(96,165,250,0.2);\n}\n\n.ynkap-dark .ynkap-method-arrow {\n color: #cbd5e1;\n}\n\n.ynkap-dark .ynkap-method-item:hover .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-method-item.selected .ynkap-method-arrow {\n color: #60a5fa;\n}\n\n/* --- Retry Information Styles --- */\n.ynkap-retry-info {\n margin-top: 8px;\n padding: 8px 12px;\n background: rgba(59, 130, 246, 0.1);\n border-radius: 8px;\n border-left: 3px solid #3b82f6;\n}\n\n.ynkap-retry-info small {\n color: #1e40af;\n font-size: 12px;\n font-weight: 500;\n}\n\n.ynkap-dark .ynkap-retry-info {\n background: rgba(96, 165, 250, 0.15);\n border-left-color: #60a5fa;\n}\n\n.ynkap-dark .ynkap-retry-info small {\n color: #93c5fd;\n}\n\n/* --- Retry Button Disabled State --- */\n.ynkap-retry-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ynkap-retry-button:disabled .ynkap-border-svg rect {\n animation: none;\n stroke: #94a3b8;\n filter: none;\n}\n\n/* --- Dark Theme Overrides for Layout --- */\n.ynkap-dark .ynkap-header-cool,\n.ynkap-dark .ynkap-payment-summary {\n background: linear-gradient(135deg, #2b2b40, #1e1e2d);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n}\n\n/* Text colors */\n.ynkap-dark .ynkap-header-brand,\n.ynkap-dark .ynkap-amount {\n color: #ffffff;\n}\n\n.ynkap-dark .ynkap-header-pay,\n.ynkap-dark .ynkap-description {\n color: #a0a0b0;\n}\n\n/* Secondary Button (Cancel) */\n.ynkap-dark .ynkap-button-secondary {\n background: transparent;\n color: #e0e0e0;\n border-color: rgba(255, 255, 255, 0.2);\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: rgba(255, 255, 255, 0.1);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #e0e0e0;\n}\n\n/* --- Styles complets pour le th\u00E8me sombre --- */\n\n/* Rend le fond du formulaire transparent pour h\u00E9riter de celui de la modale */\n.ynkap-dark .ynkap-payment {\n background: transparent;\n box-shadow: none;\n backdrop-filter: none;\n border: none;\n}\n\n/* --- Boutons Secondaires (Annuler/Retour) --- */\n.ynkap-dark .ynkap-button-secondary {\n background: rgba(57, 53, 53, 0.938);\n color: #ffffff;\n /* border-color: rgb(255, 255, 255); */\n}\n\n.ynkap-dark .ynkap-button-secondary:hover {\n background: linear-gradient(90deg, #2f2f3a 80%, #2e2e3c 100%);\n /* border-color: rgba(255, 255, 255, 0.4); */\n}\n\n/* Ic\u00F4nes des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-icon path {\n fill: #fffeff;\n}\n\n/* Bordure anim\u00E9e des boutons secondaires */\n.ynkap-dark .ynkap-button-secondary .ynkap-border-svg rect {\n animation-name: border-shine-svg-dark;\n}\n\n@keyframes border-shine-svg-dark {\n 0% {\n stroke-dashoffset: 580;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n 60% {\n stroke: rgba(255, 255, 255, 0.9);\n filter: drop-shadow(0 0 12px #a8b2ffcc);\n }\n 100% {\n stroke-dashoffset: 0;\n stroke: rgba(255, 255, 255, 0.5);\n filter: drop-shadow(0 0 6px #6a7cff99);\n }\n}\n"] }]
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }, { type: PaymentService }, { type: AuthService }, { type: ErrorHandlingService }, { type: RetryService }, { type: LogoService }]; }, propDecorators: { amount: [{
type: Input
}], currency: [{
type: Input
}], merchantReference: [{
type: Input
}], theme: [{
type: Input
}], description: [{
type: Input
}], successUrl: [{
type: Input
}], cancelUrl: [{
type: Input
}], webhookUrl: [{
type: Input
}], logoUrl: [{
type: Input
}], primaryColor: [{
type: Input
}], payButtonText: [{
type: Input
}], paymentSuccess: [{
type: Output
}], paymentError: [{
type: Output
}], cancelled: [{
type: Output
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}] } });
/**
* Module partagé contenant les pipes et utilitaires communs
*/
class SharedModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: SharedModule, declarations: [FcfaPipe], imports: [CommonModule], exports: [FcfaPipe] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SharedModule, providers: [
LogoService
], imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SharedModule, decorators: [{
type: NgModule,
args: [{
declarations: [
FcfaPipe
],
imports: [
CommonModule
],
exports: [
FcfaPipe
],
providers: [
LogoService
]
}]
}] });
class PaymentModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: PaymentModule, declarations: [PaymentComponent], imports: [CommonModule,
FormsModule,
ReactiveFormsModule,
SharedModule], exports: [PaymentComponent,
CommonModule,
FormsModule,
ReactiveFormsModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentModule, imports: [CommonModule,
FormsModule,
ReactiveFormsModule,
SharedModule, CommonModule,
FormsModule,
ReactiveFormsModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PaymentModule, decorators: [{
type: NgModule,
args: [{
declarations: [
PaymentComponent
],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
SharedModule
],
exports: [
PaymentComponent,
CommonModule,
FormsModule,
ReactiveFormsModule
]
}]
}] });
class ErrorHandlingComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ErrorHandlingComponent, selector: "lib-error-handling", ngImport: i0, template: "<p>error-handling works!</p>\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-error-handling', template: "<p>error-handling works!</p>\n" }]
}] });
class ErrorHandlingModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingModule, declarations: [ErrorHandlingComponent], imports: [CommonModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingModule, decorators: [{
type: NgModule,
args: [{
declarations: [
ErrorHandlingComponent
],
imports: [
CommonModule
]
}]
}] });
/**
* Service pour gérer la stabilité des modals et éviter les problèmes de détection de changements
*/
class ModalStabilityService {
constructor(ngZone) {
this.ngZone = ngZone;
}
/**
* Ouvre un modal de manière stable
* @param callback Fonction qui change l'état du modal
* @param cdr ChangeDetectorRef du composant
*/
openModalStable(callback, cdr) {
// Force l'exécution dans la zone Angular pour les applications tierces
this.ngZone.run(() => {
callback();
// Détection immédiate
cdr.detectChanges();
// Détection après micro-tick pour les applications tierces
Promise.resolve().then(() => {
cdr.detectChanges();
});
// Détection de sécurité pour les cas complexes d'applications tierces
setTimeout(() => {
cdr.detectChanges();
}, 16); // 1 frame à 60fps
});
}
/**
* Ferme un modal de manière stable
* @param callback Fonction qui change l'état du modal
* @param cdr ChangeDetectorRef du composant
*/
closeModalStable(callback, cdr) {
this.ngZone.run(() => {
callback();
cdr.detectChanges();
});
}
/**
* Exécute une action liée au modal de manière stable
* @param callback Fonction à exécuter
* @param cdr ChangeDetectorRef du composant
*/
executeModalAction(callback, cdr) {
this.ngZone.run(() => {
callback();
cdr.detectChanges();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalStabilityService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalStabilityService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ModalStabilityService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
class YnkapPayButtonComponent {
constructor(logoService, cdr, ngZone, modalStability) {
this.logoService = logoService;
this.cdr = cdr;
this.ngZone = ngZone;
this.modalStability = modalStability;
this.currency = 'XAF';
this.theme = 'light';
this.paymentSuccess = new EventEmitter();
this.paymentError = new EventEmitter();
this.paymentCancel = new EventEmitter();
this.isModalOpen = false;
}
openModal() {
this.modalStability.openModalStable(() => {
this.isModalOpen = true;
}, this.cdr);
}
closeModal() {
this.modalStability.closeModalStable(() => {
this.isModalOpen = false;
}, this.cdr);
}
onPaymentSuccess(event) {
this.modalStability.executeModalAction(() => {
this.paymentSuccess.emit(event);
this.closeModal();
}, this.cdr);
}
onPaymentError(event) {
this.modalStability.executeModalAction(() => {
this.paymentError.emit(event);
// On ne ferme pas la modale en cas d'erreur pour permettre de réessayer
}, this.cdr);
}
onPaymentCancel() {
this.modalStability.executeModalAction(() => {
this.paymentCancel.emit();
this.closeModal();
}, this.cdr);
}
/**
* Get Y-Nkap logo URL
*/
getYnkapLogoUrl() {
return this.logoService.getOperatorLogoUrl('ynkap');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapPayButtonComponent, deps: [{ token: LogoService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: ModalStabilityService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: YnkapPayButtonComponent, selector: "ynkap-pay-button", inputs: { amount: "amount", currency: "currency", description: "description", merchantReference: "merchantReference", primaryColor: "primaryColor", theme: "theme" }, outputs: { paymentSuccess: "paymentSuccess", paymentError: "paymentError", paymentCancel: "paymentCancel" }, ngImport: i0, template: "<!-- Le bouton qui sera visible par l'utilisateur -->\r\n<button (click)=\"openModal()\" class=\"ynkap-entry-button\" [class.dark-theme]=\"theme === 'dark'\">\r\n <!-- Le logo et le texte du bouton sont fixes -->\r\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Y-Nkap\" class=\"ynkap-logo\">\r\n Payer avec Y-Nkap\r\n</button>\r\n\r\n<!-- La modale qui contient le formulaire de paiement -->\r\n<div *ngIf=\"isModalOpen\" class=\"ynkap-modal-overlay\" [class.dark-modal]=\"theme === 'dark'\" (click)=\"closeModal()\">\r\n <div class=\"ynkap-modal-content\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Le composant de paiement existant est maintenant \u00E0 l'int\u00E9rieur de la modale -->\r\n <lib-ynkap-payment\r\n [amount]=\"amount\"\r\n [currency]=\"currency\"\r\n [description]=\"description\"\r\n [merchantReference]=\"merchantReference\"\r\n [primaryColor]=\"primaryColor\"\r\n [theme]=\"theme\"\r\n (paymentSuccess)=\"onPaymentSuccess($event)\"\r\n (paymentError)=\"onPaymentError($event)\"\r\n (cancelled)=\"onPaymentCancel()\">\r\n </lib-ynkap-payment>\r\n\r\n </div>\r\n</div> ", styles: [".ynkap-entry-button{background-color:#007bff;color:#fff;padding:12px 24px;border:none;border-radius:8px;font-size:16px;font-weight:700;cursor:pointer;transition:background-color .3s ease,transform .2s ease;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 12px #007bff33}.ynkap-entry-button:hover{background-color:#0056b3;transform:translateY(-2px)}.ynkap-entry-button:active{transform:translateY(0)}.ynkap-logo{height:20px;width:auto;margin-right:8px;border-radius:3px}.ynkap-entry-button.dark-theme{background-color:#4caf50;box-shadow:0 4px 12px #4caf5033}.ynkap-entry-button.dark-theme:hover{background-color:#45a049}.ynkap-modal-overlay{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;background-color:#0009!important;display:flex!important;justify-content:center!important;align-items:center!important;z-index:9999!important;-webkit-backdrop-filter:blur(5px)!important;backdrop-filter:blur(5px)!important;padding:1rem!important;opacity:1!important;visibility:visible!important;pointer-events:auto!important;transform:translateZ(0)!important;will-change:opacity!important;transition:opacity .2s ease-in-out!important;isolation:isolate!important}.ynkap-modal-content{position:relative!important;z-index:10000!important;background:#fff!important;border-radius:12px!important;box-shadow:0 20px 60px #0006!important;max-width:90vw!important;max-height:90vh!important;overflow-y:auto!important;width:100%!important;max-width:500px!important;transform:translateZ(0) scale(1)!important;backface-visibility:hidden!important;perspective:1000px!important;animation:modalFadeIn .2s ease-out!important}@keyframes modalFadeIn{0%{opacity:0;transform:translateZ(0) scale(.95) translateY(-20px)}to{opacity:1;transform:translateZ(0) scale(1) translateY(0)}}.dark-modal{background-color:#15151fb3!important}.dark-modal .ynkap-modal-content{background:#1a1a1a!important;color:#fff!important}.ynkap-modal-content>*{position:relative!important;z-index:1!important}body .ynkap-modal-overlay.ynkap-modal-overlay{position:fixed!important;inset:0!important;width:100vw!important;height:100vh!important;z-index:999999!important;display:flex!important;justify-content:center!important;align-items:center!important}body .ynkap-modal-content.ynkap-modal-content{position:relative!important;z-index:1000000!important;transform:none!important;margin:auto!important}\n"], dependencies: [{ kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PaymentComponent, selector: "lib-ynkap-payment", inputs: ["amount", "currency", "merchantReference", "theme", "description", "successUrl", "cancelUrl", "webhookUrl", "logoUrl", "primaryColor", "payButtonText"], outputs: ["paymentSuccess", "paymentError", "cancelled"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapPayButtonComponent, decorators: [{
type: Component,
args: [{ selector: 'ynkap-pay-button', template: "<!-- Le bouton qui sera visible par l'utilisateur -->\r\n<button (click)=\"openModal()\" class=\"ynkap-entry-button\" [class.dark-theme]=\"theme === 'dark'\">\r\n <!-- Le logo et le texte du bouton sont fixes -->\r\n <img [src]=\"getYnkapLogoUrl()\" alt=\"Y-Nkap\" class=\"ynkap-logo\">\r\n Payer avec Y-Nkap\r\n</button>\r\n\r\n<!-- La modale qui contient le formulaire de paiement -->\r\n<div *ngIf=\"isModalOpen\" class=\"ynkap-modal-overlay\" [class.dark-modal]=\"theme === 'dark'\" (click)=\"closeModal()\">\r\n <div class=\"ynkap-modal-content\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Le composant de paiement existant est maintenant \u00E0 l'int\u00E9rieur de la modale -->\r\n <lib-ynkap-payment\r\n [amount]=\"amount\"\r\n [currency]=\"currency\"\r\n [description]=\"description\"\r\n [merchantReference]=\"merchantReference\"\r\n [primaryColor]=\"primaryColor\"\r\n [theme]=\"theme\"\r\n (paymentSuccess)=\"onPaymentSuccess($event)\"\r\n (paymentError)=\"onPaymentError($event)\"\r\n (cancelled)=\"onPaymentCancel()\">\r\n </lib-ynkap-payment>\r\n\r\n </div>\r\n</div> ", styles: [".ynkap-entry-button{background-color:#007bff;color:#fff;padding:12px 24px;border:none;border-radius:8px;font-size:16px;font-weight:700;cursor:pointer;transition:background-color .3s ease,transform .2s ease;display:inline-flex;align-items:center;gap:8px;box-shadow:0 4px 12px #007bff33}.ynkap-entry-button:hover{background-color:#0056b3;transform:translateY(-2px)}.ynkap-entry-button:active{transform:translateY(0)}.ynkap-logo{height:20px;width:auto;margin-right:8px;border-radius:3px}.ynkap-entry-button.dark-theme{background-color:#4caf50;box-shadow:0 4px 12px #4caf5033}.ynkap-entry-button.dark-theme:hover{background-color:#45a049}.ynkap-modal-overlay{position:fixed!important;top:0!important;left:0!important;width:100vw!important;height:100vh!important;background-color:#0009!important;display:flex!important;justify-content:center!important;align-items:center!important;z-index:9999!important;-webkit-backdrop-filter:blur(5px)!important;backdrop-filter:blur(5px)!important;padding:1rem!important;opacity:1!important;visibility:visible!important;pointer-events:auto!important;transform:translateZ(0)!important;will-change:opacity!important;transition:opacity .2s ease-in-out!important;isolation:isolate!important}.ynkap-modal-content{position:relative!important;z-index:10000!important;background:#fff!important;border-radius:12px!important;box-shadow:0 20px 60px #0006!important;max-width:90vw!important;max-height:90vh!important;overflow-y:auto!important;width:100%!important;max-width:500px!important;transform:translateZ(0) scale(1)!important;backface-visibility:hidden!important;perspective:1000px!important;animation:modalFadeIn .2s ease-out!important}@keyframes modalFadeIn{0%{opacity:0;transform:translateZ(0) scale(.95) translateY(-20px)}to{opacity:1;transform:translateZ(0) scale(1) translateY(0)}}.dark-modal{background-color:#15151fb3!important}.dark-modal .ynkap-modal-content{background:#1a1a1a!important;color:#fff!important}.ynkap-modal-content>*{position:relative!important;z-index:1!important}body .ynkap-modal-overlay.ynkap-modal-overlay{position:fixed!important;inset:0!important;width:100vw!important;height:100vh!important;z-index:999999!important;display:flex!important;justify-content:center!important;align-items:center!important}body .ynkap-modal-content.ynkap-modal-content{position:relative!important;z-index:1000000!important;transform:none!important;margin:auto!important}\n"] }]
}], ctorParameters: function () { return [{ type: LogoService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: ModalStabilityService }]; }, propDecorators: { amount: [{
type: Input
}], currency: [{
type: Input
}], description: [{
type: Input
}], merchantReference: [{
type: Input
}], primaryColor: [{
type: Input
}], theme: [{
type: Input
}], paymentSuccess: [{
type: Output
}], paymentError: [{
type: Output
}], paymentCancel: [{
type: Output
}] } });
class PayButtonModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PayButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: PayButtonModule, declarations: [YnkapPayButtonComponent], imports: [CommonModule,
PaymentModule // Import PaymentModule here
], exports: [YnkapPayButtonComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PayButtonModule, imports: [CommonModule,
PaymentModule // Import PaymentModule here
] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PayButtonModule, decorators: [{
type: NgModule,
args: [{
declarations: [
YnkapPayButtonComponent
],
imports: [
CommonModule,
PaymentModule // Import PaymentModule here
],
exports: [
YnkapPayButtonComponent
]
}]
}] });
/**
* Module principal de Y-Nkap, passerelle de paiement en ligne
*/
class YnkapModule {
/**
* Méthode pour initialiser Y-Nkap avec la configuration API
* @param config Configuration de l'API Y-Nkap
* @returns Module avec fournisseurs configurés
*/
static forRoot(config) {
return {
ngModule: YnkapModule,
providers: [
{
provide: ConfigurationService,
useValue: config
}
]
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: YnkapModule, declarations: [YnkapComponent], imports: [CommonModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule], exports: [YnkapComponent,
ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapModule, providers: [
PaymentService,
ErrorHandlingService
], imports: [CommonModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule, ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: YnkapModule, decorators: [{
type: NgModule,
args: [{
declarations: [
YnkapComponent
],
imports: [
CommonModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule
],
exports: [
YnkapComponent,
ConfigurationModule,
PaymentModule,
ErrorHandlingModule,
PayButtonModule,
SharedModule
],
providers: [
PaymentService,
ErrorHandlingService
]
}]
}] });
/*
* Public API Surface of ynkap
*/
// Core exports
/**
* Generated bundle index. Do not edit.
*/
export { ConfigurationModule, ConfigurationService, ErrorCategory, ErrorHandlingModule, ErrorHandlingService, FcfaPipe, PayButtonModule, PaymentComponent, PaymentModule, PaymentService, RetryService, SharedModule, YnkapComponent, YnkapError, YnkapModule, YnkapPayButtonComponent, YnkapService };
//# sourceMappingURL=ynkap-payment.mjs.map