From 380184cd4a395dfcc2f210d856a5fd6dfa74a272 Mon Sep 17 00:00:00 2001
From: imfenghuang <20472384+imfenghuang@users.noreply.github.com>
Date: Mon, 18 Nov 2024 15:33:21 +0800
Subject: [PATCH 1/4] feat: support pathLength pathOffset pathSpacing
---
playgrounds/vite/src/App.vue | 7 ++
playgrounds/vite/src/demos/SVGPath.vue | 109 +++++++++++++++++++++++
playgrounds/vite/src/examples/svgpath.ts | 103 +++++++++++++++++++++
src/reactiveStyle.ts | 11 ++-
src/useElementStyle.ts | 31 ++++++-
src/utils/style.ts | 57 ++++++++++++
6 files changed, 308 insertions(+), 10 deletions(-)
create mode 100644 playgrounds/vite/src/demos/SVGPath.vue
create mode 100644 playgrounds/vite/src/examples/svgpath.ts
diff --git a/playgrounds/vite/src/App.vue b/playgrounds/vite/src/App.vue
index 613f890c..f2d78495 100644
--- a/playgrounds/vite/src/App.vue
+++ b/playgrounds/vite/src/App.vue
@@ -3,6 +3,7 @@ import Delay from './demos/Delay.vue'
import Editor from './demos/Editor.vue'
import Transitions from './demos/Transitions.vue'
import Sandbox from './demos/Sandbox.vue'
+import SVGPath from './demos/SVGPath.vue'
const sandbox = false
@@ -33,6 +34,12 @@ const sandbox = false
+
+
+ SVGPath
+
+
+
diff --git a/playgrounds/vite/src/demos/SVGPath.vue b/playgrounds/vite/src/demos/SVGPath.vue
new file mode 100644
index 00000000..d507d257
--- /dev/null
+++ b/playgrounds/vite/src/demos/SVGPath.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
diff --git a/playgrounds/vite/src/examples/svgpath.ts b/playgrounds/vite/src/examples/svgpath.ts
new file mode 100644
index 00000000..6188af14
--- /dev/null
+++ b/playgrounds/vite/src/examples/svgpath.ts
@@ -0,0 +1,103 @@
+export default () => `
+
+
+
+
+
+`
diff --git a/src/reactiveStyle.ts b/src/reactiveStyle.ts
index 03488a1c..bca1c21c 100644
--- a/src/reactiveStyle.ts
+++ b/src/reactiveStyle.ts
@@ -1,27 +1,26 @@
import type { Ref } from 'vue'
import { reactive, ref, watch } from 'vue'
-import type { StyleProperties } from './types'
+import type { SVGPathProperties, StyleProperties } from './types'
import { getValueAsType, getValueType } from './utils/style'
-
/**
* Reactive style object implementing all native CSS properties.
*
* @param props
*/
-export function reactiveStyle(props: StyleProperties = {}) {
+export function reactiveStyle(props: StyleProperties | SVGPathProperties = {}) {
// Reactive StyleProperties object
- const state = reactive({
+ const state = reactive({
...props,
})
- const style = ref({}) as Ref
+ const style = ref({}) as Ref
// Reactive DOM Element compatible `style` object bound to state
watch(
state,
() => {
// Init result object
- const result: StyleProperties = {}
+ const result: StyleProperties | SVGPathProperties = {}
for (const [key, value] of Object.entries(state)) {
// Get value type for key
diff --git a/src/useElementStyle.ts b/src/useElementStyle.ts
index 6168b028..82fb822a 100644
--- a/src/useElementStyle.ts
+++ b/src/useElementStyle.ts
@@ -1,9 +1,9 @@
import type { MaybeRef } from '@vueuse/core'
import { watch } from 'vue'
import { reactiveStyle } from './reactiveStyle'
-import type { MotionTarget, PermissiveTarget, StyleProperties } from './types'
+import type { MotionTarget, PermissiveTarget, SVGPathProperties, StyleProperties } from './types'
import { usePermissiveTarget } from './usePermissiveTarget'
-import { valueTypes } from './utils/style'
+import { getSVGPath, isSVGPathProp, setSVGPath, valueTypes } from './utils/style'
import { isTransformOriginProp, isTransformProp } from './utils/transform'
/**
@@ -13,7 +13,7 @@ import { isTransformOriginProp, isTransformProp } from './utils/transform'
*/
export function useElementStyle(target: MaybeRef, onInit?: (initData: Partial) => void) {
// Transform cache available before the element is mounted
- let _cache: StyleProperties | undefined
+ let _cache: StyleProperties | SVGPathProperties | undefined
// Local target cache as we need to resolve the element from PermissiveTarget
let _target: MotionTarget
// Create a reactive style object
@@ -22,10 +22,19 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
usePermissiveTarget(target, (el) => {
_target = el
+ if ((_target as SVGElement)?.ownerSVGElement) {
+ const { pathLength, pathSpacing, pathOffset } = getSVGPath(_target as SVGElement)
+ if (pathLength !== undefined) {
+ (state as SVGPathProperties).pathLength = pathLength;
+ (state as SVGPathProperties).pathSpacing = pathSpacing;
+ (state as SVGPathProperties).pathOffset = pathOffset
+ }
+ }
+
// Loop on style keys
for (const key of Object.keys(valueTypes)) {
// @ts-expect-error - Fix errors later for typescript 5
- if (el.style[key] === null || el.style[key] === '' || isTransformProp(key) || isTransformOriginProp(key))
+ if (el.style[key] === null || el.style[key] === '' || isTransformProp(key) || isTransformOriginProp(key) || isSVGPathProp(key))
continue
// Append a defined key to the local StyleProperties state object
@@ -35,6 +44,13 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
// If cache is present, init the target with the current cached value
if (_cache) {
+ if ((_target as SVGElement)?.ownerSVGElement) {
+ const { pathLength, pathOffset, pathSpacing } = _cache as SVGPathProperties
+ if (pathLength !== undefined) {
+ setSVGPath((_target as SVGElement), pathLength, pathSpacing, pathOffset)
+ }
+ }
+
// @ts-expect-error - Fix errors later for typescript 5
Object.entries(_cache).forEach(([key, value]) => (el.style[key] = value))
}
@@ -53,6 +69,13 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
return
}
+ if ((_target as SVGElement)?.ownerSVGElement) {
+ const { pathLength, pathOffset, pathSpacing } = newVal as SVGPathProperties
+ if (pathLength !== undefined) {
+ setSVGPath((_target as SVGElement), pathLength, pathSpacing, pathOffset)
+ }
+ }
+
// Append the state object to the target style properties
// @ts-expect-error - Fix errors later for typescript 5
for (const key in newVal) _target.style[key] = newVal[key]
diff --git a/src/utils/style.ts b/src/utils/style.ts
index db036b44..09695dea 100644
--- a/src/utils/style.ts
+++ b/src/utils/style.ts
@@ -103,6 +103,11 @@ export const valueTypes: ValueTypeMap = {
fillOpacity: alpha,
strokeOpacity: alpha,
numOctaves: int,
+
+ // custom SVG properties
+ pathLength: px,
+ pathOffset: px,
+ pathSpacing: px,
}
/**
@@ -135,3 +140,55 @@ export function getAnimatableNone(key: string, value: string): any {
// If value is not recognised as animatable, ie "none", create an animatable version origin based on the target
return defaultValueType.getAnimatableNone ? defaultValueType.getAnimatableNone(value) : undefined
}
+
+/**
+ * A quick lookup for custom SVG props.
+ */
+const SVGPathProps = new Set(['pathLength', 'pathOffset', 'pathSpacing'])
+export function isSVGPathProp(key: string): boolean {
+ return SVGPathProps.has(key)
+}
+
+/**
+ * Build SVG path properties from custom properties
+ * pathLength always normalize to 1
+ * pathOffset to stroke-dashoffset
+ * pathLength and pathSpacing to stroke-dasharray
+ *
+ * pathLength: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/pathLength
+ * the path is always normalize to 1, so you need deal with other paths by yourself
+ * base the total length is 1.
+ * for example stroke-dasharray will assume the start of the path being 0 and
+ * the end point the value defined in the pathLength attribute as 1.
+ *
+ * @param target
+ * @param length
+ * @param spacing
+ * @param offset
+ */
+export function setSVGPath(target: SVGElement, length: number | string, spacing = 1, offset = 0) {
+ target.setAttribute('pathLength', '1') // normalize to 1
+ target.setAttribute('stroke-dashoffset', `${offset}`)
+ target.setAttribute('stroke-dasharray', `${length} ${spacing}`)
+}
+
+/**
+ * Get pathLength pathSpacing pathOffset from svg element
+ * Convert stroke-dashoffset stroke-dasharray to custome properties
+ * @param target
+ */
+export function getSVGPath(target: SVGElement) {
+ // pathLength is normalize to 1
+ const pathLength = target.getAttribute('pathLength') ? 1 : undefined
+ const pathOffset = target.getAttribute('stroke-dashoffset') ? Number.parseFloat(target.getAttribute('stroke-dashoffset')!) : 0
+ // TODO need to support odd?
+ // sinle: dashes and gaps are same size
+ // two: dashes and gaps are different sizes
+ // odd: dashes and gaps of various sizes with an odd number of values, [4,1,2] is equivalent to [4,1,2,4,1,2]
+ const pathSpacing = target.getAttribute('stroke-dasharray') ? Number.parseFloat(target.getAttribute('stroke-dasharray')!.split(' ')[1]!) : 1
+ return {
+ pathLength,
+ pathSpacing,
+ pathOffset,
+ }
+}
From 29bc224ebb317bdbd31816f1aae3f219dfe3b8c0 Mon Sep 17 00:00:00 2001
From: imfenghuang <20472384+imfenghuang@users.noreply.github.com>
Date: Mon, 18 Nov 2024 18:24:52 +0800
Subject: [PATCH 2/4] feat: support pathLength pathOffset pathSpacing
---
playgrounds/vite/src/demos/SVGPath.vue | 36 +++++-
playgrounds/vite/src/examples/svgpath.ts | 155 ++++++++++++++---------
src/useElementStyle.ts | 8 +-
src/utils/style.ts | 20 ++-
tests/components.spec.ts | 147 ++++++++++++++++++++-
tests/useElementStyle.spec.ts | 107 ++++++++++++++++
tests/utils/index.ts | 28 ++++
7 files changed, 421 insertions(+), 80 deletions(-)
diff --git a/playgrounds/vite/src/demos/SVGPath.vue b/playgrounds/vite/src/demos/SVGPath.vue
index d507d257..67560dcd 100644
--- a/playgrounds/vite/src/demos/SVGPath.vue
+++ b/playgrounds/vite/src/demos/SVGPath.vue
@@ -1,14 +1,18 @@
-
+
+
`
diff --git a/src/useElementStyle.ts b/src/useElementStyle.ts
index 82fb822a..95336ba1 100644
--- a/src/useElementStyle.ts
+++ b/src/useElementStyle.ts
@@ -3,7 +3,7 @@ import { watch } from 'vue'
import { reactiveStyle } from './reactiveStyle'
import type { MotionTarget, PermissiveTarget, SVGPathProperties, StyleProperties } from './types'
import { usePermissiveTarget } from './usePermissiveTarget'
-import { getSVGPath, isSVGPathProp, setSVGPath, valueTypes } from './utils/style'
+import { getSVGPath, isSVGElement, isSVGPathProp, setSVGPath, valueTypes } from './utils/style'
import { isTransformOriginProp, isTransformProp } from './utils/transform'
/**
@@ -22,7 +22,7 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
usePermissiveTarget(target, (el) => {
_target = el
- if ((_target as SVGElement)?.ownerSVGElement) {
+ if (isSVGElement(_target)) {
const { pathLength, pathSpacing, pathOffset } = getSVGPath(_target as SVGElement)
if (pathLength !== undefined) {
(state as SVGPathProperties).pathLength = pathLength;
@@ -44,7 +44,7 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
// If cache is present, init the target with the current cached value
if (_cache) {
- if ((_target as SVGElement)?.ownerSVGElement) {
+ if (isSVGElement(_target)) {
const { pathLength, pathOffset, pathSpacing } = _cache as SVGPathProperties
if (pathLength !== undefined) {
setSVGPath((_target as SVGElement), pathLength, pathSpacing, pathOffset)
@@ -69,7 +69,7 @@ export function useElementStyle(target: MaybeRef, onInit?: (in
return
}
- if ((_target as SVGElement)?.ownerSVGElement) {
+ if (isSVGElement(_target)) {
const { pathLength, pathOffset, pathSpacing } = newVal as SVGPathProperties
if (pathLength !== undefined) {
setSVGPath((_target as SVGElement), pathLength, pathSpacing, pathOffset)
diff --git a/src/utils/style.ts b/src/utils/style.ts
index 09695dea..20ee0d71 100644
--- a/src/utils/style.ts
+++ b/src/utils/style.ts
@@ -105,9 +105,9 @@ export const valueTypes: ValueTypeMap = {
numOctaves: int,
// custom SVG properties
- pathLength: px,
- pathOffset: px,
- pathSpacing: px,
+ pathLength: auto,
+ pathOffset: auto,
+ pathSpacing: auto,
}
/**
@@ -149,6 +149,14 @@ export function isSVGPathProp(key: string): boolean {
return SVGPathProps.has(key)
}
+/**
+ * Determine whether it is an svg element
+ * @param target
+ */
+export function isSVGElement(target: HTMLElement | SVGElement): boolean {
+ return !!((target as SVGElement)?.ownerSVGElement || target.tagName.toLowerCase() === 'svg')
+}
+
/**
* Build SVG path properties from custom properties
* pathLength always normalize to 1
@@ -166,7 +174,7 @@ export function isSVGPathProp(key: string): boolean {
* @param spacing
* @param offset
*/
-export function setSVGPath(target: SVGElement, length: number | string, spacing = 1, offset = 0) {
+export function setSVGPath(target: SVGElement, length: number, spacing = 1, offset = 0) {
target.setAttribute('pathLength', '1') // normalize to 1
target.setAttribute('stroke-dashoffset', `${offset}`)
target.setAttribute('stroke-dasharray', `${length} ${spacing}`)
@@ -180,12 +188,12 @@ export function setSVGPath(target: SVGElement, length: number | string, spacing
export function getSVGPath(target: SVGElement) {
// pathLength is normalize to 1
const pathLength = target.getAttribute('pathLength') ? 1 : undefined
- const pathOffset = target.getAttribute('stroke-dashoffset') ? Number.parseFloat(target.getAttribute('stroke-dashoffset')!) : 0
+ const pathOffset = target.getAttribute('stroke-dashoffset') ? Number.parseFloat(target.getAttribute('stroke-dashoffset')!) : undefined
// TODO need to support odd?
// sinle: dashes and gaps are same size
// two: dashes and gaps are different sizes
// odd: dashes and gaps of various sizes with an odd number of values, [4,1,2] is equivalent to [4,1,2,4,1,2]
- const pathSpacing = target.getAttribute('stroke-dasharray') ? Number.parseFloat(target.getAttribute('stroke-dasharray')!.split(' ')[1]!) : 1
+ const pathSpacing = target.getAttribute('stroke-dasharray') ? Number.parseFloat(target.getAttribute('stroke-dasharray')!.split(' ')[1]!) : undefined
return {
pathLength,
pathSpacing,
diff --git a/tests/components.spec.ts b/tests/components.spec.ts
index 1548a169..c0d30493 100644
--- a/tests/components.spec.ts
+++ b/tests/components.spec.ts
@@ -4,7 +4,12 @@ import { h, nextTick, ref } from 'vue'
import { MotionComponent, MotionPlugin } from '../src'
import MotionGroup from '../src/components/MotionGroup'
import { intersect } from './utils/intersectionObserver'
-import { getTestComponent, useCompletionFn, waitForMockCalls } from './utils'
+import {
+ getTestComponent,
+ getTestComponentSVG,
+ useCompletionFn,
+ waitForMockCalls,
+} from './utils'
// Register plugin
config.global.plugins.push([
@@ -236,3 +241,143 @@ describe('`` component', async () => {
).toEqual('0')
})
})
+
+/**
+ * tests for svg path
+ * pathLegnth
+ * pathSpacing
+ * pathOffset
+ */
+describe.each([
+ { t: 'dirctive', name: 'v-motion svg element directive' },
+ { t: 'component', name: ' svg element directive' },
+])(`$name`, async ({ t }) => {
+ const TestComponentSVG = getTestComponentSVG(t)
+
+ it('svg variants number', async () => {
+ const onComplete = useCompletionFn()
+
+ const wrapper = mount(TestComponentSVG, {
+ props: {
+ initial: {
+ pathLength: 1,
+ pathSpacing: 1,
+ pathOffset: 2,
+ },
+ enter: {
+ pathLength: 2,
+ pathSpacing: 2,
+ pathOffset: 3,
+ transition: { onComplete },
+ },
+ duration: 10,
+ },
+ })
+
+ const el = wrapper.element as SVGElement
+ await nextTick()
+
+ // Renders initial variant
+ expect(el.style.pathLength).toEqual(1)
+ expect(el.style.pathSpacing).toEqual(1)
+ expect(el.style.pathOffset).toEqual(2)
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('2')
+ expect(el.getAttribute('stroke-dasharray')).toBe('1 1')
+
+ await waitForMockCalls(onComplete)
+
+ // Renders enter variant
+ expect(el.style.pathLength).toEqual(2)
+ expect(el.style.pathSpacing).toEqual(2)
+ expect(el.style.pathOffset).toEqual(3)
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('3')
+ expect(el.getAttribute('stroke-dasharray')).toBe('2 2')
+ })
+
+ it('svg variants px', async () => {
+ const onComplete = useCompletionFn()
+
+ const wrapper = mount(TestComponentSVG, {
+ props: {
+ initial: {
+ pathLength: '1px',
+ pathSpacing: '1px',
+ pathOffset: '2px',
+ },
+ enter: {
+ pathLength: '2px',
+ pathSpacing: '2px',
+ pathOffset: '3px',
+ transition: { onComplete },
+ },
+ duration: 10,
+ },
+ })
+
+ const el = wrapper.element as SVGElement
+ await nextTick()
+
+ // Renders initial variant
+ expect(el.style.pathLength).toEqual('1px')
+ expect(el.style.pathSpacing).toEqual('1px')
+ expect(el.style.pathOffset).toEqual('2px')
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('2px')
+ expect(el.getAttribute('stroke-dasharray')).toBe('1px 1px')
+
+ await waitForMockCalls(onComplete)
+
+ // Renders enter variant
+ expect(el.style.pathLength).toEqual('2px')
+ expect(el.style.pathSpacing).toEqual('2px')
+ expect(el.style.pathOffset).toEqual('3px')
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('3px')
+ expect(el.getAttribute('stroke-dasharray')).toBe('2px 2px')
+ })
+
+ it('svg event variants', async () => {
+ const onComplete = useCompletionFn()
+
+ const wrapper = mount(TestComponentSVG, {
+ props: {
+ initial: {
+ pathLength: 1,
+ pathSpacing: 1,
+ pathOffset: 2,
+ },
+ hovered: {
+ pathLength: 2,
+ pathSpacing: 2,
+ pathOffset: 4,
+ transition: { onComplete },
+ },
+ duration: 10,
+ },
+ })
+
+ const el = wrapper.element as SVGElement
+ await nextTick()
+
+ // Renders initial variant
+ expect(el.style.pathLength).toEqual(1)
+ expect(el.style.pathSpacing).toEqual(1)
+ expect(el.style.pathOffset).toEqual(2)
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('2')
+ expect(el.getAttribute('stroke-dasharray')).toBe('1 1')
+
+ await wrapper.trigger('mouseenter')
+ await waitForMockCalls(onComplete)
+
+ // Renders enter variant
+ expect(el.style.pathLength).toEqual(2)
+ expect(el.style.pathSpacing).toEqual(2)
+ expect(el.style.pathOffset).toEqual(4)
+ expect(el.getAttribute('pathLength')).toBe('1')
+ expect(el.getAttribute('stroke-dashoffset')).toBe('4')
+ expect(el.getAttribute('stroke-dasharray')).toBe('2 2')
+ })
+})
diff --git a/tests/useElementStyle.spec.ts b/tests/useElementStyle.spec.ts
index 4ae78cd0..ed9c7305 100644
--- a/tests/useElementStyle.spec.ts
+++ b/tests/useElementStyle.spec.ts
@@ -44,3 +44,110 @@ describe('useElementStyle', () => {
expect(element.value.style.backgroundColor).toBe('blue')
})
})
+
+/**
+ * tests for svg path
+ * pathLegnth
+ * pathSpacing
+ * pathOffset
+ */
+const TestComponentSVG = {
+ template: `
+
+
+`,
+}
+
+function getSVGElementRef() {
+ const c = mount(TestComponentSVG)
+
+ return ref(c.element as SVGElement)
+}
+
+describe('useElementStyle Test SVGPath', () => {
+ it('accepts an svg element', () => {
+ const element = getSVGElementRef()
+
+ const { style } = useElementStyle(element)
+
+ expect(style).toBeDefined()
+ })
+
+ it('mutates pathLength', async () => {
+ const element = getSVGElementRef()
+ const { style } = useElementStyle(element)
+ style.pathLength = 2
+
+ const line = element.value.querySelector('line')
+ const { style: lineStyle } = useElementStyle(line)
+ lineStyle.pathLength = 3
+
+ await nextTick()
+
+ // svg
+ expect(element.value.getAttribute('pathLength')).toBe('1')
+ expect(element.value.getAttribute('stroke-dashoffset')).toBe('0')
+ expect(element.value.getAttribute('stroke-dasharray')).toBe('2 1')
+
+ // line
+ expect(line.getAttribute('pathLength')).toBe('1')
+ expect(line.getAttribute('stroke-dashoffset')).toBe('0')
+ expect(line.getAttribute('stroke-dasharray')).toBe('3 1')
+
+ // number
+ lineStyle.pathLength = 3
+ lineStyle.pathOffset = 3
+ lineStyle.pathSpacing = 3
+
+ await nextTick()
+
+ expect(line.getAttribute('pathLength')).toBe('1')
+ expect(line.getAttribute('stroke-dashoffset')).toBe('3')
+ expect(line.getAttribute('stroke-dasharray')).toBe('3 3')
+
+ // string
+ lineStyle.pathLength = '3'
+ lineStyle.pathOffset = '3'
+ lineStyle.pathSpacing = '2'
+
+ await nextTick()
+
+ expect(line.getAttribute('pathLength')).toBe('1')
+ expect(line.getAttribute('stroke-dashoffset')).toBe('3')
+ expect(line.getAttribute('stroke-dasharray')).toBe('3 2')
+
+ // px
+ lineStyle.pathLength = '3px'
+ lineStyle.pathOffset = '3px'
+ lineStyle.pathSpacing = '2px'
+
+ await nextTick()
+
+ expect(line.getAttribute('pathLength')).toBe('1')
+ expect(line.getAttribute('stroke-dashoffset')).toBe('3px')
+ expect(line.getAttribute('stroke-dasharray')).toBe('3px 2px')
+
+
+ // percentage
+ lineStyle.pathLength = '3%'
+ lineStyle.pathOffset = '3%'
+ lineStyle.pathSpacing = '2%'
+
+ await nextTick()
+
+ expect(line.getAttribute('pathLength')).toBe('1')
+ expect(line.getAttribute('stroke-dashoffset')).toBe('3%')
+ expect(line.getAttribute('stroke-dasharray')).toBe('3% 2%')
+ })
+})
diff --git a/tests/utils/index.ts b/tests/utils/index.ts
index 5f28b1d3..f6bd9731 100644
--- a/tests/utils/index.ts
+++ b/tests/utils/index.ts
@@ -33,3 +33,31 @@ export async function waitForMockCalls(fn: Mock, calls = 1, options: Parameters<
throw err
}
}
+
+export function getTestComponentSVG(t: string) {
+ if (t === 'directive') {
+ return {
+ template: `
+
+
+
+`,
+ }
+ }
+ return {
+ render: () => h(MotionComponent, {
+ is: 'svg',
+ }),
+ }
+}
From 6bf9effd71310a07ea96e6e0b116880678e24345 Mon Sep 17 00:00:00 2001
From: imfenghuang <20472384+imfenghuang@users.noreply.github.com>
Date: Sun, 8 Dec 2024 00:07:35 +0800
Subject: [PATCH 3/4] fix: useElementStyle.spec.ts lint fix
---
tests/useElementStyle.spec.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/useElementStyle.spec.ts b/tests/useElementStyle.spec.ts
index ed9c7305..244250de 100644
--- a/tests/useElementStyle.spec.ts
+++ b/tests/useElementStyle.spec.ts
@@ -138,7 +138,6 @@ describe('useElementStyle Test SVGPath', () => {
expect(line.getAttribute('stroke-dashoffset')).toBe('3px')
expect(line.getAttribute('stroke-dasharray')).toBe('3px 2px')
-
// percentage
lineStyle.pathLength = '3%'
lineStyle.pathOffset = '3%'
From e8199eb68c381348542d3193d84aa661129afee2 Mon Sep 17 00:00:00 2001
From: imfenghuang <20472384+imfenghuang@users.noreply.github.com>
Date: Sun, 8 Dec 2024 00:17:56 +0800
Subject: [PATCH 4/4] fix: style type
---
src/utils/component.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/utils/component.ts b/src/utils/component.ts
index f447bc06..a70f25e7 100644
--- a/src/utils/component.ts
+++ b/src/utils/component.ts
@@ -15,6 +15,7 @@ import * as presets from '../presets'
import type { MotionInstance } from '../types/instance'
import type {
MotionVariants,
+ SVGPathProperties,
StyleProperties,
Variant,
} from '../types/variants'
@@ -228,7 +229,7 @@ export function setupMotionComponent(
}
// Set node style and register to `instances` on mount
- function setNodeInstance(node: VNode, index: number, style: StyleProperties) {
+ function setNodeInstance(node: VNode, index: number, style: StyleProperties | SVGPathProperties) {
node.props ??= {}
node.props.style ??= {}