Skip to content

Commit c1b41c9

Browse files
committed
Port VisualElement to styleEffect
Latest Latest
1 parent a4d48de commit c1b41c9

36 files changed

+298
-404
lines changed

packages/framer-motion/src/animation/hooks/animation-controls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { VisualElement } from "../../render/VisualElement"
55
import { animateVisualElement } from "../interfaces/visual-element"
66

77
function stopAnimation(visualElement: VisualElement) {
8-
visualElement.values.forEach((value) => value.stop())
8+
visualElement.state.values.forEach(({ value }) => value.stop())
99
}
1010

1111
function setVariants(visualElement: VisualElement, variantLabels: string[]) {

packages/framer-motion/src/animation/hooks/use-animated-state.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { TargetAndTransition } from "motion-dom"
1+
import { MotionNodeState, TargetAndTransition } from "motion-dom"
22
import { useLayoutEffect, useState } from "react"
3-
import { makeUseVisualState } from "../../motion/utils/use-visual-state"
3+
import { makeUseMotionNodeState } from "../../motion/utils/use-motion-value-state"
44
import { createBox } from "../../projection/geometry/models"
55
import { ResolvedValues } from "../../render/types"
66
import { VisualElement } from "../../render/VisualElement"
@@ -23,7 +23,6 @@ class StateVisualElement extends VisualElement<
2323
measureInstanceViewportBox = createBox
2424
resetTransform() {}
2525
restoreTransform() {}
26-
removeValueFromRenderState() {}
2726
renderInstance() {}
2827
scrapeMotionValuesFromProps() {
2928
return createObject()
@@ -45,9 +44,9 @@ class StateVisualElement extends VisualElement<
4544
}
4645
}
4746

