chore: extract logic for floaing UI update

This commit is contained in:
Phan An 2022-11-13 12:57:39 +01:00
parent 2d912039bc
commit af30e632fd
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
4 changed files with 56 additions and 72 deletions

View file

@ -1,5 +1,6 @@
import { isRef, Ref } from 'vue'
import { arrow as arrowMiddleware, autoUpdate, computePosition, flip, offset, Placement } from '@floating-ui/dom'
import { arrow as arrowMiddleware, autoUpdate, flip, offset, Placement } from '@floating-ui/dom'
import { updateFloatingUi } from '@/utils'
export type Config = {
placement: Placement,
@ -29,54 +30,28 @@ export const useFloatingUi = (
floating.style.display = 'none'
let arrow: HTMLElement | null = null
if (mergedConfig.useArrow) {
arrow = document.createElement('div')
arrow.className = 'arrow'
floating.appendChild(arrow)
}
const middleware = [
flip(),
offset(6)
]
if (arrow) {
let arrow: HTMLElement
if (mergedConfig.useArrow) {
arrow = document.createElement('div')
arrow.className = 'arrow'
floating.appendChild(arrow)
middleware.push(arrowMiddleware({
element: arrow,
padding: 6
}))
}
const update = async () => {
const { x, y, placement: _, middlewareData } = await computePosition(reference, floating, {
placement: mergedConfig.placement,
middleware
})
floating.style.left = `${x}px`
floating.style.top = `${y}px`
if (arrow) {
const { x: arrowX, y: arrowY } = middlewareData.arrow
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
}[mergedConfig.placement.split('-')[0]]
Object.assign(arrow.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
right: '',
bottom: '',
[staticSide]: '-4px'
})
}
}
const update = async () => await updateFloatingUi(reference, floating, {
placement: mergedConfig.placement,
middleware
}, arrow)
_cleanUp = autoUpdate(reference, floating, update)

View file

@ -1,5 +1,6 @@
import { arrow, autoUpdate, computePosition, offset, Placement } from '@floating-ui/dom'
import { arrow, autoUpdate, offset, Placement } from '@floating-ui/dom'
import { Directive, DirectiveBinding } from 'vue'
import { updateFloatingUi } from '@/utils'
type ElementWithTooltip = HTMLElement & {
$tooltip?: HTMLDivElement,
@ -50,39 +51,13 @@ const init = (el: ElementWithTooltip, binding: DirectiveBinding) => {
}
})
const update = async () => {
const { x, y, middlewareData } = await computePosition(el, $tooltip, {
placement,
middleware: [
arrow({ element: $arrow }),
offset(8)
]
})
Object.assign($tooltip.style, {
top: `${y}px`,
left: `${x}px`
})
// @ts-ignore
const { x: arrowX, y: arrowY } = middlewareData.arrow
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
}[placement.split('-')[0]]
Object.assign($arrow.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
right: '',
bottom: '',
// @ts-ignore
[staticSide]: '-4px'
})
}
const update = async () => await updateFloatingUi(el, $tooltip, {
placement,
middleware: [
arrow({ element: $arrow }),
offset(8)
]
}, $arrow)
el.$cleanup = el.$cleanup || autoUpdate(el, $tooltip, update)

View file

@ -0,0 +1,33 @@
import { computePosition, ComputePositionConfig } from '@floating-ui/dom'
export const updateFloatingUi = async (
reference: HTMLElement,
floating: HTMLElement,
options: Partial<ComputePositionConfig>,
arrow?: HTMLElement
) => {
const { x, y, middlewareData } = await computePosition(reference, floating, options)
floating.style.left = `${x}px`
floating.style.top = `${y}px`
if (arrow) {
const { x: arrowX, y: arrowY } = middlewareData.arrow
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
}[options.placement.split('-')[0]]
Object.assign(arrow.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
right: '',
bottom: '',
[staticSide]: '-4px'
})
}
}

View file

@ -7,3 +7,4 @@ export * from './helpers'
export * from './fileReader'
export * from './directoryReader'
export * from './logger'
export * from './floatingUi'