{"version":3,"file":"vgs-collect-loader-CTLSv4qv.mjs","names":["loadPromise: Promise<void> | null","observers: MutationObserver[]","containers: Element[]","fieldMap: [VGSCollectField, string][]"],"sources":["../src/payment-methods/vgs-collect-loader.ts"],"sourcesContent":["const VGS_COLLECT_CDN = \"https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js\";\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads VGS Collect JS from CDN. Idempotent — subsequent calls return the same promise.\n */\nexport function loadVgsCollectScript(): Promise<void> {\n  if (loadPromise) {\n    console.log(\"[PaymentKit] VGS Collect CDN load already in progress — reusing promise\");\n    return loadPromise;\n  }\n\n  loadPromise = new Promise<void>((resolve, reject) => {\n    if (typeof window !== \"undefined\" && window.VGSCollect) {\n      console.log(\"[PaymentKit] VGS Collect JS already available on window\");\n      resolve();\n      return;\n    }\n\n    console.log(`[PaymentKit] Loading VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n    const script = document.createElement(\"script\");\n    script.src = VGS_COLLECT_CDN;\n    script.async = true;\n    script.onload = () => {\n      console.log(\"[PaymentKit] VGS Collect JS loaded successfully from CDN\");\n      resolve();\n    };\n    script.onerror = () => {\n      console.error(`[PaymentKit] Failed to load VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n      loadPromise = null;\n      reject(new Error(\"Failed to load VGS Collect JS\"));\n    };\n    document.head.appendChild(script);\n  });\n\n  return loadPromise;\n}\n\n/**\n * Initializes a VGS Collect form instance.\n */\nexport function initVgsCollect(vaultId: string, environment: string): VGSCollectForm {\n  if (!window.VGSCollect) {\n    throw new Error(\"VGS Collect JS not loaded. Call loadVgsCollectScript() first.\");\n  }\n  return window.VGSCollect.create(vaultId, environment, () => {});\n}\n\n/**\n * Creates and mounts VGS Collect card fields using CMP-specific field methods.\n *\n * Uses cardNumberField(), cardExpirationDateField(), cardCVCField() which are\n * required for the CMP createCard() flow. After mounting, call form.createCard()\n * to create a card in the VGS vault, which returns aliases for PAN and CVC.\n *\n * @param form - VGS Collect form instance\n * @param mountPoints - CSS selectors for PAN, expiry, and CVC containers\n * @param css - Optional CSS to apply to VGS Collect iframe fields\n */\nexport function createVgsCardFields(\n  form: VGSCollectForm,\n  mountPoints: { pan: string; exp: string; cvc: string },\n  css?: Record<string, string>,\n  onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>,\n  placeholders?: Partial<Record<string, string>>,\n): () => void {\n  // Read container padding so the VGS input content matches the merchant's\n  // visual intent. The iframe uses absolute positioning (inset: 0) to fill\n  // the full container, so the input needs its own padding for alignment.\n  const sampleContainer = document.querySelector(mountPoints.pan) as HTMLElement | null;\n  const containerPadding = sampleContainer ? getComputedStyle(sampleContainer).padding : undefined;\n\n  const baseCss = css ?? {\n    \"font-size\": \"1rem\",\n    color: \"#18181b\",\n    \"font-family\": \"ui-sans-serif, system-ui, sans-serif\",\n  };\n\n  const fieldCss = {\n    ...baseCss,\n    height: \"100%\",\n    \"box-sizing\": \"border-box\",\n    ...(containerPadding && containerPadding !== \"0px\" ? { padding: containerPadding } : {}),\n  };\n\n  // Remove stale iframes from previous VGS form mounts to prevent overlap.\n  // VGS's form.unmount() does not remove iframes from the DOM.\n  // IMPORTANT: This must run BEFORE VGS field methods below, because VGS may\n  // insert new iframes synchronously — removing after would destroy fresh iframes.\n  for (const selector of [mountPoints.pan, mountPoints.exp, mountPoints.cvc]) {\n    const container = document.querySelector(selector);\n    if (!container) continue;\n    const staleIframes = container.querySelectorAll(\"iframe\");\n    for (const iframe of staleIframes) {\n      iframe.remove();\n    }\n  }\n\n  const panField = form.cardNumberField(mountPoints.pan, {\n    placeholder: placeholders?.card_pan ?? \"Card number\",\n    validations: [\"required\", \"validCardNumber\"],\n    css: fieldCss,\n  });\n\n  const expField = form.field(mountPoints.exp, {\n    type: \"card-expiration-date\",\n    name: \"exp-date\",\n    placeholder: placeholders?.card_exp ?? \"MM / YY\",\n    yearLength: 2,\n    serializers: [{ name: \"separate\", options: { monthName: \"month\", yearName: \"year\" } }],\n    validations: [\"required\", \"validCardExpirationDate\"],\n    css: fieldCss,\n  });\n\n  const cvcField = form.cardCVCField(mountPoints.cvc, {\n    placeholder: placeholders?.card_cvc ?? \"123\",\n    validations: [\"required\", \"validCardSecurityCode\"],\n    css: fieldCss,\n  });\n\n  // Track observers for cleanup\n  const observers: MutationObserver[] = [];\n  const containers: Element[] = [];\n\n  // VGS Collect doesn't set width/height on its iframes, so they may not\n  // fill the merchant's container. Force them to stretch like direct-mode iframes.\n  // Iframes may be inserted asynchronously, so use MutationObserver as a fallback.\n  for (const selector of [mountPoints.pan, mountPoints.exp, mountPoints.cvc]) {\n    const container = document.querySelector(selector);\n    if (!container) continue;\n    containers.push(container);\n\n    const styleIframe = (iframe: HTMLIFrameElement) => {\n      // Use absolute positioning so the iframe covers the full container\n      // including any padding the merchant's CSS applies.\n      const containerEl = container as HTMLElement;\n      if (getComputedStyle(containerEl).position === \"static\") {\n        containerEl.style.position = \"relative\";\n      }\n      iframe.style.position = \"absolute\";\n      iframe.style.inset = \"0\";\n      iframe.style.width = \"100%\";\n      iframe.style.height = \"100%\";\n      iframe.style.border = \"none\";\n    };\n\n    // Always set up a MutationObserver to catch asynchronously inserted iframes.\n    // VGS inserts iframes after field creation, so we need the observer even if\n    // no iframe exists yet.\n    const observer = new MutationObserver(() => {\n      const iframe = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n      if (iframe && iframe.style.position !== \"absolute\") {\n        styleIframe(iframe);\n      }\n    });\n    observer.observe(container, { childList: true, subtree: true });\n    observers.push(observer);\n\n    // Style any iframe VGS may have inserted synchronously during field creation.\n    // The MutationObserver only fires on future mutations, so this handles the\n    // case where VGS inserts the iframe before the observer is attached.\n    const existing = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n    if (existing && existing.style.position !== \"absolute\") {\n      styleIframe(existing);\n    }\n  }\n\n  if (onFocusChangeCallbacks) {\n    const fieldMap: [VGSCollectField, string][] = [\n      [panField, \"card_pan\"],\n      [expField, \"card_exp\"],\n      [cvcField, \"card_cvc\"],\n    ];\n    for (const [field, key] of fieldMap) {\n      const cb = onFocusChangeCallbacks[key];\n      if (cb) {\n        field.on(\"focus\", () => cb(true));\n        field.on(\"blur\", () => cb(false));\n      }\n    }\n  }\n\n  // Return cleanup function to disconnect observers and remove iframes\n  return () => {\n    for (const observer of observers) {\n      observer.disconnect();\n    }\n    for (const container of containers) {\n      const iframes = container.querySelectorAll(\"iframe\");\n      for (const iframe of iframes) {\n        iframe.remove();\n      }\n    }\n  };\n}\n"],"mappings":"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"}