framer-motion 5.2.1 → 5.3.2

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.
Files changed (39) hide show
  1. package/dist/es/animation/utils/transitions.mjs +8 -2
  2. package/dist/es/components/Reorder/Item.mjs +4 -3
  3. package/dist/es/gestures/use-hover-gesture.mjs +4 -1
  4. package/dist/es/gestures/use-tap-gesture.mjs +4 -1
  5. package/dist/es/index.mjs +1 -0
  6. package/dist/es/motion/features/definitions.mjs +6 -0
  7. package/dist/es/motion/features/gestures.mjs +2 -0
  8. package/dist/es/motion/features/viewport/observers.mjs +52 -0
  9. package/dist/es/motion/features/viewport/use-viewport.mjs +97 -0
  10. package/dist/es/motion/utils/use-visual-state.mjs +29 -10
  11. package/dist/es/motion/utils/valid-prop.mjs +5 -0
  12. package/dist/es/render/html/use-props.mjs +5 -3
  13. package/dist/es/render/utils/animation-state.mjs +7 -4
  14. package/dist/es/render/utils/setters.mjs +1 -3
  15. package/dist/es/render/utils/types.mjs +1 -0
  16. package/dist/es/utils/use-force-update.mjs +13 -9
  17. package/dist/es/utils/use-instant-transition-state.mjs +5 -0
  18. package/dist/es/utils/use-instant-transition.mjs +28 -0
  19. package/dist/es/utils/warn-once.mjs +11 -0
  20. package/dist/framer-motion.cjs.js +266 -42
  21. package/dist/framer-motion.dev.js +266 -42
  22. package/dist/framer-motion.js +1 -1
  23. package/dist/projection.dev.js +20 -6
  24. package/dist/size-rollup-dom-animation.js +1 -1
  25. package/dist/size-rollup-dom-max.js +1 -1
  26. package/dist/size-rollup-m.js +1 -1
  27. package/package.json +11 -11
  28. package/types/components/Reorder/Item.d.ts +1 -1
  29. package/types/index.d.ts +1 -0
  30. package/types/motion/features/types.d.ts +2 -0
  31. package/types/motion/features/viewport/observers.d.ts +3 -0
  32. package/types/motion/features/viewport/types.d.ts +20 -0
  33. package/types/motion/features/viewport/use-viewport.d.ts +2 -0
  34. package/types/motion/types.d.ts +2 -1
  35. package/types/render/utils/animation-state.d.ts +1 -1
  36. package/types/render/utils/types.d.ts +1 -0
  37. package/types/utils/use-instant-transition-state.d.ts +3 -0
  38. package/types/utils/use-instant-transition.d.ts +1 -0
  39. package/types/utils/warn-once.d.ts +2 -0
@@ -6,6 +6,8 @@ import { isAnimatable } from './is-animatable.mjs';
6
6
  import { getDefaultTransition } from './default-transitions.mjs';
7
7
  import { warning } from 'hey-listen';
8
8
  import { getAnimatableNone } from '../../render/dom/value-types/animatable-none.mjs';
9
+ import { instantAnimationState } from '../../utils/use-instant-transition-state.mjs';
10
+ import { resolveFinalValueInKeyframes } from '../../utils/resolve-value.mjs';
9
11
 
10
12
  /**
11
13
  * Decide whether a transition is defined on a given Transition.
@@ -148,9 +150,10 @@ function getAnimation(key, value, target, transition, onComplete) {
148
150
  }
149
151
  function set() {
150
152
  var _a, _b;
151
- value.set(target);
153
+ var finalTarget = resolveFinalValueInKeyframes(target);
154
+ value.set(finalTarget);
152
155
  onComplete();
153
- (_a = valueTransition === null || valueTransition === void 0 ? void 0 : valueTransition.onUpdate) === null || _a === void 0 ? void 0 : _a.call(valueTransition, target);
156
+ (_a = valueTransition === null || valueTransition === void 0 ? void 0 : valueTransition.onUpdate) === null || _a === void 0 ? void 0 : _a.call(valueTransition, finalTarget);
154
157
  (_b = valueTransition === null || valueTransition === void 0 ? void 0 : valueTransition.onComplete) === null || _b === void 0 ? void 0 : _b.call(valueTransition);
155
158
  return { stop: function () { } };
156
159
  }
@@ -182,6 +185,9 @@ function getValueTransition(transition, key) {
182
185
  */
