Skip to content

Commit

Permalink
Merge pull request #1415 from framer/fix/remove-transformtemplate
Browse files Browse the repository at this point in the history
Handle removal of transformTemplate
  • Loading branch information
mergetron[bot] committed Jan 12, 2022
2 parents 68fb2a7 + 9af1444 commit cb730bd
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 55 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,12 @@

Framer Motion adheres to [Semantic Versioning](http://semver.org/).

## [5.5.8] 2022-01-12

### Fixed

- Removing `transformTemplate` prop correctly rerenders element.

## [5.5.7] 2022-01-11

### Fixed
Expand Down
55 changes: 0 additions & 55 deletions src/motion/__tests__/component.test.tsx
Expand Up @@ -257,68 +257,13 @@ describe("motion component rendering and styles", () => {
expect(container.firstChild).toHaveStyle("background-color: #f00")
})

it("applies transformTemplate on initial render", () => {
const { container } = render(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) =>
`translateY(${x}) ${generated}`
}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(10px) translateX(10px) translateZ(0)"
)
})

it("renders transform", () => {
const { container } = render(
<motion.div style={{ transform: "translateX(10px)" }} />
)
expect(container.firstChild).toHaveStyle("transform: translateX(10px)")
})

it("applies updated transformTemplate", () => {
const { container, rerender } = render(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) =>
`translateY(${x}) ${generated}`
}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(10px) translateX(10px) translateZ(0)"
)

rerender(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) => {
const newX = typeof x === "string" ? parseFloat(x) : x
return `translateY(${(newX as number) * 2}px) ${generated}`
}}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(20px) translateX(10px) translateZ(0)"
)
})

it("renders transform with transformTemplate", () => {
const { container } = render(
<motion.div
transformTemplate={(_, generated) =>
`translateY(20px) ${generated}`
}
style={{ x: 10 }}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(20px) translateX(10px) translateZ(0)"
)
})

it("filters MotionProps from the DOM", () => {
const { container } = render(<motion.div initial={{ opacity: 0 }} />)
expect(container.firstChild).not.toHaveAttribute("initial")
Expand Down
114 changes: 114 additions & 0 deletions src/motion/__tests__/transformTemplate.test.tsx
@@ -0,0 +1,114 @@
import { render } from "../../../jest.setup"
import { motion } from "../../"
import * as React from "react"
import sync from "framesync"

describe("transformTemplate", () => {
it("applies transformTemplate on initial render", () => {
const { container } = render(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) =>
`translateY(${x}) ${generated}`
}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(10px) translateX(10px) translateZ(0)"
)
})

it("applies updated transformTemplate", () => {
const { container, rerender } = render(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) =>
`translateY(${x}) ${generated}`
}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(10px) translateX(10px) translateZ(0)"
)

rerender(
<motion.div
initial={{ x: 10 }}
transformTemplate={({ x }, generated) => {
const newX = typeof x === "string" ? parseFloat(x) : x
return `translateY(${(newX as number) * 2}px) ${generated}`
}}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(20px) translateX(10px) translateZ(0)"
)
})

it("renders transform with transformTemplate", () => {
const { container } = render(
<motion.div
transformTemplate={(_, generated) =>
`translateY(20px) ${generated}`
}
style={{ x: 10 }}
/>
)
expect(container.firstChild).toHaveStyle(
"transform: translateY(20px) translateX(10px) translateZ(0)"
)
})

it("renders transformTemplate without any transform", () => {
const { container } = render(
<motion.div transformTemplate={() => `translateY(20px)`} />
)
expect(container.firstChild).toHaveStyle("transform: translateY(20px)")
})

it("removes transformTemplate if prop is removed and transform is changed", async () => {
const { container, rerender } = render(
<motion.div
transformTemplate={() => `translateY(20px)`}
style={{ x: 10 }}
/>
)
expect(container.firstChild).toHaveStyle("transform: translateY(20px)")
rerender(<motion.div style={{ x: 20 }} />)

await new Promise((resolve) => sync.postRender(resolve))

expect(container.firstChild).toHaveStyle(
"transform: translateX(20px) translateZ(0)"
)
})

it("removes transformTemplate if prop is removed and transform is not changed", async () => {
const { container, rerender } = render(
<motion.div
transformTemplate={() => `translateY(20px)`}
style={{ x: 10 }}
/>
)
expect(container.firstChild).toHaveStyle("transform: translateY(20px)")
rerender(<motion.div style={{ x: 10 }} />)

await new Promise((resolve) => sync.postRender(resolve))

expect(container.firstChild).toHaveStyle(
"transform: translateX(10px) translateZ(0)"
)
})

it("removes transformTemplate if prop is removed", async () => {
const { container, rerender } = render(
<motion.div transformTemplate={() => `translateY(20px)`} />
)
expect(container.firstChild).toHaveStyle("transform: translateY(20px)")
rerender(<motion.div />)

await new Promise((resolve) => sync.postRender(resolve))

expect(container.firstChild).toHaveStyle("transform: none")
})
})
2 changes: 2 additions & 0 deletions src/render/html/utils/build-styles.ts
Expand Up @@ -79,6 +79,8 @@ export function buildHTMLStyles(
)
} else if (transformTemplate) {
style.transform = transformTemplate({}, "")
} else if (!latestValues.transform && style.transform) {
style.transform = "none"
}

if (hasTransformOrigin) {
Expand Down
4 changes: 4 additions & 0 deletions src/render/index.ts
Expand Up @@ -449,6 +449,10 @@ export const visualElement =
* added to our map, old ones removed, and listeners updated.
*/
setProps(newProps) {
if (newProps.transformTemplate || props.transformTemplate) {
element.scheduleRender()
}

props = newProps
lifecycles.updatePropListeners(newProps)

Expand Down

0 comments on commit cb730bd

Please sign in to comment.