# Collapsible — accessible headless expand/collapse section
#
# Single open/close section. Simpler than Accordion (no item IDs,
# no single/multiple mode). Exposes content dimensions as CSS
# custom properties for animated expand/collapse. Ships zero CSS.
#
# Usage:
#   Collapsible open <=> isOpen
#     button $trigger: true, "Show details"
#     div $content: true
#       p "Hidden content here"

export Collapsible = component
  @open:: boolean := false
  @disabled:: boolean := false

  _ready := false

  mounted: ->
    _ready = true
    trigger = @_root?.querySelector('[data-trigger]')
    return unless trigger
    trigger.addEventListener 'click', => @toggle() unless @disabled
    trigger.addEventListener 'keydown', (e) =>
      if e.key in ['Enter', ' '] and not @disabled
        e.preventDefault()
        @toggle()

  toggle: ->
    @open = not @open
    @emit 'change', @open

  ~>
    return unless _ready
    trigger = @_root?.querySelector('[data-trigger]')
    content = @_root?.querySelector('[data-content]')
    if trigger
      trigger.setAttribute 'aria-expanded', !!@open
      if @disabled then trigger.setAttribute 'aria-disabled', true else trigger.removeAttribute 'aria-disabled'
      trigger.tabIndex = if @disabled then -1 else 0
    if content
      content.hidden = not @open
      if @open
        rect = content.getBoundingClientRect()
        content.style.setProperty '--collapsible-height', "#{rect.height}px"
        content.style.setProperty '--collapsible-width', "#{rect.width}px"

  render
    div ref: "_root", $open: @open?!, $disabled: @disabled?!
      slot
