Skip to content

Commit 1e4116c

Browse files
feat: adds component support to useAutoAnimate for Vue
1 parent 3a4c6bf commit 1e4116c

File tree

3 files changed

+27
-40
lines changed

3 files changed

+27
-40
lines changed

playwright-report/index.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/index.ts

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,11 @@ function observePosition(el: Element) {
168168
/**
169169
* Update the exact position of a given element.
170170
* @param el - An element to update the position of.
171-
* @param debounce - Whether or not to debounce the update. After an animation is finished, it should update as soon as possible to prevent flickering on quick toggles.
172171
*/
173-
function updatePos(el: Element, debounce = true) {
172+
function updatePos(el: Element) {
174173
clearTimeout(debounces.get(el))
175174
const optionsOrPlugin = getOptions(el)
176-
const delay = debounce
177-
? isPlugin(optionsOrPlugin)
178-
? 500
179-
: optionsOrPlugin.duration
180-
: 0
175+
const delay = isPlugin(optionsOrPlugin) ? 500 : optionsOrPlugin.duration
181176
debounces.set(
182177
el,
183178
setTimeout(async () => {
@@ -351,8 +346,7 @@ function animate(el: Element) {
351346
const isMounted = el.isConnected
352347
const preExisting = coords.has(el)
353348
if (isMounted && siblings.has(el)) siblings.delete(el)
354-
355-
if (animations.get(el)?.playState !== "finished") {
349+
if (animations.has(el)) {
356350
animations.get(el)?.cancel()
357351
}
358352
if (NEW in el) {
@@ -529,24 +523,15 @@ function remain(el: Element) {
529523
if (!oldCoords) return
530524
const pluginOrOptions = getOptions(el)
531525
if (typeof pluginOrOptions !== "function") {
532-
let deltaLeft = oldCoords.left - newCoords.left
533-
let deltaTop = oldCoords.top - newCoords.top
534-
const deltaRight =
535-
oldCoords.left + oldCoords.width - (newCoords.left + newCoords.width)
536-
const deltaBottom =
537-
oldCoords.top + oldCoords.height - (newCoords.top + newCoords.height)
538-
539-
// element is probably anchored and doesn't need to be offset
540-
if (deltaBottom == 0) deltaTop = 0
541-
if (deltaRight == 0) deltaLeft = 0
542-
526+
const deltaX = oldCoords.left - newCoords.left
527+
const deltaY = oldCoords.top - newCoords.top
543528
const [widthFrom, widthTo, heightFrom, heightTo] = getTransitionSizes(
544529
el,
545530
oldCoords,
546531
newCoords,
547532
)
548533
const start: Record<string, any> = {
549-
transform: `translate(${deltaLeft}px, ${deltaTop}px)`,
534+
transform: `translate(${deltaX}px, ${deltaY}px)`,
550535
}
551536
const end: Record<string, any> = {
552537
transform: `translate(0, 0)`,
@@ -572,9 +557,7 @@ function remain(el: Element) {
572557
}
573558
animations.set(el, animation)
574559
coords.set(el, newCoords)
575-
animation.addEventListener("finish", updatePos.bind(null, el, false), {
576-
once: true,
577-
})
560+
animation.addEventListener("finish", () => updatePos(el), { once: true })
578561
}
579562

580563
/**
@@ -606,9 +589,7 @@ function add(el: Element) {
606589
animation.play()
607590
}
608591
animations.set(el, animation)
609-
animation.addEventListener("finish", updatePos.bind(null, el, false), {
610-
once: true,
611-
})
592+
animation.addEventListener("finish", () => updatePos(el), { once: true })
612593
}
613594

614595
/**
@@ -798,11 +779,7 @@ function deletePosition(
798779
}
799780
if (!offsetParent) offsetParent = document.body
800781
const parentStyles = getComputedStyle(offsetParent)
801-
const parentCoords =
802-
!animations.has(el) || animations.get(el)?.playState === "finished"
803-
? getCoords(offsetParent)
804-
: coords.get(offsetParent)!
805-
782+
const parentCoords = coords.get(offsetParent) || getCoords(offsetParent)
806783
const top =
807784
Math.round(oldCoords.top - parentCoords.top) -
808785
raw(parentStyles.borderTopWidth)

src/vue/index.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ref, onMounted, watchEffect, Plugin, Ref, onBeforeUnmount } from "vue"
2-
import type { Directive } from "vue"
2+
import type { Component, Directive } from "vue"
33
import autoAnimate, {
44
vAutoAnimate as autoAnimateDirective,
55
AutoAnimateOptions,
@@ -8,10 +8,10 @@ import autoAnimate, {
88
} from "../index"
99

1010
export const vAutoAnimate: Directive<
11-
HTMLElement,
11+
HTMLElement | Component,
1212
Partial<AutoAnimateOptions>
1313
> = autoAnimateDirective as unknown as Directive<
14-
HTMLElement,
14+
HTMLElement | Component,
1515
Partial<AutoAnimateOptions>
1616
>
1717

@@ -27,8 +27,8 @@ export const autoAnimatePlugin: Plugin = {
2727
* @returns A template ref. Use the `ref` attribute of your parent element
2828
* to store the element in this template ref.
2929
*/
30-
export function useAutoAnimate<T extends Element>(
31-
options?: Partial<AutoAnimateOptions> | AutoAnimationPlugin
30+
export function useAutoAnimate<T extends Element | Component>(
31+
options?: Partial<AutoAnimateOptions> | AutoAnimationPlugin,
3232
): [Ref<T>, (enabled: boolean) => void] {
3333
const element = ref<T>()
3434
let controller: AnimationController | undefined
@@ -39,9 +39,19 @@ export function useAutoAnimate<T extends Element>(
3939
}
4040
onMounted(() => {
4141
watchEffect(() => {
42-
const el = element.value?.$el || element.value
43-
if (el instanceof HTMLElement)
42+
let el: HTMLElement | undefined
43+
if (element.value instanceof HTMLElement) {
44+
el = element.value
45+
} else if (
46+
element.value &&
47+
"$el" in element.value &&
48+
element.value.$el instanceof HTMLElement
49+
) {
50+
el = element.value.$el
51+
}
52+
if (el) {
4453
controller = autoAnimate(el, options || {})
54+
}
4555
})
4656
})
4757
onBeforeUnmount(() => {

0 commit comments

Comments
 (0)