{"version":3,"file":"index.mjs","names":[],"sources":["../../src/GlobalFocusRing/index.ts"],"sourcesContent":["import { globalFocusRingCSS } from './style';\n\nconst installations = new WeakMap<Document, { dispose: () => void; users: number }>();\n\n/** Install once per document. The returned cleanup is safe for nested providers and Strict Mode. */\nexport const installGlobalFocusRing = (doc: Document = document): (() => void) => {\n  const existing = installations.get(doc);\n  if (existing) {\n    existing.users += 1;\n    let released = false;\n    return () => {\n      if (released) return;\n      released = true;\n      if (--existing.users === 0) existing.dispose();\n    };\n  }\n\n  const win = doc.defaultView;\n  if (\n    !win ||\n    !doc.body ||\n    !win.CSS?.supports('top', 'anchor(top)') ||\n    !win.CSS.supports('position-visibility', 'anchors-visible') ||\n    !('showPopover' in doc.createElement('div'))\n  )\n    return () => {};\n\n  const sheet = doc.createElement('style');\n  sheet.textContent = globalFocusRingCSS;\n  const ring = doc.createElement('div');\n  ring.setAttribute('data-lobe-global-focus-ring', '');\n  ring.setAttribute('aria-hidden', 'true');\n  ring.setAttribute('popover', 'manual');\n  doc.head.append(sheet);\n  doc.body.append(ring);\n\n  let target: HTMLElement | undefined;\n  let restoreTarget: (() => void) | undefined;\n  let frame = 0;\n  let disposed = false;\n\n  const clear = () => {\n    if (ring.matches(':popover-open')) ring.hidePopover();\n    restoreTarget?.();\n    restoreTarget = undefined;\n    target = undefined;\n  };\n\n  const sync = () => {\n    if (disposed) return;\n    const next = doc.activeElement;\n    if (\n      next === target &&\n      next?.matches(':focus-visible') &&\n      next.isConnected &&\n      ring.matches(':popover-open')\n    )\n      return;\n    clear();\n    // Shadow roots and fragmented inline text retain their own focus treatment.\n    if (\n      !next ||\n      next === doc.body ||\n      next.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||\n      next.shadowRoot ||\n      next.closest('[data-lobe-focus-ring=\"off\"]') ||\n      next.matches('textarea') ||\n      (next as HTMLElement).isContentEditable ||\n      (next.matches('input') &&\n        ![\n          'button',\n          'submit',\n          'reset',\n          'image',\n          'checkbox',\n          'radio',\n          'range',\n          'color',\n          'file',\n        ].includes((next as HTMLInputElement).type)) ||\n      !next.matches(':focus-visible')\n    )\n      return;\n\n    const element = next as HTMLElement;\n    let scope = element.parentElement;\n    while (scope && win.getComputedStyle(scope).contain === 'none') scope = scope.parentElement;\n    // Anchor names do not cross CSS containment, while a popover still escapes its clipping.\n    const ringParent = scope || doc.body;\n    const moved = ring.parentElement !== ringParent;\n    if (moved) ringParent.append(ring);\n\n    const computed = win.getComputedStyle(element);\n    const borderRadius = computed.borderRadius;\n    const color =\n      computed.getPropertyValue('--lobe-focus-ring-color').trim() ||\n      computed.getPropertyValue('--ant-color-info').trim() ||\n      '#1677ff';\n    const styleChanged =\n      ring.style.borderRadius !== borderRadius ||\n      ring.style.getPropertyValue('--lobe-focus-ring-color') !== color;\n    if (styleChanged) {\n      ring.style.borderRadius = borderRadius;\n      ring.style.setProperty('--lobe-focus-ring-color', color);\n    }\n    if (moved || styleChanged) {\n      schedule();\n      return;\n    }\n\n    const saved = ['anchor-name', 'outline'].map((property) => ({\n      priority: element.style.getPropertyPriority(property),\n      property,\n      value: element.style.getPropertyValue(property),\n    }));\n    const oldMarker = element.getAttribute('data-lobe-focus-ring');\n    const anchor = computed.getPropertyValue('anchor-name').trim();\n    const assignedAnchor =\n      anchor && anchor !== 'none' ? `${anchor}, --lobe-global-focus` : '--lobe-global-focus';\n    element.style.setProperty('anchor-name', assignedAnchor, 'important');\n\n    restoreTarget = () => {\n      for (const { property, value, priority } of saved) {\n        const assigned = property === 'anchor-name' ? assignedAnchor : 'none';\n        if (element.style.getPropertyValue(property) !== assigned) continue;\n        if (value) element.style.setProperty(property, value, priority);\n        else element.style.removeProperty(property);\n      }\n      if (element.getAttribute('data-lobe-focus-ring') === 'managed') {\n        if (oldMarker === null) element.removeAttribute('data-lobe-focus-ring');\n        else element.setAttribute('data-lobe-focus-ring', oldMarker);\n      }\n    };\n    const rect = element.getBoundingClientRect();\n    if (\n      element.getClientRects().length !== 1 ||\n      !rect.width ||\n      !rect.height ||\n      computed.visibility !== 'visible'\n    ) {\n      clear();\n      return;\n    }\n    try {\n      ring.showPopover();\n      // Do not suppress a working native outline when an anchor cannot resolve.\n      const bounds = ring.getBoundingClientRect();\n      if (\n        Math.max(\n          ...(['top', 'right', 'bottom', 'left'] as const).map((edge) =>\n            Math.abs(bounds[edge] - rect[edge]),\n          ),\n        ) > 1\n      ) {\n        clear();\n        return;\n      }\n      element.style.setProperty('outline', 'none', 'important');\n      element.setAttribute('data-lobe-focus-ring', 'managed');\n      target = element;\n    } catch {\n      clear();\n    }\n  };\n\n  const schedule = () => {\n    if (!frame)\n      frame = win.requestAnimationFrame(() => {\n        frame = 0;\n        sync();\n      });\n  };\n  const focus = () => win.queueMicrotask(sync);\n  const blur = () => {\n    win.cancelAnimationFrame(frame);\n    frame = 0;\n    if (ring.matches(':popover-open')) ring.hidePopover();\n  };\n  const observer = new MutationObserver(() => {\n    if (target && !target.isConnected) clear();\n  });\n  observer.observe(doc.body, { childList: true, subtree: true });\n  doc.addEventListener('focusin', focus, true);\n  doc.addEventListener('focusout', schedule, true);\n  doc.addEventListener('keydown', schedule, true);\n  doc.addEventListener('pointerdown', schedule, true);\n  win.addEventListener('blur', blur);\n  win.addEventListener('focus', schedule);\n\n  const installation = {\n    dispose: () => {\n      disposed = true;\n      win.cancelAnimationFrame(frame);\n      observer.disconnect();\n      doc.removeEventListener('focusin', focus, true);\n      doc.removeEventListener('focusout', schedule, true);\n      doc.removeEventListener('keydown', schedule, true);\n      doc.removeEventListener('pointerdown', schedule, true);\n      win.removeEventListener('blur', blur);\n      win.removeEventListener('focus', schedule);\n      clear();\n      ring.remove();\n      sheet.remove();\n      installations.delete(doc);\n    },\n    users: 0,\n  };\n  installations.set(doc, installation);\n  sync();\n  return installGlobalFocusRing(doc);\n};\n"],"mappings":"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"}