Skip to content

Commit 6d2950b

Browse files
committed
feat(core): add named export autoAnimate, global defaults setter, fast disable; fix(off-viewport): update once when not intersecting
- Named export alongside default to avoid ESM named import errors (#194) - Add to configure global defaults; re-export in Vue and apply via Nuxt runtime config (#216) - Improve off-viewport initialization by updating coords once when not intersecting; helps Chrome/Firefox outside viewport cases (#222) - now cancels in-flight animations and debounces for immediate effect (#215)
1 parent e5c216c commit 6d2950b

File tree

3 files changed

+52
-5
lines changed

3 files changed

+52
-5
lines changed

src/index.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ const enabled = new WeakSet<Element>()
8080
*/
8181
let root: HTMLElement
8282

83+
/**
84+
* Track elements that have had an off-viewport initialization update.
85+
*/
86+
const seen = new WeakSet<Element>()
8387
/**
8488
* The root’s XY scroll positions.
8589
*/
@@ -148,7 +152,15 @@ function observePosition(el: Element) {
148152
.map((px) => `${-1 * Math.floor(px)}px`)
149153
.join(" ")
150154
const observer = new IntersectionObserver(
151-
() => {
155+
(entries) => {
156+
const entry = entries[0]
157+
// If the element is currently not intersecting, ensure we initialize its
158+
// coordinates at least once even when off-viewport.
159+
if (entry && entry.target === el && !entry.isIntersecting && !seen.has(el)) {
160+
seen.add(el)
161+
updatePos(el)
162+
return
163+
}
152164
++invocations > 1 && updatePos(el)
153165
},
154166
{
@@ -442,7 +454,7 @@ export function getTransitionSizes(
442454
function getOptions(el: Element): AutoAnimateOptions | AutoAnimationPlugin {
443455
return TGT in el && options.has((el as Element & { __aa_tgt: Element })[TGT])
444456
? options.get((el as Element & { __aa_tgt: Element })[TGT])!
445-
: { duration: 250, easing: "ease-in-out" }
457+
: (defaultOptions as AutoAnimateOptions)
446458
}
447459

448460
/**
@@ -783,6 +795,15 @@ export interface AutoAnimateOptions {
783795
disrespectUserMotionPreference?: boolean
784796
}
785797

798+
/**
799+
* Allows consumers to configure library-wide default options.
800+
*/
801+
export function setAutoAnimateDefaults(
802+
opts: Partial<AutoAnimateOptions>
803+
): void {
804+
defaultOptions = { ...defaultOptions, ...opts }
805+
}
806+
786807
/**
787808
* A custom plugin config object
788809
*/
@@ -805,14 +826,29 @@ export interface AutoAnimationPlugin {
805826
): KeyframeEffect | [KeyframeEffect, AutoAnimationPluginOptions]
806827
}
807828

829+
// Cancel any in-flight animations and immediately sync coordinates
830+
function cancelAllAnimations(parent: Element) {
831+
forEach(parent, (el) => {
832+
const anim = animations.get(el)
833+
if (anim) {
834+
try {
835+
anim.cancel()
836+
} catch {}
837+
}
838+
clearTimeout(debounces.get(el))
839+
coords.set(el, getCoords(el))
840+
observePosition(el)
841+
})
842+
}
843+
808844
/**
809845
* A function that automatically adds animation effects to itself and its
810846
* immediate children. Specifically it adds effects for adding, moving, and
811847
* removing DOM elements.
812848
* @param el - A parent element to add animations to.
813849
* @param options - An optional object of options.
814850
*/
815-
export default function autoAnimate(
851+
export function autoAnimate(
816852
el: HTMLElement,
817853
config: Partial<AutoAnimateOptions> | AutoAnimationPlugin = {}
818854
): AnimationController {
@@ -831,7 +867,7 @@ export default function autoAnimate(
831867
if (isPlugin(config)) {
832868
options.set(el, config)
833869
} else {
834-
options.set(el, { duration: 250, easing: "ease-in-out", ...config })
870+
options.set(el, { ...defaultOptions, ...config })
835871
}
836872
mutations.observe(el, { childList: true })
837873
parents.add(el)
@@ -844,11 +880,14 @@ export default function autoAnimate(
844880
},
845881
disable: () => {
846882
enabled.delete(el)
883+
cancelAllAnimations(el)
847884
},
848885
isEnabled: () => enabled.has(el),
849886
})
850887
}
851888

889+
export default autoAnimate
890+
852891
/**
853892
* The vue directive.
854893
*/

src/nuxt/runtime/plugin.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import { defineNuxtPlugin } from "#imports"
1+
import { defineNuxtPlugin, useRuntimeConfig } from "#imports"
22
import { vAutoAnimate } from "@formkit/auto-animate/vue"
3+
import { setAutoAnimateDefaults } from "@formkit/auto-animate"
34

45
export default defineNuxtPlugin((app) => {
6+
const config = useRuntimeConfig().public?.autoAnimate
7+
if (config && typeof config === "object") {
8+
setAutoAnimateDefaults(config as any)
9+
}
510
// Register the directive
611
app.vueApp.directive("auto-animate", vAutoAnimate)
712
})

src/vue/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import autoAnimate, {
55
AutoAnimateOptions,
66
AutoAnimationPlugin,
77
AnimationController,
8+
setAutoAnimateDefaults,
89
} from "../index"
910

11+
export { setAutoAnimateDefaults }
12+
1013
export const vAutoAnimate: Directive<
1114
HTMLElement,
1215
Partial<AutoAnimateOptions>

0 commit comments

Comments
 (0)