{"version":3,"sources":["../src/detect/detect.ts"],"names":["isIOSDevice","nav","ua","isIOSSafari","isSafari","isIOSHomeScreenWebApp","win","getExtensionInstallState","detectPlatform","resolve","immediateState","getInstallState","checks","interval","state","isExtensionInstalled"],"mappings":"qCAsBO,SAASA,CAAAA,CAAYC,CAAAA,CAAyB,CACnD,IAAMC,EAAKD,CAAAA,CAAI,SAAA,CACf,OAAO,kBAAA,CAAmB,IAAA,CAAKC,CAAE,CAAA,EAAMD,CAAAA,CAAI,WAAa,UAAA,EAAcA,CAAAA,CAAI,cAAA,CAAiB,CAC7F,CAEO,SAASE,CAAAA,EAAuB,CACrC,GAAI,OAAO,SAAA,CAAc,GAAA,CAAa,OAAO,OAE7C,IAAMC,CAAAA,CAAW,4CAAA,CAA6C,IAAA,CAAK,UAAU,SAAS,CAAA,CAEtF,OAAOJ,CAAAA,CAAY,SAAS,CAAA,EAAKI,CACnC,CAsBO,SAASC,CAAAA,CAAsBJ,CAAAA,CAAgBK,CAAAA,CAAsB,CAC1E,OACEN,CAAAA,CAAYC,CAAG,CAAA,GACbA,EAA6C,UAAA,GAAe,IAAA,EAC3D,OAAOK,CAAAA,CAAI,UAAA,EAAe,UAAA,EAAcA,CAAAA,CAAI,UAAA,CAAW,4BAA4B,CAAA,CAAE,OAAA,CAE5F,CAEA,eAAsBC,GAA2D,CAG/E,GAAI,CACF,GAAM,CAAE,cAAA,CAAAC,CAAe,CAAA,CAAI,MAAM,OAAO,yBAAa,CAAA,CACrD,GAAIA,GAAe,GAAM,kBAAA,CAAoB,OAAO,QACtD,CAAA,KAAQ,CAAqE,CAE7E,OAAO,IAAI,OAAA,CAASC,CAAAA,EAAY,CAE9B,IAAMC,CAAAA,CAAiBC,CAAAA,EAAgB,CACvC,GAAID,IAAmB,eAAA,CAAiB,CACtCD,CAAAA,CAAQC,CAAc,EACtB,MACF,CAIA,IAAIE,CAAAA,CAAS,EACPC,CAAAA,CAAW,WAAA,CAAY,IAAM,CACjCD,CAAAA,EAAAA,CACA,IAAME,CAAAA,CAAQH,CAAAA,GACVG,CAAAA,GAAU,eAAA,GACZ,aAAA,CAAcD,CAAQ,EACtBJ,CAAAA,CAAQK,CAAK,CAAA,CAAA,CAEXF,CAAAA,CAAS,KAEX,aAAA,CAAcC,CAAQ,CAAA,CACtBJ,CAAAA,CAAQ,eAAe,CAAA,EAE3B,CAAA,CAAG,GAAG,EACR,CAAC,CACH,CAEA,eAAsBM,GAAyC,CAC7D,OAAQ,MAAMR,CAAAA,KAAgC,eAChD","file":"chunk-CI3DFY6L.mjs","sourcesContent":["/**\n * Platform detection utilities for Beacio\n */\n\n// SB-SDK-12: the install-state marker derivation now lives in the single shared\n// install-state module (consumed here, by the react-sdk ExtensionDetector, and by\n// the headless API), so the detection logic is shared rather than duplicated.\nimport { getInstallState, type ExtensionInstallState } from './install-state';\n\nexport type { ExtensionInstallState } from './install-state';\n\n/**\n * Is this an iOS/iPadOS DEVICE, irrespective of which browser engine surface is\n * rendering the page? Extracted from {@link isIOSSafari} because GH #448 needs the\n * device test WITHOUT the `Safari/`-token test: a Home Screen web app runs on iOS\n * but reports neither `Safari/` nor `Version/`. iPadOS presents a desktop\n * \"Macintosh\" UA, so the `MacIntel` + touch-points pair is the arm that catches it.\n *\n * `nav` is a REQUIRED parameter (owner's no-optional-args rule) — the caller owns\n * the `typeof navigator === 'undefined'` guard, and passing the global explicitly\n * keeps the predicate pure and testable without mutating jsdom.\n */\nexport function isIOSDevice(nav: Navigator): boolean {\n  const ua = nav.userAgent;\n  return /iPad|iPhone|iPod/.test(ua) || (nav.platform === 'MacIntel' && nav.maxTouchPoints > 1);\n}\n\nexport function isIOSSafari(): boolean {\n  if (typeof navigator === 'undefined') return false;\n\n  const isSafari = /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);\n\n  return isIOSDevice(navigator) && isSafari;\n}\n\n/**\n * GH #448: is this page running as an iOS Home Screen web app (\"Add to Home\n * Screen\" with \"Open as Web App\" ON)? Safari extensions NEVER load in that\n * standalone context, so beacio is inert there even when the app is installed and\n * enabled — and because the standalone UA drops the `Safari/` token,\n * {@link isIOSSafari} is false and every caller would otherwise report the generic\n * \"unsupported browser\" / \"not installed\" dead end instead of the real diagnosis\n * (\"open this page in Safari, or re-add it with Open as Web App off\").\n *\n * Two signals, either of which is sufficient: the classic WebKit\n * `navigator.standalone` boolean, and the `(display-mode: standalone)` media query\n * (which also covers third-party-browser Home Screen web apps on iOS 16.4+, where\n * extensions are likewise unavailable — the diagnosis holds). This is a\n * DETERMINISTIC platform API, not a heuristic like the Private-Browsing probe.\n *\n * `nav` and `win` are REQUIRED parameters: the caller owns the\n * `typeof window !== 'undefined'` guard. The `typeof win.matchMedia` test is not an\n * optionality check on our own API — it is a capability probe for environments\n * (jsdom, older WebKit) that do not implement matchMedia at all.\n */\nexport function isIOSHomeScreenWebApp(nav: Navigator, win: Window): boolean {\n  return (\n    isIOSDevice(nav) &&\n    ((nav as Navigator & { standalone?: boolean }).standalone === true ||\n      (typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches))\n  );\n}\n\nexport async function getExtensionInstallState(): Promise<ExtensionInstallState> {\n  // Fast-path: use core's platform detection (detect now lives INSIDE @beacio/core,\n  // so this is an intra-package import — no optional-peer boundary any more).\n  try {\n    const { detectPlatform } = await import('../platform');\n    if (detectPlatform() === 'safari-extension') return 'active';\n  } catch { /* defensive — platform probe must never throw the install flow */ }\n\n  return new Promise((resolve) => {\n    // Method 1: Check for the global marker set by injected-full.ts\n    const immediateState = getInstallState();\n    if (immediateState !== 'not-installed') {\n      resolve(immediateState);\n      return;\n    }\n\n    // Method 3: Wait briefly for injection to complete\n    // The content script runs at document_start, so injection should be fast\n    let checks = 0;\n    const interval = setInterval(() => {\n      checks++;\n      const state = getInstallState();\n      if (state !== 'not-installed') {\n        clearInterval(interval);\n        resolve(state);\n      }\n      if (checks > 20) {\n        // 2 seconds max wait\n        clearInterval(interval);\n        resolve('not-installed');\n      }\n    }, 100);\n  });\n}\n\nexport async function isExtensionInstalled(): Promise<boolean> {\n  return (await getExtensionInstallState()) !== 'not-installed';\n}\n"]}