# Drawer — accessible headless slide-out panel
#
# A Dialog variant that slides from an edge of the screen.
# Supports dismiss on escape, click-outside, and optional swipe-to-close.
# Ships zero CSS.
#
# Usage:
#   Drawer open <=> showDrawer, side: "right"
#     h2 "Settings"
#     p "Panel content here"

export Drawer = component
  @open:: boolean := false
  @side:: "top" | "right" | "bottom" | "left" := "right"
  @dismissable:: boolean := true

  _prevFocus = null
  _id =! "drw-#{Math.random().toString(36).slice(2, 8)}"

  ~>
    ARIA.bindDialog @open, (=> @_dialog), ((isOpen) =>
      if not isOpen and @open
        @open = false
        @emit 'close'
    ), @dismissable

  ~>
    if @open
      _prevFocus = document.activeElement
      ARIA.lockScroll(this)
      requestAnimationFrame =>
        panel = @_dialog
        if panel
          ARIA.wireAria panel, _id
          panel.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')?[0]?.focus()
      return ->
        ARIA.unlockScroll(this)
        _prevFocus?.focus()

  close: ->
    @open = false
    @emit 'close'

  onKeydown: (e) ->
    if e.key is 'Escape' and @dismissable
      e.preventDefault()
      @close()

  onBackdropClick: (e) ->
    if e.target is e.currentTarget and @dismissable
      @_dialog?.close()

  render
    dialog ref: "_dialog", $open: @open?!, $side: @side
      @click: @onBackdropClick
      @keydown: @onKeydown
      $side: @side
      slot
