framer-motion 9.1.0 → 9.1.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 (67) hide show
  1. package/README.md +15 -15
  2. package/dist/cjs/index.js +605 -116
  3. package/dist/es/animation/hooks/animation-controls.mjs +1 -1
  4. package/dist/es/animation/index.mjs +1 -1
  5. package/dist/es/animation/legacy-popmotion/find-spring.mjs +1 -1
  6. package/dist/es/animation/legacy-popmotion/keyframes.mjs +3 -8
  7. package/dist/es/animation/utils/easing.mjs +1 -1
  8. package/dist/es/components/AnimateSharedLayout.mjs +2 -2
  9. package/dist/es/components/Reorder/Group.mjs +1 -1
  10. package/dist/es/components/Reorder/Item.mjs +1 -1
  11. package/dist/es/gestures/drag/VisualElementDragControls.mjs +3 -4
  12. package/dist/es/gestures/focus.mjs +2 -3
  13. package/dist/es/gestures/hover.mjs +1 -2
  14. package/dist/es/gestures/press.mjs +2 -3
  15. package/dist/es/index.mjs +1 -0
  16. package/dist/es/motion/features/animation/exit.mjs +1 -2
  17. package/dist/es/motion/features/viewport/index.mjs +2 -3
  18. package/dist/es/render/VisualElement.mjs +3 -4
  19. package/dist/es/render/dom/resize/handle-element.mjs +64 -0
  20. package/dist/es/render/dom/resize/handle-window.mjs +30 -0
  21. package/dist/es/render/dom/resize/index.mjs +8 -0
  22. package/dist/es/render/dom/scroll/index.mjs +74 -0
  23. package/dist/es/render/dom/scroll/info.mjs +56 -0
  24. package/dist/es/render/dom/scroll/offsets/edge.mjs +45 -0
  25. package/dist/es/render/dom/scroll/offsets/index.mjs +54 -0
  26. package/dist/es/render/dom/scroll/offsets/inset.mjs +25 -0
  27. package/dist/es/render/dom/scroll/offsets/offset.mjs +35 -0
  28. package/dist/es/render/dom/scroll/offsets/presets.mjs +20 -0
  29. package/dist/es/render/dom/scroll/on-scroll-handler.mjs +38 -0
  30. package/dist/es/render/dom/utils/css-variables-conversion.mjs +5 -7
  31. package/dist/es/render/dom/utils/is-css-variable.mjs +4 -7
  32. package/dist/es/render/dom/utils/resolve-element.mjs +21 -0
  33. package/dist/es/render/dom/utils/unit-conversion.mjs +2 -11
  34. package/dist/es/render/dom/viewport/index.mjs +52 -0
  35. package/dist/es/render/html/HTMLVisualElement.mjs +2 -2
  36. package/dist/es/render/html/utils/build-styles.mjs +2 -2
  37. package/dist/es/render/utils/animation-state.mjs +16 -21
  38. package/dist/es/render/utils/is-controlling-variants.mjs +1 -10
  39. package/dist/es/render/utils/motion-values.mjs +1 -1
  40. package/dist/es/render/utils/variant-props.mjs +12 -0
  41. package/dist/es/utils/errors.mjs +18 -0
  42. package/dist/es/utils/interpolate.mjs +1 -1
  43. package/dist/es/utils/mix-color.mjs +1 -1
  44. package/dist/es/utils/mix-complex.mjs +1 -1
  45. package/dist/es/utils/offsets/default.mjs +9 -0
  46. package/dist/es/utils/offsets/fill.mjs +12 -0
  47. package/dist/es/utils/offsets/time.mjs +5 -0
  48. package/dist/es/utils/use-in-view.mjs +1 -1
  49. package/dist/es/value/index.mjs +1 -1
  50. package/dist/es/value/use-inverted-scale.mjs +1 -1
  51. package/dist/es/value/use-scroll.mjs +2 -2
  52. package/dist/es/value/use-will-change/index.mjs +2 -2
  53. package/dist/framer-motion.dev.js +238 -370
  54. package/dist/framer-motion.js +1 -1
  55. package/dist/index.d.ts +12 -3
  56. package/dist/projection.dev.js +53 -78
  57. package/dist/size-rollup-dom-animation-assets.js +1 -1
  58. package/dist/size-rollup-dom-animation.js +1 -1
  59. package/dist/size-rollup-dom-max-assets.js +1 -1
  60. package/dist/size-rollup-dom-max.js +1 -1
  61. package/dist/size-rollup-m.js +1 -1
  62. package/dist/size-rollup-motion.js +1 -1
  63. package/dist/size-webpack-dom-animation.js +1 -1
  64. package/dist/size-webpack-dom-max.js +1 -1
  65. package/dist/size-webpack-m.js +1 -1
  66. package/dist/three-entry.d.ts +1 -1
  67. package/package.json +9 -11
