@mygigsters/card-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-sdk-entry.js","sources":["../card-sdk-api.js","../card-sdk-renderer.js","../card-sdk-styles.js","../../../node_modules/airwallex-payment-elements/lib/bin/airwallex.es.js","../card-sdk-entry.js"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\r\n// card-sdk-api.js\r\n// API abstraction for the Card SDK — handles client-secret and save-consent\r\n// endpoints. No UI logic. Mirrors BeneficiaryAPI architecture.\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport class CardAPI {\r\n constructor(baseUrl) {\r\n this.baseUrl = baseUrl.replace(/\\/+$/, '');\r\n }\r\n\r\n // ── Internal helpers ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * Makes a JSON POST request.\r\n * @param {string} path - API path (appended to baseUrl + /api/v1)\r\n * @param {object} body - Request body\r\n * @param {string|null} [token] - Optional Bearer token\r\n * @param {object} [extraHeaders] - Additional headers\r\n * @returns {Promise<object>}\r\n */\r\n async _post(path, body, token = null, extraHeaders = {}) {\r\n const headers = {\r\n 'Content-Type': 'application/json',\r\n ...extraHeaders,\r\n };\r\n if (token) {\r\n headers['Authorization'] =\r\n token.startsWith('Basic ') || token.startsWith('Bearer ')\r\n ? token\r\n : `Bearer ${token}`;\r\n }\r\n\r\n const response = await fetch(`${this.baseUrl}/api/v1${path}`, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify(body),\r\n });\r\n\r\n const rawText = await response.text();\r\n let data = null;\r\n if (rawText && rawText.trim().length > 0) {\r\n try {\r\n data = JSON.parse(rawText);\r\n } catch {\r\n data = null;\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const errMsg =\r\n (data && (data.message || data.error)) ||\r\n rawText ||\r\n response.statusText ||\r\n `HTTP ${response.status}`;\r\n throw new Error(errMsg);\r\n }\r\n\r\n return data ?? {};\r\n }\r\n\r\n // ── Public methods ────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Authenticate using apiKey and apiSecret via /api/v1/sdk-initialization.\r\n * Mirrors BeneficiaryAPI authentication architecture.\r\n *\r\n * @param {string} apiKey - UUID-style API key\r\n * @param {string} apiSecret - One-time API secret\r\n * @returns {Promise<{ token: string, clientId: string, expiresIn: number, tokenType: string }>}\r\n */\r\n async authenticate(apiKey, apiSecret) {\r\n const credentials = btoa(`${apiKey}:${apiSecret}`);\r\n\r\n const response = await fetch(`${this.baseUrl}/api/v1/sdk-initialization`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-version': '1.1',\r\n 'Authorization': `Basic ${credentials}`,\r\n },\r\n });\r\n\r\n const rawText = await response.text();\r\n let data = null;\r\n if (rawText && rawText.trim().length > 0) {\r\n try {\r\n data = JSON.parse(rawText);\r\n } catch {\r\n data = null;\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const errMsg =\r\n (data && (data.message || data.error)) ||\r\n rawText ||\r\n response.statusText ||\r\n `HTTP ${response.status}`;\r\n throw new Error(errMsg);\r\n }\r\n\r\n if (!data?.success || !data?.data?.token) {\r\n throw new Error('Authentication failed: Unexpected response from server');\r\n }\r\n\r\n return {\r\n token: data.data.token,\r\n clientId: data.data.clientId,\r\n expiresIn: data.data.expiresIn,\r\n tokenType: data.data.tokenType,\r\n paymentsIndia: data.data.paymentsIndia || false,\r\n };\r\n }\r\n\r\n /**\r\n * Retrieve a client secret for Airwallex card element initialization.\r\n *\r\n * POST /api/v1/customer/client-secret\r\n * Body: { customerId, accountId }\r\n *\r\n * @param {string} customerId\r\n * @param {string} accountId\r\n * @param {string|null} [token] - Bearer token if authenticated\r\n * @returns {Promise<{ clientSecret: string }>}\r\n */\r\n async getClientSecret(customerId, accountId, token = null) {\r\n console.log('🔐 CardAPI.getClientSecret()', {\r\n customerId,\r\n accountId,\r\n hasToken: !!token,\r\n });\r\n const result = await this._post(\r\n '/customer/client-secret',\r\n {\r\n customerId,\r\n accountId,\r\n },\r\n token\r\n );\r\n\r\n // The backend returns { client_secret: \"...\" } or { clientSecret: \"...\" } or inside data\r\n const secret =\r\n result.client_secret ||\r\n result.clientSecret ||\r\n result?.data?.client_secret ||\r\n result?.data?.clientSecret;\r\n\r\n if (!secret) {\r\n throw new Error('Failed to retrieve client secret from server');\r\n }\r\n\r\n return { clientSecret: secret };\r\n }\r\n\r\n /**\r\n * Save the payment consent after Airwallex createPaymentConsent succeeds.\r\n *\r\n * POST /api/v1/customer/save-consent\r\n * Body: { customerId, paymentConsentId }\r\n *\r\n * @param {string} customerId\r\n * @param {string} paymentConsentId\r\n * @param {string|null} [token] - Bearer token if authenticated\r\n * @returns {Promise<object>}\r\n */\r\n async saveConsent(customerId, paymentConsentId, token = null) {\r\n return this._post(\r\n '/customer/save-consent',\r\n {\r\n customerId,\r\n paymentConsentId,\r\n },\r\n token\r\n );\r\n }\r\n}\r\n","// ─────────────────────────────────────────────────────────────────────────────\r\n// card-sdk-renderer.js\r\n// Manages all Card SDK DOM/UI state. No API requests.\r\n// Single-step flow: Direct Card Entry (Card Number, MM/YY, CVC, Submit).\r\n// Uses surgical DOM patches to protect the mounted Airwallex card iframe.\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nconst ICONS = {\r\n close: `<svg width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2.2\" d=\"M6 18L18 6M6 6l12 12\"/>\r\n </svg>`,\r\n\r\n check: `<svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M20 6L9 17l-5-5\"/>\r\n </svg>`,\r\n\r\n lock: `<svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>\r\n </svg>`,\r\n};\r\n\r\nexport class CardRenderer {\r\n constructor(shadowRoot, callbacks) {\r\n this.shadowRoot = shadowRoot;\r\n this.callbacks = callbacks;\r\n\r\n // ── Internal state ─────────────────────────────────────────────────────\r\n this.state = {\r\n loading: true,\r\n cardLoaded: false,\r\n cardComplete: false,\r\n submitting: false,\r\n error: '',\r\n success: false,\r\n };\r\n\r\n // Flag: once the Airwallex card element is mounted, never re-render\r\n // the form via innerHTML — use surgical DOM patches only.\r\n this._cardMounted = false;\r\n }\r\n\r\n // ── Container helper ────────────────────────────────────────────────────\r\n\r\n _getContainer() {\r\n let container = this.shadowRoot.querySelector('#mc-sdk-root');\r\n if (!container) {\r\n container = document.createElement('div');\r\n container.id = 'mc-sdk-root';\r\n const themeContainer = this.shadowRoot.querySelector('#mc-theme-container');\r\n if (themeContainer) {\r\n themeContainer.appendChild(container);\r\n } else {\r\n this.shadowRoot.appendChild(container);\r\n }\r\n }\r\n return container;\r\n }\r\n\r\n // ══════════════════════════════════════════════════════════════════════════\r\n // SINGLE-STEP CARD FORM\r\n // ══════════════════════════════════════════════════════════════════════════\r\n\r\n render() {\r\n this.state.loading = true;\r\n const container = this._getContainer();\r\n\r\n container.innerHTML = `\r\n <div class=\"mc-backdrop\" id=\"mc-backdrop\">\r\n <div class=\"mc-modal\" id=\"mc-modal\">\r\n <button class=\"mc-close-btn\" aria-label=\"Close\" id=\"mc-close-btn\" type=\"button\">${ICONS.close}</button>\r\n\r\n <div class=\"mc-header\">\r\n <h1 class=\"mc-title\">Card Details</h1>\r\n <p class=\"mc-subtitle\">Please enter your card details</p>\r\n </div>\r\n\r\n <div class=\"mc-body\">\r\n <!-- Error banner (initially hidden) -->\r\n <div class=\"mc-error-banner\" style=\"display:none;\" id=\"mc-error-banner\"></div>\r\n\r\n <!-- Loading spinner (shown initially) -->\r\n <div class=\"mc-loading\" id=\"mc-loading\">\r\n <div class=\"mc-spinner\"></div>\r\n <span class=\"mc-loading-text\">Loading payment form...</span>\r\n </div>\r\n\r\n <!-- Card wrapper (hidden until Airwallex loads) -->\r\n <div class=\"mc-card-wrapper\" id=\"mc-card-wrapper\" style=\"display:none;\">\r\n <div id=\"card-root\"></div>\r\n </div>\r\n\r\n <!-- Submit button (hidden until Airwallex loads) -->\r\n <button class=\"mc-submit-btn\" id=\"mc-submit-btn\" disabled style=\"display:none;\" type=\"button\">\r\n Submit\r\n </button>\r\n </div>\r\n\r\n <div class=\"mc-powered-by\">\r\n Powered by <a href=\"https://mygigsters.com.au\" target=\"_blank\" rel=\"noopener\">MyGigsters</a>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n\r\n this._attachListeners();\r\n }\r\n\r\n _attachListeners() {\r\n // Close button click\r\n const closeBtns = this.shadowRoot.querySelectorAll('.mc-close-btn, #mc-close-btn');\r\n closeBtns.forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onClose();\r\n });\r\n });\r\n\r\n // Backdrop click (dismiss when clicking outside the modal)\r\n const backdrop = this.shadowRoot.querySelector('#mc-backdrop') || this.shadowRoot.querySelector('.mc-backdrop');\r\n if (backdrop) {\r\n backdrop.addEventListener('click', (e) => {\r\n if (e.target === backdrop) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onClose();\r\n }\r\n });\r\n }\r\n\r\n // Submit button click\r\n const submitBtn = this.shadowRoot.querySelector('#mc-submit-btn');\r\n if (submitBtn) {\r\n submitBtn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onSubmit();\r\n });\r\n }\r\n\r\n // Delegated click fallback on shadowRoot\r\n this.shadowRoot.addEventListener('click', (e) => {\r\n const target = e.target;\r\n if (target && (target.closest('.mc-close-btn') || target.closest('#mc-close-btn'))) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onClose();\r\n }\r\n });\r\n }\r\n\r\n // ── Surgical state patches (safe after card mount) ──────────────────────\r\n\r\n /**\r\n * Call when Airwallex card element is ready and about to be mounted.\r\n * Hides the spinner and reveals the card wrapper + submit button.\r\n */\r\n setCardLoaded() {\r\n this.state.cardLoaded = true;\r\n this.state.loading = false;\r\n\r\n const loading = this.shadowRoot.querySelector('#mc-loading');\r\n const cardWrapper = this.shadowRoot.querySelector('#mc-card-wrapper');\r\n const submitBtn = this.shadowRoot.querySelector('#mc-submit-btn');\r\n\r\n if (loading) loading.style.display = 'none';\r\n if (cardWrapper) cardWrapper.style.display = 'block';\r\n if (submitBtn) submitBtn.style.display = 'flex';\r\n }\r\n\r\n /**\r\n * Mark the Airwallex card as mounted — after this, no full re-renders.\r\n */\r\n markCardMounted() {\r\n this._cardMounted = true;\r\n }\r\n\r\n /**\r\n * Enable/disable the submit button based on card completeness.\r\n * Surgical patch — only touches the button element.\r\n */\r\n setCardComplete(complete) {\r\n this.state.cardComplete = complete;\r\n\r\n const btn = this.shadowRoot.querySelector('#mc-submit-btn');\r\n if (!btn) return;\r\n\r\n btn.disabled = !complete || this.state.submitting;\r\n }\r\n\r\n /**\r\n * Show/hide the submitting state on the button.\r\n * Surgical patch — only touches the button element.\r\n */\r\n setSubmitting(submitting) {\r\n this.state.submitting = submitting;\r\n\r\n const btn = this.shadowRoot.querySelector('#mc-submit-btn');\r\n if (!btn) return;\r\n\r\n btn.disabled = submitting || !this.state.cardComplete;\r\n btn.innerHTML = submitting\r\n ? `<span class=\"mc-btn-inner\"><div class=\"mc-spinner mc-spinner-sm\"></div>Saving...</span>`\r\n : 'Submit';\r\n }\r\n\r\n /**\r\n * Show/hide an error banner inside the modal.\r\n * Surgical patch — never destroys the Airwallex iframe.\r\n */\r\n setError(message) {\r\n this.state.error = message;\r\n\r\n const banner = this.shadowRoot.querySelector('#mc-error-banner');\r\n if (!banner) return;\r\n\r\n if (message) {\r\n banner.textContent = message;\r\n banner.style.display = 'block';\r\n } else {\r\n banner.textContent = '';\r\n banner.style.display = 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Show an initialization error when the SDK fails to load.\r\n * Only safe to call BEFORE the card element is mounted.\r\n */\r\n showInitError(message) {\r\n this.state.loading = false;\r\n this.state.error = message;\r\n\r\n const loading = this.shadowRoot.querySelector('#mc-loading');\r\n if (loading) {\r\n loading.innerHTML = `\r\n <div style=\"text-align:center; padding: 12px 0;\">\r\n <p style=\"color:#ef4444; font-size:14px; font-weight:600; margin-bottom:8px;\">${this._escapeHtml(message)}</p>\r\n <p style=\"color:#94a3b8; font-size:13px;\">Please check your configuration credentials and try again.</p>\r\n </div>\r\n `;\r\n }\r\n }\r\n\r\n /**\r\n * Replace the entire modal body with a success state.\r\n * This is safe because we no longer need the Airwallex iframe.\r\n */\r\n showSuccess(result) {\r\n this.state.success = true;\r\n\r\n const modal = this.shadowRoot.querySelector('.mc-modal');\r\n if (!modal) return;\r\n\r\n modal.innerHTML = `\r\n <button class=\"mc-close-btn\" aria-label=\"Close\" id=\"mc-close-btn\" type=\"button\">${ICONS.close}</button>\r\n\r\n <div class=\"mc-body\">\r\n <div class=\"mc-success-wrap\">\r\n <div class=\"mc-success-icon\">${ICONS.check}</div>\r\n <h2 class=\"mc-success-title\">Card Saved Successfully</h2>\r\n <p class=\"mc-success-sub\">Your card details have been securely tokenized and saved.</p>\r\n <button class=\"mc-done-btn\" id=\"mc-done-btn\" type=\"button\">Done</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"mc-powered-by\">\r\n Powered by <a href=\"https://mygigsters.com.au\" target=\"_blank\" rel=\"noopener\">MyGigsters</a>\r\n </div>\r\n `;\r\n\r\n // Re-attach close / done listeners\r\n modal.querySelectorAll('.mc-close-btn, #mc-close-btn').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onClose();\r\n });\r\n });\r\n\r\n modal.querySelector('#mc-done-btn')\r\n ?.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.callbacks.onClose();\r\n });\r\n }\r\n\r\n // ── Helpers ─────────────────────────────────────────────────────────────\r\n\r\n _escapeHtml(str) {\r\n const div = document.createElement('div');\r\n div.textContent = str;\r\n return div.innerHTML;\r\n }\r\n\r\n // ── Cleanup ─────────────────────────────────────────────────────────────\r\n\r\n destroy() {\r\n const container = this.shadowRoot.querySelector('#mc-sdk-root');\r\n if (container) container.innerHTML = '';\r\n this._cardMounted = false;\r\n }\r\n}\r\n","// ─────────────────────────────────────────────────────────────────────────────\r\n// card-sdk-styles.js\r\n// All CSS for the Card SDK as a JS string for Shadow DOM injection.\r\n// Namespace: mc- (MyGigsters Card) to avoid collisions with host page.\r\n// Supports high-contrast Light and Sleek Dark themes.\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nexport const CARD_SDK_STYLES = `\r\n/* ── Reset inside shadow DOM ───────────────────────────────────────────────── */\r\n*, *::before, *::after {\r\n box-sizing: border-box;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n:host {\r\n display: block !important;\r\n position: fixed !important;\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100vw !important;\r\n height: 100vh !important;\r\n z-index: 2147483647 !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\r\n font-size: 14px;\r\n color: #e5e7eb;\r\n line-height: 1.5;\r\n pointer-events: auto !important;\r\n}\r\n\r\n#mc-theme-container, #mc-sdk-root {\r\n width: 100%;\r\n height: 100%;\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n}\r\n\r\n/* ══════════════════════════════════════════════════════════════════════════════\r\n DARK THEME (DEFAULT)\r\n ══════════════════════════════════════════════════════════════════════════════ */\r\n\r\n/* ── Backdrop ──────────────────────────────────────────────────────────────── */\r\n.mc-backdrop {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n width: 100vw;\r\n height: 100vh;\r\n background: rgba(0, 0, 0, 0.75);\r\n backdrop-filter: blur(5px);\r\n -webkit-backdrop-filter: blur(5px);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 2147483647;\r\n padding: 16px;\r\n box-sizing: border-box;\r\n animation: mc-fade-in 0.2s ease;\r\n}\r\n\r\n/* ── Modal ──────────────────────────────────────────────────────────────────── */\r\n.mc-modal {\r\n background: #111827;\r\n border: 1px solid rgba(255, 255, 255, 0.12);\r\n border-radius: 16px;\r\n width: 100%;\r\n max-width: 460px;\r\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255, 255, 255, 0.05);\r\n overflow: hidden;\r\n animation: mc-modal-in 0.25s cubic-bezier(0.16, 1, 0.3, 1);\r\n position: relative;\r\n display: flex;\r\n flex-direction: column;\r\n color: #ffffff;\r\n}\r\n\r\n/* ── Close button ──────────────────────────────────────────────────────────── */\r\n.mc-close-btn {\r\n position: absolute;\r\n top: 16px;\r\n right: 16px;\r\n background: rgba(255, 255, 255, 0.08);\r\n border: 1px solid rgba(255, 255, 255, 0.08);\r\n border-radius: 8px;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer !important;\r\n color: #94a3b8;\r\n transition: all 0.15s ease;\r\n padding: 0;\r\n line-height: 0;\r\n z-index: 100;\r\n outline: none;\r\n pointer-events: auto !important;\r\n user-select: none;\r\n}\r\n\r\n.mc-close-btn svg,\r\n.mc-close-btn path {\r\n pointer-events: none !important;\r\n}\r\n\r\n.mc-close-btn:hover {\r\n background: rgba(255, 255, 255, 0.18);\r\n color: #ffffff;\r\n transform: scale(1.05);\r\n}\r\n\r\n.mc-close-btn:active {\r\n transform: scale(0.95);\r\n}\r\n\r\n/* ── Header ────────────────────────────────────────────────────────────────── */\r\n.mc-header {\r\n text-align: center;\r\n padding: 28px 24px 0;\r\n}\r\n\r\n.mc-title {\r\n font-size: 22px;\r\n font-weight: 700;\r\n color: #ffffff;\r\n margin: 0 0 6px;\r\n line-height: 1.2;\r\n}\r\n\r\n.mc-subtitle {\r\n font-size: 14px;\r\n color: #94a3b8;\r\n margin: 0;\r\n font-weight: 400;\r\n}\r\n\r\n/* ── Body ──────────────────────────────────────────────────────────────────── */\r\n.mc-body {\r\n padding: 20px 24px 24px;\r\n flex: 1;\r\n}\r\n\r\n/* ── Card mount area ───────────────────────────────────────────────────────── */\r\n.mc-card-wrapper {\r\n background: #1f2937;\r\n border: 1px solid rgba(255, 255, 255, 0.12);\r\n border-radius: 10px;\r\n padding: 14px 16px;\r\n margin-bottom: 20px;\r\n min-height: 48px;\r\n transition: border-color 0.2s, box-shadow 0.2s;\r\n}\r\n\r\n.mc-card-wrapper:focus-within {\r\n border-color: #6366f1;\r\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.25);\r\n}\r\n\r\n#card-root {\r\n margin: 0;\r\n padding: 0;\r\n min-height: 40px;\r\n width: 100%;\r\n}\r\n\r\n#card-root iframe {\r\n display: block !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n width: 100% !important;\r\n border: none !important;\r\n}\r\n\r\n/* ── Loading state ─────────────────────────────────────────────────────────── */\r\n.mc-loading {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 32px 20px;\r\n gap: 12px;\r\n}\r\n\r\n.mc-loading-text {\r\n font-size: 13.5px;\r\n color: #94a3b8;\r\n font-weight: 500;\r\n}\r\n\r\n/* ── Spinner ────────────────────────────────────────────────────────────────── */\r\n.mc-spinner {\r\n width: 32px;\r\n height: 32px;\r\n border: 3px solid rgba(255, 255, 255, 0.15);\r\n border-top-color: #6366f1;\r\n border-radius: 50%;\r\n animation: mc-spin 0.7s linear infinite;\r\n flex-shrink: 0;\r\n}\r\n\r\n.mc-spinner-sm {\r\n width: 16px;\r\n height: 16px;\r\n border-width: 2px;\r\n border-color: rgba(255, 255, 255, 0.3);\r\n border-top-color: #fff;\r\n}\r\n\r\n@keyframes mc-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n/* ── Submit button ─────────────────────────────────────────────────────────── */\r\n.mc-submit-btn {\r\n width: 100%;\r\n padding: 13px 24px;\r\n background: #6366f1;\r\n color: #ffffff;\r\n border: none;\r\n border-radius: 9px;\r\n font-size: 15px;\r\n font-weight: 600;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);\r\n outline: none;\r\n}\r\n\r\n.mc-submit-btn:hover:not(:disabled) {\r\n background: #4f46e5;\r\n box-shadow: 0 6px 16px rgba(99, 102, 241, 0.45);\r\n transform: translateY(-1px);\r\n}\r\n\r\n.mc-submit-btn:active:not(:disabled) {\r\n transform: translateY(0);\r\n}\r\n\r\n.mc-submit-btn:disabled {\r\n opacity: 0.55;\r\n cursor: not-allowed;\r\n transform: none;\r\n box-shadow: none;\r\n}\r\n\r\n.mc-btn-inner {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 8px;\r\n}\r\n\r\n/* ── Error banner ──────────────────────────────────────────────────────────── */\r\n.mc-error-banner {\r\n background: rgba(239, 68, 68, 0.12);\r\n border: 1px solid rgba(239, 68, 68, 0.3);\r\n border-radius: 8px;\r\n padding: 10px 14px;\r\n margin-bottom: 16px;\r\n font-size: 13px;\r\n color: #fca5a5;\r\n line-height: 1.4;\r\n animation: mc-fade-in 0.2s ease;\r\n}\r\n\r\n/* ── Success state ─────────────────────────────────────────────────────────── */\r\n.mc-success-wrap {\r\n text-align: center;\r\n padding: 30px 20px 16px;\r\n animation: mc-fade-in 0.3s ease;\r\n}\r\n\r\n.mc-success-icon {\r\n width: 56px;\r\n height: 56px;\r\n border-radius: 50%;\r\n background: rgba(34, 197, 94, 0.15);\r\n border: 2px solid rgba(34, 197, 94, 0.4);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin: 0 auto 16px;\r\n}\r\n\r\n.mc-success-icon svg {\r\n width: 28px;\r\n height: 28px;\r\n color: #22c55e;\r\n}\r\n\r\n.mc-success-title {\r\n font-size: 20px;\r\n font-weight: 700;\r\n color: #f8fafc;\r\n margin: 0 0 6px;\r\n}\r\n\r\n.mc-success-sub {\r\n font-size: 13.5px;\r\n color: #94a3b8;\r\n margin: 0 0 24px;\r\n}\r\n\r\n.mc-done-btn {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 11px 36px;\r\n background: #6366f1;\r\n color: #fff;\r\n border: none;\r\n border-radius: 8px;\r\n font-size: 14px;\r\n font-weight: 600;\r\n cursor: pointer;\r\n font-family: inherit;\r\n transition: all 0.2s ease;\r\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);\r\n}\r\n\r\n.mc-done-btn:hover {\r\n background: #4f46e5;\r\n transform: translateY(-1px);\r\n}\r\n\r\n/* ── Powered by ────────────────────────────────────────────────────────────── */\r\n.mc-powered-by {\r\n text-align: center;\r\n padding: 8px 0 16px;\r\n font-size: 11.5px;\r\n color: #64748b;\r\n}\r\n\r\n.mc-powered-by a {\r\n color: #94a3b8;\r\n text-decoration: none;\r\n font-weight: 600;\r\n transition: color 0.15s ease;\r\n}\r\n\r\n.mc-powered-by a:hover {\r\n color: #818cf8;\r\n}\r\n\r\n/* ── Animations ────────────────────────────────────────────────────────────── */\r\n@keyframes mc-modal-in {\r\n from {\r\n opacity: 0;\r\n transform: translateY(12px) scale(0.97);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0) scale(1);\r\n }\r\n}\r\n\r\n@keyframes mc-fade-in {\r\n from { opacity: 0; }\r\n to { opacity: 1; }\r\n}\r\n\r\n/* ══════════════════════════════════════════════════════════════════════════════\r\n LIGHT THEME (High Contrast & Clean)\r\n ══════════════════════════════════════════════════════════════════════════════ */\r\n\r\n[data-theme='light'] .mc-backdrop {\r\n background: rgba(15, 23, 42, 0.45);\r\n backdrop-filter: blur(5px);\r\n -webkit-backdrop-filter: blur(5px);\r\n}\r\n\r\n[data-theme='light'] .mc-modal {\r\n background: #ffffff;\r\n border: 1px solid #e2e8f0;\r\n color: #0f172a;\r\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.12), 0 8px 10px -6px rgba(0, 0, 0, 0.06);\r\n}\r\n\r\n[data-theme='light'] .mc-close-btn {\r\n background: #f1f5f9;\r\n border: 1px solid #e2e8f0;\r\n color: #64748b;\r\n}\r\n\r\n[data-theme='light'] .mc-close-btn:hover {\r\n background: #e2e8f0;\r\n color: #0f172a;\r\n}\r\n\r\n[data-theme='light'] .mc-title {\r\n color: #0f172a;\r\n}\r\n\r\n[data-theme='light'] .mc-subtitle {\r\n color: #64748b;\r\n}\r\n\r\n/* ── Light: Card area ─────────────────────────────────────────────────────── */\r\n[data-theme='light'] .mc-card-wrapper {\r\n background: #ffffff;\r\n border: 1.5px solid #cbd5e1;\r\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n[data-theme='light'] .mc-card-wrapper:focus-within {\r\n border-color: #6366f1;\r\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);\r\n}\r\n\r\n[data-theme='light'] .mc-loading-text {\r\n color: #64748b;\r\n}\r\n\r\n[data-theme='light'] .mc-spinner {\r\n border-color: rgba(99, 102, 241, 0.2);\r\n border-top-color: #6366f1;\r\n}\r\n\r\n[data-theme='light'] .mc-error-banner {\r\n background: #fef2f2;\r\n border-color: #fecaca;\r\n color: #dc2626;\r\n}\r\n\r\n[data-theme='light'] .mc-success-icon {\r\n background: #f0fdf4;\r\n border-color: #bbf7d0;\r\n}\r\n\r\n[data-theme='light'] .mc-success-icon svg {\r\n color: #16a34a;\r\n}\r\n\r\n[data-theme='light'] .mc-success-title {\r\n color: #0f172a;\r\n}\r\n\r\n[data-theme='light'] .mc-success-sub {\r\n color: #64748b;\r\n}\r\n\r\n[data-theme='light'] .mc-powered-by {\r\n color: #94a3b8;\r\n}\r\n\r\n[data-theme='light'] .mc-powered-by a {\r\n color: #6366f1;\r\n}\r\n\r\n[data-theme='light'] .mc-powered-by a:hover {\r\n color: #4f46e5;\r\n}\r\n`;\r\n","/* Airwallex Checkout Component Version [1.160.0] */\nconst e={prod:\"checkout.airwallex.com\",demo:\"checkout-demo.airwallex.com\",staging:\"checkout-staging.airwallex.com\",dev:\"checkout-dev.airwallex.com\",local:\"localhost:3000\"},r=r=>`https://${e[r]||e.prod}`,o=\"/assets/elements.bundle.min.js?version=1.160.0\",n=e=>{const r=document.createElement(\"script\");r.src=`${e}${o}`,r.crossOrigin=\"anonymous\";const n=document.head||document.body;if(!n)throw new Error(\"Airwallex payment scripts requires a <head> or <body> html element in order to be loaded.\");return n.appendChild(r),r},l=async e=>{if(\"undefined\"==typeof window)return null;if(window.Airwallex)return window.Airwallex;let l=0;const t=async()=>{const l=document.querySelector(`script[src=\"${o}\"], script[src=\"${o}/\"]`)||n(r((null==e?void 0:e.env)||\"prod\"));return new Promise(((r,o)=>{l.addEventListener(\"load\",(()=>{window.Airwallex?(window.Airwallex.init(e),r(window.Airwallex)):o(new Error(\"Failed to load Airwallex on load event\"))})),l.addEventListener(\"error\",(()=>{o(new Error(\"Failed to load Airwallex scripts\")),l.remove&&l.remove()}))}))};for(;l<3;)try{return await t()}catch(e){l++,await new Promise((e=>window.setTimeout(e,500)))}return null},t=e=>{window.Airwallex?window.Airwallex.init(e):console.error(\"Please loadAirwallex() before init();\")},a=e=>{if(window.Airwallex)return window.Airwallex.redirectToCheckout(e);console.error(\"Please loadAirwallex() before redirectToCheckout();\")},i=(e,r)=>window.Airwallex?window.Airwallex.createElement(e,r):(console.error(\"Please loadAirwallex() before createElement();\"),null),w=e=>window.Airwallex?window.Airwallex.destroyElement(e):(console.error(\"Please loadAirwallex() before destroyElement();\"),!1),d=e=>window.Airwallex?window.Airwallex.getElement(e):(console.error(\"Please loadAirwallex() before getElement();\"),null),c=async e=>{if(window.Airwallex)return window.Airwallex.confirmPaymentIntent(e);{const e=\"Please loadAirwallex() before confirmPaymentIntent();\";throw console.error(e),new Error(e)}},s=async e=>{if(window.Airwallex)return window.Airwallex.confirmPaymentIntentWithSavedCard(e);{const e=\"Please loadAirwallex() before confirmPaymentIntentWithSavedCard();\";throw console.error(e),new Error(e)}},m=async(e,r)=>{if(window.Airwallex)return window.Airwallex.createPaymentMethod(e,r);{const e=\"Please loadAirwallex() before createPaymentMethod();\";throw console.error(e),new Error(e)}},x=async(e,r)=>{if(window.Airwallex)return window.Airwallex.getPaymentIntent(e,r);{const e=\"Please loadAirwallex() before getPaymentIntent();\";throw console.error(e),new Error(e)}},A=async e=>{if(window.Airwallex)return window.Airwallex.createPaymentConsent(e);{const e=\"Please loadAirwallex() before createPaymentConsent();\";throw console.error(e),new Error(e)}},u=e=>window.Airwallex.getDeviceFingerprint(e);var y={getGatewayUrl:r,loadAirwallex:l,loadAirwallexJs:n,init:t,redirectToCheckout:a,createElement:i,destroyElement:w,getDeviceFingerprint:u,getElement:d,getPaymentIntent:x,createPaymentMethod:m,createPaymentConsent:A,confirmPaymentIntent:c,confirmPaymentIntentWithSavedCard:s};export default y;export{c as confirmPaymentIntent,s as confirmPaymentIntentWithSavedCard,i as createElement,A as createPaymentConsent,m as createPaymentMethod,w as destroyElement,u as getDeviceFingerprint,d as getElement,r as getGatewayUrl,x as getPaymentIntent,t as init,l as loadAirwallex,n as loadAirwallexJs,a as redirectToCheckout};\n//# sourceMappingURL=airwallex.es.js.map\n","// ─────────────────────────────────────────────────────────────────────────────\r\n// card-sdk-entry.js\r\n// Main entry point for the MyGigsters Card SDK.\r\n// Orchestrates: config validation → Auth → Shadow DOM → Single-Step Card Modal.\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\nimport { CardAPI } from './card-sdk-api.js';\r\nimport { CardRenderer } from './card-sdk-renderer.js';\r\nimport { CARD_SDK_STYLES } from './card-sdk-styles.js';\r\nimport Airwallex from 'airwallex-payment-elements';\r\n\r\n// ─── Environment base URLs ────────────────────────────────────────────────────\r\n// NOTE: To remove the dev server later, comment out or delete the 'dev' line below.\r\nconst ENV_URLS = {\r\n dev: 'http://3.108.128.110:5000', // ← Comment this line when dev server is removed\r\n demo: 'https://qa-payments.mygigsters.com.au', // QA Demo environment\r\n prod: 'https://prod-payments.mygigsters.com.au',// Production environment\r\n};\r\n\r\n// ─── Airwallex environment mapping ────────────────────────────────────────────\r\nconst AIRWALLEX_ENV = {\r\n dev: 'demo',\r\n demo: 'demo',\r\n prod: 'prod',\r\n};\r\n\r\nclass MygigstersCardSDK {\r\n constructor() {\r\n this.config = null;\r\n this.api = null;\r\n this.renderer = null;\r\n this.host = null;\r\n this.shadowRoot = null;\r\n this.cardElement = null;\r\n this.clientSecret = null;\r\n this.authToken = null;\r\n this.tokenExpiresAt = null;\r\n this.airwallexClientId = null;\r\n this.isInitialized = false;\r\n this.isSubmitting = false;\r\n this._handleKeyDown = this._handleKeyDown.bind(this);\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────────────────\r\n // PUBLIC: init\r\n // ─────────────────────────────────────────────────────────────────────────\r\n /**\r\n * Initialize the Card SDK.\r\n *\r\n * @param {object} config\r\n * @param {string} config.apiKey - API key (required)\r\n * @param {string} config.apiSecret - API secret (required)\r\n * @param {string} config.customerId - Customer ID (required)\r\n * @param {string} [config.myGigsterId]- MyGigster ID (required from frontend)\r\n * @param {string} [config.accountId] - Account ID (legacy alias for myGigsterId)\r\n * @param {string} config.containerId - ID of the DOM container\r\n * @param {'dev'|'demo'|'prod'} [config.env='demo'] - Environment (\"dev\" | \"demo\" | \"prod\")\r\n * @param {string} [config.baseUrl] - Custom base URL override\r\n * @param {'light'|'dark'} [config.mode='dark']- UI theme\r\n * @param {function} [config.onSuccess] - Callback on successful card save\r\n * @param {function} [config.onError] - Callback on error\r\n * @param {function} [config.onClose] - Callback when modal closes\r\n */\r\n async init(config) {\r\n try {\r\n if (!config) {\r\n throw new Error('Configuration object is required for MygigstersCard.init()');\r\n }\r\n\r\n // ── Validate required fields ──────────────────────────────────────────\r\n if (!config.apiKey) throw new Error('apiKey is required');\r\n if (!config.apiSecret) throw new Error('apiSecret is required');\r\n if (!config.customerId) throw new Error('customerId is required');\r\n const resolvedMyGigsterId = config.myGigsterId || config.accountId;\r\n if (!resolvedMyGigsterId) throw new Error('myGigsterId is required');\r\n if (!config.containerId) throw new Error('containerId is required');\r\n\r\n const container = document.getElementById(config.containerId);\r\n if (!container) {\r\n throw new Error(`Container element with ID '${config.containerId}' not found`);\r\n }\r\n\r\n // ── Resolve environment & baseUrl ─────────────────────────────────────\r\n let env = config.env || 'demo';\r\n if (env === 'qa') env = 'demo'; // Graceful alias for qa -> demo\r\n\r\n if (!ENV_URLS[env]) {\r\n throw new Error(`Unknown env \"${env}\". Use \"dev\", \"demo\", or \"prod\".`);\r\n }\r\n const baseUrl = config.baseUrl || ENV_URLS[env];\r\n\r\n // ── Store merged config ───────────────────────────────────────────────\r\n this.config = {\r\n mode: 'dark',\r\n onSuccess: () => {},\r\n onError: (err) => console.error('MyGigsters Card SDK Error:', err),\r\n onClose: () => {},\r\n ...config,\r\n myGigsterId: resolvedMyGigsterId,\r\n accountId: resolvedMyGigsterId,\r\n env,\r\n baseUrl,\r\n };\r\n\r\n // Clean up any existing host DOM node\r\n const existingHost = document.getElementById('mygigsters-card-sdk-host');\r\n if (existingHost?.parentNode) {\r\n existingHost.parentNode.removeChild(existingHost);\r\n }\r\n\r\n // ── Initialize API client ─────────────────────────────────────────────\r\n this.api = new CardAPI(this.config.baseUrl);\r\n\r\n // ── Create Shadow DOM host ────────────────────────────────────\r\n // Mounted on <body> so position:fixed escapes any overflow context.\r\n this.host = document.createElement('div');\r\n this.host.id = 'mygigsters-card-sdk-host';\r\n this.host.style.cssText =\r\n 'display:block;position:fixed;top:0;left:0;right:0;bottom:0;width:100vw;height:100vh;z-index:2147483647;pointer-events:auto;';\r\n\r\n this.shadowRoot = this.host.attachShadow({ mode: 'closed' });\r\n\r\n // ── Inject styles ─────────────────────────────────────────────────────\r\n const styleElement = document.createElement('style');\r\n styleElement.textContent = CARD_SDK_STYLES;\r\n this.shadowRoot.appendChild(styleElement);\r\n\r\n // ── Theme container ───────────────────────────────────────────────────\r\n const themeContainer = document.createElement('div');\r\n themeContainer.id = 'mc-theme-container';\r\n themeContainer.setAttribute(\r\n 'data-theme',\r\n this.config.mode === 'light' ? 'light' : 'dark'\r\n );\r\n this.shadowRoot.appendChild(themeContainer);\r\n\r\n document.body.appendChild(this.host);\r\n\r\n // ── Create renderer & render single-step card modal ───────────────────\r\n this.renderer = new CardRenderer(this.shadowRoot, {\r\n onClose: () => this.handleClose(),\r\n onSubmit: () => this.handleSubmit(),\r\n });\r\n\r\n this.renderer.render();\r\n this.isInitialized = true;\r\n this.show();\r\n\r\n // Listen for Escape key on window\r\n window.addEventListener('keydown', this._handleKeyDown);\r\n\r\n // ── Authenticate & initialize Airwallex card element ──────────────────\r\n await this.authenticate();\r\n await this._initializeCard();\r\n\r\n } catch (error) {\r\n if (this.renderer) {\r\n this.renderer.showInitError(error.message || 'Initialization failed');\r\n }\r\n if (this.config?.onError) {\r\n this.config.onError(error);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n _handleKeyDown(e) {\r\n if (e.key === 'Escape' && this.isInitialized) {\r\n this.handleClose();\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────────────────\r\n // PUBLIC: authenticate\r\n // ─────────────────────────────────────────────────────────────────────────\r\n async authenticate() {\r\n try {\r\n console.info(\r\n `[MyGigsters Card SDK] Authenticating in \"${this.config.env}\" mode → ${this.config.baseUrl}`\r\n );\r\n\r\n const authResult = await this.api.authenticate(\r\n this.config.apiKey,\r\n this.config.apiSecret\r\n );\r\n\r\n this.authToken = authResult.token;\r\n this.airwallexClientId = authResult.clientId;\r\n\r\n if (authResult.expiresIn) {\r\n this.tokenExpiresAt = Date.now() + authResult.expiresIn * 1000;\r\n }\r\n\r\n console.info('[MyGigsters Card SDK] Authentication successful.');\r\n if (this.config.env === 'demo' || this.config.env === 'dev') {\r\n console.info(`ℹ️ Connected to [${this.config.env.toUpperCase()}] backend.`);\r\n }\r\n } catch (error) {\r\n const msg = error.message || '';\r\n if (msg.includes('401') || msg.toLowerCase().includes('unauthorized')) {\r\n throw new Error(\r\n 'Invalid API credentials: Please check your apiKey and apiSecret.'\r\n );\r\n }\r\n throw new Error(`Authentication failed: ${msg}`);\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────────────────\r\n // HANDLERS\r\n // ─────────────────────────────────────────────────────────────────────────\r\n handleClose() {\r\n const onCloseCb = this.config?.onClose;\r\n // Destroy completely so modal is removed from DOM\r\n this.destroy();\r\n if (onCloseCb) {\r\n try {\r\n onCloseCb();\r\n } catch (err) {\r\n console.error('Error in onClose callback:', err);\r\n }\r\n }\r\n }\r\n\r\n async handleSubmit() {\r\n if (this.isSubmitting) return;\r\n if (!this.renderer.state.cardComplete) return;\r\n\r\n this.isSubmitting = true;\r\n this.renderer.setSubmitting(true);\r\n this.renderer.setError('');\r\n\r\n try {\r\n // ── Create payment consent via Airwallex ──────────────────────────────\r\n const response = await Airwallex.createPaymentConsent({\r\n customer_id: this.config.customerId,\r\n client_secret: this.clientSecret,\r\n currency: 'AUD',\r\n element: this.cardElement,\r\n requires_cvc: false,\r\n next_triggered_by: 'merchant',\r\n });\r\n\r\n const paymentConsentId = response.payment_consent_id;\r\n\r\n if (!paymentConsentId) {\r\n throw new Error('Failed to create payment consent from card element');\r\n }\r\n\r\n // ── Save consent to backend ───────────────────────────────────────────\r\n const authHeader = (this.config.apiKey && this.config.apiSecret)\r\n ? `Basic ${btoa(`${this.config.apiKey}:${this.config.apiSecret}`)}`\r\n : (this.authToken ? `Bearer ${this.authToken}` : null);\r\n\r\n const result = await this.api.saveConsent(\r\n this.config.customerId,\r\n paymentConsentId,\r\n authHeader\r\n );\r\n\r\n const successPayload = {\r\n ...result,\r\n paymentConsentId,\r\n customerId: this.config.customerId,\r\n myGigsterId: this.config.myGigsterId,\r\n accountId: this.config.accountId,\r\n timestamp: new Date().toISOString(),\r\n event: 'card.saved',\r\n };\r\n\r\n // ── Show success UI ──────────────────────────────────────────────────\r\n this.renderer.showSuccess(successPayload);\r\n\r\n // Trigger onSuccess callback\r\n if (this.config?.onSuccess) {\r\n this.config.onSuccess(successPayload);\r\n }\r\n\r\n } catch (error) {\r\n const message =\r\n error.message || 'Payment could not be completed. Please check your card details and try again.';\r\n this.renderer.setError(message);\r\n this.renderer.setSubmitting(false);\r\n\r\n if (this.config?.onError) {\r\n this.config.onError(error);\r\n }\r\n } finally {\r\n this.isSubmitting = false;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────────────────\r\n // PRIVATE: Card initialization sequence\r\n // ─────────────────────────────────────────────────────────────────────────\r\n async _initializeCard() {\r\n try {\r\n // ── Step 1: Get client secret from backend ────────────────────────────\r\n const authHeader = (this.config.apiKey && this.config.apiSecret)\r\n ? `Basic ${btoa(`${this.config.apiKey}:${this.config.apiSecret}`)}`\r\n : (this.authToken ? `Bearer ${this.authToken}` : null);\r\n\r\n const { clientSecret } = await this.api.getClientSecret(\r\n this.config.customerId,\r\n this.config.accountId,\r\n authHeader\r\n );\r\n this.clientSecret = clientSecret;\r\n\r\n // ── Step 2: Load Airwallex SDK ────────────────────────────────────────\r\n await Airwallex.loadAirwallex();\r\n\r\n // ── Step 3: Initialize Airwallex ──────────────────────────────────────\r\n const airwallexInitOptions = {\r\n env: AIRWALLEX_ENV[this.config.env] || 'demo',\r\n origin: window.location.origin,\r\n };\r\n if (this.airwallexClientId) {\r\n airwallexInitOptions.clientId = this.airwallexClientId;\r\n }\r\n Airwallex.init(airwallexInitOptions);\r\n\r\n // ── Step 4: Create card element with responsive styles ────────────────\r\n const isLight = this.config.mode === 'light';\r\n const cardStyleBase = {\r\n color: isLight ? '#0f172a' : '#ffffff',\r\n fontSize: '15px',\r\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n '::placeholder': {\r\n color: isLight ? '#94a3b8' : 'rgba(255, 255, 255, 0.45)',\r\n fontSize: '15px',\r\n },\r\n };\r\n\r\n const card = Airwallex.createElement('card', {\r\n style: { base: cardStyleBase },\r\n });\r\n\r\n this.cardElement = card;\r\n\r\n // ── Step 5: Show card area (before mount) ─────────────────────────────\r\n this.renderer.setCardLoaded();\r\n\r\n // Allow DOM to settle before mounting\r\n await new Promise((r) => setTimeout(r, 0));\r\n\r\n // ── Step 6: Mount card element ────────────────────────────────────────\r\n const cardRoot = this.shadowRoot.querySelector('#card-root');\r\n if (!cardRoot) throw new Error('Card mount point not found');\r\n\r\n try {\r\n card.mount(cardRoot);\r\n } catch (_) {\r\n // Fallback: try mounting by ID selector\r\n card.mount('#card-root');\r\n }\r\n\r\n this.renderer.markCardMounted();\r\n\r\n // ── Step 7: Listen for card change events ─────────────────────────────\r\n card.on('change', (event) => {\r\n const complete = event?.detail?.complete || false;\r\n this.renderer.setCardComplete(complete);\r\n });\r\n\r\n } catch (error) {\r\n // Show initialization error in the UI\r\n const message = error.message || 'Failed to load card elements';\r\n this.renderer.showInitError(message);\r\n\r\n if (this.config?.onError) {\r\n this.config.onError(error);\r\n }\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────────────────────\r\n // PUBLIC: show / hide / destroy / setTheme / getInstance\r\n // ─────────────────────────────────────────────────────────────────────────\r\n show() {\r\n if (!this.isInitialized) {\r\n throw new Error('SDK not initialized. Call init() first.');\r\n }\r\n if (this.host) {\r\n this.host.style.display = 'block';\r\n this.host.style.width = '100vw';\r\n this.host.style.height = '100vh';\r\n this.host.style.pointerEvents = 'auto';\r\n }\r\n }\r\n\r\n hide() {\r\n if (this.host) {\r\n this.host.style.display = 'none';\r\n this.host.style.width = '0';\r\n this.host.style.height = '0';\r\n this.host.style.pointerEvents = 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Update the theme after initialization.\r\n * @param {'light'|'dark'} mode\r\n */\r\n setTheme(mode) {\r\n if (!this.shadowRoot) return;\r\n const themeContainer = this.shadowRoot.querySelector('#mc-theme-container');\r\n if (themeContainer) {\r\n themeContainer.setAttribute('data-theme', mode === 'light' ? 'light' : 'dark');\r\n }\r\n if (this.config) this.config.mode = mode;\r\n }\r\n\r\n destroy() {\r\n // ── Remove keydown listener ────────────────────────────────────────────\r\n window.removeEventListener('keydown', this._handleKeyDown);\r\n\r\n // ── Unmount Airwallex card element ──────────────────────────────────────\r\n if (this.cardElement) {\r\n try {\r\n this.cardElement.unmount();\r\n } catch (_) {\r\n // Idempotent\r\n }\r\n }\r\n\r\n // ── Clean up renderer ──────────────────────────────────────────────────\r\n if (this.renderer) {\r\n this.renderer.destroy();\r\n }\r\n\r\n // ── Remove host from DOM ───────────────────────────────────────────────\r\n if (this.host?.parentNode) {\r\n this.host.parentNode.removeChild(this.host);\r\n }\r\n const existingHost = document.getElementById('mygigsters-card-sdk-host');\r\n if (existingHost?.parentNode) {\r\n existingHost.parentNode.removeChild(existingHost);\r\n }\r\n\r\n // ── Reset references ───────────────────────────────────────────────────\r\n this.isInitialized = false;\r\n this.isSubmitting = false;\r\n this.config = null;\r\n this.api = null;\r\n this.renderer = null;\r\n this.host = null;\r\n this.shadowRoot = null;\r\n this.cardElement = null;\r\n this.clientSecret = null;\r\n this.authToken = null;\r\n this.tokenExpiresAt = null;\r\n this.airwallexClientId = null;\r\n }\r\n}\r\n\r\n// ─── Export for npm / modern bundler usage ────────────────────────────────────\r\nlet sdkInstance = null;\r\n\r\nconst MygigstersCard = {\r\n init: async (config) => {\r\n if (sdkInstance) {\r\n sdkInstance.destroy();\r\n sdkInstance = null;\r\n }\r\n sdkInstance = new MygigstersCardSDK();\r\n await sdkInstance.init(config);\r\n return sdkInstance;\r\n },\r\n\r\n show: () => {\r\n sdkInstance?.show();\r\n },\r\n\r\n hide: () => {\r\n sdkInstance?.hide();\r\n },\r\n\r\n destroy: () => {\r\n if (sdkInstance) {\r\n sdkInstance.destroy();\r\n sdkInstance = null;\r\n }\r\n },\r\n\r\n setTheme: (mode) => {\r\n sdkInstance?.setTheme(mode);\r\n },\r\n\r\n getInstance: () => sdkInstance,\r\n};\r\n\r\nexport { MygigstersCardSDK, MygigstersCard };\r\nexport default MygigstersCardSDK;\r\n\r\n// ─── CDN / window global (singleton pattern) ──────────────────────────────────\r\nif (typeof window !== 'undefined') {\r\n window.MygigstersCard = MygigstersCard;\r\n window.MygigstersCardSDK = MygigstersCardSDK;\r\n\r\n // ── Auto-initialize if script tag carries data-mygigsters-config ────────\r\n document.addEventListener('DOMContentLoaded', () => {\r\n const scriptTag = document.querySelector(\r\n 'script[data-mygigsters-config][src*=\"card-sdk\"]'\r\n );\r\n if (scriptTag) {\r\n try {\r\n const config = JSON.parse(scriptTag.dataset.mygigstersConfig);\r\n window.MygigstersCard.init(config).catch((err) => {\r\n console.error('MyGigsters Card SDK auto-init failed:', err);\r\n });\r\n } catch (error) {\r\n console.error('Failed to parse MyGigsters Card SDK config:', error);\r\n }\r\n }\r\n });\r\n}\r\n"],"names":["CardAPI","constructor","baseUrl","this","replace","_post","path","body","token","extraHeaders","headers","startsWith","response","fetch","method","JSON","stringify","rawText","text","data","trim","length","parse","ok","errMsg","message","error","statusText","status","Error","authenticate","apiKey","apiSecret","credentials","btoa","Authorization","success","clientId","expiresIn","tokenType","paymentsIndia","getClientSecret","customerId","accountId","console","log","hasToken","result","secret","client_secret","clientSecret","saveConsent","paymentConsentId","ICONS","CardRenderer","shadowRoot","callbacks","state","loading","cardLoaded","cardComplete","submitting","_cardMounted","_getContainer","container","querySelector","document","createElement","id","themeContainer","appendChild","render","innerHTML","_attachListeners","querySelectorAll","forEach","btn","addEventListener","e","preventDefault","stopPropagation","onClose","backdrop","target","submitBtn","onSubmit","closest","setCardLoaded","cardWrapper","style","display","markCardMounted","setCardComplete","complete","disabled","setSubmitting","setError","banner","textContent","showInitError","_escapeHtml","showSuccess","modal","str","div","destroy","prod","demo","staging","dev","local","r","o","n","src","crossOrigin","head","y","async","window","Airwallex","l","t","env","Promise","init","remove","setTimeout","createPaymentConsent","ENV_URLS","AIRWALLEX_ENV","MygigstersCardSDK","config","api","renderer","host","cardElement","authToken","tokenExpiresAt","airwallexClientId","isInitialized","isSubmitting","_handleKeyDown","bind","resolvedMyGigsterId","myGigsterId","containerId","getElementById","mode","onSuccess","onError","err","existingHost","parentNode","removeChild","cssText","attachShadow","styleElement","setAttribute","handleClose","handleSubmit","show","_initializeCard","key","info","authResult","Date","now","toUpperCase","msg","includes","toLowerCase","onCloseCb","customer_id","currency","element","requires_cvc","next_triggered_by","payment_consent_id","authHeader","successPayload","timestamp","toISOString","event","airwallexInitOptions","origin","location","isLight","card","base","color","fontSize","fontFamily","cardRoot","mount","_","on","detail","width","height","pointerEvents","hide","setTheme","removeEventListener","unmount","sdkInstance","MygigstersCard","getInstance","scriptTag","dataset","mygigstersConfig","catch"],"mappings":"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","x_google_ignoreList":[3]}