mirror of
https://github.com/koel/koel
synced 2024-11-24 13:13:05 +00:00
chore: extract logic for floaing UI update
This commit is contained in:
parent
2d912039bc
commit
af30e632fd
4 changed files with 56 additions and 72 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
33
resources/assets/js/utils/floatingUi.ts
Normal file
33
resources/assets/js/utils/floatingUi.ts
Normal 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'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -7,3 +7,4 @@ export * from './helpers'
|
|||
export * from './fileReader'
|
||||
export * from './directoryReader'
|
||||
export * from './logger'
|
||||
export * from './floatingUi'
|
||||
|
|
Loading…
Reference in a new issue