183
186
  function startAnimation(key, value, target, transition) {
184
187
  if (transition === void 0) { transition = {}; }
188
+ if (instantAnimationState.current) {
189
+ transition = { type: false };
190
+ }
185
191
  return value.start(function (onComplete) {
186
192
  var delayTimer;
187
193
  var controls;
@@ -14,7 +14,7 @@ function useDefaultMotionValue(value, defaultValue) {
14
14
  return isMotionValue(value) ? value : useMotionValue(defaultValue);
15
15
  }
16
16
  function ReorderItem(_a, externalRef) {
17
- var children = _a.children, style = _a.style, value = _a.value, _b = _a.as, as = _b === void 0 ? "li" : _b, props = __rest(_a, ["children", "style", "value", "as"]);
17
+ var children = _a.children, style = _a.style, value = _a.value, _b = _a.as, as = _b === void 0 ? "li" : _b, onDrag = _a.onDrag, props = __rest(_a, ["children", "style", "value", "as", "onDrag"]);
18
18
  var Component = useConstant(function () { return motion(as); });
19
19
  var context = useContext(ReorderContext);
20
20
  var point = {
@@ -31,10 +31,11 @@ function ReorderItem(_a, externalRef) {
31
31
  useEffect(function () {
32
32
  registerItem(value, layout.current);
33
33
  }, [context]);
34
- return (React.createElement(Component, __assign({ drag: axis }, props, { dragSnapToOrigin: true, style: __assign(__assign({}, style), { x: point.x, y: point.y, zIndex: zIndex }), layout: true, onDrag: function (_event, _a) {
35
- var velocity = _a.velocity;
34
+ return (React.createElement(Component, __assign({ drag: axis }, props, { dragSnapToOrigin: true, style: __assign(__assign({}, style), { x: point.x, y: point.y, zIndex: zIndex }), layout: true, onDrag: function (event, gesturePoint) {
35
+ var velocity = gesturePoint.velocity;
36
36
  velocity[axis] &&
37
37
  updateOrder(value, point[axis].get(), velocity[axis]);
38
+ onDrag === null || onDrag === void 0 ? void 0 : onDrag(event, gesturePoint);
38
39
  }, onLayoutMeasure: function (measured) {
39
40
  layout.current = measured;
40
41
  }, ref: externalRef }), children));
@@ -8,8 +8,11 @@ function createHoverEvent(visualElement, isActive, callback) {
8
8
  var _a;
9
9
  if (!isMouseEvent(event) || isDragActive())
10
10
  return;
11
- callback === null || callback === void 0 ? void 0 : callback(event, info);
11
+ /**
12
+ * Ensure we trigger animations before firing event callback
13
+ */
12
14
  (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Hover, isActive);
15
+ callback === null || callback === void 0 ? void 0 : callback(event, info);
13
16
  };
14
17
  }
15
18
  function useHoverGesture(_a) {
@@ -50,8 +50,11 @@ function useTapGesture(_a) {
50
50
  return;
51
51
  isPressing.current = true;
52
52
  cancelPointerEndListeners.current = pipe(addPointerEvent(window, "pointerup", onPointerUp), addPointerEvent(window, "pointercancel", onPointerCancel));
53
- onTapStart === null || onTapStart === void 0 ? void 0 : onTapStart(event, info);
53
+ /**
54
+ * Ensure we trigger animations before firing event callback
55
+ */
54
56
  (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.Tap, true);
57
+ onTapStart === null || onTapStart === void 0 ? void 0 : onTapStart(event, info);
55
58
  }
56
59
  usePointerEvent(visualElement, "pointerdown", hasPressListeners ? onPointerDown : undefined);
57
60
  useUnmountEffect(removePointerEndListener);
package/dist/es/index.mjs CHANGED
@@ -31,6 +31,7 @@ export { useDomEvent } from './events/use-dom-event.mjs';
31
31
  export { createMotionComponent } from './motion/index.mjs';
32
32
  export { visualElement } from './render/index.mjs';
33
33
  export { addScaleCorrector } from './projection/styles/scale-correction.mjs';
34
+ export { useInstantTransition } from './utils/use-instant-transition.mjs';
34
35
  export { useInstantLayoutTransition } from './projection/use-instant-layout-transition.mjs';
35
36
  export { useResetProjection } from './projection/use-reset-projection.mjs';
36
37
  export { MotionConfigContext } from './context/MotionConfigContext.mjs';
@@ -11,6 +11,7 @@ var featureDefinitions = {
11
11
  "whileTap",
12
12
  "whileFocus",
13
13
  "whileDrag",
14
+ "whileInView",
14
15
  ]),
15
16
  exit: createDefinition(["exit"]),
16
17
  drag: createDefinition(["drag", "dragControls"]),
@@ -23,6 +24,11 @@ var featureDefinitions = {
23
24
  "onPanSessionStart",
24
25
  "onPanEnd",
25
26
  ]),
27
+ inView: createDefinition([
28
+ "whileInView",
29
+ "onViewportEnter",
30
+ "onViewportLeave",
31
+ ]),
26
32
  };
27
33
  function loadFeatures(features) {
28
34
  for (var key in features) {
@@ -1,9 +1,11 @@
1
1
  import { useFocusGesture } from '../../gestures/use-focus-gesture.mjs';
2
2
  import { useHoverGesture } from '../../gestures/use-hover-gesture.mjs';
3
3
  import { useTapGesture } from '../../gestures/use-tap-gesture.mjs';
4
+ import { useViewport } from './viewport/use-viewport.mjs';
4
5
  import { makeRenderlessComponent } from '../utils/make-renderless-component.mjs';
5
6
 
6
7
  var gestureAnimations = {
8
+ inView: makeRenderlessComponent(useViewport),
7
9
  tap: makeRenderlessComponent(useTapGesture),
8
10
  focus: makeRenderlessComponent(useFocusGesture),
9
11
  hover: makeRenderlessComponent(useHoverGesture),
@@ -0,0 +1,52 @@
1
+ import { __rest, __assign } from 'tslib';
2
+
3
+ /**
4
+ * Map an IntersectionHandler callback to an element. We only ever make one handler for one
5
+ * element, so even though these handlers might all be triggered by different
6
+ * observers, we can keep them in the same map.
7
+ */
8
+ var observerCallbacks = new WeakMap();
9
+ /**
10
+ * Multiple observers can be created for multiple element/document roots. Each with
11
+ * different settings. So here we store dictionaries of observers to each root,
12
+ * using serialised settings (threshold/margin) as lookup keys.
13
+ */
14
+ var observers = new WeakMap();
15
+ var fireObserverCallback = function (entry) {
16
+ var _a;
17
+ (_a = observerCallbacks.get(entry.target)) === null || _a === void 0 ? void 0 : _a(entry);
18
+ };
19
+ var fireAllObserverCallbacks = function (entries) {
20
+ entries.forEach(fireObserverCallback);
21
+ };
22
+ function initIntersectionObserver(_a) {
23
+ var root = _a.root, options = __rest(_a, ["root"]);
24
+ var lookupRoot = root || document;
25
+ /**
26
+ * If we don't have an observer lookup map for this root, create one.
27
+ */
28
+ if (!observers.has(lookupRoot)) {
29
+ observers.set(lookupRoot, {});
30
+ }
31
+ var rootObservers = observers.get(lookupRoot);
32
+ var key = JSON.stringify(options);
33
+ /**
34
+ * If we don't have an observer for this combination of root and settings,
35
+ * create one.
36
+ */
37
+ if (!rootObservers[key]) {
38
+ rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, __assign({ root: root }, options));
39
+ }
40
+ return rootObservers[key];
41
+ }
42
+ function observeIntersection(element, options, callback) {
43
+ var rootInteresectionObserver = initIntersectionObserver(options);
44
+ observerCallbacks.set(element, callback);
45
+ rootInteresectionObserver.observe(element);
46
+ return function () {
47
+ observerCallbacks.delete(element);
48
+ rootInteresectionObserver.unobserve(element);
49
+ };
50
+ }
51
+
52
+ export { observeIntersection };
@@ -0,0 +1,97 @@
1
+ import { useRef, useEffect } from 'react';
2
+ import { AnimationType } from '../../../render/utils/types.mjs';
3
+ import { warnOnce } from '../../../utils/warn-once.mjs';
4
+ import { observeIntersection } from './observers.mjs';
5
+
6
+ function useViewport(_a) {
7
+ var visualElement = _a.visualElement, whileInView = _a.whileInView, onViewportEnter = _a.onViewportEnter, onViewportLeave = _a.onViewportLeave, _b = _a.viewport, viewport = _b === void 0 ? {} : _b;
8
+ var state = useRef({
9
+ hasEnteredView: false,
10
+ isInView: false,
11
+ });
12
+ var shouldObserve = Boolean(whileInView || onViewportEnter || onViewportLeave);
13
+ if (viewport.once && state.current.hasEnteredView)
14
+ shouldObserve = false;
15
+ var useObserver = typeof IntersectionObserver === "undefined"
16
+ ? useMissingIntersectionObserver
17
+ : useIntersectionObserver;
18
+ useObserver(shouldObserve, state.current, visualElement, viewport);
19
+ }
20
+ var thresholdNames = {
21
+ some: 0,
22
+ all: 1,
23
+ };
24
+ function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
25
+ var root = _a.root, rootMargin = _a.margin, _b = _a.amount, amount = _b === void 0 ? "some" : _b, once = _a.once;
26
+ useEffect(function () {
27
+ if (!shouldObserve)
28
+ return;
29
+ var options = {
30
+ root: root === null || root === void 0 ? void 0 : root.current,
31
+ rootMargin: rootMargin,
32
+ threshold: typeof amount === "number" ? amount : thresholdNames[amount],
33
+ };
34
+ var intersectionCallback = function (entry) {
35
+ var _a;
36
+ var isIntersecting = entry.isIntersecting;
37
+ /**
38
+ * If there's been no change in the viewport state, early return.
39
+ */
40
+ if (state.isInView === isIntersecting)
41
+ return;
42
+ state.isInView = isIntersecting;
43
+ /**
44
+ * Handle hasEnteredView. If this is only meant to run once, and
45
+ * element isn't visible, early return. Otherwise set hasEnteredView to true.
46
+ */
47
+ if (once && !isIntersecting && state.hasEnteredView) {
48
+ return;
49
+ }
50
+ else if (isIntersecting) {
51
+ state.hasEnteredView = true;
52
+ }
53
+ (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, isIntersecting);
54
+ /**
55
+ * Use the latest committed props rather than the ones in scope
56
+ * when this observer is created
57
+ */
58
+ var props = visualElement.getProps();
59
+ var callback = isIntersecting
60
+ ? props.onViewportEnter
61
+ : props.onViewportLeave;
62
+ callback === null || callback === void 0 ? void 0 : callback(entry);
63
+ };
64
+ return observeIntersection(visualElement.getInstance(), options, intersectionCallback);
65
+ }, [shouldObserve, root, rootMargin, amount]);
66
+ }
67
+ /**
68
+ * If IntersectionObserver is missing, we activate inView and fire onViewportEnter
69
+ * on mount. This way, the page will be in the state the author expects users
70
+ * to see it in for everyone.
71
+ */
72
+ function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
73
+ useEffect(function () {
74
+ if (!shouldObserve)
75
+ return;
76
+ if (process.env.NODE_ENV !== "production") {
77
+ warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
78
+ }
79
+ /**
80
+ * Fire this in an rAF because, at this point, the animation state
81
+ * won't have flushed for the first time and there's certain logic in
82
+ * there that behaves differently on the initial animation.
83
+ *
84
+ * This hook should be quite rarely called so setting this in an rAF
85
+ * is preferred to changing the behaviour of the animation state.
86
+ */
87
+ requestAnimationFrame(function () {
88
+ var _a;
89
+ state.hasEnteredView = true;
90
+ var onViewportEnter = visualElement.getProps().onViewportEnter;
91
+ onViewportEnter === null || onViewportEnter === void 0 ? void 0 : onViewportEnter(null);
92
+ (_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(AnimationType.InView, true);
93
+ });
94
+ }, [shouldObserve]);
95
+ }
96
+
97
+ export { useViewport };
@@ -18,13 +18,17 @@ function makeState(_a, props, context, presenceContext) {
18
18
  }
19
19
  return state;
20
20
  }
21
- var makeUseVisualState = function (config) { return function (props, isStatic) {
22
- var context = useContext(MotionContext);
23
- var presenceContext = useContext(PresenceContext);
24
- return isStatic
25
- ? makeState(config, props, context, presenceContext)
26
- : useConstant(function () { return makeState(config, props, context, presenceContext); });
27
- }; };
21
+ var makeUseVisualState = function (config) {
22
+ return function (props, isStatic) {
23
+ var context = useContext(MotionContext);
24
+ var presenceContext = useContext(PresenceContext);
25
+ return isStatic
26
+ ? makeState(config, props, context, presenceContext)
27
+ : useConstant(function () {
28
+ return makeState(config, props, context, presenceContext);
29
+ });
30
+ };
31
+ };
28
32
  function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
29
33
  var values = {};
30
34
  var blockInitialAnimation = (presenceContext === null || presenceContext === void 0 ? void 0 : presenceContext.initial) === false;
@@ -42,7 +46,8 @@ function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
42
46
  initial !== null && initial !== void 0 ? initial : (initial = context.initial);
43
47
  animate !== null && animate !== void 0 ? animate : (animate = context.animate);
44
48
  }
45
- var variantToSet = blockInitialAnimation || initial === false ? animate : initial;
49
+ var initialAnimationIsBlocked = blockInitialAnimation || initial === false;
50
+ var variantToSet = initialAnimationIsBlocked ? animate : initial;
46
51
  if (variantToSet &&
47
52
  typeof variantToSet !== "boolean" &&
48
53
  !isAnimationControls(variantToSet)) {
@@ -52,8 +57,22 @@ function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
52
57
  if (!resolved)
53
58
  return;
54
59
  var transitionEnd = resolved.transitionEnd; resolved.transition; var target = __rest(resolved, ["transitionEnd", "transition"]);
55
- for (var key in target)
56
- values[key] = target[key];
60
+ for (var key in target) {
61
+ var valueTarget = target[key];
62
+ if (Array.isArray(valueTarget)) {
63
+ /**
64
+ * Take final keyframe if the initial animation is blocked because
65
+ * we want to initialise at the end of that blocked animation.
66
+ */
67
+ var index = initialAnimationIsBlocked
68
+ ? valueTarget.length - 1
69
+ : 0;
70
+ valueTarget = valueTarget[index];
71
+ }
72
+ if (valueTarget !== null) {
73
+ values[key] = valueTarget;
74
+ }
75
+ }
57
76
  for (var key in transitionEnd)
58
77
  values[key] = transitionEnd[key];
59
78
  });
@@ -17,6 +17,7 @@ var validMotionProps = new Set([
17
17
  "inherit",
18
18
  "layout",
19
19
  "layoutId",
20
+ "layoutDependency",
20
21
  "onLayoutAnimationComplete",
21
22
  "onLayoutMeasure",
22
23
  "onBeforeLayoutMeasure",
@@ -54,6 +55,10 @@ var validMotionProps = new Set([
54
55
  "whileFocus",
55
56
  "whileTap",
56
57
  "whileHover",
58
+ "whileInView",
59
+ "onViewportEnter",
60
+ "onViewportLeave",
61
+ "viewport",
57
62
  "layoutScroll",
58
63
  ]);
59
64
  /**
@@ -38,12 +38,14 @@ function useHTMLProps(props, visualState, isStatic) {
38
38
  // The `any` isn't ideal but it is the type of createElement props argument
39
39
  var htmlProps = {};
40
40
  var style = useStyle(props, visualState, isStatic);
41
- if (Boolean(props.drag)) {
41
+ if (Boolean(props.drag) && props.dragListener !== false) {
42
42
  // Disable the ghost element when a user drags
43
43
  htmlProps.draggable = false;
44
44
  // Disable text selection
45
- style.userSelect = style.WebkitUserSelect = style.WebkitTouchCallout =
46
- "none";
45
+ style.userSelect =
46
+ style.WebkitUserSelect =
47
+ style.WebkitTouchCallout =
48
+ "none";
47
49
  // Disable scrolling on the draggable direction
48
50
  style.touchAction =
49
51
  props.drag === true
@@ -8,6 +8,7 @@ import { isVariantLabels, resolveVariant, isVariantLabel } from './variants.mjs'
8
8
 
9
9
  var variantPriorityOrder = [
10
10
  AnimationType.Animate,
11
+ AnimationType.InView,
11
12
  AnimationType.Focus,
12
13
  AnimationType.Hover,
13
14
  AnimationType.Tap,
@@ -134,7 +135,8 @@ function createAnimationState(visualElement) {
134
135
  * a changed value or a value that was removed in a higher priority, we set
135
136
  * this to true and add this prop to the animation list.
136
137
  */
137
- var shouldAnimateType = variantsHaveChanged(typeState.prevProp, prop) ||
138
+ var variantDidChange = checkVariantsDidChange(typeState.prevProp, prop);
139
+ var shouldAnimateType = variantDidChange ||
138
140
  // If we're making this variant active, we want to always make it active
139
141
  (type === changedActiveType &&
140
142
  typeState.isActive &&
@@ -185,7 +187,7 @@ function createAnimationState(visualElement) {
185
187
  * detect whether any value has changed. If it has, we animate it.
186
188
  */
187
189
  if (isKeyframesTarget(next) && isKeyframesTarget(prev)) {
188
- if (!shallowCompare(next, prev)) {
190
+ if (!shallowCompare(next, prev) || variantDidChange) {
189
191
  markToAnimate(key);
190
192
  }
191
193
  else {
@@ -302,7 +304,7 @@ function createAnimationState(visualElement) {
302
304
  getState: function () { return state; },
303
305
  };
304
306
  }
305
- function variantsHaveChanged(prev, next) {
307
+ function checkVariantsDidChange(prev, next) {
306
308
  if (typeof next === "string") {
307
309
  return next !== prev;
308
310
  }
@@ -324,6 +326,7 @@ function createState() {
324
326
  var _a;
325
327
  return _a = {},
326
328
  _a[AnimationType.Animate] = createTypeState(true),
329
+ _a[AnimationType.InView] = createTypeState(),
327
330
  _a[AnimationType.Hover] = createTypeState(),
328
331
  _a[AnimationType.Tap] = createTypeState(),
329
332
  _a[AnimationType.Drag] = createTypeState(),
@@ -332,4 +335,4 @@ function createState() {
332
335
  _a;
333
336
  }
334
337
 
335
- export { createAnimationState, variantPriorityOrder, variantsHaveChanged };
338
+ export { checkVariantsDidChange, createAnimationState, variantPriorityOrder };
@@ -22,9 +22,7 @@ function setMotionValue(visualElement, key, value) {
22
22
  }
23
23
  function setTarget(visualElement, definition) {
24
24
  var resolved = resolveVariant(visualElement, definition);
25
- var _a = resolved
26
- ? visualElement.makeTargetAnimatable(resolved, false)
27
- : {}, _b = _a.transitionEnd, transitionEnd = _b === void 0 ? {} : _b; _a.transition; var target = __rest(_a, ["transitionEnd", "transition"]);
25
+ var _a = resolved ? visualElement.makeTargetAnimatable(resolved, false) : {}, _b = _a.transitionEnd, transitionEnd = _b === void 0 ? {} : _b; _a.transition; var target = __rest(_a, ["transitionEnd", "transition"]);
28
26
  target = __assign(__assign({}, target), transitionEnd);
29
27
  for (var key in target) {
30
28
  var value = resolveFinalValueInKeyframes(target[key]);
@@ -5,6 +5,7 @@ var AnimationType;
5
5
  AnimationType["Tap"] = "whileTap";
6
6
  AnimationType["Drag"] = "whileDrag";
7
7
  AnimationType["Focus"] = "whileFocus";
8
+ AnimationType["InView"] = "whileInView";
8
9
  AnimationType["Exit"] = "exit";
9
10
  })(AnimationType || (AnimationType = {}));
10
11
 
@@ -1,17 +1,21 @@
1
1
  import { __read } from 'tslib';
2
- import { useCallback, useRef, useState } from 'react';
2
+ import sync from 'framesync';
3
+ import { useRef, useState, useCallback } from 'react';
3
4
  import { useUnmountEffect } from './use-unmount-effect.mjs';
4
5
 
5
6
  function useForceUpdate() {
6
- var unloadingRef = useRef(false);
7
+ var isUnmountingRef = useRef(false);
7
8
  var _a = __read(useState(0), 2), forcedRenderCount = _a[0], setForcedRenderCount = _a[1];
8
- useUnmountEffect(function () { return (unloadingRef.current = true); });
9
- return [
10
- useCallback(function () {
11
- !unloadingRef.current && setForcedRenderCount(forcedRenderCount + 1);
12
- }, [forcedRenderCount]),
13
- forcedRenderCount,
14
- ];
9
+ useUnmountEffect(function () { return (isUnmountingRef.current = true); });
10
+ var forceRender = useCallback(function () {
11
+ !isUnmountingRef.current && setForcedRenderCount(forcedRenderCount + 1);
12
+ }, [forcedRenderCount]);
13
+ /**
14
+ * Defer this to the end of the next animation frame in case there are multiple
15
+ * synchronous calls.
16
+ */
17
+ var deferredForceRender = useCallback(function () { return sync.postRender(forceRender); }, [forceRender]);
18
+ return [deferredForceRender, forcedRenderCount];
15
19
  }
16
20
 
17
21
  export { useForceUpdate };
@@ -0,0 +1,5 @@
1
+ var instantAnimationState = {
2
+ current: false,
3
+ };
4
+
5
+ export { instantAnimationState };
@@ -0,0 +1,28 @@
1
+ import { __read } from 'tslib';
2
+ import sync from 'framesync';
3
+ import { useEffect } from 'react';
4
+ import { useInstantLayoutTransition } from '../projection/use-instant-layout-transition.mjs';
5
+ import { useForceUpdate } from './use-force-update.mjs';
6
+ import { instantAnimationState } from './use-instant-transition-state.mjs';
7
+
8
+ function useInstantTransition() {
9
+ var _a = __read(useForceUpdate(), 2), forceUpdate = _a[0], forcedRenderCount = _a[1];
10
+ var startInstantLayoutTransition = useInstantLayoutTransition();
11
+ useEffect(function () {
12
+ /**
13
+ * Unblock after two animation frames, otherwise this will unblock too soon.
14
+ */
15
+ sync.postRender(function () {
16
+ return sync.postRender(function () { return (instantAnimationState.current = false); });
17
+ });
18
+ }, [forcedRenderCount]);
19
+ return function (callback) {
20
+ startInstantLayoutTransition(function () {
21
+ instantAnimationState.current = true;
22
+ forceUpdate();
23
+ callback();
24
+ });
25
+ };
26
+ }
27
+
28
+ export { useInstantTransition };
@@ -0,0 +1,11 @@
1
+ var warned = new Set();
2
+ function warnOnce(condition, message, element) {
3
+ if (condition || warned.has(message))
4
+ return;
5
+ console.warn(message);
6
+ if (element)
7
+ console.warn(element);
8
+ warned.add(message);
9
+ }
10
+
11
+ export { warnOnce };