Skip to content

Commit

Permalink
Merge pull request #2650 from framer/fix/async-handlers
Browse files Browse the repository at this point in the history
Reimplementing async event handlers
  • Loading branch information
mergetron[bot] committed May 7, 2024
2 parents 373a355 + b4760f6 commit 4a30f29
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 28 deletions.
22 changes: 7 additions & 15 deletions packages/framer-motion/src/gestures/__tests__/hover.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
} from "../../../jest.setup"
import { motion } from "../../"
import { motionValue } from "../../value"
import { frame } from "../../frameloop"
import { nextFrame } from "./utils"

describe("hover", () => {
Expand All @@ -21,13 +20,10 @@ describe("hover", () => {
pointerEnter(container.firstChild as Element)
pointerLeave(container.firstChild as Element)

return new Promise<void>((resolve) => {
frame.render(() => {
expect(hoverIn).toBeCalledTimes(1)
expect(hoverOut).toBeCalledTimes(1)
resolve()
})
})
await nextFrame()

expect(hoverIn).toBeCalledTimes(1)
expect(hoverOut).toBeCalledTimes(1)
})

test("filters touch events", async () => {
Expand All @@ -41,13 +37,9 @@ describe("hover", () => {
pointerEnter(container.firstChild as Element, { pointerType: "touch" })
pointerLeave(container.firstChild as Element, { pointerType: "touch" })

return new Promise<void>((resolve) => {
frame.render(() => {
expect(hoverIn).toBeCalledTimes(0)
expect(hoverOut).toBeCalledTimes(0)
resolve()
})
})
await nextFrame()
expect(hoverIn).toBeCalledTimes(0)
expect(hoverOut).toBeCalledTimes(0)
})

test("whileHover applied", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { mixNumber } from "../../utils/mix/number"
import { percent } from "../../value/types/numbers/units"
import { animateMotionValue } from "../../animation/interfaces/motion-value"
import { getContextWindow } from "../../utils/get-context-window"
import { frame } from "../../frameloop"

export const elementDragControls = new WeakMap<
VisualElement,
Expand Down Expand Up @@ -152,7 +153,9 @@ export class VisualElementDragControls {
})

// Fire onDragStart event
if (onDragStart) onDragStart(event, info)
if (onDragStart) {
frame.postRender(() => onDragStart(event, info))
}

const { animationState } = this.visualElement
animationState && animationState.setActive("whileDrag", true)
Expand Down Expand Up @@ -240,7 +243,9 @@ export class VisualElementDragControls {
this.startAnimation(velocity)

const { onDragEnd } = this.getProps()
if (onDragEnd) onDragEnd(event, info)
if (onDragEnd) {
frame.postRender(() => onDragEnd(event, info))
}
}

private cancel() {
Expand Down
5 changes: 4 additions & 1 deletion packages/framer-motion/src/gestures/hover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { isDragActive } from "./drag/utils/lock"
import { EventInfo } from "../events/types"
import type { VisualElement } from "../render/VisualElement"
import { Feature } from "../motion/features/Feature"
import { frame } from "../frameloop"

function addHoverEvent(node: VisualElement<Element>, isActive: boolean) {
const eventName = isActive ? "pointerenter" : "pointerleave"
Expand All @@ -19,7 +20,9 @@ function addHoverEvent(node: VisualElement<Element>, isActive: boolean) {
}

const callback = props[callbackName]
if (callback) callback(event, info)
if (callback) {
frame.postRender(() => callback(event, info))
}
}

return addPointerEvent(node.current!, eventName, handleEvent, {
Expand Down
7 changes: 5 additions & 2 deletions packages/framer-motion/src/gestures/pan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { addPointerEvent } from "../../events/add-pointer-event"
import { Feature } from "../../motion/features/Feature"
import { noop } from "../../utils/noop"
import { getContextWindow } from "../../utils/get-context-window"
import { frame } from "../../frameloop"

type PanEventHandler = (event: PointerEvent, info: PanInfo) => void
const asyncHandler =
(handler?: PanEventHandler) => (event: PointerEvent, info: PanInfo) => {
if (handler) {
handler(event, info)
frame.postRender(() => handler(event, info))
}
}

Expand Down Expand Up @@ -38,7 +39,9 @@ export class PanGesture extends Feature<Element> {
onMove: onPan,
onEnd: (event: PointerEvent, info: PanInfo) => {
delete this.session
if (onPanEnd) onPanEnd(event, info)
if (onPanEnd) {
frame.postRender(() => onPanEnd(event, info))
}
},
}
}
Expand Down
24 changes: 17 additions & 7 deletions packages/framer-motion/src/gestures/press.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { pipe } from "../utils/pipe"
import { isDragActive } from "./drag/utils/lock"
import { isNodeOrChild } from "./utils/is-node-or-child"
import { noop } from "../utils/noop"
import { frame } from "../frameloop"

function fireSyntheticPointerEvent(
name: string,
Expand Down Expand Up @@ -40,7 +41,7 @@ export class PressGesture extends Feature<Element> {
}

if (onTapStart) {
onTapStart(event, info)
frame.postRender(() => onTapStart(event, info))
}
}

Expand Down Expand Up @@ -79,10 +80,15 @@ export class PressGesture extends Feature<Element> {
* We only count this as a tap gesture if the event.target is the same
* as, or a child of, this component's element
*/
!globalTapTarget &&
!isNodeOrChild(this.node.current, endEvent.target as Element)
? onTapCancel && onTapCancel(endEvent, endInfo)
: onTap && onTap(endEvent, endInfo)
const handler =
!globalTapTarget &&
!isNodeOrChild(this.node.current, endEvent.target as Element)
? onTapCancel
: onTap

if (handler) {
frame.update(() => handler(endEvent, endInfo))
}
}

const removePointerUpListener = addPointerEvent(
Expand Down Expand Up @@ -121,7 +127,9 @@ export class PressGesture extends Feature<Element> {
if (!this.checkPressEnd()) return

const { onTapCancel } = this.node.getProps()
if (onTapCancel) onTapCancel(event, info)
if (onTapCancel) {
frame.postRender(() => onTapCancel(event, info))
}
}

private startAccessiblePress = () => {
Expand All @@ -133,7 +141,9 @@ export class PressGesture extends Feature<Element> {

fireSyntheticPointerEvent("up", (event, info) => {
const { onTap } = this.node.getProps()
if (onTap) onTap(event, info)
if (onTap) {
frame.postRender(() => onTap(event, info))
}
})
}

Expand Down
4 changes: 3 additions & 1 deletion packages/framer-motion/src/motion/__tests__/waapi.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
render,
} from "../../../jest.setup"
import { motion, useMotionValue } from "../../"
import { useState, createRef } from "react";
import { useState, createRef } from "react"
import { nextFrame } from "../../gestures/__tests__/utils"
import "../../animation/animators/waapi/__tests__/setup"
import { act } from "react-dom/test-utils"
Expand Down Expand Up @@ -310,8 +310,10 @@ describe("WAAPI animations", () => {
await nextFrame()
pointerLeave(container.firstChild as Element)
await nextFrame()
await nextFrame()
rerender(<Component />)
await nextFrame()
await nextFrame()

expect(ref.current!.animate).toBeCalledTimes(2)
})
Expand Down

0 comments on commit 4a30f29

Please sign in to comment.