Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ function cleanUp(el: Element, styles?: Partial<CSSStyleDeclaration>) {
setTimeout(() => {
if (DEL in el) delete (el as any)[DEL]
Object.defineProperty(el, NEW, { value: true, configurable: true })
if (styles && el instanceof HTMLElement) {
if (styles && (el instanceof HTMLElement || el instanceof SVGElement)) {
for (const style in styles) {
;(el.style as any)[style as any] = ""
}
Expand Down Expand Up @@ -877,11 +877,11 @@ export interface AutoAnimationPlugin {
* A function that automatically adds animation effects to itself and its
* immediate children. Specifically it adds effects for adding, moving, and
* removing DOM elements.
* @param el - A parent element to add animations to.
* @param el - An HTML or SVG parent element to add animations to.
* @param options - An optional object of options.
*/
export default function autoAnimate(
el: HTMLElement,
el: HTMLElement | SVGElement,
config: Partial<AutoAnimateOptions> | AutoAnimationPlugin = {},
): AnimationController {
if (supportedBrowser && resize) {
Expand Down Expand Up @@ -978,15 +978,15 @@ export { autoAnimate }
*/
export const vAutoAnimate = {
mounted: (
el: HTMLElement,
el: HTMLElement | SVGElement,
binding: {
value: Partial<AutoAnimateOptions> | AutoAnimationPlugin | undefined
},
) => {
const ctl = autoAnimate(el, binding.value || {})
Object.defineProperty(el, "__aa_ctl", { value: ctl, configurable: true })
},
unmounted: (el: HTMLElement) => {
unmounted: (el: HTMLElement | SVGElement) => {
const ctl = (el as any)["__aa_ctl"] as AnimationController | undefined
ctl?.destroy?.()
try {
Expand Down
2 changes: 1 addition & 1 deletion src/marko/auto-animate.marko
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
export interface Input {
// A reference to the parent element whose *direct children* will be animated.
// Pass a native element tag-variable, e.g. `<ul/listRef>` then `parent=listRef`.
parent: () => HTMLElement;
parent: () => HTMLElement | SVGElement;
// auto-animate options (duration / easing / disrespectUserMotionPreference)
// OR a plugin function. Read once when the tag mounts; the core has no setOptions,
// so changing this later has no effect (remount the tag to apply new options).
Expand Down
5 changes: 4 additions & 1 deletion src/preact/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ export function useAutoAnimate<T extends Element>(
}
}
useEffect(() => {
if (element.current instanceof HTMLElement)
if (
element.current instanceof HTMLElement ||
element.current instanceof SVGElement
)
setController(autoAnimate(element.current, options || {}))
}, [])
useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/qwik/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import autoAnimate, {
* @param options - Auto animate options or a plugin
* @returns
*/
export function useAutoAnimate<T extends HTMLElement>(
export function useAutoAnimate<T extends HTMLElement | SVGElement>(
options?: Partial<AutoAnimateOptions> | AutoAnimationPlugin
): [
Signal<T | undefined>,
Expand Down
2 changes: 1 addition & 1 deletion src/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function useAutoAnimate<T extends Element>(
const memoizedOptions = useMemo(() => options, [])
const element = useCallback(
(node: T) => {
if (node instanceof HTMLElement) {
if (node instanceof HTMLElement || node instanceof SVGElement) {
setController(autoAnimate(node, memoizedOptions))
} else {
setController(undefined)
Expand Down
4 changes: 2 additions & 2 deletions src/solid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ declare module "solid-js" {
}
}

export const createAutoAnimate = <T extends HTMLElement>(
export const createAutoAnimate = <T extends HTMLElement | SVGElement>(
options: Partial<AutoAnimateOptions> | AutoAnimationPlugin = {}
): [Setter<T | null>, (enabled: boolean) => void] => {
const [element, setElement] = createSignal<T | null>(null)
Expand Down Expand Up @@ -43,7 +43,7 @@ export const createAutoAnimate = <T extends HTMLElement>(

export const createAutoAnimateDirective = () => {
return (
el: HTMLElement,
el: HTMLElement | SVGElement,
options: Accessor<Partial<AutoAnimateOptions> | AutoAnimationPlugin | true>
) => {
let optionsValue = options()
Expand Down
21 changes: 14 additions & 7 deletions src/vue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import autoAnimate, {
} from "../index"

export const vAutoAnimate: Directive<
HTMLElement | Component,
HTMLElement | SVGElement | Component,
Partial<AutoAnimateOptions>
> = autoAnimateDirective as unknown as Directive<
HTMLElement | Component,
HTMLElement | SVGElement | Component,
Partial<AutoAnimateOptions>
>

Expand All @@ -20,7 +20,10 @@ export const vAutoAnimate: Directive<
*/
export function createVAutoAnimate(
defaults?: Partial<AutoAnimateOptions> | AutoAnimationPlugin
): Directive<HTMLElement, Partial<AutoAnimateOptions> | AutoAnimationPlugin> {
): Directive<
HTMLElement | SVGElement,
Partial<AutoAnimateOptions> | AutoAnimationPlugin
> {
return {
mounted(el, binding) {
let resolved: Partial<AutoAnimateOptions> | AutoAnimationPlugin = {}
Expand All @@ -44,7 +47,7 @@ export function createVAutoAnimate(
},
getSSRProps: () => ({}),
} as unknown as Directive<
HTMLElement,
HTMLElement | SVGElement,
Partial<AutoAnimateOptions> | AutoAnimationPlugin
>
}
Expand Down Expand Up @@ -73,13 +76,17 @@ export function useAutoAnimate<T extends Element | Component>(
}
onMounted(() => {
watchEffect((onCleanup) => {
let el: HTMLElement | undefined
if (element.value instanceof HTMLElement) {
let el: HTMLElement | SVGElement | undefined
if (
element.value instanceof HTMLElement ||
element.value instanceof SVGElement
) {
el = element.value
} else if (
element.value &&
"$el" in element.value &&
element.value.$el instanceof HTMLElement
(element.value.$el instanceof HTMLElement ||
element.value.$el instanceof SVGElement)
) {
el = element.value.$el
}
Expand Down
23 changes: 23 additions & 0 deletions tests/e2e/svg-types.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { test, expect } from '@playwright/test'
import { execFileSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import path from 'node:path'

test.describe('SVG type assignability (issue #100)', () => {
test('autoAnimate and vAutoAnimate accept SVG elements', () => {
const root = fileURLToPath(new URL('../..', import.meta.url))
const tsc = path.join(root, 'node_modules/typescript/bin/tsc')
let output = ''
try {
output = execFileSync(
tsc,
['--pretty', 'false', '-p', 'tests/types/tsconfig.json'],
{ encoding: 'utf8', cwd: root },
)
} catch (err) {
const error = err as { stdout?: string; stderr?: string }
throw new Error(error.stdout || error.stderr || String(err))
}
expect(output).toBe('')
})
})
17 changes: 17 additions & 0 deletions tests/types/svg-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import autoAnimate, { vAutoAnimate } from "../../src/index"

declare const svg: SVGSVGElement
declare const html: HTMLElement
declare const group: SVGGElement

autoAnimate(svg)
autoAnimate(html)
autoAnimate(group)

const binding = {
value: undefined as undefined,
}
vAutoAnimate.mounted(svg, binding)
vAutoAnimate.mounted(html, binding)
vAutoAnimate.unmounted(svg)
vAutoAnimate.unmounted(html)
9 changes: 9 additions & 0 deletions tests/types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"noEmit": true,
"noUnusedLocals": false,
"noUnusedParameters": false
},
"include": ["./svg-element.ts"]
}