Files
ui/src/runtime/composables/usePopper.ts
Anthony Fu edc1bd677b chore: improve types (#115)
* wip: improve types

* feat: improve types

* Apply suggestions from code review

Co-authored-by: Sylvain Marroufin <marroufin.sylvain@gmail.com>

* chore: update

* chore: enable ci typecheck

* chore: fix

Co-authored-by: Sylvain Marroufin <marroufin.sylvain@gmail.com>
2022-11-23 11:30:18 +01:00

83 lines
2.5 KiB
TypeScript

import { ref, onMounted, watchEffect } from 'vue'
import type { Ref } from 'vue'
import { popperGenerator, defaultModifiers, VirtualElement } from '@popperjs/core/lib/popper-lite'
import type { Instance } from '@popperjs/core'
import { omitBy, isUndefined } from 'lodash-es'
import flip from '@popperjs/core/lib/modifiers/flip'
import offset from '@popperjs/core/lib/modifiers/offset'
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow'
import computeStyles from '@popperjs/core/lib/modifiers/computeStyles'
import eventListeners from '@popperjs/core/lib/modifiers/eventListeners'
import { MaybeElement, unrefElement } from '@vueuse/core'
import type { PopperOptions } from '../types'
export const createPopper = popperGenerator({
defaultModifiers: [...defaultModifiers, offset, flip, preventOverflow, computeStyles, eventListeners]
})
export function usePopper ({
locked = false,
overflowPadding = 8,
offsetDistance = 8,
offsetSkid = 0,
gpuAcceleration = true,
adaptive = true,
scroll = true,
resize = true,
placement,
strategy
}: PopperOptions, virtualReference?: Ref<Element | VirtualElement>) {
const reference = ref<MaybeElement>(null)
const popper = ref<MaybeElement>(null)
const instance = ref<Instance | null>(null)
onMounted(() => {
watchEffect((onInvalidate) => {
if (!popper.value) { return }
if (!reference.value && !virtualReference?.value) { return }
const popperEl = unrefElement(popper)
const referenceEl = virtualReference?.value || unrefElement(reference)
// if (!(referenceEl instanceof HTMLElement)) { return }
if (!(popperEl instanceof HTMLElement)) { return }
if (!referenceEl) { return }
instance.value = createPopper(referenceEl, popperEl, omitBy({
placement,
strategy,
modifiers: [{
name: 'flip',
enabled: !locked
}, {
name: 'preventOverflow',
options: {
padding: overflowPadding
}
}, {
name: 'offset',
options: {
offset: [offsetSkid, offsetDistance]
}
}, {
name: 'computeStyles',
options: {
adaptive,
gpuAcceleration
}
}, {
name: 'eventListeners',
options: {
scroll,
resize
}
}]
}, isUndefined))
onInvalidate(instance.value.destroy)
})
})
return [reference, popper, instance] as const
}