Skip to content

Commit

Permalink
Merge pull request #1299 from framer/fix/cancelled-animations-notify-…
Browse files Browse the repository at this point in the history
…when-done

Fix cancelled animations neglecting to notify they are done
  • Loading branch information
mergetron[bot] committed Oct 22, 2021
2 parents 0568791 + c225c23 commit 22601f1
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 8 deletions.
12 changes: 12 additions & 0 deletions cypress/integration/layout-cancelled-finishes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
describe("Cancelled Animation", () => {
it("Allows the animation to be marked complete", () => {
cy.visit("?test=layout-cancelled-finishes")
.get("[data-testid='cancellable']")
.trigger("click")
.wait(200)
.should(($cancellable: any) => {
const cancellable = $cancellable[0] as HTMLDivElement
expect(cancellable).to.not.exist
})
})
})
19 changes: 19 additions & 0 deletions dev/tests/layout-cancelled-finishes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react"
import { motion, AnimatePresence, useInstantLayoutTransition } from "@framer"

export const App = () => {
const [isVisible, setIsVisible] = React.useState(true)
const startTransition = useInstantLayoutTransition()

return (
<AnimatePresence>
{isVisible && (
<motion.div
onClick={() => startTransition(() => setIsVisible(false))}
data-testid="cancellable"
style={{ height: 100 }}
/>
)}
</AnimatePresence>
)
}
4 changes: 2 additions & 2 deletions src/motion/features/animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const animations: FeatureComponents = {
),
exit: makeRenderlessComponent((props: FeatureProps) => {
const { custom, visualElement } = props
const [isPresent, onExitComplete] = usePresence()
const [isPresent, safeToRemove] = usePresence()
const presenceContext = useContext(PresenceContext)

useEffect(() => {
Expand All @@ -37,7 +37,7 @@ export const animations: FeatureComponents = {
{ custom: presenceContext?.custom ?? custom }
)

!isPresent && animation?.then(onExitComplete)
!isPresent && animation?.then(safeToRemove)
}, [isPresent])
}),
}
14 changes: 11 additions & 3 deletions src/motion/features/layout/MeasureLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ class MeasureLayoutWithContext extends React.Component<
}

getSnapshotBeforeUpdate(prevProps: FeatureProps & MeasureContextProps) {
const { layoutDependency, visualElement, drag, isPresent } = this.props
const {
layoutDependency,
visualElement,
drag,
isPresent,
safeToRemove,
} = this.props
const projection = visualElement.projection

if (!projection) return null
Expand All @@ -74,13 +80,15 @@ class MeasureLayoutWithContext extends React.Component<
layoutDependency === undefined
) {
projection.willUpdate()
} else {
safeToRemove?.()
}

if (prevProps.isPresent !== isPresent) {
if (isPresent) {
projection.promote()
} else {
projection.relegate()
} else if (!projection.relegate()) {
safeToRemove?.()
}
}

Expand Down
15 changes: 12 additions & 3 deletions src/projection/node/create-projection-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,10 @@ export function createProjectionNode<I>({
}: LayoutUpdateData) => {
const dragControls =
elementDragControls.get(visualElement)
if (dragControls?.isDragging) return
if (dragControls?.isDragging) {
this.options.onExitComplete?.()
return
}

// TODO: Check here if an animation exists
const layoutTransition =
Expand Down Expand Up @@ -453,6 +456,8 @@ export function createProjectionNode<I>({
),
onComplete: onLayoutAnimationComplete,
})
} else {
this.options.onExitComplete?.()
}

this.targetLayout = newLayout
Expand Down Expand Up @@ -492,7 +497,10 @@ export function createProjectionNode<I>({
}

willUpdate(shouldNotifyListeners = true) {
if (this.root.isUpdateBlocked()) return
if (this.root.isUpdateBlocked()) {
this.options.onExitComplete?.()
return
}
!this.root.isUpdating && this.root.startUpdate()
if (this.isLayoutDirty) return

Expand Down Expand Up @@ -534,7 +542,6 @@ export function createProjectionNode<I>({
this.nodes!.forEach(clearMeasurements)
return
}

if (!this.isUpdating) return

this.isUpdating = false
Expand Down Expand Up @@ -1553,6 +1560,8 @@ function notifyLayoutUpdate(node: IProjectionNode) {
hasLayoutChanged,
hasRelativeTargetChanged,
})
} else {
node.options.onExitComplete?.()
}

/**
Expand Down

0 comments on commit 22601f1

Please sign in to comment.