Skip to content
Merged
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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ Framer Motion adheres to [Semantic Versioning](http://semver.org/).

Undocumented APIs should be considered internal and may change without warning.

## [11.11.4] 2024-10-08

### Fixed

- Memoize `AnimatePresence` `safeToRemove`.
- Remove duplicate `layout="size"` annotation.

## [11.11.3] 2024-10-08

### Fixed

- Remove `as any` requirement for CSS variables.

## [11.11.2] 2024-10-08

### Fixed

- Make `BezierDefinition` `readonly` for easier definition outside a `Transition`.

## [11.11.1] 2024-10-04

### Fix
Expand Down
4 changes: 2 additions & 2 deletions dev/next/package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "next-env",
"private": true,
"version": "11.11.1",
"version": "11.11.4",
"type": "module",
"scripts": {
"dev": "next dev",
"dev-server": "next dev",
"start": "next start"
},
"dependencies": {
"framer-motion": "^11.11.1",
"framer-motion": "^11.11.4",
"next": "14.x",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
4 changes: 2 additions & 2 deletions dev/react/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-env",
"private": true,
"version": "11.11.1",
"version": "11.11.4",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -11,7 +11,7 @@
"preview": "vite preview"
},
"dependencies": {
"framer-motion": "^11.11.1",
"framer-motion": "^11.11.4",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "11.11.1",
"version": "11.11.4",
"packages": [
"packages/*"
],
Expand Down
4 changes: 2 additions & 2 deletions packages/framer-motion-3d/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "framer-motion-3d",
"version": "11.11.1",
"version": "11.11.4",
"description": "A simple and powerful React animation library for @react-three/fiber",
"main": "dist/cjs/index.js",
"module": "dist/es/index.mjs",
Expand Down Expand Up @@ -47,7 +47,7 @@
"postpublish": "git push --tags"
},
"dependencies": {
"framer-motion": "^11.11.1",
"framer-motion": "^11.11.4",
"react-merge-refs": "^2.0.1"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/framer-motion/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "framer-motion",
"version": "11.11.1",
"version": "11.11.4",
"description": "A simple and powerful JavaScript animation library",
"main": "dist/cjs/index.js",
"module": "dist/es/index.mjs",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { render } from "../../../jest.setup"
import { motion } from "../.."
import * as React from "react"
import { motion, animate, animateMini } from "../.."
import { parseCSSVariable } from "../../render/dom/utils/css-variables-conversion"

const fromName = "--from"
Expand All @@ -13,7 +12,7 @@ const toVariable = `var(${toName})`
const style = {
[fromName]: fromValue,
[toName]: toValue,
} as React.CSSProperties
}

// Stub getPropertyValue because CSS variables aren't supported by JSDom

Expand Down Expand Up @@ -53,6 +52,23 @@ describe("css variables", () => {
beforeAll(stubGetComputedStyles)
afterAll(resetComputedStyles)

test("types work", () => {
;() => (
<motion.div
initial={{ x: 0, "--from": "#f00", "--to": 0 }}
transition={{ "--from": { duration: 1 } }}
whileHover={{ x: 100, "--from": "#f00", "--to": 0 }}
style={{ "--from": "#f00", "--to": 0, x: 100 }}
/>
)

animate(document.createElement("div"), { x: 0, "--color": "#f00" })
animateMini(document.createElement("div"), {
transform: "none",
"--color": "#f00",
})
})

test("should animate css color variables", async () => {
const promise = new Promise((resolve) => {
let frameCount = 0
Expand Down Expand Up @@ -89,8 +105,8 @@ describe("css variables", () => {
const output: string[] = []
const Component = () => (
<motion.div
style={{ "--color": " #fff " } as any}
animate={{ "--a": "20px", "--color": "#000" } as any}
style={{ "--color": " #fff " }}
animate={{ "--a": "20px", "--color": "#000" }}
transition={{ duration: 0.001 }}
onUpdate={(latest: any) => output.push(latest)}
onAnimationComplete={() => resolve(output)}
Expand Down
2 changes: 1 addition & 1 deletion packages/framer-motion/src/animation/sequence/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ export function getValueTransition(
transition: DynamicAnimationOptions & At,
key: string
): DynamicAnimationOptions {
return transition[key as keyof typeof transition]
return transition && transition[key as keyof typeof transition]
? {
...transition,
...(transition[key as keyof typeof transition] as Transition),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Transition } from "../../types"

export function getValueTransition(transition: Transition, key: string) {
return (
transition[key as keyof typeof transition] ||
(transition as any)["default"] ||
transition
)
return transition
? transition[key as keyof typeof transition] ||
(transition as any)["default"] ||
transition
: undefined
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import * as React from "react"
import { useId, useMemo } from "react"
import { useId, useMemo, useCallback } from "react"
import {
PresenceContext,
PresenceContextProps,
Expand Down Expand Up @@ -32,21 +32,26 @@ export const PresenceChild = ({
const presenceChildren = useConstant(newChildrenMap)
const id = useId()

const memoizedOnExitComplete = useCallback(
(childId: string) => {
presenceChildren.set(childId, true)

for (const isComplete of presenceChildren.values()) {
if (!isComplete) return // can stop searching when any is incomplete
}

onExitComplete && onExitComplete()
},
[presenceChildren, onExitComplete]
)

const context = useMemo(
(): PresenceContextProps => ({
id,
initial,
isPresent,
custom,
onExitComplete: (childId: string) => {
presenceChildren.set(childId, true)

for (const isComplete of presenceChildren.values()) {
if (!isComplete) return // can stop searching when any is incomplete
}

onExitComplete && onExitComplete()
},
onExitComplete: memoizedOnExitComplete,
register: (childId: string) => {
presenceChildren.set(childId, false)
return () => presenceChildren.delete(childId)
Expand All @@ -57,7 +62,9 @@ export const PresenceChild = ({
* we want to make a new context value to ensure they get re-rendered
* so they can detect that layout change.
*/
presenceAffectsLayout ? [Math.random()] : [isPresent]
presenceAffectsLayout
? [Math.random(), memoizedOnExitComplete]
: [isPresent, memoizedOnExitComplete]
)

useMemo(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/framer-motion/src/easing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export type EasingFunction = (v: number) => number

export type EasingModifier = (easing: EasingFunction) => EasingFunction

export type BezierDefinition = [number, number, number, number]
export type BezierDefinition = readonly [number, number, number, number]

export type EasingDefinition =
| BezierDefinition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ test("isBezierDefinition", () => {
expect(isBezierDefinition((v) => v)).toEqual(false)
expect(isBezierDefinition(["linear"])).toEqual(false)
expect(isBezierDefinition([0, 1, 2, 3])).toEqual(true)
expect(isBezierDefinition([0, 1, 2, 3] as const)).toEqual(true)
})
3 changes: 2 additions & 1 deletion packages/framer-motion/src/easing/utils/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { circIn, circInOut, circOut } from "../../easing/circ"
import { backIn, backInOut, backOut } from "../../easing/back"
import { anticipate } from "../../easing/anticipate"
import { Easing } from "../../easing/types"
import { isBezierDefinition } from "./is-bezier-definition";

const easingLookup = {
linear: noop,
Expand All @@ -22,7 +23,7 @@ const easingLookup = {
}

export const easingDefinitionToFunction = (definition: Easing) => {
if (Array.isArray(definition)) {
if (isBezierDefinition(definition)) {
// If cubic bezier definition, create bezier curve
invariant(
definition.length === 4,
Expand Down
2 changes: 0 additions & 2 deletions packages/framer-motion/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ export {
MotionStyle,
MotionTransform,
VariantLabels,
RelayoutInfo,
ResolveLayoutTransition,
} from "./motion/types"
export {
Orchestration,
Expand Down
3 changes: 1 addition & 2 deletions packages/framer-motion/src/motion/features/layout/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ export interface LayoutProps {
* animated on this component. Otherwise, set them directly via the `initial` prop.
*
* If `layout` is set to `"position"`, the size of the component will change instantly and
* only its position will animate. If `layout` is set to `"size"`, the position of the
* component will change instantly but its size will animate.
* only its position will animate.
*
* If `layout` is set to `"size"`, the position of the component will change instantly and
* only its size will animate.
Expand Down
32 changes: 10 additions & 22 deletions packages/framer-motion/src/motion/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
} from "../gestures/types"
import { ViewportProps } from "./features/viewport/types"

export type MotionStyleProp = string | number | MotionValue

/**
* Either a string, or array of strings, that reference variants defined via the `variants` prop.
* @public
Expand Down Expand Up @@ -90,35 +88,25 @@ export type MotionCSS = MakeMotion<
*/
export type MotionTransform = MakeMotion<TransformProperties>

export type MotionCSSVariables = {
[key: `--${string}`]:
| MotionValue<number>
| MotionValue<string>
| string
| number
}

/**
* @public
*/
export type MotionStyle = MotionCSS &
export type MotionStyle = MotionCSSVariables &
MotionCSS &
MotionTransform &
MakeMotion<SVGPathProperties> &
MakeCustomValueType<CustomStyles>

export type OnUpdate = (v: Target) => void

/**
* @public
*/
export interface RelayoutInfo {
delta: {
x: number
y: number
width: number
height: number
}
}

/**
* @public
*/
export type ResolveLayoutTransition = (
info: RelayoutInfo
) => Transition | boolean

/**
* @public
*/
Expand Down
4 changes: 3 additions & 1 deletion packages/framer-motion/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CustomStyles,
SVGPathProperties,
} from "./motion/types"
import { VariableKeyframesDefinition } from "./animation/types"

export type GenericKeyframesTarget<V> = V[] | Array<null | V>

Expand Down Expand Up @@ -975,7 +976,8 @@ type TargetProperties = CSSPropertiesWithoutTransitionOrSingleTransforms &
SVGTransformAttributes &
TransformProperties &
CustomStyles &
SVGPathProperties
SVGPathProperties &
VariableKeyframesDefinition

/**
* @public
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7318,7 +7318,7 @@ __metadata:
"@react-three/fiber": ^8.2.2
"@react-three/test-renderer": ^9.0.0
"@rollup/plugin-commonjs": ^22.0.1
framer-motion: ^11.11.1
framer-motion: ^11.11.4
react-merge-refs: ^2.0.1
three: ^0.137.0
peerDependencies:
Expand All @@ -7329,7 +7329,7 @@ __metadata:
languageName: unknown
linkType: soft

"framer-motion@^11.11.1, framer-motion@workspace:packages/framer-motion":
"framer-motion@^11.11.4, framer-motion@workspace:packages/framer-motion":
version: 0.0.0-use.local
resolution: "framer-motion@workspace:packages/framer-motion"
dependencies:
Expand Down Expand Up @@ -10997,7 +10997,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "next-env@workspace:dev/next"
dependencies:
framer-motion: ^11.11.1
framer-motion: ^11.11.4
next: 14.x
react: ^18.3.1
react-dom: ^18.3.1
Expand Down Expand Up @@ -12545,7 +12545,7 @@ __metadata:
"@typescript-eslint/parser": ^7.2.0
"@vitejs/plugin-react-swc": ^3.5.0
eslint-plugin-react-refresh: ^0.4.6
framer-motion: ^11.11.1
framer-motion: ^11.11.4
react: ^18.3.1
react-dom: ^18.3.1
styled-components: ^6.1.11
Expand Down