text: /**
   * --------------------------------------------------------------------------
   * Ace (v4.0.0): sidebar.js
     Handling Sidebar
  */
  
  import Util from './util'
  import EventHandler from './event-handler'
  
  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */
  
  const NAME = 'aceSidebar'
  const VERSION = '4.0.0'
  const DATA_KEY = 'ace.sidebar'
  const EVENT_KEY = `.${DATA_KEY}`
  const DATA_API_KEY = '.data-api'
  
  const Event = {
    SHOW: `show${EVENT_KEY}`,
    HIDE: `hide${EVENT_KEY}`,
    COLLAPSE: `collapse${EVENT_KEY}`,
    EXPAND: `expand${EVENT_KEY}`,
    SHOWN: `shown${EVENT_KEY}`,
    HIDDEN: `hidden${EVENT_KEY}`,
    COLLAPSED: `collapsed${EVENT_KEY}`,
    EXPANDED: `expanded${EVENT_KEY}`,
    LOAD_DATA_API: `load${EVENT_KEY}${DATA_API_KEY}`,
    CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`
  }
  
  const Selector = {
    SIDEBAR: '.sidebar',
    DATA_TOGGLE: '[data-toggle="sidebar"]',
    DATA_TOGGLE_MOBILE: '[data-toggle-mobile="sidebar"]'
  }
  
  const DefaultType = {
    swipe: 'boolean',
    dismiss: 'boolean',
    backdrop: 'boolean',
  
    gotoactive: 'boolean',
    subscroll: 'boolean',
    subtoggle: 'boolean',
  
    pullup: 'boolean'
  }
  
  const Default = {
    swipe: false,
    dismiss: false,
    backdrop: false,
  
    gotoactive: false,
    subscroll: true,
    subtoggle: true,
  
    pullup: false
  }
  
  const ClassName = {
    DESKTOP_HIDE: 'collapsed',
    MOBILE_SHOW: 'sidebar-visible',
    COLLAPSED:	'collapsed',
  
    TOGGLING: 'toggling',
  
    INNER_HOVER: 'is-hover',
  
    BACKDROP: 'sidebar-backdrop',
  
    HORIZONTAL: 'sidebar-h'
  }
  
  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */
  
  class Sidebar {
    constructor (element, config) {
      this._config = this._getConfig(config)
  
      this._hasTransitionEvent = false
      this._hasTransitionEventMobile = false
      this._isTransitioning = false
      this._isTransitioningMobile = false
  
      this._sidebar = element
  
      Util.reflow(this._sidebar) // force reflow, so that if we instantly call 'collapse' or 'expand', transition effect takes place
      this._sidebar.classList.add('sidebar')
      this._inner = this._sidebar.querySelector('.sidebar-inner')
      this._scroller = this._sidebar.querySelector('[class*="ace-scroll"]')
  
      this._isSubOpening = false
      if (this._sidebar.querySelector('.submenu.show') !== null) this._sidebar.classList.add('has-open')
  
      this._pullupEnabled = false
      this._pullupCallback = null
  
      this._triggerArray = [].slice.call(document.querySelectorAll(
        `[data-toggle="sidebar"][href="#${element.id}"],` +
        `[data-toggle="sidebar"][data-target="#${element.id}"]`
      ))
      this._triggerArrayMobile = [].slice.call(document.querySelectorAll(
        `[data-toggle-mobile="sidebar"][href="#${element.id}"],` +
        `[data-toggle-mobile="sidebar"][data-target="#${element.id}"]`
      ))
  
      this._horizontal = this._sidebar.classList.contains(ClassName.HORIZONTAL)
      this._desktopCollapsedClass = this._triggerArray.length > 0 ? (this._triggerArray[0].getAttribute('data-toggle-class') || ClassName.DESKTOP_HIDE) : ClassName.DESKTOP_HIDE
  
      //
      this._collapsed = this._sidebar.classList.contains(this._desktopCollapsedClass)
      this._hidden = !this._sidebar.classList.contains(ClassName.MOBILE_SHOW)
  
      EventHandler.on(this._inner, 'focus', 'input', (e) => {
        if (!this._collapsed) return
        this._inner.classList.add('has-focus')
        EventHandler.one(e.delegateTarget, 'blur', () => {
          this._inner.classList.remove('has-focus')
        })
      })
      //
  
      this._handleTriggerEvents()
  
      if (this._config.subtoggle) this.enableSubmenuToggle()
  
      if (this._config.pullup) this.enableSubmenuPullup()
      if (this._config.gotoactive) this.scrollToActive()
      if (this._config.backdrop) {
        this._sidebar.classList.add(ClassName.BACKDROP)
      } else if (this._sidebar.classList.contains(ClassName.BACKDROP)) {
        this._config.backdrop = true
      }
  
      if (!this._horizontal && this._collapsed) {
        this._addTransitionEvent()
      }
    }
  
    // Getters
    static get VERSION () {
      return VERSION
    }
  
    static get Default () {
      return Default
    }
  
    static get DefaultType () {
      return DefaultType
    }
  
    _handleTriggerEvents () {
      this._triggerArray.forEach((el) => {
        el.addEventListener('click', () => this.toggle(el))
      })
  
      this._triggerArrayMobile.forEach((el) => {
        el.addEventListener('click', () => this.toggleMobile(el))
      })
    }
  
    toggle (btn = null) {
      if (this._sidebar.classList.contains(this._desktopCollapsedClass)) {
        this.expand(btn)
      } else {
        this.collapse(btn)
      }
    }
  
    toggleMobile (btn = null) {
      if (!this._sidebar.classList.contains(ClassName.MOBILE_SHOW)) {
        this.show(btn)
      } else {
        this.hide(btn)
      }
    }
  
    /// ////
  
    expand (btn = null) {
      if (!this._hasTransitionEvent) this._addTransitionEvent()
      if (this._isTransitioning || !this._collapsed) return
  
      const ev = EventHandler.trigger(this._sidebar, Event.EXPAND)
      if (ev.defaultPrevented) return
  
      this._isTransitioning = true
      this._collapsed = false
  
      this._sidebar.classList.add(ClassName.TOGGLING)
      this._sidebar.classList.remove(this._desktopCollapsedClass)
  
      this._updateTriggerBtns(this._triggerArray, true)
  
      /**
       * If no transition or horizontal or in mobile view (width == 0)
       */
      if (Util.isReducedMotion() || this._sidebar.classList.contains('no-transition') || this._horizontal || this._sidebar.offsetWidth === 0) this._toggleCompleted()// call completion now
  
      //
      if (this._pullupEnabled) this._resetPullUp()
    }
  
    collapse (btn = null) {
      if (!this._hasTransitionEvent) this._addTransitionEvent()
      if (this._isTransitioning || this._collapsed) return
  
      const ev = EventHandler.trigger(this._sidebar, Event.COLLAPSE)
      if (ev.defaultPrevented) return
  
      this._isTransitioning = true
      this._collapsed = true
  
      this._sidebar.classList.add(ClassName.TOGGLING)
      this._sidebar.classList.add(this._desktopCollapsedClass)
  
      this._updateTriggerBtns(this._triggerArray, false)
  
      /**
       * If no transition or horizontal or in mobile view (width == 0)
       */
      if (Util.isReducedMotion() || this._sidebar.classList.contains('no-transition') || this._horizontal || this._sidebar.offsetWidth === 0) this._toggleCompleted()// call completion now
  
      //
      if (this._pullupEnabled) this._resetPullUp()
  
      // if the triggering button is inside sidebar and we want it to remain expanded (.let-expanded), add .is-hover class as well
      if (btn !== null && this._sidebar.classList.contains('expandable') && this._sidebar.classList.contains('let-expanded') && this._inner.contains(btn)) {
        this._inner.classList.add(ClassName.INNER_HOVER)
      }
    }
  
    isCollapsed () {
      return this._collapsed
    }
  
    show (btn = null) {
      if (!this._hasTransitionEventMobile) this._addTransitionEventMobile()
      if (this._isTransitioningMobile || !this._hidden) return
  
      const ev = EventHandler.trigger(this._sidebar, Event.SHOW)
      if (ev.defaultPrevented) return
  
      this._isTransitioningMobile = true
      this._hidden = false
  
      this._sidebar.classList.add(ClassName.MOBILE_SHOW)
      this._updateTriggerBtns(this._triggerArrayMobile, true)
  
      // hide sidebar if clicked outside of it
      if (this._config.dismiss) {
        this._triggerArrayMobile.forEach((el) => { el.style.pointerEvents = 'none' }) // disable this button, because if we click on it, it will hide and then instantly show the sidebar again
  
        EventHandler.on(document, 'mouseup.sidebar-dismiss', (e) => {
          if (!this._inner.contains(e.target)) { // if clicked outside sidebar
            this.hide()
          }
        })
      }
  
      if (this._config.swipe) this.enableSwipeHide()
  
      if (Util.isReducedMotion()) this._toggleMobileCompleted()// call completion now
  
      // in some webkit mobile browsers, sidebar scrolling works but scrollbars are not visible, unless something like this forces it to become visible
      if (this._scroller && !this._scroller.classList.contains('overflow-hidden')) {
        this._scroller.classList.add('overflow-hidden')
        Util.reflow(this._scroller)// force redraw
        this._scroller.classList.remove('overflow-hidden')
      }
  
      // hide body scrollbars
      // if sidebar is fixed and has backdrop or is .sidebar-push
      const scrollbarInfo = Util.getScrollbarInfo()
      if (scrollbarInfo.width === 0 && this._sidebar.classList.contains('sidebar-fixed') && (this._config.backdrop || this._sidebar.classList.contains('sidebar-push'))) {
        document.body.classList.add('mob-sidebar-body')
      }
    }
  
    hide (btn = null) {
      if (!this._hasTransitionEventMobile) this._addTransitionEventMobile()
      if (this._isTransitioningMobile || this._hidden) return
  
      const ev = EventHandler.trigger(this._sidebar, Event.HIDE)
      if (ev.defaultPrevented) return
  
      this._isTransitioningMobile = true
      this._hidden = true
  
      this._sidebar.classList.remove(ClassName.MOBILE_SHOW)
      this._updateTriggerBtns(this._triggerArrayMobile, false)
  
      if (this._config.dismiss) {
        this._triggerArrayMobile.forEach((el) => { el.style.pointerEvents = '' })
        EventHandler.off(document, '.sidebar-dismiss')
      }
      if (this._config.swipe) {
        EventHandler.off(document, '.sidebar-swipe')
      }
  
      if (Util.isReducedMotion()) this._toggleMobileCompleted()// call completion now
    }
  
    isHidden () {
      return this._hidden
    }
  
    _updateTriggerBtns (btns, expanded = false) {
      for (let i = 0, len = btns.length; i < len; i++) {
        if (expanded) btns[i].classList.remove(ClassName.COLLAPSED)
        else btns[i].classList.add(ClassName.COLLAPSED)
  
        btns[i].setAttribute('aria-expanded', expanded)
      }
    }
  
    _toggleCompleted () {
      this._isTransitioning = false
      this._sidebar.classList.remove(ClassName.TOGGLING)
  
      const expanded = !this._sidebar.classList.contains(this._desktopCollapsedClass)
      if (expanded) {
        this._inner.classList.remove(ClassName.INNER_HOVER)
        EventHandler.trigger(this._sidebar, Event.EXPANDED)
      } else {
        EventHandler.trigger(this._sidebar, Event.COLLAPSED)
      }
    }
  
    _toggleMobileCompleted () {
      this._isTransitioningMobile = false
      const shown = this._sidebar.classList.contains(ClassName.MOBILE_SHOW)
      if (shown) EventHandler.trigger(this._sidebar, Event.SHOWN)
      else {
        document.body.classList.remove('mob-sidebar-body')
        if (this._config.swipe) {
          document.body.classList.remove('mob-sidebarswipe-body')
        }
  
        EventHandler.trigger(this._sidebar, Event.HIDDEN)
      }
    }
  
    _addTransitionEvent () {
      if (this._hasTransitionEvent) return
      this._hasTransitionEvent = true
      let counter = 0
  
      this._sidebar.addEventListener('transitionend', (e) => {
        if (e.target !== this._sidebar) return// make sure its not the children triggerring the event!
  
        this._toggleCompleted()
  
        counter = 0
      })
  
      // add 'is-hover' class to '.sidebar-inner' when it becomes expanded (i.e. when mouse hovers it)
      this._inner.addEventListener('transitionstart', (e) => {
        // skip on mobile (in which propertyName is `transform`)
        if (e.target !== this._inner || this._isTransitioning || e.propertyName !== 'width') return
  
        counter++
        if (counter === 1) this._inner.classList.add(ClassName.INNER_HOVER)
      })
  
      this._inner.addEventListener('transitionend', (e) => {
        // skip `transitionend` on mobile (in which propertyName is `transform`)
        if (e.target !== this._inner || e.propertyName !== 'width') return
  
        if (this._inner.clientWidth < 140) {
          // just to make sure we remove the extra class name when not needed
          this._inner.classList.remove(ClassName.INNER_HOVER)
          counter = 0
          // blur input element
          if (document.activeElement.tagName === 'INPUT' && this._inner.contains(document.activeElement)) document.activeElement.blur()
        }
      })
    }
  
    _addTransitionEventMobile () {
      if (this._hasTransitionEventMobile) return
      this._hasTransitionEventMobile = true
  
      this._inner.addEventListener('transitionstart', (e) => {
        if (e.target !== this._inner || e.propertyName !== 'transform') return
  
        this._toggleMobileCompleted()
      })
    }
  
    // swipe to hide sidebar
    enableSwipeHide () {
      let x1 = 0
      let y1 = 0
      let swipeDir = 0
  
      let isRTL = false
      let lastX = 0
  
      let pushContent = false
      let sidebarWidth = 0
  
      const touchMoveCallback = (ev) => {
        const touches = ev.changedTouches[0] || null
        if (!touches) return
  
        const newX = touches.pageX
        const newY = touches.pageY
        lastX = newX
  
        if (swipeDir === 0) {
          const diffY = Math.abs(y1 - newY)
          const diffX = Math.abs(x1 - newX)
  
          if (diffY > diffX) {
            swipeDir = 2// vertical i.e. scroll
            if (this._scroller) this._scroller.classList.remove('overflow-hidden')
            document.body.classList.remove('mob-sidebarswipe-body')
  
            EventHandler.off(document, 'touchmove.sidebar-swipe')
          } else if (diffX > 10) {
            swipeDir = 1// horizontal swipe
            this._inner.setAttribute('style', 'transition: none !important; touch-action: none;')
            if (this._scroller) this._scroller.classList.add('overflow-hidden')
            document.body.classList.add('mob-sidebarswipe-body')
          }
        }
        if (swipeDir !== 1) return
  
        const moveX = parseInt(x1 - newX)
        if ((!isRTL && moveX > 0) || (isRTL && moveX < 0)) { // move it outside of view
          this._inner.style.transform = 'translateX(' + (-1 * moveX) + 'px)'
          if (pushContent) this._sidebar.style.width = (sidebarWidth - (moveX > 0 ? moveX : -1 * moveX)) + 'px'
        } else {
          this._inner.style.transform = ''
          if (pushContent) this._sidebar.style.width = ''
        }
      }
  
      let t1 = 0
      EventHandler.on(document, 'touchstart.sidebar-swipe', (e) => {
        const touches = e.changedTouches[0] || null
        if (!touches) return
  
        x1 = touches.pageX
        y1 = touches.pageY
  
        t1 = Date.now()
        isRTL = Util.isRTL()
  
        pushContent = this._sidebar.classList.contains('sidebar-push')
        if (pushContent) {
          sidebarWidth = this._sidebar.clientWidth
          this._sidebar.style.minWidth = 'auto'
          this._sidebar.style.transition = 'none'
        }
  
        EventHandler.on(document, 'touchmove.sidebar-swipe', (e) => {
          touchMoveCallback(e)
        })
      })
  
      const touchEndHandler = (e) => {
        const touches = e.changedTouches[0] || null
        // if (!touches) return // in case we're coming from a `dismiss` mouseup event
  
        this._inner.setAttribute('style', '')
        if (pushContent) {
          this._sidebar.style.width = ''
          this._sidebar.style.minWidth = ''
          this._sidebar.style.transition = ''
        }
  
        const x2 = touches !== null ? touches.pageX : lastX
        const t2 = Date.now()
  
        if (swipeDir === 1 &&
            ( // dismiss if moved by more than 100px or moved more than 40px in a short time (less than 300ms)
              (!isRTL && (x1 - x2 > 100 || (x1 - x2 > 40 && t2 - t1 < 300))) || (isRTL && (x1 - x2 < -100 || (x1 - x2 < -40 && t2 - t1 < 300)))
            )
        ) { // if moved more than 100px or 40px in less than 300ms
          this.hide()
        } else {
          // remove '.mob-sidebarswipe-body' to bring back body scrollbars if sidebar isn't swiped to hide
          // but we probably won't have body scrollbars because of `.mob-sidebar-body`
          document.body.classList.remove('mob-sidebarswipe-body')
        }
  
        // bring back sidebar scrollbars
        if (this._scroller) this._scroller.classList.remove('overflow-hidden')
  
        swipeDir = 0
      }
  
      EventHandler.on(document, 'touchend.sidebar-swipe', touchEndHandler)
      EventHandler.on(document, 'touchcancel.sidebar-swipe', touchEndHandler)
    }
  
    enableSubmenuToggle () {
      this._isSubOpening = false
      const _jQueryBS = typeof jQuery !== 'undefined' && typeof bootstrap !== 'undefined'
  
      EventHandler.on(this._sidebar, 'click', '.dropdown-toggle', (ev) => {
        ev.preventDefault()
        if (this._isSubOpening) return
  
        const navItem = Util.closest(ev.delegateTarget, '.nav-item')// get the parent LI.nav-item
        const subMenu = navItem.querySelector('* > .submenu')// get the direct submenu (not the children)
        const navLink = navItem.querySelector('* > .nav-link')// get the parent LI.nav-item
  
        if (!subMenu || !navLink) return
  
        if ((this._collapsed && this._sidebar.classList.contains('hoverable')) || this._sidebar.classList.contains('sidebar-hover')) {
          // don't toggle submenu if submenu is supposed to be displayed as popup (this includes horizontal sidebar when it's `.sidebar-hover`)
          if (window.getComputedStyle(subMenu).position === 'absolute') return
        }
  
        if (subMenu.classList.contains('collapsing')) return// don't toggle in the middle of toggling
  
        // hide sibling submenus
        navItem.classList.add('is-toggling')
        navItem.parentNode.querySelectorAll('* > .nav-item.open').forEach((_item) => {
          if (_item === navItem) return
          _item.classList.add('is-toggling')
  
          _item.classList.remove('open')
  
          const sub = _item.querySelector('* > .submenu.show')
          if (sub) {
            if (_jQueryBS) window.jQuery(sub).collapse('hide')
            else sub.classList.remove('show')
          }
        })
  
        // toggle submenu
        if (navItem.classList.contains('open')) {
          navItem.classList.remove('open')
          navLink.classList.add('collapsed')
  
          this._sidebar.classList.remove('has-open')
  
          if (_jQueryBS) window.jQuery(subMenu).collapse('hide')
          else subMenu.classList.remove('show')
        } else {
          this._isSubOpening = true
  
          navItem.classList.add('open')
          navLink.classList.remove('collapsed')
  
          this._sidebar.classList.add('has-open')
  
          if (_jQueryBS) window.jQuery(subMenu).collapse('show')
          else subMenu.classList.add('show')
        }
  
        if (_jQueryBS) {
          if (!subMenu.getAttribute('data-sub-event')) {
            subMenu
              .setAttribute('data-sub-event', 'true')
  
            window.jQuery(subMenu).on('shown.bs.collapse.is-toggling hidden.bs.collapse.is-toggling', () => {
              this._submenuIsToggled()
            })
          }
        } else {
          this._submenuIsToggled()
        }
  
        if (navItem && navItem.classList.contains('open')) this._submenuScroll(subMenu)
      })
    }
  
    _submenuIsToggled () {
      this._isSubOpening = false
  
      this._sidebar.querySelectorAll('.is-toggling').forEach((el) => {
        el.classList.remove('is-toggling')
      })
  
      // firefox continues to disable scroll chaining when sidebar is not scrollable anymore, so a little fix around here
      if ('MozAppearance' in document.documentElement.style) {
        if (this._scroller === null) return
        if (this._scroller.scrollHeight <= this._scroller.clientHeight) {
          this._scroller.style.overscrollBehavior = 'auto'
        } else this._scroller.style.overscrollBehavior = ''
      }
    }
  
    // scroll submenu into view (only on modern browsers)
    _submenuScroll (subMenu, delay = 150) {
      if (subMenu && !Util.isReducedMotion() && 'scrollBehavior' in document.documentElement.style && this._config.subscroll && this._sidebar.classList.contains('sidebar-fixed')) {
        if (this._sidebar.classList.contains(ClassName.HORIZONTAL)) {
          if (window.getComputedStyle(subMenu).position === 'absolute') return // no scroll for desktop horizontal menu (when it's not `.sidebar-hover`)
        }
  
        setTimeout(() => {
          subMenu.scrollIntoView({
            behavior: 'smooth',
            block: 'nearest'
          })
        }, delay)
      }
    }
  
    enableSubmenuPullup () {
      if (this._pullupEnabled) return
      this._pullupEnabled = true
  
      const marginProp = 'margin-' + (!Util.isRTL() ? 'left' : 'right')
  
      if (this._pullupCallback === null) {
        this._pullupCallback = (ev) => {
          if (ev.target !== ev.delegateTarget || ev.propertyName !== marginProp || !(this._collapsed || this._sidebar.classList.contains('sidebar-hover'))) return
  
          const subMenu = ev.target
          const navItem = subMenu.parentNode
  
          const navText = navItem.querySelector('* > .nav-link > .nav-text.fadeable')// only first level nav-text items
  
          if (navItem) navItem.classList.remove('submenu-pullup')
          subMenu.style.transform = ''
          if (navText) navText.style.transform = ''
  
          /// ///////////////////////
  
          const rect = subMenu.getBoundingClientRect()
          const wh = window.innerHeight
  
          let diff = parseInt(rect.bottom - wh)
  
          if (diff > 0) { // if submenu bottom is below window area
            // check to see if submenu top will go out of window if we move it up by "diff" pixels
            // also consider that the first level item's .nav-text shouldn't go out of window's top
            const navTextHeight = navText ? navText.clientHeight : 0
            let navbarHeight = document.querySelector('.navbar')
            navbarHeight = navbarHeight ? navbarHeight.clientHeight : 0
  
            const diff2 = rect.top - navTextHeight - diff - navbarHeight// don't go above navbar
            if (diff2 < 0) diff = diff + diff2
  
            diff = parseInt(diff) + 1// so that submenu's border is visible
            if (this._collapsed) {
              if (navTextHeight && diff > navTextHeight / 2 && navItem) navItem.classList.add('submenu-pullup')// this class makes the .sub-arrow's color white, to match submenu color
            } else {
              if (navItem) navItem.classList.add('submenu-pullup')
            }
  
            subMenu.style.transform = `translateY(-${diff}px)`
            if (this._collapsed && navText) {
              navText.style.transform = `translateY(-${diff}px)`
            }
          }
        }
      }
  
      EventHandler.on(this._sidebar, 'transitionstart', '.submenu', this._pullupCallback)
    }
  
    disableSubmenuPullup () {
      this._pullupEnabled = false
      if (this._pullupCallback) EventHandler.off(this._sidebar, 'transitionstart', '.submenu', this._pullupCallback)
      this._resetPullUp()
    }
  
    _resetPullUp () {
      this._sidebar.querySelectorAll('.submenu-pullup').forEach((_item) => {
        _item.classList.remove('submenu-pullup')
        _item.querySelectorAll('.nav-text, .submenu').forEach((el) => {
          el.style.transform = ''
        })
      })
    }
  
    // scroll active item into view
    scrollToActive () {
      if (!this._sidebar.classList.contains('sidebar-fixed') || this._scroller === null) return
  
      const active = this._sidebar.querySelector('.nav-item.active:not(.open) > .nav-link')
      try {
        active.scrollIntoView({ behavior: 'auto', block: 'end' })// or block: "center"?
        this._scroller.scrollTop = this._scroller.scrollTop + 30
      } catch (e) {}
    }
  
    //
    _getConfig (config) {
      config = {
        ...Default,
        ...typeof config === 'object' && config ? config : {}
      }
  
      if (typeof window.bootstrap !== 'undefined') {
        window.bootstrap.Util.typeCheckConfig(
          NAME,
          config,
          this.constructor.DefaultType
        )
      }
  
      return config
    }
  
    // Static methods
    static getInstance (element, config = null) {
      if (!element) throw new Error('element for Sidebar is null')
  
      const name = `__${NAME}__`
      if (typeof element[name] !== 'undefined') return element[name]
  
      element[name] = new Sidebar(element, config)
      return element[name]
    }
  
    static _jQueryInterface (config) {
      return this.each(function () {
        const $this = window.jQuery(this)
        let data = $this.data(DATA_KEY)
  
        const _config = {
          ...Default,
          ...$this.data(),
          ...typeof config === 'object' && config ? config : {}
        }
  
        if (!data) {
          data = Sidebar.getInstance(this, _config)
          $this.data(DATA_KEY, data)
        }
  
        if (typeof config === 'string') {
          if (typeof data[config] === 'undefined') {
            throw new TypeError(`No method named "${config}"`)
          }
          data[config]()
        }
      })
    }
  }
  
  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
  */
  
  if (typeof window.jQuery !== 'undefined') {
    const $ = window.jQuery
    $(window).on(Event.LOAD_DATA_API, () => {
      const sidebars = [].slice.call(document.querySelectorAll(Selector.SIDEBAR))
  
      for (let i = 0; i < sidebars.length; i++) {
        const $sidebar = $(sidebars[i])
        Sidebar._jQueryInterface.call($sidebar, $sidebar.data())
      }
    })
  
    const JQUERY_NO_CONFLICT = $.fn[NAME]
    $.fn[NAME] = Sidebar._jQueryInterface
    $.fn[NAME].Constructor = Sidebar
    $.fn[NAME].noConflict = () => {
      $.fn[NAME] = JQUERY_NO_CONFLICT
      return Sidebar._jQueryInterface
    }
  }
  
  export default Sidebar
  