48-
const useVisualState = makeUseVisualState({
47+
const useVisualState = makeUseMotionNodeState({
4948
scrapeMotionValuesFromProps: createObject,
50-
createRenderState: createObject,
49+
StateConstructor: MotionNodeState, // TODO ObjectMotionNodeState
5150
})
5251

5352
/**
@@ -56,7 +55,7 @@ const useVisualState = makeUseVisualState({
5655
*/
5756
export function useAnimatedState(initialState: any) {
5857
const [animationState, setAnimationState] = useState(initialState)
59-
const visualState = useVisualState({}, false)
58+
const state = useVisualState({}, false)
6059

6160
const element = useConstant(() => {
6261
return new StateVisualElement(
@@ -66,7 +65,7 @@ export function useAnimatedState(initialState: any) {
6665
setAnimationState({ ...v })
6766
},
6867
},
69-
visualState,
68+
state,
7069
presenceContext: null,
7170
},
7271
{ initialState }

packages/framer-motion/src/animation/interfaces/visual-element-target.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function animateTarget(
5353
for (const key in target) {
5454
const value = visualElement.getValue(
5555
key,
56-
visualElement.latestValues[key] ?? null
56+
visualElement.state.latest[key] ?? null
5757
)
5858
const valueTarget = target[key as keyof typeof target]
5959

packages/framer-motion/src/animation/utils/create-visual-element.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isSVGElement, isSVGSVGElement } from "motion-dom"
1+
import { isSVGElement, isSVGSVGElement, MotionNodeState } from "motion-dom"
22
import { HTMLVisualElement } from "../../render/html/HTMLVisualElement"
33
import { ObjectVisualElement } from "../../render/object/ObjectVisualElement"
44
import { visualElementStore } from "../../render/store"
@@ -8,16 +8,7 @@ export function createDOMVisualElement(element: HTMLElement | SVGElement) {
88
const options = {
99
presenceContext: null,
1010
props: {},
11-
visualState: {
12-
renderState: {
13-
transform: {},
14-
transformOrigin: {},
15-
style: {},
16-
vars: {},
17-
attrs: {},
18-
},
19-
latestValues: {},
20-
},
11+
state: new MotionNodeState({}),
2112
}
2213
const node =
2314
isSVGElement(element) && !isSVGSVGElement(element)
@@ -33,12 +24,7 @@ export function createObjectVisualElement(subject: Object) {
3324
const options = {
3425
presenceContext: null,
3526
props: {},
36-
visualState: {
37-
renderState: {
38-
output: {},
39-
},
40-
latestValues: {},
41-
},
27+
state: new MotionNodeState({}),
4228
}
4329
const node = new ObjectVisualElement(options)
4430

packages/framer-motion/src/gestures/drag/VisualElementDragControls.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export class VisualElementDragControls {
219219
* of a re-render we want to ensure the browser can read the latest
220220
* bounding box to ensure the pointer and element don't fall out of sync.
221221
*/
222-
this.visualElement.render()
222+
this.visualElement.state.render()
223223

224224
/**
225225
* This must fire after the render call as it might trigger a state
@@ -682,7 +682,7 @@ export class VisualElementDragControls {
682682
)
683683
})
684684

685-
this.visualElement.render()
685+
this.visualElement.state.render()
686686
}
687687
}) as any
688688
)

packages/framer-motion/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ export { addPointerEvent } from "./events/add-pointer-event"
2121
export { addPointerInfo } from "./events/event-info"
2222
export { animations } from "./motion/features/animations"
2323
export {
24-
makeUseVisualState,
25-
VisualState,
26-
} from "./motion/utils/use-visual-state"
24+
makeUseMotionNodeState,
25+
UseMotionNodeState,
26+
} from "./motion/utils/use-motion-value-state"
2727
export { calcLength } from "./projection/geometry/delta-calc"
2828
export { createBox } from "./projection/geometry/models"
2929
export { filterProps } from "./render/dom/utils/filter-props"

packages/framer-motion/src/motion/index.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import { useCreateMotionContext } from "../context/MotionContext/create"
1111
import { DOMMotionComponents } from "../render/dom/types"
1212
import { useRender } from "../render/dom/use-render"
1313
import { isSVGComponent } from "../render/dom/utils/is-svg-component"
14-
import { HTMLRenderState } from "../render/html/types"
1514
import { useHTMLVisualState } from "../render/html/use-html-visual-state"
16-
import { SVGRenderState } from "../render/svg/types"
1715
import { useSVGVisualState } from "../render/svg/use-svg-visual-state"
1816
import { CreateVisualElement } from "../render/types"
1917
import { isBrowser } from "../utils/is-browser"
@@ -96,7 +94,7 @@ export function createMotionComponent<
9694

9795
const context = useCreateMotionContext<HTMLElement | SVGElement>(props)
9896

99-
const visualState = useVisualState(props, isStatic)
97+
const state = useVisualState(props, isStatic)
10098

10199
if (!isStatic && isBrowser) {
102100
useStrictMode(configAndProps, preloadedFeatures)
@@ -112,7 +110,7 @@ export function createMotionComponent<
112110
*/
113111
context.visualElement = useVisualElement(
114112
Component,
115-
visualState,
113+
state,
116114
configAndProps,
117115
createVisualElement,
118116
layoutProjection.ProjectionNode
@@ -134,11 +132,11 @@ export function createMotionComponent<
134132
{useRender<Props, TagName>(
135133
Component,
136134
props,
137-
useMotionRef<
138-
HTMLElement | SVGElement,
139-
HTMLRenderState | SVGRenderState
140-
>(visualState, context.visualElement, externalRef),
141-
visualState,
135+
useMotionRef<HTMLElement | SVGElement>(
136+
context.visualElement,
137+
externalRef
138+
),
139+
state,
142140
isStatic,
143141
forwardMotionProps
144142
)}

packages/framer-motion/src/motion/utils/use-motion-ref.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,17 @@ import * as React from "react"
22
import { useCallback } from "react"
33
import type { VisualElement } from "../../render/VisualElement"
44
import { isRefObject } from "../../utils/is-ref-object"
5-
import { VisualState } from "./use-visual-state"
65

76
/**
87
* Creates a ref function that, when called, hydrates the provided
98
* external ref and VisualElement.
109
*/
11-
export function useMotionRef<Instance, RenderState>(
12-
visualState: VisualState<Instance, RenderState>,
10+
export function useMotionRef<Instance>(
1311
visualElement?: VisualElement<Instance> | null,
1412
externalRef?: React.Ref<Instance>
1513
): React.Ref<Instance> {
1614
return useCallback(
1715
(instance: Instance) => {
18-
if (instance) {
19-
visualState.onMount && visualState.onMount(instance)
20-
}
21-
2216
if (visualElement) {
2317
if (instance) {
2418
visualElement.mount(instance)

packages/framer-motion/src/motion/utils/use-visual-state.ts renamed to packages/framer-motion/src/motion/utils/use-motion-value-state.ts

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AnyResolvedKeyframe } from "motion-dom"
1+
import { AnyResolvedKeyframe, MotionNodeState } from "motion-dom"
22
import { useContext } from "react"
33
import { isAnimationControls } from "../../animation/utils/is-animation-controls"
44
import { MotionContext, MotionContextProps } from "../../context/MotionContext"
@@ -16,45 +16,33 @@ import { useConstant } from "../../utils/use-constant"
1616
import { resolveMotionValue } from "../../value/utils/resolve-motion-value"
1717
import { MotionProps } from "../types"
1818

19-
export interface VisualState<Instance, RenderState> {
20-
renderState: RenderState
21-
latestValues: ResolvedValues
22-
onMount?: (instance: Instance) => void
23-
}
24-
25-
export type UseVisualState<Instance, RenderState> = (
19+
export type UseMotionNodeState = (
2620
props: MotionProps,
2721
isStatic: boolean
28-
) => VisualState<Instance, RenderState>
22+
) => MotionNodeState
2923

30-
export interface UseVisualStateConfig<RenderState> {
24+
export interface UseMotionNodeStateConfig {
3125
scrapeMotionValuesFromProps: ScrapeMotionValuesFromProps
32-
createRenderState: () => RenderState
26+
StateConstructor: new (initialValues: ResolvedValues) => MotionNodeState
3327
}
3428

35-
function makeState<I, RS>(
36-
{
37-
scrapeMotionValuesFromProps,
38-
createRenderState,
39-
}: UseVisualStateConfig<RS>,
29+
function makeMotionNodeState(
30+
{ scrapeMotionValuesFromProps, StateConstructor }: UseMotionNodeStateConfig,
4031
props: MotionProps,
4132
context: MotionContextProps,
4233
presenceContext: PresenceContextProps | null
4334
) {
44-
const state: VisualState<I, RS> = {
45-
latestValues: makeLatestValues(
35+
return new StateConstructor(
36+
makeInitialValues(
4637
props,
4738
context,
4839
presenceContext,
4940
scrapeMotionValuesFromProps
50-
),
51-
renderState: createRenderState(),
52-
}
53-
54-
return state
41+
)
42+
)
5543
}
5644

57-
function makeLatestValues(
45+
function makeInitialValues(
5846
props: MotionProps,
5947
context: MotionContextProps,
6048
presenceContext: PresenceContextProps | null,
@@ -128,12 +116,13 @@ function makeLatestValues(
128116
return values
129117
}
130118

131-
export const makeUseVisualState =
132-
<I, RS>(config: UseVisualStateConfig<RS>): UseVisualState<I, RS> =>
133-
(props: MotionProps, isStatic: boolean): VisualState<I, RS> => {
119+
export const makeUseMotionNodeState =
120+
(config: UseMotionNodeStateConfig): UseMotionNodeState =>
121+
(props: MotionProps, isStatic: boolean): MotionNodeState => {
134122
const context = useContext(MotionContext)
135123
const presenceContext = useContext(PresenceContext)
136-
const make = () => makeState(config, props, context, presenceContext)
124+
const make = () =>
125+
makeMotionNodeState(config, props, context, presenceContext)
137126

138127
return isStatic ? make() : useConstant(make)
139128
}

packages/framer-motion/src/motion/utils/use-visual-element.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MotionNodeState } from "motion-dom"
12
import * as React from "react"
23
import { useContext, useEffect, useInsertionEffect, useRef } from "react"
34
import { optimizedAppearDataAttribute } from "../../animation/optimized-appear/data-id"
@@ -12,22 +13,17 @@ import {
1213
import { MotionProps } from "../../motion/types"
1314
import { IProjectionNode } from "../../projection/node/types"
1415
import { DOMMotionComponents } from "../../render/dom/types"
15-
import { HTMLRenderState } from "../../render/html/types"
16-
import { SVGRenderState } from "../../render/svg/types"
1716
import { CreateVisualElement } from "../../render/types"
1817
import type { VisualElement } from "../../render/VisualElement"
1918
import { isRefObject } from "../../utils/is-ref-object"
2019
import { useIsomorphicLayoutEffect } from "../../utils/use-isomorphic-effect"
21-
import { VisualState } from "./use-visual-state"
2220

2321
export function useVisualElement<
2422
Props,
2523
TagName extends keyof DOMMotionComponents | string
2624
>(
2725
Component: TagName | string | React.ComponentType<Props>,
28-
visualState:
29-
| VisualState<SVGElement, SVGRenderState>
30-
| VisualState<HTMLElement, HTMLRenderState>,
26+
state: MotionNodeState,
3127
props: MotionProps & Partial<MotionConfigContext>,
3228
createVisualElement?: CreateVisualElement<Props, TagName>,
3329
ProjectionNodeConstructor?: any
@@ -50,7 +46,7 @@ export function useVisualElement<
5046

5147
if (!visualElementRef.current && createVisualElement) {
5248
visualElementRef.current = createVisualElement(Component, {
53-
visualState,
49+
state,
5450
parent,
5551
props,
5652
presenceContext,
@@ -167,7 +163,7 @@ function createProjectionNode(
167163
} = props
168164

169165
visualElement.projection = new ProjectionNodeConstructor(
170-
visualElement.latestValues,
166+
visualElement.state.latest,
171167
props["data-framer-portal-id"]
172168
? undefined
173169
: getClosestProjectingNode(visualElement.parent)

0 commit comments

Comments
 (0)