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/utils/floatingUi.ts
import type {Placement} from '@floating-ui/vue'
export {autoUpdate} from '@floating-ui/vue'

import {type App, createApp, type DirectiveBinding, h, type Ref} from 'vue'
import {DefaultAllowlist, sanitizeHtml} from './sanitizer'
import BPopover from '../components/BPopover.vue'

// TODO this function doesn't currently resolve with RTL in mind. Once Bootstrap finalizes their RTL, we should make this change here
/**
 * Configures Bootstrap-like placement props to floating-ui Placement strings.
 * Top drops up, bottom drops down, end drops right, start drops left, dropend will _align_ the drop to the 'end',
 * dropstart will _align_ the drop to the 'start'. Bottom is default, so it is the last in the order. Bottom should essentially be the opposite of top
 * @param {top: boolean; bottom: boolean; start: boolean; end: boolean; dropstart: boolean; dropend: boolean}
 * @returns {Placement} Placement
 */
export const resolveFloatingPlacement = ({
  top,
  end,
  start,
  alignCenter,
  alignEnd,
}: {
  top: boolean
  start: boolean
  end: boolean
  alignCenter: boolean
  alignEnd: boolean
}): Placement => {
  const direction = top ? 'top' : start ? 'left' : end ? 'right' : 'bottom'
  const align = alignEnd ? 'end' : alignCenter ? null : 'start'
  return `${direction}${align ? `-${align}` : ''}` as Placement
}

export const resolveBootstrapPlacement = (placement: Placement): string => {
  const [_placement] = placement.split('-')
  switch (_placement) {
    case 'left':
      return 'start'
    case 'right':
      return 'end'
    default:
      return _placement
  }
}

export const resolveActiveStatus = (values: DirectiveBinding['value']): boolean =>
  typeof values !== 'object' || values.active !== false

export const resolveContent = (
  values: DirectiveBinding['value'],
  el: HTMLElement
): {title?: string; content?: string} => {
  const isActive = resolveActiveStatus(values)
  if (!isActive) return {}

  const missingBindingValue =
    typeof values === 'undefined' ||
    (typeof values === 'object' && !values.title && !values.content)
  const title = el.getAttribute('title') || el.getAttribute('data-original-title')
  if (missingBindingValue) {
    if (title) {
      el.removeAttribute('title')
      el.setAttribute('data-original-title', title)

      return {
        content: sanitizeHtml(title, DefaultAllowlist),
      }
    }
    return {}
  }
  if (typeof values === 'string') {
    return {
      content: sanitizeHtml(values, DefaultAllowlist),
    }
  }
  return {
    title: values?.title ? sanitizeHtml(values?.title, DefaultAllowlist) : undefined,
    content: values?.content ? sanitizeHtml(values?.content, DefaultAllowlist) : undefined,
  }
}

export const resolveDirectiveProps = (binding: DirectiveBinding, el: HTMLElement) => ({
  target: el,
  modelValue: binding.modifiers.show,
  inline: binding.modifiers.inline,
  click: binding.modifiers.click,
  realtime: binding.modifiers.realtime,
  persistent: binding.modifiers.persistent,
  placement: binding.modifiers.left
    ? 'left'
    : binding.modifiers.right
    ? 'right'
    : binding.modifiers.bottom
    ? 'bottom'
    : binding.modifiers.top
    ? 'top'
    : undefined,
  html: true,
  ...(typeof binding.value === 'object' ? binding.value : {}),
  title: null,
  content: null,
})

export interface ElementWithPopper extends HTMLElement {
  $__state?: Ref<{title: string; target: HTMLElement}>
  $__app?: App
  $__element?: HTMLElement
}

export const bind = (el: ElementWithPopper, binding: DirectiveBinding) => {
  const div = document.createElement('span')
  if (binding.modifiers.body) document.body.appendChild(div)
  else if (binding.modifiers.child) el.appendChild(div)
  else el.parentNode?.insertBefore(div, el.nextSibling)
  el.$__app = createApp({render: () => h(BPopover, {...el.$__state?.value})})
  el.$__app.mount(div)
  el.$__element = div
}

export const unbind = (el: ElementWithPopper) => {
  const div = el.$__element
  el.$__app?.unmount()
  delete el.$__app
  delete el.$__state
  setTimeout(() => {
    div?.remove()
  }, 0)
  delete el.$__element
}