@@ -1,4 +1,4 @@
1
- import { invariant } from 'hey-listen';
1
+ import { invariant } from '../../utils/errors.mjs';
2
2
  import { animateVisualElement, stopAnimation } from '../../render/utils/animation.mjs';
3
3
  import { setValues } from '../../render/utils/setters.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { warning } from 'hey-listen';
1
+ import { warning } from '../utils/errors.mjs';
2
2
  import { secondsToMilliseconds } from '../utils/time-conversion.mjs';
3
3
  import { instantAnimationState } from '../utils/use-instant-transition-state.mjs';
4
4
  import { createAcceleratedAnimation } from './waapi/create-accelerated-animation.mjs';
@@ -1,4 +1,4 @@
1
- import { warning } from 'hey-listen';
1
+ import { warning } from '../../utils/errors.mjs';
2
2
  import { clamp } from '../../utils/clamp.mjs';
3
3
 
4
4
  const safeMin = 0.001;
@@ -1,17 +1,12 @@
1
1
  import { easeInOut } from '../../easing/ease.mjs';
2
2
  import { interpolate } from '../../utils/interpolate.mjs';
3
+ import { defaultOffset } from '../../utils/offsets/default.mjs';
4
+ import { convertOffsetToTimes } from '../../utils/offsets/time.mjs';
3
5
  import { isEasingArray, easingDefinitionToFunction } from '../utils/easing.mjs';
4
6
 
5
7
  function defaultEasing(values, easing) {
6
8
  return values.map(() => easing || easeInOut).splice(0, values.length - 1);
7
9
  }
