motion 11.11.12 → 11.11.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +14 -11
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/react-client.js +2 -2
- package/dist/es/framer-motion/dist/es/animation/animators/BaseAnimation.mjs +2 -1
- package/dist/es/framer-motion/dist/es/animation/animators/MainThreadAnimation.mjs +5 -1
- package/dist/es/framer-motion/dist/es/animation/hooks/animation-controls.mjs +80 -0
- package/dist/es/framer-motion/dist/es/animation/hooks/use-animate-style.mjs +17 -0
- package/dist/es/framer-motion/dist/es/animation/hooks/use-animate.mjs +17 -0
- package/dist/es/framer-motion/dist/es/animation/hooks/use-animated-state.mjs +64 -0
- package/dist/es/framer-motion/dist/es/animation/hooks/use-animation.mjs +41 -0
- package/dist/es/framer-motion/dist/es/animation/interfaces/motion-value.mjs +8 -0
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/handoff.mjs +40 -0
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/start.mjs +173 -0
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/store-id.mjs +8 -0
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/store.mjs +4 -0
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs +77 -0
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs +61 -0
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/index.mjs +163 -0
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/use-presence.mjs +27 -1
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/utils.mjs +14 -0
- package/dist/es/framer-motion/dist/es/components/AnimateSharedLayout.mjs +15 -0
- package/dist/es/framer-motion/dist/es/components/LayoutGroup/index.mjs +32 -0
- package/dist/es/framer-motion/dist/es/components/LazyMotion/index.mjs +68 -0
- package/dist/es/framer-motion/dist/es/components/MotionConfig/index.mjs +48 -0
- package/dist/es/framer-motion/dist/es/components/Reorder/Group.mjs +53 -0
- package/dist/es/framer-motion/dist/es/components/Reorder/Item.mjs +34 -0
- package/dist/es/framer-motion/dist/es/components/Reorder/namespace.mjs +2 -0
- package/dist/es/framer-motion/dist/es/components/Reorder/utils/check-reorder.mjs +24 -0
- package/dist/es/framer-motion/dist/es/context/DeprecatedLayoutGroupContext.mjs +10 -0
- package/dist/es/framer-motion/dist/es/context/ReorderContext.mjs +6 -0
- package/dist/es/framer-motion/dist/es/events/use-dom-event.mjs +34 -0
- package/dist/es/framer-motion/dist/es/frameloop/batcher.mjs +4 -1
- package/dist/es/framer-motion/dist/es/gestures/drag/use-drag-controls.mjs +88 -0
- package/dist/es/framer-motion/dist/es/motion/utils/is-motion-component.mjs +12 -0
- package/dist/es/framer-motion/dist/es/motion/utils/unwrap-motion-component.mjs +17 -0
- package/dist/es/framer-motion/dist/es/projection/node/group.mjs +24 -0
- package/dist/es/framer-motion/dist/es/projection/use-instant-layout-transition.mjs +14 -0
- package/dist/es/framer-motion/dist/es/projection/use-reset-projection.mjs +14 -0
- package/dist/es/framer-motion/dist/es/render/components/create-proxy.mjs +38 -0
- package/dist/es/framer-motion/dist/es/render/components/m/proxy.mjs +6 -0
- package/dist/es/framer-motion/dist/es/render/components/motion/proxy.mjs +6 -0
- package/dist/es/framer-motion/dist/es/render/dom/features-animation.mjs +14 -0
- package/dist/es/framer-motion/dist/es/render/dom/features-max.mjs +14 -0
- package/dist/es/framer-motion/dist/es/render/dom/features-min.mjs +12 -0
- package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/array.mjs +11 -1
- package/dist/es/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion-config.mjs +19 -0
- package/dist/es/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.mjs +47 -0
- package/dist/es/framer-motion/dist/es/utils/use-animation-frame.mjs +21 -0
- package/dist/es/framer-motion/dist/es/utils/use-cycle.mjs +47 -0
- package/dist/es/framer-motion/dist/es/utils/use-force-update.mjs +19 -0
- package/dist/es/framer-motion/dist/es/utils/use-in-view.mjs +23 -0
- package/dist/es/framer-motion/dist/es/utils/use-instant-transition-state.mjs +5 -0
- package/dist/es/framer-motion/dist/es/utils/use-instant-transition.mjs +41 -0
- package/dist/es/framer-motion/dist/es/utils/use-is-mounted.mjs +15 -0
- package/dist/es/framer-motion/dist/es/utils/use-motion-value-event.mjs +13 -0
- package/dist/es/framer-motion/dist/es/utils/use-unmount-effect.mjs +7 -0
- package/dist/es/framer-motion/dist/es/value/index.mjs +8 -2
- package/dist/es/framer-motion/dist/es/value/scroll/use-element-scroll.mjs +14 -0
- package/dist/es/framer-motion/dist/es/value/scroll/use-viewport-scroll.mjs +14 -0
- package/dist/es/framer-motion/dist/es/value/types/color/rgba.mjs +1 -1
- package/dist/es/framer-motion/dist/es/value/use-combine-values.mjs +37 -0
- package/dist/es/framer-motion/dist/es/value/use-computed.mjs +19 -0
- package/dist/es/framer-motion/dist/es/value/use-inverted-scale.mjs +52 -0
- package/dist/es/framer-motion/dist/es/value/use-motion-template.mjs +45 -0
- package/dist/es/framer-motion/dist/es/value/use-motion-value.mjs +38 -0
- package/dist/es/framer-motion/dist/es/value/use-scroll.mjs +39 -0
- package/dist/es/framer-motion/dist/es/value/use-spring.mjs +85 -0
- package/dist/es/framer-motion/dist/es/value/use-time.mjs +10 -0
- package/dist/es/framer-motion/dist/es/value/use-transform.mjs +29 -0
- package/dist/es/framer-motion/dist/es/value/use-velocity.mjs +35 -0
- package/dist/es/framer-motion/dist/es/value/use-will-change/WillChangeMotionValue.mjs +22 -0
- package/dist/es/framer-motion/dist/es/value/use-will-change/get-will-change-name.mjs +14 -0
- package/dist/es/framer-motion/dist/es/value/use-will-change/index.mjs +8 -0
- package/dist/es/motion/lib/react.mjs +110 -0
- package/dist/motion.dev.js +2 -2
- package/dist/motion.js +1 -1
- package/dist/react.d.ts +1 -0
- package/package.json +17 -17
- package/rollup.config.mjs +12 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useConstant } from '../../utils/use-constant.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Can manually trigger a drag gesture on one or more `drag`-enabled `motion` components.
|
|
5
|
+
*
|
|
6
|
+
* ```jsx
|
|
7
|
+
* const dragControls = useDragControls()
|
|
8
|
+
*
|
|
9
|
+
* function startDrag(event) {
|
|
10
|
+
* dragControls.start(event, { snapToCursor: true })
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* return (
|
|
14
|
+
* <>
|
|
15
|
+
* <div onPointerDown={startDrag} />
|
|
16
|
+
* <motion.div drag="x" dragControls={dragControls} />
|
|
17
|
+
* </>
|
|
18
|
+
* )
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
class DragControls {
|
|
24
|
+
constructor() {
|
|
25
|
+
this.componentControls = new Set();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe a component's internal `VisualElementDragControls` to the user-facing API.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
subscribe(controls) {
|
|
33
|
+
this.componentControls.add(controls);
|
|
34
|
+
return () => this.componentControls.delete(controls);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start a drag gesture on every `motion` component that has this set of drag controls
|
|
38
|
+
* passed into it via the `dragControls` prop.
|
|
39
|
+
*
|
|
40
|
+
* ```jsx
|
|
41
|
+
* dragControls.start(e, {
|
|
42
|
+
* snapToCursor: true
|
|
43
|
+
* })
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @param event - PointerEvent
|
|
47
|
+
* @param options - Options
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
start(event, options) {
|
|
52
|
+
this.componentControls.forEach((controls) => {
|
|
53
|
+
controls.start(event.nativeEvent || event, options);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const createDragControls = () => new DragControls();
|
|
58
|
+
/**
|
|
59
|
+
* Usually, dragging is initiated by pressing down on a `motion` component with a `drag` prop
|
|
60
|
+
* and moving it. For some use-cases, for instance clicking at an arbitrary point on a video scrubber, we
|
|
61
|
+
* might want to initiate that dragging from a different component than the draggable one.
|
|
62
|
+
*
|
|
63
|
+
* By creating a `dragControls` using the `useDragControls` hook, we can pass this into
|
|
64
|
+
* the draggable component's `dragControls` prop. It exposes a `start` method
|
|
65
|
+
* that can start dragging from pointer events on other components.
|
|
66
|
+
*
|
|
67
|
+
* ```jsx
|
|
68
|
+
* const dragControls = useDragControls()
|
|
69
|
+
*
|
|
70
|
+
* function startDrag(event) {
|
|
71
|
+
* dragControls.start(event, { snapToCursor: true })
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* return (
|
|
75
|
+
* <>
|
|
76
|
+
* <div onPointerDown={startDrag} />
|
|
77
|
+
* <motion.div drag="x" dragControls={dragControls} />
|
|
78
|
+
* </>
|
|
79
|
+
* )
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @public
|
|
83
|
+
*/
|
|
84
|
+
function useDragControls() {
|
|
85
|
+
return useConstant(createDragControls);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { DragControls, useDragControls };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { motionComponentSymbol } from './symbol.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a component is a `motion` component.
|
|
5
|
+
*/
|
|
6
|
+
function isMotionComponent(component) {
|
|
7
|
+
return (component !== null &&
|
|
8
|
+
typeof component === "object" &&
|
|
9
|
+
motionComponentSymbol in component);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { isMotionComponent };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isMotionComponent } from './is-motion-component.mjs';
|
|
2
|
+
import { motionComponentSymbol } from './symbol.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Unwraps a `motion` component and returns either a string for `motion.div` or
|
|
6
|
+
* the React component for `motion(Component)`.
|
|
7
|
+
*
|
|
8
|
+
* If the component is not a `motion` component it returns undefined.
|
|
9
|
+
*/
|
|
10
|
+
function unwrapMotionComponent(component) {
|
|
11
|
+
if (isMotionComponent(component)) {
|
|
12
|
+
return component[motionComponentSymbol];
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { unwrapMotionComponent };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const notify = (node) => !node.isLayoutDirty && node.willUpdate(false);
|
|
2
|
+
function nodeGroup() {
|
|
3
|
+
const nodes = new Set();
|
|
4
|
+
const subscriptions = new WeakMap();
|
|
5
|
+
const dirtyAll = () => nodes.forEach(notify);
|
|
6
|
+
return {
|
|
7
|
+
add: (node) => {
|
|
8
|
+
nodes.add(node);
|
|
9
|
+
subscriptions.set(node, node.addEventListener("willUpdate", dirtyAll));
|
|
10
|
+
},
|
|
11
|
+
remove: (node) => {
|
|
12
|
+
nodes.delete(node);
|
|
13
|
+
const unsubscribe = subscriptions.get(node);
|
|
14
|
+
if (unsubscribe) {
|
|
15
|
+
unsubscribe();
|
|
16
|
+
subscriptions.delete(node);
|
|
17
|
+
}
|
|
18
|
+
dirtyAll();
|
|
19
|
+
},
|
|
20
|
+
dirty: dirtyAll,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { nodeGroup };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { rootProjectionNode } from './node/HTMLProjectionNode.mjs';
|
|
2
|
+
|
|
3
|
+
function useInstantLayoutTransition() {
|
|
4
|
+
return startTransition;
|
|
5
|
+
}
|
|
6
|
+
function startTransition(callback) {
|
|
7
|
+
if (!rootProjectionNode.current)
|
|
8
|
+
return;
|
|
9
|
+
rootProjectionNode.current.isUpdating = false;
|
|
10
|
+
rootProjectionNode.current.blockUpdate();
|
|
11
|
+
callback && callback();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useInstantLayoutTransition };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { rootProjectionNode } from './node/HTMLProjectionNode.mjs';
|
|
3
|
+
|
|
4
|
+
function useResetProjection() {
|
|
5
|
+
const reset = useCallback(() => {
|
|
6
|
+
const root = rootProjectionNode.current;
|
|
7
|
+
if (!root)
|
|
8
|
+
return;
|
|
9
|
+
root.resetTree();
|
|
10
|
+
}, []);
|
|
11
|
+
return reset;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useResetProjection };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { warnOnce } from '../../utils/warn-once.mjs';
|
|
2
|
+
|
|
3
|
+
function createDOMMotionComponentProxy(componentFactory) {
|
|
4
|
+
if (typeof Proxy === "undefined") {
|
|
5
|
+
return componentFactory;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A cache of generated `motion` components, e.g `motion.div`, `motion.input` etc.
|
|
9
|
+
* Rather than generating them anew every render.
|
|
10
|
+
*/
|
|
11
|
+
const componentCache = new Map();
|
|
12
|
+
const deprecatedFactoryFunction = (...args) => {
|
|
13
|
+
if (process.env.NODE_ENV !== "production") {
|
|
14
|
+
warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
|
|
15
|
+
}
|
|
16
|
+
return componentFactory(...args);
|
|
17
|
+
};
|
|
18
|
+
return new Proxy(deprecatedFactoryFunction, {
|
|
19
|
+
/**
|
|
20
|
+
* Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
|
|
21
|
+
* The prop name is passed through as `key` and we can use that to generate a `motion`
|
|
22
|
+
* DOM component with that name.
|
|
23
|
+
*/
|
|
24
|
+
get: (_target, key) => {
|
|
25
|
+
if (key === "create")
|
|
26
|
+
return componentFactory;
|
|
27
|
+
/**
|
|
28
|
+
* If this element doesn't exist in the component cache, create it and cache.
|
|
29
|
+
*/
|
|
30
|
+
if (!componentCache.has(key)) {
|
|
31
|
+
componentCache.set(key, componentFactory(key));
|
|
32
|
+
}
|
|
33
|
+
return componentCache.get(key);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { createDOMMotionComponentProxy };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { animations } from '../../motion/features/animations.mjs';
|
|
2
|
+
import { gestureAnimations } from '../../motion/features/gestures.mjs';
|
|
3
|
+
import { createDomVisualElement } from './create-visual-element.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
const domAnimation = {
|
|
9
|
+
renderer: createDomVisualElement,
|
|
10
|
+
...animations,
|
|
11
|
+
...gestureAnimations,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { domAnimation };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { drag } from '../../motion/features/drag.mjs';
|
|
2
|
+
import { layout } from '../../motion/features/layout.mjs';
|
|
3
|
+
import { domAnimation } from './features-animation.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
const domMax = {
|
|
9
|
+
...domAnimation,
|
|
10
|
+
...drag,
|
|
11
|
+
...layout,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { domMax };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { animations } from '../../motion/features/animations.mjs';
|
|
2
|
+
import { createDomVisualElement } from './create-visual-element.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
const domMin = {
|
|
8
|
+
renderer: createDomVisualElement,
|
|
9
|
+
...animations,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { domMin };
|
|
@@ -17,7 +17,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
17
17
|
* and warn against mismatches.
|
|
18
18
|
*/
|
|
19
19
|
if (process.env.NODE_ENV === "development") {
|
|
20
|
-
warnOnce(nextValue.version === "11.11.
|
|
20
|
+
warnOnce(nextValue.version === "11.11.13", `Attempting to mix Motion versions ${nextValue.version} with 11.11.13 may not work as expected.`);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
else if (isMotionValue(prevValue)) {
|
|
@@ -7,5 +7,15 @@ function removeItem(arr, item) {
|
|
|
7
7
|
if (index > -1)
|
|
8
8
|
arr.splice(index, 1);
|
|
9
9
|
}
|
|
10
|
+
// Adapted from array-move
|
|
11
|
+
function moveItem([...arr], fromIndex, toIndex) {
|
|
12
|
+
const startIndex = fromIndex < 0 ? arr.length + fromIndex : fromIndex;
|
|
13
|
+
if (startIndex >= 0 && startIndex < arr.length) {
|
|
14
|
+
const endIndex = toIndex < 0 ? arr.length + toIndex : toIndex;
|
|
15
|
+
const [item] = arr.splice(fromIndex, 1);
|
|
16
|
+
arr.splice(endIndex, 0, item);
|
|
17
|
+
}
|
|
18
|
+
return arr;
|
|
19
|
+
}
|
|
10
20
|
|
|
11
|
-
export { addUniqueItem, removeItem };
|
|
21
|
+
export { addUniqueItem, moveItem, removeItem };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { MotionConfigContext } from '../../context/MotionConfigContext.mjs';
|
|
3
|
+
import { useReducedMotion } from './use-reduced-motion.mjs';
|
|
4
|
+
|
|
5
|
+
function useReducedMotionConfig() {
|
|
6
|
+
const reducedMotionPreference = useReducedMotion();
|
|
7
|
+
const { reducedMotion } = useContext(MotionConfigContext);
|
|
8
|
+
if (reducedMotion === "never") {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
else if (reducedMotion === "always") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return reducedMotionPreference;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { useReducedMotionConfig };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { initPrefersReducedMotion } from './index.mjs';
|
|
3
|
+
import { warnOnce } from '../warn-once.mjs';
|
|
4
|
+
import { hasReducedMotionListener, prefersReducedMotion } from './state.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
|
|
8
|
+
*
|
|
9
|
+
* This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
|
|
10
|
+
* `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
|
|
11
|
+
*
|
|
12
|
+
* It will actively respond to changes and re-render your components with the latest setting.
|
|
13
|
+
*
|
|
14
|
+
* ```jsx
|
|
15
|
+
* export function Sidebar({ isOpen }) {
|
|
16
|
+
* const shouldReduceMotion = useReducedMotion()
|
|
17
|
+
* const closedX = shouldReduceMotion ? 0 : "-100%"
|
|
18
|
+
*
|
|
19
|
+
* return (
|
|
20
|
+
* <motion.div animate={{
|
|
21
|
+
* opacity: isOpen ? 1 : 0,
|
|
22
|
+
* x: isOpen ? 0 : closedX
|
|
23
|
+
* }} />
|
|
24
|
+
* )
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @return boolean
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
function useReducedMotion() {
|
|
33
|
+
/**
|
|
34
|
+
* Lazy initialisation of prefersReducedMotion
|
|
35
|
+
*/
|
|
36
|
+
!hasReducedMotionListener.current && initPrefersReducedMotion();
|
|
37
|
+
const [shouldReduceMotion] = useState(prefersReducedMotion.current);
|
|
38
|
+
if (process.env.NODE_ENV !== "production") {
|
|
39
|
+
warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* TODO See if people miss automatically updating shouldReduceMotion setting
|
|
43
|
+
*/
|
|
44
|
+
return shouldReduceMotion;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { useReducedMotion };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useRef, useContext, useEffect } from 'react';
|
|
2
|
+
import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
|
|
3
|
+
import { frame, cancelFrame } from '../frameloop/frame.mjs';
|
|
4
|
+
|
|
5
|
+
function useAnimationFrame(callback) {
|
|
6
|
+
const initialTimestamp = useRef(0);
|
|
7
|
+
const { isStatic } = useContext(MotionConfigContext);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (isStatic)
|
|
10
|
+
return;
|
|
11
|
+
const provideTimeSinceStart = ({ timestamp, delta }) => {
|
|
12
|
+
if (!initialTimestamp.current)
|
|
13
|
+
initialTimestamp.current = timestamp;
|
|
14
|
+
callback(timestamp - initialTimestamp.current, delta);
|
|
15
|
+
};
|
|
16
|
+
frame.update(provideTimeSinceStart, true);
|
|
17
|
+
return () => cancelFrame(provideTimeSinceStart);
|
|
18
|
+
}, [callback]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { useAnimationFrame };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useRef, useState, useCallback } from 'react';
|
|
2
|
+
import { wrap } from './wrap.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
|
|
6
|
+
*
|
|
7
|
+
* An index value can be passed to the returned `cycle` function to cycle to a specific index.
|
|
8
|
+
*
|
|
9
|
+
* ```jsx
|
|
10
|
+
* import * as React from "react"
|
|
11
|
+
* import { motion, useCycle } from "framer-motion"
|
|
12
|
+
*
|
|
13
|
+
* export const MyComponent = () => {
|
|
14
|
+
* const [x, cycleX] = useCycle(0, 50, 100)
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <motion.div
|
|
18
|
+
* animate={{ x: x }}
|
|
19
|
+
* onTap={() => cycleX()}
|
|
20
|
+
* />
|
|
21
|
+
* )
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param items - items to cycle through
|
|
26
|
+
* @returns [currentState, cycleState]
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
function useCycle(...items) {
|
|
31
|
+
const index = useRef(0);
|
|
32
|
+
const [item, setItem] = useState(items[index.current]);
|
|
33
|
+
const runCycle = useCallback((next) => {
|
|
34
|
+
index.current =
|
|
35
|
+
typeof next !== "number"
|
|
36
|
+
? wrap(0, items.length, index.current + 1)
|
|
37
|
+
: next;
|
|
38
|
+
setItem(items[index.current]);
|
|
39
|
+
},
|
|
40
|
+
// The array will change on each call, but by putting items.length at
|
|
41
|
+
// the front of this array, we guarantee the dependency comparison will match up
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
+
[items.length, ...items]);
|
|
44
|
+
return [item, runCycle];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { useCycle };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import { useIsMounted } from './use-is-mounted.mjs';
|
|
3
|
+
import { frame } from '../frameloop/frame.mjs';
|
|
4
|
+
|
|
5
|
+
function useForceUpdate() {
|
|
6
|
+
const isMounted = useIsMounted();
|
|
7
|
+
const [forcedRenderCount, setForcedRenderCount] = useState(0);
|
|
8
|
+
const forceRender = useCallback(() => {
|
|
9
|
+
isMounted.current && setForcedRenderCount(forcedRenderCount + 1);
|
|
10
|
+
}, [forcedRenderCount]);
|
|
11
|
+
/**
|
|
12
|
+
* Defer this to the end of the next animation frame in case there are multiple
|
|
13
|
+
* synchronous calls.
|
|
14
|
+
*/
|
|
15
|
+
const deferredForceRender = useCallback(() => frame.postRender(forceRender), [forceRender]);
|
|
16
|
+
return [deferredForceRender, forcedRenderCount];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { useForceUpdate };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { inView } from '../render/dom/viewport/index.mjs';
|
|
3
|
+
|
|
4
|
+
function useInView(ref, { root, margin, amount, once = false } = {}) {
|
|
5
|
+
const [isInView, setInView] = useState(false);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!ref.current || (once && isInView))
|
|
8
|
+
return;
|
|
9
|
+
const onEnter = () => {
|
|
10
|
+
setInView(true);
|
|
11
|
+
return once ? undefined : () => setInView(false);
|
|
12
|
+
};
|
|
13
|
+
const options = {
|
|
14
|
+
root: (root && root.current) || undefined,
|
|
15
|
+
margin,
|
|
16
|
+
amount,
|
|
17
|
+
};
|
|
18
|
+
return inView(ref.current, onEnter, options);
|
|
19
|
+
}, [root, ref, margin, once, amount]);
|
|
20
|
+
return isInView;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { useInView };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
import { useInstantLayoutTransition } from '../projection/use-instant-layout-transition.mjs';
|
|
3
|
+
import { useForceUpdate } from './use-force-update.mjs';
|
|
4
|
+
import { instantAnimationState } from './use-instant-transition-state.mjs';
|
|
5
|
+
import { frame } from '../frameloop/frame.mjs';
|
|
6
|
+
|
|
7
|
+
function useInstantTransition() {
|
|
8
|
+
const [forceUpdate, forcedRenderCount] = useForceUpdate();
|
|
9
|
+
const startInstantLayoutTransition = useInstantLayoutTransition();
|
|
10
|
+
const unlockOnFrameRef = useRef();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
/**
|
|
13
|
+
* Unblock after two animation frames, otherwise this will unblock too soon.
|
|
14
|
+
*/
|
|
15
|
+
frame.postRender(() => frame.postRender(() => {
|
|
16
|
+
/**
|
|
17
|
+
* If the callback has been called again after the effect
|
|
18
|
+
* triggered this 2 frame delay, don't unblock animations. This
|
|
19
|
+
* prevents the previous effect from unblocking the current
|
|
20
|
+
* instant transition too soon. This becomes more likely when
|
|
21
|
+
* used in conjunction with React.startTransition().
|
|
22
|
+
*/
|
|
23
|
+
if (forcedRenderCount !== unlockOnFrameRef.current)
|
|
24
|
+
return;
|
|
25
|
+
instantAnimationState.current = false;
|
|
26
|
+
}));
|
|
27
|
+
}, [forcedRenderCount]);
|
|
28
|
+
return (callback) => {
|
|
29
|
+
startInstantLayoutTransition(() => {
|
|
30
|
+
instantAnimationState.current = true;
|
|
31
|
+
forceUpdate();
|
|
32
|
+
callback();
|
|
33
|
+
unlockOnFrameRef.current = forcedRenderCount + 1;
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function disableInstantTransitions() {
|
|
38
|
+
instantAnimationState.current = false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { disableInstantTransitions, useInstantTransition };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { useIsomorphicLayoutEffect } from './use-isomorphic-effect.mjs';
|
|
3
|
+
|
|
4
|
+
function useIsMounted() {
|
|
5
|
+
const isMounted = useRef(false);
|
|
6
|
+
useIsomorphicLayoutEffect(() => {
|
|
7
|
+
isMounted.current = true;
|
|
8
|
+
return () => {
|
|
9
|
+
isMounted.current = false;
|
|
10
|
+
};
|
|
11
|
+
}, []);
|
|
12
|
+
return isMounted;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { useIsMounted };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useInsertionEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
function useMotionValueEvent(value, event, callback) {
|
|
4
|
+
/**
|
|
5
|
+
* useInsertionEffect will create subscriptions before any other
|
|
6
|
+
* effects will run. Effects run upwards through the tree so it
|
|
7
|
+
* can be that binding a useLayoutEffect higher up the tree can
|
|
8
|
+
* miss changes from lower down the tree.
|
|
9
|
+
*/
|
|
10
|
+
useInsertionEffect(() => value.on(event, callback), [value, event, callback]);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { useMotionValueEvent };
|
|
@@ -12,6 +12,9 @@ const MAX_VELOCITY_DELTA = 30;
|
|
|
12
12
|
const isFloat = (value) => {
|
|
13
13
|
return !isNaN(parseFloat(value));
|
|
14
14
|
};
|
|
15
|
+
const collectMotionValues = {
|
|
16
|
+
current: undefined,
|
|
17
|
+
};
|
|
15
18
|
/**
|
|
16
19
|
* `MotionValue` is used to track the state and velocity of motion values.
|
|
17
20
|
*
|
|
@@ -31,7 +34,7 @@ class MotionValue {
|
|
|
31
34
|
* This will be replaced by the build step with the latest version number.
|
|
32
35
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
33
36
|
*/
|
|
34
|
-
this.version = "11.11.
|
|
37
|
+
this.version = "11.11.13";
|
|
35
38
|
/**
|
|
36
39
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
37
40
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -210,6 +213,9 @@ class MotionValue {
|
|
|
210
213
|
* @public
|
|
211
214
|
*/
|
|
212
215
|
get() {
|
|
216
|
+
if (collectMotionValues.current) {
|
|
217
|
+
collectMotionValues.current.push(this);
|
|
218
|
+
}
|
|
213
219
|
return this.current;
|
|
214
220
|
}
|
|
215
221
|
/**
|
|
@@ -310,4 +316,4 @@ function motionValue(init, options) {
|
|
|
310
316
|
return new MotionValue(init, options);
|
|
311
317
|
}
|
|
312
318
|
|
|
313
|
-
export { MotionValue, motionValue };
|
|
319
|
+
export { MotionValue, collectMotionValues, motionValue };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { warnOnce } from '../../utils/warn-once.mjs';
|
|
2
|
+
import { useScroll } from '../use-scroll.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated useElementScroll is deprecated. Convert to useScroll({ container: ref })
|
|
6
|
+
*/
|
|
7
|
+
function useElementScroll(ref) {
|
|
8
|
+
if (process.env.NODE_ENV === "development") {
|
|
9
|
+
warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
|
|
10
|
+
}
|
|
11
|
+
return useScroll({ container: ref });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useElementScroll };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { warnOnce } from '../../utils/warn-once.mjs';
|
|
2
|
+
import { useScroll } from '../use-scroll.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated useViewportScroll is deprecated. Convert to useScroll()
|
|
6
|
+
*/
|
|
7
|
+
function useViewportScroll() {
|
|
8
|
+
if (process.env.NODE_ENV !== "production") {
|
|
9
|
+
warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
|
|
10
|
+
}
|
|
11
|
+
return useScroll();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useViewportScroll };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clamp } from '../../../utils/clamp.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import { alpha, number } from '../numbers/index.mjs';
|
|
3
3
|
import { sanitize } from '../utils/sanitize.mjs';
|
|
4
4
|
import { isColorString, splitColor } from './utils.mjs';
|
|
5
5
|
|