diff --git a/.yarn/cache/@motionone-animation-npm-10.10.1-d0255a2947-11c5361043.zip b/.yarn/cache/@motionone-animation-npm-10.10.1-d0255a2947-11c5361043.zip deleted file mode 100644 index 16f8a06d5..000000000 Binary files a/.yarn/cache/@motionone-animation-npm-10.10.1-d0255a2947-11c5361043.zip and /dev/null differ diff --git a/.yarn/cache/@motionone-animation-npm-10.12.0-1d89e3c156-1e7c230da2.zip b/.yarn/cache/@motionone-animation-npm-10.12.0-1d89e3c156-1e7c230da2.zip new file mode 100644 index 000000000..b74c577a4 Binary files /dev/null and b/.yarn/cache/@motionone-animation-npm-10.12.0-1d89e3c156-1e7c230da2.zip differ diff --git a/.yarn/cache/@motionone-dom-npm-10.11.1-762dc658fd-df57870e05.zip b/.yarn/cache/@motionone-dom-npm-10.11.1-762dc658fd-df57870e05.zip deleted file mode 100644 index 26f44926f..000000000 Binary files a/.yarn/cache/@motionone-dom-npm-10.11.1-762dc658fd-df57870e05.zip and /dev/null differ diff --git a/.yarn/cache/@motionone-dom-npm-10.12.0-bbffbf0daa-123356f28e.zip b/.yarn/cache/@motionone-dom-npm-10.12.0-bbffbf0daa-123356f28e.zip new file mode 100644 index 000000000..8a2130a6a Binary files /dev/null and b/.yarn/cache/@motionone-dom-npm-10.12.0-bbffbf0daa-123356f28e.zip differ diff --git a/.yarn/cache/@motionone-easing-npm-10.9.0-ba0b919b6e-b0c63b161e.zip b/.yarn/cache/@motionone-easing-npm-10.12.0-5be92ac408-81f3a31829.zip similarity index 70% rename from .yarn/cache/@motionone-easing-npm-10.9.0-ba0b919b6e-b0c63b161e.zip rename to .yarn/cache/@motionone-easing-npm-10.12.0-5be92ac408-81f3a31829.zip index 60de7db8a..0df605644 100644 Binary files a/.yarn/cache/@motionone-easing-npm-10.9.0-ba0b919b6e-b0c63b161e.zip and b/.yarn/cache/@motionone-easing-npm-10.12.0-5be92ac408-81f3a31829.zip differ diff --git a/.yarn/cache/@motionone-generators-npm-10.9.0-c2d3b358e8-f1d8aa5064.zip b/.yarn/cache/@motionone-generators-npm-10.12.0-3107d354ec-9e55478e2c.zip similarity index 87% rename from .yarn/cache/@motionone-generators-npm-10.9.0-c2d3b358e8-f1d8aa5064.zip rename to .yarn/cache/@motionone-generators-npm-10.12.0-3107d354ec-9e55478e2c.zip index 4b21a5f95..ec0caf5ca 100644 Binary files a/.yarn/cache/@motionone-generators-npm-10.9.0-c2d3b358e8-f1d8aa5064.zip and b/.yarn/cache/@motionone-generators-npm-10.12.0-3107d354ec-9e55478e2c.zip differ diff --git a/.yarn/cache/@motionone-types-npm-10.9.0-0083d58cd6-aab2966c8a.zip b/.yarn/cache/@motionone-types-npm-10.12.0-93c236a2da-91b53fa78f.zip similarity index 59% rename from .yarn/cache/@motionone-types-npm-10.9.0-0083d58cd6-aab2966c8a.zip rename to .yarn/cache/@motionone-types-npm-10.12.0-93c236a2da-91b53fa78f.zip index aa8a84a88..6a6c1d279 100644 Binary files a/.yarn/cache/@motionone-types-npm-10.9.0-0083d58cd6-aab2966c8a.zip and b/.yarn/cache/@motionone-types-npm-10.12.0-93c236a2da-91b53fa78f.zip differ diff --git a/.yarn/cache/@motionone-utils-npm-10.9.0-59a43b5270-b13d9eb6d6.zip b/.yarn/cache/@motionone-utils-npm-10.12.0-066c183e92-407e43e9bc.zip similarity index 52% rename from .yarn/cache/@motionone-utils-npm-10.9.0-59a43b5270-b13d9eb6d6.zip rename to .yarn/cache/@motionone-utils-npm-10.12.0-066c183e92-407e43e9bc.zip index 2f0ccad72..069efe4d7 100644 Binary files a/.yarn/cache/@motionone-utils-npm-10.9.0-59a43b5270-b13d9eb6d6.zip and b/.yarn/cache/@motionone-utils-npm-10.12.0-066c183e92-407e43e9bc.zip differ diff --git a/CHANGELOG.md b/CHANGELOG.md index 63f0732ac..aca5eef53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ Framer Motion adheres to [Semantic Versioning](http://semver.org/). Undocumented APIs should be considered internal and may change without warning. +## [6.5.0] 2022-07-13 + +### Added + +- `useScroll` for creating scroll-linked animations. + +### Deprecated + +- `useViewportScroll` and `useElementScroll`. + ## [6.4.3] 2022-07-08 ### Fixed diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index 154778f6a..e375294ef 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -62,7 +62,7 @@ "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" }, "dependencies": { - "@motionone/dom": "^10.11.1", + "@motionone/dom": "10.12.0", "framesync": "6.0.1", "hey-listen": "^1.0.8", "popmotion": "11.0.3", diff --git a/packages/framer-motion/src/index.ts b/packages/framer-motion/src/index.ts index 1edbf463c..a8d5a92d2 100644 --- a/packages/framer-motion/src/index.ts +++ b/packages/framer-motion/src/index.ts @@ -31,6 +31,7 @@ export { resolveMotionValue } from "./value/utils/resolve-motion-value" export { useTransform } from "./value/use-transform" export { useSpring } from "./value/use-spring" export { useVelocity } from "./value/use-velocity" +export { useScroll } from "./value/use-scroll" export { useElementScroll } from "./value/scroll/use-element-scroll" export { useViewportScroll } from "./value/scroll/use-viewport-scroll" export { useTime } from "./value/use-time" diff --git a/packages/framer-motion/src/value/scroll/use-element-scroll.ts b/packages/framer-motion/src/value/scroll/use-element-scroll.ts index 772f39842..e8be5ed8d 100644 --- a/packages/framer-motion/src/value/scroll/use-element-scroll.ts +++ b/packages/framer-motion/src/value/scroll/use-element-scroll.ts @@ -1,84 +1,11 @@ import { RefObject } from "react" -import { useConstant } from "../../utils/use-constant" -import { - createScrollMotionValues, - ScrollMotionValues, - createScrollUpdater, -} from "./utils" -import { addDomEvent } from "../../events/use-dom-event" -import { useIsomorphicLayoutEffect } from "../../utils/use-isomorphic-effect" -import { invariant } from "hey-listen" - -const getElementScrollOffsets = (element: HTMLElement) => () => { - return { - xOffset: element.scrollLeft, - yOffset: element.scrollTop, - xMaxOffset: element.scrollWidth - element.offsetWidth, - yMaxOffset: element.scrollHeight - element.offsetHeight, - } -} - -/** - * Returns MotionValues that update when the provided element scrolls: - * - * - `scrollX` — Horizontal scroll distance in pixels. - * - `scrollY` — Vertical scroll distance in pixels. - * - `scrollXProgress` — Horizontal scroll progress between `0` and `1`. - * - `scrollYProgress` — Vertical scroll progress between `0` and `1`. - * - * This element must be set to `overflow: scroll` on either or both axes to report scroll offset. - * - * ```jsx - * export const MyComponent = () => { - * const ref = useRef() - * const { scrollYProgress } = useElementScroll(ref) - * - * return ( - *
- * - *
- * ) - * } - * ``` - * - * @public - */ -export function useElementScroll( - ref: RefObject -): ScrollMotionValues { - const values = useConstant(createScrollMotionValues) - - useIsomorphicLayoutEffect(() => { - const element = ref.current - - invariant( - !!element, - "ref provided to useScroll must be passed into a HTML element." - ) - if (!element) return - - const updateScrollValues = createScrollUpdater( - values, - getElementScrollOffsets(element) - ) - - const scrollListener = addDomEvent( - element, - "scroll", - updateScrollValues - ) - - const resizeListener = addDomEvent( - element, - "resize", - updateScrollValues - ) - - return () => { - scrollListener && scrollListener() - resizeListener && resizeListener() - } - }, []) - - return values +import { warnOnce } from "../../utils/warn-once" +import { useScroll } from "../use-scroll" + +export function useElementScroll(ref: RefObject) { + warnOnce( + false, + "useElementScroll is deprecated. Convert to useScroll({ container: ref })." + ) + return useScroll({ container: ref }) } diff --git a/packages/framer-motion/src/value/scroll/use-viewport-scroll.ts b/packages/framer-motion/src/value/scroll/use-viewport-scroll.ts index 562375d44..8c5524f44 100644 --- a/packages/framer-motion/src/value/scroll/use-viewport-scroll.ts +++ b/packages/framer-motion/src/value/scroll/use-viewport-scroll.ts @@ -1,67 +1,7 @@ -import { - createScrollMotionValues, - createScrollUpdater, - ScrollMotionValues, -} from "./utils" -import { addDomEvent } from "../../events/use-dom-event" -import { useIsomorphicLayoutEffect } from "../../utils/use-isomorphic-effect" +import { warnOnce } from "../../utils/warn-once" +import { useScroll } from "../use-scroll" -let viewportScrollValues: ScrollMotionValues - -function getViewportScrollOffsets() { - return { - xOffset: window.pageXOffset, - yOffset: window.pageYOffset, - xMaxOffset: document.body.clientWidth - window.innerWidth, - yMaxOffset: document.body.clientHeight - window.innerHeight, - } -} - -let hasListeners = false - -function addEventListeners() { - hasListeners = true - - const updateScrollValues = createScrollUpdater( - viewportScrollValues, - getViewportScrollOffsets - ) - - addDomEvent(window, "scroll", updateScrollValues) - addDomEvent(window, "resize", updateScrollValues) -} - -/** - * Returns MotionValues that update when the viewport scrolls: - * - * - `scrollX` — Horizontal scroll distance in pixels. - * - `scrollY` — Vertical scroll distance in pixels. - * - `scrollXProgress` — Horizontal scroll progress between `0` and `1`. - * - `scrollYProgress` — Vertical scroll progress between `0` and `1`. - * - * **Warning:** Setting `body` or `html` to `height: 100%` or similar will break the `Progress` - * values as this breaks the browser's capability to accurately measure the page length. - * - * ```jsx - * export const MyComponent = () => { - * const { scrollYProgress } = useViewportScroll() - * return - * } - * ``` - * - * @public - */ -export function useViewportScroll(): ScrollMotionValues { - /** - * Lazy-initialise the viewport scroll values - */ - if (!viewportScrollValues) { - viewportScrollValues = createScrollMotionValues() - } - - useIsomorphicLayoutEffect(() => { - !hasListeners && addEventListeners() - }, []) - - return viewportScrollValues +export function useViewportScroll() { + warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().") + return useScroll() } diff --git a/packages/framer-motion/src/value/use-scroll.ts b/packages/framer-motion/src/value/use-scroll.ts new file mode 100644 index 000000000..c6a564087 --- /dev/null +++ b/packages/framer-motion/src/value/use-scroll.ts @@ -0,0 +1,43 @@ +import { scroll, ScrollOptions } from "@motionone/dom" +import { RefObject } from "react" +import { motionValue } from "." +import { useIsomorphicLayoutEffect } from "../three-entry" +import { useConstant } from "../utils/use-constant" + +interface UseScrollOptions extends Omit { + container?: RefObject + target?: RefObject +} + +const createScrollMotionValues = () => ({ + scrollX: motionValue(0), + scrollY: motionValue(0), + scrollXProgress: motionValue(0), + scrollYProgress: motionValue(0), +}) + +export function useScroll({ + container, + target, + ...options +}: UseScrollOptions = {}) { + const values = useConstant(createScrollMotionValues) + + useIsomorphicLayoutEffect(() => { + return scroll( + ({ x, y }) => { + values.scrollX.set(x.current) + values.scrollXProgress.set(x.progress) + values.scrollY.set(y.current) + values.scrollYProgress.set(y.progress) + }, + { + ...options, + container: container?.current || undefined, + target: target?.current || undefined, + } + ) + }, []) + + return values +} diff --git a/yarn.lock b/yarn.lock index b986d1937..82994f1a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2393,68 +2393,68 @@ __metadata: languageName: node linkType: hard -"@motionone/animation@npm:^10.10.1": - version: 10.10.1 - resolution: "@motionone/animation@npm:10.10.1" +"@motionone/animation@npm:^10.12.0": + version: 10.12.0 + resolution: "@motionone/animation@npm:10.12.0" dependencies: - "@motionone/easing": ^10.9.0 - "@motionone/types": ^10.9.0 - "@motionone/utils": ^10.9.0 + "@motionone/easing": ^10.12.0 + "@motionone/types": ^10.12.0 + "@motionone/utils": ^10.12.0 tslib: ^2.3.1 - checksum: 11c5361043403f586cbe7e731dd801b3ea7e1bab4c0e1281e86b0a535841eca114fdc9606462d4a72324d6a2aac940debe5bc0910c334f3bfff250ce1a519f12 + checksum: 1e7c230da289ee3e3906288d5efb98f4c2c641b1be2d97b6136384b632db74e67c2ab36e99547467aebbcdf00a02f070356fc3a739a67f57213373b5a9631d04 languageName: node linkType: hard -"@motionone/dom@npm:^10.11.1": - version: 10.11.1 - resolution: "@motionone/dom@npm:10.11.1" +"@motionone/dom@npm:10.12.0": + version: 10.12.0 + resolution: "@motionone/dom@npm:10.12.0" dependencies: - "@motionone/animation": ^10.10.1 - "@motionone/generators": ^10.9.0 - "@motionone/types": ^10.9.0 - "@motionone/utils": ^10.9.0 + "@motionone/animation": ^10.12.0 + "@motionone/generators": ^10.12.0 + "@motionone/types": ^10.12.0 + "@motionone/utils": ^10.12.0 hey-listen: ^1.0.8 tslib: ^2.3.1 - checksum: df57870e059c4d702da62148ae6e872e4dc75d85d948ca51eccd33bbf345b8e4ec42d83f9471115eb1e38aaff6074686ee4ed3cb5906ba5d2fa7ed230f4f8b2a + checksum: 123356f28e44362c4f081aae3df22e576f46bfcb07e01257b2ac64a115668448f29b8de67e4b6e692c5407cffb78ffe7cf9fa1bc064007482bab5dd23a69d380 languageName: node linkType: hard -"@motionone/easing@npm:^10.9.0": - version: 10.9.0 - resolution: "@motionone/easing@npm:10.9.0" +"@motionone/easing@npm:^10.12.0": + version: 10.12.0 + resolution: "@motionone/easing@npm:10.12.0" dependencies: - "@motionone/utils": ^10.9.0 + "@motionone/utils": ^10.12.0 tslib: ^2.3.1 - checksum: b0c63b161ec595b08eab3dea37da175c5ed09e3383b8553e0346c24c000e4e5b411fc02ee0b697a0821745082343207b6a4432f6aa741d22b3371da807bffcee + checksum: 81f3a3182927ec2b24e129a31b873f66ba711bdd47fd465cc02ddd50e41da752e11325fccbdc27f06d02f9321d8c79d085f896b5b9d4ce549246f873ce352967 languageName: node linkType: hard -"@motionone/generators@npm:^10.9.0": - version: 10.9.0 - resolution: "@motionone/generators@npm:10.9.0" +"@motionone/generators@npm:^10.12.0": + version: 10.12.0 + resolution: "@motionone/generators@npm:10.12.0" dependencies: - "@motionone/types": ^10.9.0 - "@motionone/utils": ^10.9.0 + "@motionone/types": ^10.12.0 + "@motionone/utils": ^10.12.0 tslib: ^2.3.1 - checksum: f1d8aa5064ae6e138c0873a077368b46ff6c2fc6fa3d6855aaf54b456a65ce32a708e33e4a6010c9e38dd1454aaa83251acba10fb2b1d2b5c2c47148a89e4879 + checksum: 9e55478e2caab63268ff14c8f9e4d3cbb4a83f5e6aecd0f8be8bcd81a65c38bb2c9484174b74d757426c314c059ecbd949c73e2f5eaa8c70454455ba4b838d2a languageName: node linkType: hard -"@motionone/types@npm:^10.9.0": - version: 10.9.0 - resolution: "@motionone/types@npm:10.9.0" - checksum: aab2966c8a6d85d5d5b008457aa0cfb671436c441c2fd11a97bca4b01c61ba0f46f030ecc6e8b917f032eb9eef47e48f5b3898566e02af48d9a96ec2fd899bf9 +"@motionone/types@npm:^10.12.0": + version: 10.12.0 + resolution: "@motionone/types@npm:10.12.0" + checksum: 91b53fa78f464f5f6be32c44b5ac3c041fc25ff5ed19274d6bc561e207ee6abfcd9fdc89c9a4d9990059f1eb055594e318ab34d2f5f894b6bedaf975b1e54c59 languageName: node linkType: hard -"@motionone/utils@npm:^10.9.0": - version: 10.9.0 - resolution: "@motionone/utils@npm:10.9.0" +"@motionone/utils@npm:^10.12.0": + version: 10.12.0 + resolution: "@motionone/utils@npm:10.12.0" dependencies: - "@motionone/types": ^10.9.0 + "@motionone/types": ^10.12.0 hey-listen: ^1.0.8 tslib: ^2.3.1 - checksum: b13d9eb6d6f4de4b315fd77ccf7537d3bd30e66d7930c52fe6f17f134f84d97ba7c9807d6ec9245328f36cfeec217751f1a716a9cf0fd5c4b4cdc44c24907f5d + checksum: 407e43e9bcefd11520bbd60378bcb0109d671aabbdf05b2d3b8ce1b3fccd54fae48b5d3f628050f0f2624fc04d12a5bc4b24f32c504e6994d56c79997f75a6fa languageName: node linkType: hard @@ -7779,7 +7779,7 @@ __metadata: resolution: "framer-motion@workspace:packages/framer-motion" dependencies: "@emotion/is-prop-valid": ^0.8.2 - "@motionone/dom": ^10.11.1 + "@motionone/dom": 10.12.0 framesync: 6.0.1 hey-listen: ^1.0.8 jest: ^27.4.7