8
- function defaultOffset(values) {
9
- const numValues = values.length;
10
- return values.map((_value, i) => i !== 0 ? i / (numValues - 1) : 0);
11
- }
12
- function convertOffsetToTimes(offset, duration) {
13
- return offset.map((o) => o * duration);
14
- }
15
10
  function keyframes({ keyframes: keyframeValues, ease = easeInOut, times, duration = 300, }) {
16
11
  keyframeValues = [...keyframeValues];
17
12
  /**
@@ -59,4 +54,4 @@ function keyframes({ keyframes: keyframeValues, ease = easeInOut, times, duratio
59
54
  };
60
55
  }
61
56
 
62
- export { convertOffsetToTimes, defaultEasing, defaultOffset, keyframes };
57
+ export { defaultEasing, keyframes };
@@ -1,4 +1,4 @@
1
- import { invariant } from 'hey-listen';
1
+ import { invariant } from '../../utils/errors.mjs';
2
2
  import { cubicBezier } from '../../easing/cubic-bezier.mjs';
3
3
  import { noop } from '../../utils/noop.mjs';
4
4
  import { easeIn, easeInOut, easeOut } from '../../easing/ease.mjs';
@@ -1,10 +1,10 @@
1
- import { warning } from 'hey-listen';
1
+ import { warning } from '../utils/errors.mjs';
2
2
  import * as React from 'react';
3
3
  import { useConstant } from '../utils/use-constant.mjs';
4
4
  import { LayoutGroup } from './LayoutGroup/index.mjs';
5
5
 
6
6
  let id = 0;
7
- const AnimateSharedLayout = ({ children, }) => {
7
+ const AnimateSharedLayout = ({ children }) => {
8
8
  React.useEffect(() => {
9
9
  warning(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
10
10
  }, []);
@@ -1,4 +1,4 @@
1
- import { invariant } from 'hey-listen';
1
+ import { invariant } from '../../utils/errors.mjs';
2
2
  import * as React from 'react';
3
3
  import { forwardRef, useRef, useEffect } from 'react';
4
4
  import { ReorderContext } from '../../context/ReorderContext.mjs';
@@ -1,4 +1,4 @@
1
- import { invariant } from 'hey-listen';
1
+ import { invariant } from '../../utils/errors.mjs';
2
2
  import * as React from 'react';
3
3
  import { forwardRef, useContext, useRef, useEffect } from 'react';
4
4
  import { ReorderContext } from '../../context/ReorderContext.mjs';
@@ -1,10 +1,9 @@
1
- import { invariant } from 'hey-listen';
1
+ import { invariant } from '../../utils/errors.mjs';
2
2
  import { PanSession } from '../pan/PanSession.mjs';
3
3
  import { getGlobalLock } from './utils/lock.mjs';
4
4
  import { isRefObject } from '../../utils/is-ref-object.mjs';
5
5
  import { addPointerEvent } from '../../events/add-pointer-event.mjs';
6
6
  import { applyConstraints, calcRelativeConstraints, resolveDragElastic, calcViewportConstraints, defaultElastic, rebaseAxisConstraints, calcOrigin } from './utils/constraints.mjs';
7
- import { AnimationType } from '../../render/utils/types.mjs';
8
7
  import { createBox } from '../../projection/geometry/models.mjs';
9
8
  import { eachAxis } from '../../projection/utils/each-axis.mjs';
10
9
  import { measurePageBox } from '../../projection/utils/measure.mjs';
@@ -97,7 +96,7 @@ class VisualElementDragControls {
97
96
  // Fire onDragStart event
98
97
  onDragStart && onDragStart(event, info);
99
98
  const { animationState } = this.visualElement;
100
- animationState && animationState.setActive(AnimationType.Drag, true);
99
+ animationState && animationState.setActive("whileDrag" /* AnimationType.Drag */, true);
101
100
  };
102
101
  const onMove = (event, info) => {
103
102
  // latestPointerEvent = event
@@ -162,7 +161,7 @@ class VisualElementDragControls {
162
161
  this.openGlobalLock();
163
162
  this.openGlobalLock = null;
164
163
  }
165
- animationState && animationState.setActive(AnimationType.Drag, false);
164
+ animationState && animationState.setActive("whileDrag" /* AnimationType.Drag */, false);
166
165
  }
