HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/buyercall/node_modules/bootstrap-vue-next/src/directives/BToggle.ts
import {RX_HASH, RX_HASH_ID, RX_SPACE_SPLIT} from '../constants/regex'
import {getAttr, isTag} from '../utils'
import type {Directive, DirectiveBinding} from 'vue'

const getTargets = (binding: DirectiveBinding<string | string[]>, el: HTMLElement) => {
  const {modifiers, arg, value} = binding
  // Any modifiers are considered target Ids
  const targets = Object.keys(modifiers || {})

  // If value is a string, split out individual targets (if space delimited)
  const localValue = typeof value === 'string' ? value.split(RX_SPACE_SPLIT) : value

  // Support target Id as link href (`href="#id"`)
  if (isTag(el.tagName, 'a')) {
    const href = getAttr(el, 'href') || ''
    if (RX_HASH_ID.test(href)) {
      targets.push(href.replace(RX_HASH, ''))
    }
  }

  // Add Id from `arg` (if provided), and support value
  // as a single string Id or an array of string Ids
  // If `value` is not an array or string, then it gets filtered out
  Array.prototype.concat
    .apply([], [arg, localValue])
    .forEach((t) => typeof t === 'string' && targets.push(t))

  // Return only unique and truthy target Ids
  return targets.filter((t, index, arr) => t && arr.indexOf(t) === index)
}

const toggle = (targetIds: string[], el: HTMLElement) => {
  targetIds.forEach((targetId) => {
    const target = document.getElementById(targetId)

    if (target !== null) {
      target.dispatchEvent(new Event('bv-toggle'))
    }
  })
  setTimeout(() => checkVisibility(targetIds, el), 50)
}

const checkVisibility = (targetIds: string[], el: HTMLElement) => {
  let visible = false
  targetIds.forEach((targetId) => {
    const target = document.getElementById(targetId)

    if (target?.classList.contains('show')) {
      visible = true
    }
    if (target?.classList.contains('closing')) {
      visible = false
    }
  })
  el.setAttribute('aria-expanded', visible ? 'true' : 'false')
  el.classList.remove(visible ? 'collapsed' : 'not-collapsed')
  el.classList.add(visible ? 'not-collapsed' : 'collapsed')
}

const handleUpdate = (el: WithToggle, binding: DirectiveBinding<string | string[] | undefined>) => {
  // Determine targets
  if (binding.value === undefined && Object.keys(binding.modifiers || {}).length === 0) return
  const targets = getTargets(binding as DirectiveBinding<string | string[]>, el)

  // Set up click handler
  if (el.__toggle) {
    el.removeEventListener('click', el.__toggle)
  }
  el.__toggle = () => toggle(targets, el)
  el.addEventListener('click', el.__toggle)

  // Update attributes
  el.setAttribute('aria-controls', targets.join(' '))
  checkVisibility(targets, el)
}

export interface WithToggle extends HTMLElement {
  __toggle: () => void
}

export default {
  mounted: handleUpdate,
  updated: handleUpdate,
  unmounted(el: WithToggle): void {
    el.removeEventListener('click', el.__toggle)
    el.removeAttribute('aria-controls')
    el.removeAttribute('aria-expanded')
  },
} satisfies Directive<WithToggle>