# PreviewCard — accessible headless hover preview card
#
# Shows a floating card on hover/focus of a trigger element. Dismisses
# on mouse leave or blur. Ships zero CSS.
#
# Usage:
#   PreviewCard delay: 400
#     a $trigger: true, href: "/user/42", "View Profile"
#     div $content: true
#       p "User details here..."

export PreviewCard = component
  @delay := 400
  @closeDelay := 200

  open := false
  _ready := false
  _openTimer := null
  _closeTimer := null

  beforeUnmount: ->
    clearTimeout _openTimer if _openTimer
    clearTimeout _closeTimer if _closeTimer

  mounted: ->
    _ready = true
    trigger = @_root?.querySelector('[data-trigger]')
    return unless trigger
    trigger.addEventListener 'mouseenter', =>
      clearTimeout _closeTimer if _closeTimer
      _openTimer = setTimeout (=> open = true; @_position()), @delay
    trigger.addEventListener 'mouseleave', =>
      clearTimeout _openTimer if _openTimer
      _closeTimer = setTimeout (=> open = false), @closeDelay
    trigger.addEventListener 'focus', =>
      clearTimeout _closeTimer if _closeTimer
      _openTimer = setTimeout (=> open = true; @_position()), @delay
    trigger.addEventListener 'blur', =>
      clearTimeout _openTimer if _openTimer
      _closeTimer = setTimeout (=> open = false), @closeDelay

  _position: ->
    trigger = @_root?.querySelector('[data-trigger]')
    floating = @_root?.querySelector('[data-content]')
    return unless trigger and floating
    @_root.style.position = 'relative'
    tr = trigger.getBoundingClientRect()
    cr = @_root.getBoundingClientRect()
    floating.style.position = 'absolute'
    floating.style.left = "0px"
    floating.style.top = "#{tr.bottom - cr.top + 4}px"
    floating.style.zIndex = '50'

  ~>
    return unless _ready
    floating = @_root?.querySelector('[data-content]')
    return unless floating
    floating.hidden = not open
    if open
      floating.setAttribute 'data-open', ''
      onEnter = => clearTimeout _closeTimer if _closeTimer
      onLeave = => _closeTimer = setTimeout (=> open = false), @closeDelay
      floating.addEventListener 'mouseenter', onEnter
      floating.addEventListener 'mouseleave', onLeave
      return ->
        floating.removeEventListener 'mouseenter', onEnter
        floating.removeEventListener 'mouseleave', onLeave
    else
      floating.removeAttribute 'data-open'

  render
    div ref: "_root"
      slot