167
166
  updateAxis(axis, _point, offset) {
168
167
  const { drag } = this.getProps();
@@ -1,6 +1,5 @@
1
1
  import { addDomEvent } from '../events/add-dom-event.mjs';
2
2
  import { Feature } from '../motion/features/Feature.mjs';
3
- import { AnimationType } from '../render/utils/types.mjs';
4
3
  import { pipe } from '../utils/pipe.mjs';
5
4
 
6
5
  class FocusGesture extends Feature {
@@ -24,13 +23,13 @@ class FocusGesture extends Feature {
24
23
  }
25
24
  if (!isFocusVisible || !this.node.animationState)
26
25
  return;
27
- this.node.animationState.setActive(AnimationType.Focus, true);
26
+ this.node.animationState.setActive("whileFocus" /* AnimationType.Focus */, true);
28
27
  this.isActive = true;
29
28
  }
30
29
  onBlur() {
31
30
  if (!this.isActive || !this.node.animationState)
32
31
  return;
33
- this.node.animationState.setActive(AnimationType.Focus, false);
32
+ this.node.animationState.setActive("whileFocus" /* AnimationType.Focus */, false);
34
33
  this.isActive = false;
35
34
  }
36
35
  mount() {
@@ -1,5 +1,4 @@
1
1
  import { addPointerEvent } from '../events/add-pointer-event.mjs';
2
- import { AnimationType } from '../render/utils/types.mjs';
3
2
  import { pipe } from '../utils/pipe.mjs';
4
3
  import { isDragActive } from './drag/utils/lock.mjs';
5
4
  import { Feature } from '../motion/features/Feature.mjs';
@@ -12,7 +11,7 @@ function addHoverEvent(node, isActive) {
12
11
  return;
13
12
  const props = node.getProps();
14
13
  if (node.animationState && props.whileHover) {
15
- node.animationState.setActive(AnimationType.Hover, isActive);
14
+ node.animationState.setActive("whileHover" /* AnimationType.Hover */, isActive);
16
15
  }
17
16
  if (props[callbackName]) {
18
17
  props[callbackName](event, info);
@@ -2,7 +2,6 @@ import { extractEventInfo } from '../events/event-info.mjs';
2
2
  import { addDomEvent } from '../events/add-dom-event.mjs';
3
3
  import { addPointerEvent } from '../events/add-pointer-event.mjs';
4
4
  import { Feature } from '../motion/features/Feature.mjs';
5
- import { AnimationType } from '../render/utils/types.mjs';
6
5
  import { pipe } from '../utils/pipe.mjs';
7
6
  import { isDragActive } from './drag/utils/lock.mjs';
8
7
  import { isNodeOrChild } from './utils/is-node-or-child.mjs';
@@ -74,7 +73,7 @@ class PressGesture extends Feature {
74
73
  * Ensure we trigger animations before firing event callback
75
74
  */
76
75
  if (whileTap && this.node.animationState) {
77
- this.node.animationState.setActive(AnimationType.Tap, true);
76
+ this.node.animationState.setActive("whileTap" /* AnimationType.Tap */, true);
78
77
  }
79
78
  onTapStart && onTapStart(event, info);
80
79
  }
@@ -83,7 +82,7 @@ class PressGesture extends Feature {
83
82
  this.isPressing = false;
84
83
  const props = this.node.getProps();
85
84
  if (props.whileTap && this.node.animationState) {
86
- this.node.animationState.setActive(AnimationType.Tap, false);
85
+ this.node.animationState.setActive("whileTap" /* AnimationType.Tap */, false);
87
86
  }
88
87
  return !isDragActive();
89
88
  }
package/dist/es/index.mjs CHANGED
@@ -47,6 +47,7 @@ export { buildTransform } from './render/html/utils/build-transform.mjs';
47
47
  export { clamp } from './utils/clamp.mjs';
48
48
  export { delay } from './utils/delay.mjs';
49
49
  export { distance, distance2D } from './utils/distance.mjs';
50
+ export { invariant, warning } from './utils/errors.mjs';
50
51
  export { interpolate } from './utils/interpolate.mjs';
51
52
  export { mix } from './utils/mix.mjs';
52
53
  export { pipe } from './utils/pipe.mjs';
@@ -1,4 +1,3 @@
1
- import { AnimationType } from '../../../render/utils/types.mjs';
2
1
  import { Feature } from '../Feature.mjs';
3
2
 
4
3
  let id = 0;
@@ -15,7 +14,7 @@ class ExitAnimationFeature extends Feature {
15
14
  if (!this.node.animationState || isPresent === prevIsPresent) {
16
15
  return;
17
16
  }
18
- const exitAnimation = this.node.animationState.setActive(AnimationType.Exit, !isPresent, { custom: custom !== null && custom !== void 0 ? custom : this.node.getProps().custom });
17
+ const exitAnimation = this.node.animationState.setActive("exit" /* AnimationType.Exit */, !isPresent, { custom: custom !== null && custom !== void 0 ? custom : this.node.getProps().custom });
19
18
  if (onExitComplete && !isPresent) {
20
19
  exitAnimation.then(() => onExitComplete(this.id));
21
20
  }
@@ -1,4 +1,3 @@
1
- import { AnimationType } from '../../../render/utils/types.mjs';
2
1
  import { Feature } from '../Feature.mjs';
3
2
  import { observeIntersection } from './observers.mjs';
4
3
 
@@ -26,7 +25,7 @@ class InViewFeature extends Feature {
26
25
  const { onViewportEnter } = this.node.getProps();
27
26
  onViewportEnter && onViewportEnter(null);
28
27
  if (this.node.animationState) {
29
- this.node.animationState.setActive(AnimationType.InView, true);
28
+ this.node.animationState.setActive("whileInView" /* AnimationType.InView */, true);
30
29
  }
31
30
  });
32
31
  }
@@ -63,7 +62,7 @@ class InViewFeature extends Feature {
63
62
  this.hasEnteredView = true;
64
63
  }
65
64
  if (this.node.animationState) {
66
- this.node.animationState.setActive(AnimationType.InView, isIntersecting);
65
+ this.node.animationState.setActive("whileInView" /* AnimationType.InView */, isIntersecting);
67
66
  }
68
67
  /**
69
68
  * Use the latest committed props rather than the ones in scope
@@ -1,5 +1,5 @@
1
1
  import { sync, cancelSync } from '../frameloop/index.mjs';
2
- import { warning, invariant } from 'hey-listen';
2
+ import { warning, invariant } from '../utils/errors.mjs';
3
3
  import { createBox } from '../projection/geometry/models.mjs';
4
4
  import { isRefObject } from '../utils/is-ref-object.mjs';
5
5
  import { initPrefersReducedMotion } from '../utils/reduced-motion/index.mjs';
@@ -9,13 +9,13 @@ import { motionValue } from '../value/index.mjs';
9
9
  import { isWillChangeMotionValue } from '../value/use-will-change/is.mjs';
10
10
  import { isMotionValue } from '../value/utils/is-motion-value.mjs';
11
11
  import { transformProps } from './html/utils/transform.mjs';
12
- import { variantPriorityOrder } from './utils/animation-state.mjs';
13
12
  import { isControllingVariants, isVariantNode } from './utils/is-controlling-variants.mjs';
14
13
  import { isVariantLabel } from './utils/is-variant-label.mjs';
15
14
  import { updateMotionValuesFromProps } from './utils/motion-values.mjs';
16
15
  import { resolveVariantFromProps } from './utils/resolve-variants.mjs';
17
16
  import { warnOnce } from '../utils/warn-once.mjs';
18
17
  import { featureDefinitions } from '../motion/features/definitions.mjs';
18
+ import { variantProps } from './utils/variant-props.mjs';
19
19
 
20
20
  const featureNames = Object.keys(featureDefinitions);
21
21
  const numFeatures = featureNames.length;
@@ -28,6 +28,7 @@ const propEventHandlers = [
28
28
  "LayoutAnimationStart",
29
29
  "LayoutAnimationComplete",
30
30
  ];
31
+ const numVariantProps = variantProps.length;
31
32
  /**
32
33
  * A VisualElement is an imperative abstraction around UI elements such as
33
34
  * HTMLElement, SVGElement, Three.Object3D etc.
@@ -498,7 +499,5 @@ class VisualElement {
498
499
  }
499
500
  }
500
501
  }
501
- const variantProps = ["initial", ...variantPriorityOrder];
502
- const numVariantProps = variantProps.length;
503
502
 
504
503
  export { VisualElement };
@@ -0,0 +1,64 @@
1
+ import { resolveElements } from '../utils/resolve-element.mjs';
2
+
3
+ const resizeHandlers = new WeakMap();
4
+ let observer;
5
+ function getElementSize(target, borderBoxSize) {
6
+ if (borderBoxSize) {
7
+ const { inlineSize, blockSize } = borderBoxSize[0];
8
+ return { width: inlineSize, height: blockSize };
9
+ }
10
+ else if (target instanceof SVGElement && "getBBox" in target) {
11
+ return target.getBBox();
12
+ }
13
+ else {
14
+ return {
15
+ width: target.offsetWidth,
16
+ height: target.offsetHeight,
17
+ };
18
+ }
19
+ }
20
+ function notifyTarget({ target, contentRect, borderBoxSize, }) {
21
+ var _a;
22
+ (_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
23
+ handler({
24
+ target,
25
+ contentSize: contentRect,
26
+ get size() {
27
+ return getElementSize(target, borderBoxSize);
28
+ },
29
+ });
30
+ });
31
+ }
32
+ function notifyAll(entries) {
33
+ entries.forEach(notifyTarget);
34
+ }
35
+ function createResizeObserver() {
36
+ if (typeof ResizeObserver === "undefined")
37
+ return;
38
+ observer = new ResizeObserver(notifyAll);
39
+ }
40
+ function resizeElement(target, handler) {
41
+ if (!observer)
42
+ createResizeObserver();
43
+ const elements = resolveElements(target);
44
+ elements.forEach((element) => {
45
+ let elementHandlers = resizeHandlers.get(element);
46
+ if (!elementHandlers) {
47
+ elementHandlers = new Set();
48
+ resizeHandlers.set(element, elementHandlers);
49
+ }
50
+ elementHandlers.add(handler);
51
+ observer === null || observer === void 0 ? void 0 : observer.observe(element);
52
+ });
53
+ return () => {
54
+ elements.forEach((element) => {
55
+ const elementHandlers = resizeHandlers.get(element);
56
+ elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
57
+ if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
58
+ observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
59
+ }
60
+ });
61
+ };
62
+ }
63
+
64
+ export { resizeElement };
@@ -0,0 +1,30 @@
1
+ const windowCallbacks = new Set();
2
+ let windowResizeHandler;
3
+ function createWindowResizeHandler() {
4
+ windowResizeHandler = () => {
5
+ const size = {
6
+ width: window.innerWidth,
7
+ height: window.innerHeight,
8
+ };
9
+ const info = {
10
+ target: window,
11
+ size,
12
+ contentSize: size,
13
+ };
14
+ windowCallbacks.forEach((callback) => callback(info));
15
+ };
16
+ window.addEventListener("resize", windowResizeHandler);
17
+ }
18
+ function resizeWindow(callback) {
19
+ windowCallbacks.add(callback);
20
+ if (!windowResizeHandler)
21
+ createWindowResizeHandler();
22
+ return () => {
23
+ windowCallbacks.delete(callback);
24
+ if (!windowCallbacks.size && windowResizeHandler) {
25
+ windowResizeHandler = undefined;
26
+ }
27
+ };
28
+ }
29
+
30
+ export { resizeWindow };
@@ -0,0 +1,8 @@
1
+ import { resizeElement } from './handle-element.mjs';
2
+ import { resizeWindow } from './handle-window.mjs';
3
+
4
+ function resize(a, b) {
5
+ return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
6
+ }
7
+
8
+ export { resize };
@@ -0,0 +1,74 @@
1
+ import { resize } from '../resize/index.mjs';
2
+ import { createScrollInfo } from './info.mjs';
3
+ import { createOnScrollHandler } from './on-scroll-handler.mjs';
4
+
5
+ const scrollListeners = new WeakMap();
6
+ const resizeListeners = new WeakMap();
7
+ const onScrollHandlers = new WeakMap();
8
+ const getEventTarget = (element) => element === document.documentElement ? window : element;
9
+ function scroll(onScroll, { container = document.documentElement, ...options } = {}) {
10
+ let containerHandlers = onScrollHandlers.get(container);
11
+ /**
12
+ * Get the onScroll handlers for this container.
13
+ * If one isn't found, create a new one.
14
+ */
15
+ if (!containerHandlers) {
16
+ containerHandlers = new Set();
17
+ onScrollHandlers.set(container, containerHandlers);
18
+ }
19
+ /**
20
+ * Create a new onScroll handler for the provided callback.
21
+ */
22
+ const info = createScrollInfo();
23
+ const containerHandler = createOnScrollHandler(container, onScroll, info, options);
24
+ containerHandlers.add(containerHandler);
25
+ /**
26
+ * Check if there's a scroll event listener for this container.
27
+ * If not, create one.
28
+ */
29
+ if (!scrollListeners.has(container)) {
30
+ const listener = () => {
31
+ const time = performance.now();
32
+ for (const handler of containerHandlers)
33
+ handler.measure();
34
+ for (const handler of containerHandlers)
35
+ handler.update(time);
36
+ for (const handler of containerHandlers)
37
+ handler.notify();
38
+ };
39
+ scrollListeners.set(container, listener);
40
+ const target = getEventTarget(container);
41
+ window.addEventListener("resize", listener, { passive: true });
42
+ if (container !== document.documentElement) {
43
+ resizeListeners.set(container, resize(container, listener));
44
+ }
45
+ target.addEventListener("scroll", listener, { passive: true });
46
+ }
47
+ const listener = scrollListeners.get(container);
48
+ const onLoadProcesss = requestAnimationFrame(listener);
49
+ return () => {
50
+ var _a;
51
+ cancelAnimationFrame(onLoadProcesss);
52
+ /**
53
+ * Check if we even have any handlers for this container.
54
+ */
55
+ const currentHandlers = onScrollHandlers.get(container);
56
+ if (!currentHandlers)
57
+ return;
58
+ currentHandlers.delete(containerHandler);
59
+ if (currentHandlers.size)
60
+ return;
61
+ /**
62
+ * If no more handlers, remove the scroll listener too.
63
+ */
64
+ const scrollListener = scrollListeners.get(container);
65
+ scrollListeners.delete(container);
66
+ if (scrollListener) {
67
+ getEventTarget(container).removeEventListener("scroll", scrollListener);
68
+ (_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
69
+ window.removeEventListener("resize", scrollListener);
70
+ }
71
+ };
72
+ }
73
+
74
+ export { scroll };
@@ -0,0 +1,56 @@
1
+ import { progress } from '../../../utils/progress.mjs';
2
+ import { velocityPerSecond } from '../../../utils/velocity-per-second.mjs';
3
+
4
+ /**
5
+ * A time in milliseconds, beyond which we consider the scroll velocity to be 0.
6
+ */
7
+ const maxElapsed = 50;
8
+ const createAxisInfo = () => ({
9
+ current: 0,
10
+ offset: [],
11
+ progress: 0,
12
+ scrollLength: 0,
13
+ targetOffset: 0,
14
+ targetLength: 0,
15
+ containerLength: 0,
16
+ velocity: 0,
17
+ });
18
+ const createScrollInfo = () => ({
19
+ time: 0,
20
+ x: createAxisInfo(),
21
+ y: createAxisInfo(),
22
+ });
23
+ const keys = {
24
+ x: {
25
+ length: "Width",
26
+ position: "Left",
27
+ },
28
+ y: {
29
+ length: "Height",
30
+ position: "Top",
31
+ },
32
+ };
33
+ function updateAxisInfo(element, axisName, info, time) {
34
+ const axis = info[axisName];
35
+ const { length, position } = keys[axisName];
36
+ const prev = axis.current;
37
+ const prevTime = info.time;
38
+ axis.current = element["scroll" + position];
39
+ axis.scrollLength = element["scroll" + length] - element["client" + length];
40
+ axis.offset.length = 0;
41
+ axis.offset[0] = 0;
42
+ axis.offset[1] = axis.scrollLength;
43
+ axis.progress = progress(0, axis.scrollLength, axis.current);
44
+ const elapsed = time - prevTime;
45
+ axis.velocity =
46
+ elapsed > maxElapsed
47
+ ? 0
48
+ : velocityPerSecond(axis.current - prev, elapsed);
49
+ }
50
+ function updateScrollInfo(element, info, time) {
51
+ updateAxisInfo(element, "x", info, time);
52
+ updateAxisInfo(element, "y", info, time);
53
+ info.time = time;
54
+ }
55
+
56
+ export { createScrollInfo, updateScrollInfo };
@@ -0,0 +1,45 @@
1
+ const namedEdges = {
2
+ start: 0,
3
+ center: 0.5,
4
+ end: 1,
5
+ };
6
+ function resolveEdge(edge, length, inset = 0) {
7
+ let delta = 0;
8
+ /**
9
+ * If we have this edge defined as a preset, replace the definition
10
+ * with the numerical value.
11
+ */
12
+ if (namedEdges[edge] !== undefined) {
13
+ edge = namedEdges[edge];
14
+ }
15
+ /**
16
+ * Handle unit values
17
+ */
18
+ if (typeof edge === "string") {
19
+ const asNumber = parseFloat(edge);
20
+ if (edge.endsWith("px")) {
21
+ delta = asNumber;
22
+ }
23
+ else if (edge.endsWith("%")) {
24
+ edge = asNumber / 100;
25
+ }
26
+ else if (edge.endsWith("vw")) {
27
+ delta = (asNumber / 100) * document.documentElement.clientWidth;
28
+ }
29
+ else if (edge.endsWith("vh")) {
30
+ delta = (asNumber / 100) * document.documentElement.clientHeight;
31
+ }
32
+ else {
33
+ edge = asNumber;
34
+ }
35
+ }
36
+ /**
37
+ * If the edge is defined as a number, handle as a progress value.
38
+ */
39
+ if (typeof edge === "number") {
40
+ delta = length * edge;
41
+ }
42
+ return inset + delta;
43
+ }
44
+
45
+ export { namedEdges, resolveEdge };
@@ -0,0 +1,54 @@
1
+ import { calcInset } from './inset.mjs';
2
+ import { ScrollOffset } from './presets.mjs';
3
+ import { resolveOffset } from './offset.mjs';
4
+ import { interpolate } from '../../../../utils/interpolate.mjs';
5
+ import { defaultOffset } from '../../../../utils/offsets/default.mjs';
6
+
7
+ const point = { x: 0, y: 0 };
8
+ function resolveOffsets(container, info, options) {
9
+ let { offset: offsetDefinition = ScrollOffset.All } = options;
10
+ const { target = container, axis = "y" } = options;
11
+ const lengthLabel = axis === "y" ? "height" : "width";
12
+ const inset = target !== container ? calcInset(target, container) : point;
13
+ /**
14
+ * Measure the target and container. If they're the same thing then we
15
+ * use the container's scrollWidth/Height as the target, from there
16
+ * all other calculations can remain the same.
17
+ */
18
+ const targetSize = target === container
19
+ ? { width: container.scrollWidth, height: container.scrollHeight }
20
+ : { width: target.clientWidth, height: target.clientHeight };
21
+ const containerSize = {
22
+ width: container.clientWidth,
23
+ height: container.clientHeight,
24
+ };
25
+ /**
26
+ * Reset the length of the resolved offset array rather than creating a new one.
27
+ * TODO: More reusable data structures for targetSize/containerSize would also be good.
28
+ */
29
+ info[axis].offset.length = 0;
30
+ /**
31
+ * Populate the offset array by resolving the user's offset definition into
32
+ * a list of pixel scroll offets.
33
+ */
34
+ let hasChanged = !info[axis].interpolate;
35
+ const numOffsets = offsetDefinition.length;
36
+ for (let i = 0; i < numOffsets; i++) {
37
+ const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
38
+ if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
39
+ hasChanged = true;
40
+ }
41
+ info[axis].offset[i] = offset;
42
+ }
43
+ /**
44
+ * If the pixel scroll offsets have changed, create a new interpolator function
45
+ * to map scroll value into a progress.
46
+ */
47
+ if (hasChanged) {
48
+ info[axis].interpolate = interpolate(info[axis].offset, defaultOffset(offsetDefinition));
49
+ info[axis].interpolatorOffsets = [...info[axis].offset];
50
+ }
51
+ info[axis].progress = info[axis].interpolate(info[axis].current);
52
+ }
53
+
54
+ export { resolveOffsets };
@@ -0,0 +1,25 @@
1
+ function calcInset(element, container) {
2
+ let inset = { x: 0, y: 0 };
3
+ let current = element;
4
+ while (current && current !== container) {
5
+ if (current instanceof HTMLElement) {
6
+ inset.x += current.offsetLeft;
7
+ inset.y += current.offsetTop;
8
+ current = current.offsetParent;
9
+ }
10
+ else if (current instanceof SVGGraphicsElement && "getBBox" in current) {
11
+ const { top, left } = current.getBBox();
12
+ inset.x += left;
13
+ inset.y += top;
14
+ /**
15
+ * Assign the next parent element as the <svg /> tag.
16
+ */
17
+ while (current && current.tagName !== "svg") {
18
+ current = current.parentNode;
19
+ }
20
+ }
21
+ }
22
+ return inset;
23
+ }
24
+
25
+ export { calcInset };