Skip to content

Commit

Permalink
Merge pull request #2480 from framer/feature/global-tap-handler
Browse files Browse the repository at this point in the history
Allow attach tap handler to global context
  • Loading branch information
mergetron[bot] authored Jan 10, 2024
2 parents df94ca8 + fdb4622 commit 73f321b
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 15 deletions.
24 changes: 24 additions & 0 deletions dev/examples/Events-whileTap-global.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from "react"
import { motion } from "framer-motion"

const style = {
width: 100,
height: 100,
background: "rgba(255, 0, 0, 1)",
}

export const App = () => {
return (
<motion.div globalTapTarget whileTap="pressed">
<motion.div
variants={{
pressed: {
scale: 0.5,
backgroundColor: "rgba(0, 255, 0, .5)",
},
}}
style={style}
/>
</motion.div>
)
}
4 changes: 1 addition & 3 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"version": "10.17.12",
"packages": [
"packages/*"
],
"packages": ["packages/*"],
"npmClient": "yarn",
"useWorkspaces": true
}
3 changes: 1 addition & 2 deletions packages/framer-motion-3d/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,5 @@
"@react-three/fiber": "^8.2.2",
"@react-three/test-renderer": "^9.0.0",
"@rollup/plugin-commonjs": "^22.0.1"
},
"gitHead": "f8972cf2de9a59e65915468cf4ff7126789a8d2f"
}
}
5 changes: 2 additions & 3 deletions packages/framer-motion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@
},
{
"path": "./dist/size-webpack-dom-max.js",
"maxSize": "31.88 kB"
"maxSize": "31.89 kB"
}
],
"gitHead": "f8972cf2de9a59e65915468cf4ff7126789a8d2f"
]
}
20 changes: 20 additions & 0 deletions packages/framer-motion/src/gestures/__tests__/press.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ describe("press", () => {
expect(press).toBeCalledTimes(1)
})

test("global press event listeners fire", async () => {
const press = jest.fn()
const Component = () => (
<>
<div data-testid="target" />
<motion.div globalTapTarget onTap={() => press()} />
</>
)

const { getByTestId, rerender } = render(<Component />)
rerender(<Component />)

pointerDown(getByTestId("target") as Element)
pointerUp(getByTestId("target") as Element)

await nextFrame()

expect(press).toBeCalledTimes(1)
})

test("press event listeners fire via keyboard", async () => {
const press = jest.fn()
const pressStart = jest.fn()
Expand Down
9 changes: 5 additions & 4 deletions packages/framer-motion/src/gestures/press.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ export class PressGesture extends Feature<Element> {
startEvent: PointerEvent,
startInfo: EventInfo
) => {
this.removeEndListeners()

if (this.isPressing) return

this.removeEndListeners()

const props = this.node.getProps()

const endPointerPress = (
Expand All @@ -74,13 +74,14 @@ export class PressGesture extends Feature<Element> {
) => {
if (!this.checkPressEnd()) return

const { onTap, onTapCancel } = this.node.getProps()
const { onTap, onTapCancel, globalTapTarget } = this.node.getProps()

frame.update(() => {
/**
* 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)
Expand Down Expand Up @@ -176,7 +177,7 @@ export class PressGesture extends Feature<Element> {
const props = this.node.getProps()

const removePointerListener = addPointerEvent(
this.node.current!,
props.globalTapTarget ? window : this.node.current!,
"pointerdown",
this.startPointerPress,
{ passive: !(props.onTapStart || props["onPointerStart"]) }
Expand Down
7 changes: 7 additions & 0 deletions packages/framer-motion/src/gestures/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ export interface TapHandlers {
* ```
*/
whileTap?: VariantLabels | TargetAndTransition

/**
* If `true`, the tap gesture will attach its start listener to window.
*
* Note: This is not supported publically.
*/
globalTapTarget?: boolean
}
export type PanHandler = (event: Event, info: PanInfo) => void

Expand Down
5 changes: 2 additions & 3 deletions packages/framer-motion/src/motion/utils/valid-prop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ const validMotionProps = new Set<keyof MotionProps>([
"transformValues",
"custom",
"inherit",
"onLayoutAnimationStart",
"onLayoutAnimationComplete",
"onLayoutMeasure",
"onBeforeLayoutMeasure",
"onAnimationStart",
"onAnimationComplete",
Expand All @@ -38,6 +35,7 @@ const validMotionProps = new Set<keyof MotionProps>([
"onHoverEnd",
"onViewportEnter",
"onViewportLeave",
"globalTapTarget",
"ignoreStrict",
"viewport",
])
Expand All @@ -57,6 +55,7 @@ export function isValidMotionProp(key: string) {
key.startsWith("layout") ||
key.startsWith("onTap") ||
key.startsWith("onPan") ||
key.startsWith("onLayout") ||
validMotionProps.has(key as keyof MotionProps)
)
}

0 comments on commit 73f321b

Please sign in to comment.