motion 12.4.3 → 12.4.4

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.
@@ -319,7 +319,7 @@ function isDragActive() {
319
319
 
320
320
  function resolveElements(elementOrSelector, scope, selectorCache) {
321
321
  var _a;
322
- if (elementOrSelector instanceof Element) {
322
+ if (elementOrSelector instanceof EventTarget) {
323
323
  return [elementOrSelector];
324
324
  }
325
325
  else if (typeof elementOrSelector === "string") {
@@ -494,46 +494,87 @@ function isValidPressEvent(event) {
494
494
  *
495
495
  * @public
496
496
  */
497
- function press(elementOrSelector, onPressStart, options = {}) {
498
- const [elements, eventOptions, cancelEvents] = setupGesture(elementOrSelector, options);
497
+ function press(targetOrSelector, onPressStart, options = {}) {
498
+ const [targets, eventOptions, cancelEvents] = setupGesture(targetOrSelector, options);
499
499
  const startPress = (startEvent) => {
500
- const element = startEvent.currentTarget;
501
- if (!isValidPressEvent(startEvent) || isPressing.has(element))
500
+ const target = startEvent.currentTarget;
501
+ if (!target || !isValidPressEvent(startEvent) || isPressing.has(target))
502
502
  return;
503
- isPressing.add(element);
504
- const onPressEnd = onPressStart(element, startEvent);
503
+ isPressing.add(target);
504
+ if (target.setPointerCapture && startEvent.pointerId !== undefined) {
505
+ try {
506
+ target.setPointerCapture(startEvent.pointerId);
507
+ }
508
+ catch (e) { }
509
+ }
510
+ const onPressEnd = onPressStart(target, startEvent);
505
511
  const onPointerEnd = (endEvent, success) => {
506
- window.removeEventListener("pointerup", onPointerUp);
507
- window.removeEventListener("pointercancel", onPointerCancel);
508
- if (!isValidPressEvent(endEvent) || !isPressing.has(element)) {
512
+ target.removeEventListener("pointerup", onPointerUp);
513
+ target.removeEventListener("pointercancel", onPointerCancel);
514
+ if (target.releasePointerCapture &&
515
+ endEvent.pointerId !== undefined) {
516
+ try {
517
+ target.releasePointerCapture(endEvent.pointerId);
518
+ }
519
+ catch (e) { }
520
+ }
521
+ if (!isValidPressEvent(endEvent) || !isPressing.has(target)) {
509
522
  return;
510
523
  }
511
- isPressing.delete(element);
524
+ isPressing.delete(target);
512
525
  if (typeof onPressEnd === "function") {
513
526
  onPressEnd(endEvent, { success });
514
527
  }
515
528
  };
516
529
  const onPointerUp = (upEvent) => {
517
- onPointerEnd(upEvent, options.useGlobalTarget ||
518
- isNodeOrChild(element, upEvent.target));
530
+ const isOutside = !upEvent.isTrusted
531
+ ? false
532
+ : checkOutside(upEvent, target instanceof Element
533
+ ? target.getBoundingClientRect()
534
+ : {
535
+ left: 0,
536
+ top: 0,
537
+ right: window.innerWidth,
538
+ bottom: window.innerHeight,
539
+ });
540
+ if (isOutside) {
541
+ onPointerEnd(upEvent, false);
542
+ }
543
+ else {
544
+ onPointerEnd(upEvent, !(target instanceof Element) ||
545
+ isNodeOrChild(target, upEvent.target));
546
+ }
519
547
  };
520
548
  const onPointerCancel = (cancelEvent) => {
521
549
  onPointerEnd(cancelEvent, false);
522
550
  };
523
- window.addEventListener("pointerup", onPointerUp, eventOptions);
524
- window.addEventListener("pointercancel", onPointerCancel, eventOptions);
551
+ target.addEventListener("pointerup", onPointerUp, eventOptions);
552
+ target.addEventListener("pointercancel", onPointerCancel, eventOptions);
553
+ target.addEventListener("lostpointercapture", onPointerCancel, eventOptions);
525
554
  };
526
- elements.forEach((element) => {
527
- if (!isElementKeyboardAccessible(element) &&
528
- element.getAttribute("tabindex") === null) {
529
- element.tabIndex = 0;
555
+ targets.forEach((target) => {
556
+ target = options.useGlobalTarget ? window : target;
557
+ let canAddKeyboardAccessibility = false;
558
+ if (target instanceof HTMLElement) {
559
+ canAddKeyboardAccessibility = true;
560
+ if (!isElementKeyboardAccessible(target) &&
561
+ target.getAttribute("tabindex") === null) {
562
+ target.tabIndex = 0;
563
+ }
530
564
  }
531
- const target = options.useGlobalTarget ? window : element;
532
565
  target.addEventListener("pointerdown", startPress, eventOptions);
533
- element.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions), eventOptions);
566
+ if (canAddKeyboardAccessibility) {
567
+ target.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions), eventOptions);
568
+ }
534
569
  });
535
570
  return cancelEvents;
536
571
  }
572
+ function checkOutside(event, rect) {
573
+ return (event.clientX < rect.left ||
574
+ event.clientX > rect.right ||
575
+ event.clientY < rect.top ||
576
+ event.clientY > rect.bottom);
577
+ }
537
578
 
538
579
  function setDragLock(axis) {
539
580
  if (axis === "x" || axis === "y") {
@@ -902,7 +943,7 @@ class MotionValue {
902
943
  * This will be replaced by the build step with the latest version number.
903
944
  * When MotionValues are provided to motion components, warn if versions are mixed.
904
945
  */
905
- this.version = "12.4.3";
946
+ this.version = "12.4.4";
906
947
  /**
907
948
  * Tracks whether this value can output a velocity. Currently this is only true
908
949
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -4586,165 +4627,36 @@ function addPointerEvent(target, eventName, handler, options) {
4586
4627
  return addDomEvent(target, eventName, addPointerInfo(handler), options);
4587
4628
  }
4588
4629
 
4589
- const distance = (a, b) => Math.abs(a - b);
4590
- function distance2D(a, b) {
4591
- // Multi-dimensional
4592
- const xDelta = distance(a.x, b.x);
4593
- const yDelta = distance(a.y, b.y);
4594
- return Math.sqrt(xDelta ** 2 + yDelta ** 2);
4595
- }
4596
-
4597
4630
  /**
4598
- * @internal
4631
+ * Bounding boxes tend to be defined as top, left, right, bottom. For various operations
4632
+ * it's easier to consider each axis individually. This function returns a bounding box
4633
+ * as a map of single-axis min/max values.
4599
4634
  */
4600
- class PanSession {
4601
- constructor(event, handlers, { transformPagePoint, contextWindow, dragSnapToOrigin = false, } = {}) {
4602
- /**
4603
- * @internal
4604
- */
4605
- this.startEvent = null;
4606
- /**
4607
- * @internal
4608
- */
4609
- this.lastMoveEvent = null;
4610
- /**
4611
- * @internal
4612
- */
4613
- this.lastMoveEventInfo = null;
4614
- /**
4615
- * @internal
4616
- */
4617
- this.handlers = {};
4618
- /**
4619
- * @internal
4620
- */
4621
- this.contextWindow = window;
4622
- this.updatePoint = () => {
4623
- if (!(this.lastMoveEvent && this.lastMoveEventInfo))
4624
- return;
4625
- const info = getPanInfo(this.lastMoveEventInfo, this.history);
4626
- const isPanStarted = this.startEvent !== null;
4627
- // Only start panning if the offset is larger than 3 pixels. If we make it
4628
- // any larger than this we'll want to reset the pointer history
4629
- // on the first update to avoid visual snapping to the cursoe.
4630
- const isDistancePastThreshold = distance2D(info.offset, { x: 0, y: 0 }) >= 3;
4631
- if (!isPanStarted && !isDistancePastThreshold)
4632
- return;
4633
- const { point } = info;
4634
- const { timestamp } = frameData;
4635
- this.history.push({ ...point, timestamp });
4636
- const { onStart, onMove } = this.handlers;
4637
- if (!isPanStarted) {
4638
- onStart && onStart(this.lastMoveEvent, info);
4639
- this.startEvent = this.lastMoveEvent;
4640
- }
4641
- onMove && onMove(this.lastMoveEvent, info);
4642
- };
4643
- this.handlePointerMove = (event, info) => {
4644
- this.lastMoveEvent = event;
4645
- this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint);
4646
- // Throttle mouse move event to once per frame
4647
- frame.update(this.updatePoint, true);
4648
- };
4649
- this.handlePointerUp = (event, info) => {
4650
- this.end();
4651
- const { onEnd, onSessionEnd, resumeAnimation } = this.handlers;
4652
- if (this.dragSnapToOrigin)
4653
- resumeAnimation && resumeAnimation();
4654
- if (!(this.lastMoveEvent && this.lastMoveEventInfo))
4655
- return;
4656
- const panInfo = getPanInfo(event.type === "pointercancel"
4657
- ? this.lastMoveEventInfo
4658
- : transformPoint(info, this.transformPagePoint), this.history);
4659
- if (this.startEvent && onEnd) {
4660
- onEnd(event, panInfo);
4661
- }
4662
- onSessionEnd && onSessionEnd(event, panInfo);
4663
- };
4664
- // If we have more than one touch, don't start detecting this gesture
4665
- if (!isPrimaryPointer(event))
4666
- return;
4667
- this.dragSnapToOrigin = dragSnapToOrigin;
4668
- this.handlers = handlers;
4669
- this.transformPagePoint = transformPagePoint;
4670
- this.contextWindow = contextWindow || window;
4671
- const info = extractEventInfo(event);
4672
- const initialInfo = transformPoint(info, this.transformPagePoint);
4673
- const { point } = initialInfo;
4674
- const { timestamp } = frameData;
4675
- this.history = [{ ...point, timestamp }];
4676
- const { onSessionStart } = handlers;
4677
- onSessionStart &&
4678
- onSessionStart(event, getPanInfo(initialInfo, this.history));
4679
- this.removeListeners = pipe(addPointerEvent(this.contextWindow, "pointermove", this.handlePointerMove), addPointerEvent(this.contextWindow, "pointerup", this.handlePointerUp), addPointerEvent(this.contextWindow, "pointercancel", this.handlePointerUp));
4680
- }
4681
- updateHandlers(handlers) {
4682
- this.handlers = handlers;
4683
- }
4684
- end() {
4685
- this.removeListeners && this.removeListeners();
4686
- cancelFrame(this.updatePoint);
4687
- }
4688
- }
4689
- function transformPoint(info, transformPagePoint) {
4690
- return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
4691
- }
4692
- function subtractPoint(a, b) {
4693
- return { x: a.x - b.x, y: a.y - b.y };
4694
- }
4695
- function getPanInfo({ point }, history) {
4635
+ function convertBoundingBoxToBox({ top, left, right, bottom, }) {
4696
4636
  return {
4697
- point,
4698
- delta: subtractPoint(point, lastDevicePoint(history)),
4699
- offset: subtractPoint(point, startDevicePoint(history)),
4700
- velocity: getVelocity(history, 0.1),
4637
+ x: { min: left, max: right },
4638
+ y: { min: top, max: bottom },
4701
4639
  };
4702
4640
  }
4703
- function startDevicePoint(history) {
4704
- return history[0];
4705
- }
4706
- function lastDevicePoint(history) {
4707
- return history[history.length - 1];
4641
+ function convertBoxToBoundingBox({ x, y }) {
4642
+ return { top: y.min, right: x.max, bottom: y.max, left: x.min };
4708
4643
  }
4709
- function getVelocity(history, timeDelta) {
4710
- if (history.length < 2) {
4711
- return { x: 0, y: 0 };
4712
- }
4713
- let i = history.length - 1;
4714
- let timestampedPoint = null;
4715
- const lastPoint = lastDevicePoint(history);
4716
- while (i >= 0) {
4717
- timestampedPoint = history[i];
4718
- if (lastPoint.timestamp - timestampedPoint.timestamp >
4719
- secondsToMilliseconds(timeDelta)) {
4720
- break;
4721
- }
4722
- i--;
4723
- }
4724
- if (!timestampedPoint) {
4725
- return { x: 0, y: 0 };
4726
- }
4727
- const time = millisecondsToSeconds(lastPoint.timestamp - timestampedPoint.timestamp);
4728
- if (time === 0) {
4729
- return { x: 0, y: 0 };
4730
- }
4731
- const currentVelocity = {
4732
- x: (lastPoint.x - timestampedPoint.x) / time,
4733
- y: (lastPoint.y - timestampedPoint.y) / time,
4644
+ /**
4645
+ * Applies a TransformPoint function to a bounding box. TransformPoint is usually a function
4646
+ * provided by Framer to allow measured points to be corrected for device scaling. This is used
4647
+ * when measuring DOM elements and DOM event points.
4648
+ */
4649
+ function transformBoxPoints(point, transformPoint) {
4650
+ if (!transformPoint)
4651
+ return point;
4652
+ const topLeft = transformPoint({ x: point.left, y: point.top });
4653
+ const bottomRight = transformPoint({ x: point.right, y: point.bottom });
4654
+ return {
4655
+ top: topLeft.y,
4656
+ left: topLeft.x,
4657
+ bottom: bottomRight.y,
4658
+ right: bottomRight.x,
4734
4659
  };
4735
- if (currentVelocity.x === Infinity) {
4736
- currentVelocity.x = 0;
4737
- }
4738
- if (currentVelocity.y === Infinity) {
4739
- currentVelocity.y = 0;
4740
- }
4741
- return currentVelocity;
4742
- }
4743
-
4744
- function isRefObject(ref) {
4745
- return (ref &&
4746
- typeof ref === "object" &&
4747
- Object.prototype.hasOwnProperty.call(ref, "current"));
4748
4660
  }
4749
4661
 
4750
4662
  const SCALE_PRECISION = 0.0001;
@@ -4796,216 +4708,61 @@ function calcRelativePosition(target, layout, parent) {
4796
4708
  calcRelativeAxisPosition(target.y, layout.y, parent.y);
4797
4709
  }
4798
4710
 
4711
+ const createAxisDelta = () => ({
4712
+ translate: 0,
4713
+ scale: 1,
4714
+ origin: 0,
4715
+ originPoint: 0,
4716
+ });
4717
+ const createDelta = () => ({
4718
+ x: createAxisDelta(),
4719
+ y: createAxisDelta(),
4720
+ });
4721
+ const createAxis = () => ({ min: 0, max: 0 });
4722
+ const createBox = () => ({
4723
+ x: createAxis(),
4724
+ y: createAxis(),
4725
+ });
4726
+
4727
+ function eachAxis(callback) {
4728
+ return [callback("x"), callback("y")];
4729
+ }
4730
+
4731
+ function isIdentityScale(scale) {
4732
+ return scale === undefined || scale === 1;
4733
+ }
4734
+ function hasScale({ scale, scaleX, scaleY }) {
4735
+ return (!isIdentityScale(scale) ||
4736
+ !isIdentityScale(scaleX) ||
4737
+ !isIdentityScale(scaleY));
4738
+ }
4739
+ function hasTransform(values) {
4740
+ return (hasScale(values) ||
4741
+ has2DTranslate(values) ||
4742
+ values.z ||
4743
+ values.rotate ||
4744
+ values.rotateX ||
4745
+ values.rotateY ||
4746
+ values.skewX ||
4747
+ values.skewY);
4748
+ }
4749
+ function has2DTranslate(values) {
4750
+ return is2DTranslate(values.x) || is2DTranslate(values.y);
4751
+ }
4752
+ function is2DTranslate(value) {
4753
+ return value && value !== "0%";
4754
+ }
4755
+
4799
4756
  /**
4800
- * Apply constraints to a point. These constraints are both physical along an
4801
- * axis, and an elastic factor that determines how much to constrain the point
4802
- * by if it does lie outside the defined parameters.
4757
+ * Scales a point based on a factor and an originPoint
4803
4758
  */
4804
- function applyConstraints(point, { min, max }, elastic) {
4805
- if (min !== undefined && point < min) {
4806
- // If we have a min point defined, and this is outside of that, constrain
4807
- point = elastic
4808
- ? mixNumber$1(min, point, elastic.min)
4809
- : Math.max(point, min);
4810
- }
4811
- else if (max !== undefined && point > max) {
4812
- // If we have a max point defined, and this is outside of that, constrain
4813
- point = elastic
4814
- ? mixNumber$1(max, point, elastic.max)
4815
- : Math.min(point, max);
4816
- }
4817
- return point;
4759
+ function scalePoint(point, scale, originPoint) {
4760
+ const distanceFromOrigin = point - originPoint;
4761
+ const scaled = scale * distanceFromOrigin;
4762
+ return originPoint + scaled;
4818
4763
  }
4819
4764
  /**
4820
- * Calculate constraints in terms of the viewport when defined relatively to the
4821
- * measured axis. This is measured from the nearest edge, so a max constraint of 200
4822
- * on an axis with a max value of 300 would return a constraint of 500 - axis length
4823
- */
4824
- function calcRelativeAxisConstraints(axis, min, max) {
4825
- return {
4826
- min: min !== undefined ? axis.min + min : undefined,
4827
- max: max !== undefined
4828
- ? axis.max + max - (axis.max - axis.min)
4829
- : undefined,
4830
- };
4831
- }
4832
- /**
4833
- * Calculate constraints in terms of the viewport when
4834
- * defined relatively to the measured bounding box.
4835
- */
4836
- function calcRelativeConstraints(layoutBox, { top, left, bottom, right }) {
4837
- return {
4838
- x: calcRelativeAxisConstraints(layoutBox.x, left, right),
4839
- y: calcRelativeAxisConstraints(layoutBox.y, top, bottom),
4840
- };
4841
- }
4842
- /**
4843
- * Calculate viewport constraints when defined as another viewport-relative axis
4844
- */
4845
- function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
4846
- let min = constraintsAxis.min - layoutAxis.min;
4847
- let max = constraintsAxis.max - layoutAxis.max;
4848
- // If the constraints axis is actually smaller than the layout axis then we can
4849
- // flip the constraints
4850
- if (constraintsAxis.max - constraintsAxis.min <
4851
- layoutAxis.max - layoutAxis.min) {
4852
- [min, max] = [max, min];
4853
- }
4854
- return { min, max };
4855
- }
4856
- /**
4857
- * Calculate viewport constraints when defined as another viewport-relative box
4858
- */
4859
- function calcViewportConstraints(layoutBox, constraintsBox) {
4860
- return {
4861
- x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
4862
- y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y),
4863
- };
4864
- }
4865
- /**
4866
- * Calculate a transform origin relative to the source axis, between 0-1, that results
4867
- * in an asthetically pleasing scale/transform needed to project from source to target.
4868
- */
4869
- function calcOrigin$1(source, target) {
4870
- let origin = 0.5;
4871
- const sourceLength = calcLength(source);
4872
- const targetLength = calcLength(target);
4873
- if (targetLength > sourceLength) {
4874
- origin = progress(target.min, target.max - sourceLength, source.min);
4875
- }
4876
- else if (sourceLength > targetLength) {
4877
- origin = progress(source.min, source.max - targetLength, target.min);
4878
- }
4879
- return clamp(0, 1, origin);
4880
- }
4881
- /**
4882
- * Rebase the calculated viewport constraints relative to the layout.min point.
4883
- */
4884
- function rebaseAxisConstraints(layout, constraints) {
4885
- const relativeConstraints = {};
4886
- if (constraints.min !== undefined) {
4887
- relativeConstraints.min = constraints.min - layout.min;
4888
- }
4889
- if (constraints.max !== undefined) {
4890
- relativeConstraints.max = constraints.max - layout.min;
4891
- }
4892
- return relativeConstraints;
4893
- }
4894
- const defaultElastic = 0.35;
4895
- /**
4896
- * Accepts a dragElastic prop and returns resolved elastic values for each axis.
4897
- */
4898
- function resolveDragElastic(dragElastic = defaultElastic) {
4899
- if (dragElastic === false) {
4900
- dragElastic = 0;
4901
- }
4902
- else if (dragElastic === true) {
4903
- dragElastic = defaultElastic;
4904
- }
4905
- return {
4906
- x: resolveAxisElastic(dragElastic, "left", "right"),
4907
- y: resolveAxisElastic(dragElastic, "top", "bottom"),
4908
- };
4909
- }
4910
- function resolveAxisElastic(dragElastic, minLabel, maxLabel) {
4911
- return {
4912
- min: resolvePointElastic(dragElastic, minLabel),
4913
- max: resolvePointElastic(dragElastic, maxLabel),
4914
- };
4915
- }
4916
- function resolvePointElastic(dragElastic, label) {
4917
- return typeof dragElastic === "number"
4918
- ? dragElastic
4919
- : dragElastic[label] || 0;
4920
- }
4921
-
4922
- const createAxisDelta = () => ({
4923
- translate: 0,
4924
- scale: 1,
4925
- origin: 0,
4926
- originPoint: 0,
4927
- });
4928
- const createDelta = () => ({
4929
- x: createAxisDelta(),
4930
- y: createAxisDelta(),
4931
- });
4932
- const createAxis = () => ({ min: 0, max: 0 });
4933
- const createBox = () => ({
4934
- x: createAxis(),
4935
- y: createAxis(),
4936
- });
4937
-
4938
- function eachAxis(callback) {
4939
- return [callback("x"), callback("y")];
4940
- }
4941
-
4942
- /**
4943
- * Bounding boxes tend to be defined as top, left, right, bottom. For various operations
4944
- * it's easier to consider each axis individually. This function returns a bounding box
4945
- * as a map of single-axis min/max values.
4946
- */
4947
- function convertBoundingBoxToBox({ top, left, right, bottom, }) {
4948
- return {
4949
- x: { min: left, max: right },
4950
- y: { min: top, max: bottom },
4951
- };
4952
- }
4953
- function convertBoxToBoundingBox({ x, y }) {
4954
- return { top: y.min, right: x.max, bottom: y.max, left: x.min };
4955
- }
4956
- /**
4957
- * Applies a TransformPoint function to a bounding box. TransformPoint is usually a function
4958
- * provided by Framer to allow measured points to be corrected for device scaling. This is used
4959
- * when measuring DOM elements and DOM event points.
4960
- */
4961
- function transformBoxPoints(point, transformPoint) {
4962
- if (!transformPoint)
4963
- return point;
4964
- const topLeft = transformPoint({ x: point.left, y: point.top });
4965
- const bottomRight = transformPoint({ x: point.right, y: point.bottom });
4966
- return {
4967
- top: topLeft.y,
4968
- left: topLeft.x,
4969
- bottom: bottomRight.y,
4970
- right: bottomRight.x,
4971
- };
4972
- }
4973
-
4974
- function isIdentityScale(scale) {
4975
- return scale === undefined || scale === 1;
4976
- }
4977
- function hasScale({ scale, scaleX, scaleY }) {
4978
- return (!isIdentityScale(scale) ||
4979
- !isIdentityScale(scaleX) ||
4980
- !isIdentityScale(scaleY));
4981
- }
4982
- function hasTransform(values) {
4983
- return (hasScale(values) ||
4984
- has2DTranslate(values) ||
4985
- values.z ||
4986
- values.rotate ||
4987
- values.rotateX ||
4988
- values.rotateY ||
4989
- values.skewX ||
4990
- values.skewY);
4991
- }
4992
- function has2DTranslate(values) {
4993
- return is2DTranslate(values.x) || is2DTranslate(values.y);
4994
- }
4995
- function is2DTranslate(value) {
4996
- return value && value !== "0%";
4997
- }
4998
-
4999
- /**
5000
- * Scales a point based on a factor and an originPoint
5001
- */
5002
- function scalePoint(point, scale, originPoint) {
5003
- const distanceFromOrigin = point - originPoint;
5004
- const scaled = scale * distanceFromOrigin;
5005
- return originPoint + scaled;
5006
- }
5007
- /**
5008
- * Applies a translate/scale delta to a point
4765
+ * Applies a translate/scale delta to a point
5009
4766
  */
5010
4767
  function applyPointDelta(point, translate, scale, originPoint, boxScale) {
5011
4768
  if (boxScale !== undefined) {
@@ -5124,10 +4881,308 @@ function measurePageBox(element, rootProjectionNode, transformPagePoint) {
5124
4881
  return viewportBox;
5125
4882
  }
5126
4883
 
5127
- // Fixes https://github.com/motiondivision/motion/issues/2270
5128
- const getContextWindow = ({ current }) => {
5129
- return current ? current.ownerDocument.defaultView : null;
5130
- };
4884
+ function isRefObject(ref) {
4885
+ return (ref &&
4886
+ typeof ref === "object" &&
4887
+ Object.prototype.hasOwnProperty.call(ref, "current"));
4888
+ }
4889
+
4890
+ const distance = (a, b) => Math.abs(a - b);
4891
+ function distance2D(a, b) {
4892
+ // Multi-dimensional
4893
+ const xDelta = distance(a.x, b.x);
4894
+ const yDelta = distance(a.y, b.y);
4895
+ return Math.sqrt(xDelta ** 2 + yDelta ** 2);
4896
+ }
4897
+
4898
+ /**
4899
+ * @internal
4900
+ */
4901
+ class PanSession {
4902
+ constructor(event, handlers, { transformPagePoint, dragSnapToOrigin = false } = {}) {
4903
+ /**
4904
+ * @internal
4905
+ */
4906
+ this.startEvent = null;
4907
+ /**
4908
+ * @internal
4909
+ */
4910
+ this.lastMoveEvent = null;
4911
+ /**
4912
+ * @internal
4913
+ */
4914
+ this.lastMoveEventInfo = null;
4915
+ /**
4916
+ * @internal
4917
+ */
4918
+ this.handlers = {};
4919
+ this.updatePoint = () => {
4920
+ if (!(this.lastMoveEvent && this.lastMoveEventInfo))
4921
+ return;
4922
+ const info = getPanInfo(this.lastMoveEventInfo, this.history);
4923
+ const isPanStarted = this.startEvent !== null;
4924
+ // Only start panning if the offset is larger than 3 pixels. If we make it
4925
+ // any larger than this we'll want to reset the pointer history
4926
+ // on the first update to avoid visual snapping to the cursoe.
4927
+ const isDistancePastThreshold = distance2D(info.offset, { x: 0, y: 0 }) >= 3;
4928
+ if (!isPanStarted && !isDistancePastThreshold)
4929
+ return;
4930
+ const { point } = info;
4931
+ const { timestamp } = frameData;
4932
+ this.history.push({ ...point, timestamp });
4933
+ const { onStart, onMove } = this.handlers;
4934
+ if (!isPanStarted) {
4935
+ onStart && onStart(this.lastMoveEvent, info);
4936
+ this.startEvent = this.lastMoveEvent;
4937
+ }
4938
+ onMove && onMove(this.lastMoveEvent, info);
4939
+ };
4940
+ this.handlePointerMove = (event, info) => {
4941
+ if (event.currentTarget instanceof Element &&
4942
+ event.currentTarget.hasPointerCapture &&
4943
+ event.pointerId !== undefined) {
4944
+ try {
4945
+ if (!event.currentTarget.hasPointerCapture(event.pointerId)) {
4946
+ return;
4947
+ }
4948
+ }
4949
+ catch (e) { }
4950
+ }
4951
+ this.lastMoveEvent = event;
4952
+ this.lastMoveEventInfo = transformPoint(info, this.transformPagePoint);
4953
+ // Throttle mouse move event to once per frame
4954
+ frame.update(this.updatePoint, true);
4955
+ };
4956
+ this.handlePointerUp = (event, info) => {
4957
+ capturePointer(event, "release");
4958
+ this.end();
4959
+ const { onEnd, onSessionEnd, resumeAnimation } = this.handlers;
4960
+ if (this.dragSnapToOrigin)
4961
+ resumeAnimation && resumeAnimation();
4962
+ if (!(this.lastMoveEvent && this.lastMoveEventInfo))
4963
+ return;
4964
+ const panInfo = getPanInfo(event.type === "pointercancel" ||
4965
+ event.type === "lostpointercapture"
4966
+ ? this.lastMoveEventInfo
4967
+ : transformPoint(info, this.transformPagePoint), this.history);
4968
+ if (this.startEvent && onEnd) {
4969
+ onEnd(event, panInfo);
4970
+ }
4971
+ onSessionEnd && onSessionEnd(event, panInfo);
4972
+ };
4973
+ // If we have more than one touch, don't start detecting this gesture
4974
+ if (!isPrimaryPointer(event))
4975
+ return;
4976
+ this.dragSnapToOrigin = dragSnapToOrigin;
4977
+ this.handlers = handlers;
4978
+ this.transformPagePoint = transformPagePoint;
4979
+ const info = extractEventInfo(event);
4980
+ const initialInfo = transformPoint(info, this.transformPagePoint);
4981
+ const { point } = initialInfo;
4982
+ const { timestamp } = frameData;
4983
+ this.history = [{ ...point, timestamp }];
4984
+ const { onSessionStart } = handlers;
4985
+ onSessionStart &&
4986
+ onSessionStart(event, getPanInfo(initialInfo, this.history));
4987
+ capturePointer(event, "set");
4988
+ this.removeListeners = pipe(addPointerEvent(event.currentTarget, "pointermove", this.handlePointerMove), addPointerEvent(event.currentTarget, "pointerup", this.handlePointerUp), addPointerEvent(event.currentTarget, "pointercancel", this.handlePointerUp), addPointerEvent(event.currentTarget, "lostpointercapture", this.handlePointerUp));
4989
+ }
4990
+ updateHandlers(handlers) {
4991
+ this.handlers = handlers;
4992
+ }
4993
+ end() {
4994
+ this.removeListeners && this.removeListeners();
4995
+ cancelFrame(this.updatePoint);
4996
+ }
4997
+ }
4998
+ function transformPoint(info, transformPagePoint) {
4999
+ return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
5000
+ }
5001
+ function subtractPoint(a, b) {
5002
+ return { x: a.x - b.x, y: a.y - b.y };
5003
+ }
5004
+ function getPanInfo({ point }, history) {
5005
+ return {
5006
+ point,
5007
+ delta: subtractPoint(point, lastDevicePoint(history)),
5008
+ offset: subtractPoint(point, startDevicePoint(history)),
5009
+ velocity: getVelocity(history, 0.1),
5010
+ };
5011
+ }
5012
+ function startDevicePoint(history) {
5013
+ return history[0];
5014
+ }
5015
+ function lastDevicePoint(history) {
5016
+ return history[history.length - 1];
5017
+ }
5018
+ function getVelocity(history, timeDelta) {
5019
+ if (history.length < 2) {
5020
+ return { x: 0, y: 0 };
5021
+ }
5022
+ let i = history.length - 1;
5023
+ let timestampedPoint = null;
5024
+ const lastPoint = lastDevicePoint(history);
5025
+ while (i >= 0) {
5026
+ timestampedPoint = history[i];
5027
+ if (lastPoint.timestamp - timestampedPoint.timestamp >
5028
+ secondsToMilliseconds(timeDelta)) {
5029
+ break;
5030
+ }
5031
+ i--;
5032
+ }
5033
+ if (!timestampedPoint) {
5034
+ return { x: 0, y: 0 };
5035
+ }
5036
+ const time = millisecondsToSeconds(lastPoint.timestamp - timestampedPoint.timestamp);
5037
+ if (time === 0) {
5038
+ return { x: 0, y: 0 };
5039
+ }
5040
+ const currentVelocity = {
5041
+ x: (lastPoint.x - timestampedPoint.x) / time,
5042
+ y: (lastPoint.y - timestampedPoint.y) / time,
5043
+ };
5044
+ if (currentVelocity.x === Infinity) {
5045
+ currentVelocity.x = 0;
5046
+ }
5047
+ if (currentVelocity.y === Infinity) {
5048
+ currentVelocity.y = 0;
5049
+ }
5050
+ return currentVelocity;
5051
+ }
5052
+ function capturePointer(event, action) {
5053
+ const actionName = `${action}PointerCapture`;
5054
+ if (event.currentTarget instanceof Element &&
5055
+ actionName in event.currentTarget &&
5056
+ event.pointerId !== undefined) {
5057
+ try {
5058
+ event.currentTarget[actionName](event.pointerId);
5059
+ }
5060
+ catch (e) { }
5061
+ }
5062
+ }
5063
+
5064
+ /**
5065
+ * Apply constraints to a point. These constraints are both physical along an
5066
+ * axis, and an elastic factor that determines how much to constrain the point
5067
+ * by if it does lie outside the defined parameters.
5068
+ */
5069
+ function applyConstraints(point, { min, max }, elastic) {
5070
+ if (min !== undefined && point < min) {
5071
+ // If we have a min point defined, and this is outside of that, constrain
5072
+ point = elastic
5073
+ ? mixNumber$1(min, point, elastic.min)
5074
+ : Math.max(point, min);
5075
+ }
5076
+ else if (max !== undefined && point > max) {
5077
+ // If we have a max point defined, and this is outside of that, constrain
5078
+ point = elastic
5079
+ ? mixNumber$1(max, point, elastic.max)
5080
+ : Math.min(point, max);
5081
+ }
5082
+ return point;
5083
+ }
5084
+ /**
5085
+ * Calculate constraints in terms of the viewport when defined relatively to the
5086
+ * measured axis. This is measured from the nearest edge, so a max constraint of 200
5087
+ * on an axis with a max value of 300 would return a constraint of 500 - axis length
5088
+ */
5089
+ function calcRelativeAxisConstraints(axis, min, max) {
5090
+ return {
5091
+ min: min !== undefined ? axis.min + min : undefined,
5092
+ max: max !== undefined
5093
+ ? axis.max + max - (axis.max - axis.min)
5094
+ : undefined,
5095
+ };
5096
+ }
5097
+ /**
5098
+ * Calculate constraints in terms of the viewport when
5099
+ * defined relatively to the measured bounding box.
5100
+ */
5101
+ function calcRelativeConstraints(layoutBox, { top, left, bottom, right }) {
5102
+ return {
5103
+ x: calcRelativeAxisConstraints(layoutBox.x, left, right),
5104
+ y: calcRelativeAxisConstraints(layoutBox.y, top, bottom),
5105
+ };
5106
+ }
5107
+ /**
5108
+ * Calculate viewport constraints when defined as another viewport-relative axis
5109
+ */
5110
+ function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
5111
+ let min = constraintsAxis.min - layoutAxis.min;
5112
+ let max = constraintsAxis.max - layoutAxis.max;
5113
+ // If the constraints axis is actually smaller than the layout axis then we can
5114
+ // flip the constraints
5115
+ if (constraintsAxis.max - constraintsAxis.min <
5116
+ layoutAxis.max - layoutAxis.min) {
5117
+ [min, max] = [max, min];
5118
+ }
5119
+ return { min, max };
5120
+ }
5121
+ /**
5122
+ * Calculate viewport constraints when defined as another viewport-relative box
5123
+ */
5124
+ function calcViewportConstraints(layoutBox, constraintsBox) {
5125
+ return {
5126
+ x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
5127
+ y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y),
5128
+ };
5129
+ }
5130
+ /**
5131
+ * Calculate a transform origin relative to the source axis, between 0-1, that results
5132
+ * in an asthetically pleasing scale/transform needed to project from source to target.
5133
+ */
5134
+ function calcOrigin$1(source, target) {
5135
+ let origin = 0.5;
5136
+ const sourceLength = calcLength(source);
5137
+ const targetLength = calcLength(target);
5138
+ if (targetLength > sourceLength) {
5139
+ origin = progress(target.min, target.max - sourceLength, source.min);
5140
+ }
5141
+ else if (sourceLength > targetLength) {
5142
+ origin = progress(source.min, source.max - targetLength, target.min);
5143
+ }
5144
+ return clamp(0, 1, origin);
5145
+ }
5146
+ /**
5147
+ * Rebase the calculated viewport constraints relative to the layout.min point.
5148
+ */
5149
+ function rebaseAxisConstraints(layout, constraints) {
5150
+ const relativeConstraints = {};
5151
+ if (constraints.min !== undefined) {
5152
+ relativeConstraints.min = constraints.min - layout.min;
5153
+ }
5154
+ if (constraints.max !== undefined) {
5155
+ relativeConstraints.max = constraints.max - layout.min;
5156
+ }
5157
+ return relativeConstraints;
5158
+ }
5159
+ const defaultElastic = 0.35;
5160
+ /**
5161
+ * Accepts a dragElastic prop and returns resolved elastic values for each axis.
5162
+ */
5163
+ function resolveDragElastic(dragElastic = defaultElastic) {
5164
+ if (dragElastic === false) {
5165
+ dragElastic = 0;
5166
+ }
5167
+ else if (dragElastic === true) {
5168
+ dragElastic = defaultElastic;
5169
+ }
5170
+ return {
5171
+ x: resolveAxisElastic(dragElastic, "left", "right"),
5172
+ y: resolveAxisElastic(dragElastic, "top", "bottom"),
5173
+ };
5174
+ }
5175
+ function resolveAxisElastic(dragElastic, minLabel, maxLabel) {
5176
+ return {
5177
+ min: resolvePointElastic(dragElastic, minLabel),
5178
+ max: resolvePointElastic(dragElastic, maxLabel),
5179
+ };
5180
+ }
5181
+ function resolvePointElastic(dragElastic, label) {
5182
+ return typeof dragElastic === "number"
5183
+ ? dragElastic
5184
+ : dragElastic[label] || 0;
5185
+ }
5131
5186
 
5132
5187
  const elementDragControls = new WeakMap();
5133
5188
  /**
@@ -5261,7 +5316,6 @@ class VisualElementDragControls {
5261
5316
  }, {
5262
5317
  transformPagePoint: this.visualElement.getTransformPagePoint(),
5263
5318
  dragSnapToOrigin,
5264
- contextWindow: getContextWindow(this.visualElement),
5265
5319
  });
5266
5320
  }
5267
5321
  stop(event, info) {
@@ -5627,7 +5681,6 @@ class PanGesture extends Feature {
5627
5681
  onPointerDown(pointerDownEvent) {
5628
5682
  this.session = new PanSession(pointerDownEvent, this.createPanHandlers(), {
5629
5683
  transformPagePoint: this.node.getTransformPagePoint(),
5630
- contextWindow: getContextWindow(this.node),
5631
5684
  });
5632
5685
  }
5633
5686
  createPanHandlers() {
@@ -9264,7 +9317,7 @@ function updateMotionValuesFromProps(element, next, prev) {
9264
9317
  * and warn against mismatches.
9265
9318
  */
9266
9319
  if (process.env.NODE_ENV === "development") {
9267
- warnOnce(nextValue.version === "12.4.3", `Attempting to mix Motion versions ${nextValue.version} with 12.4.3 may not work as expected.`);
9320
+ warnOnce(nextValue.version === "12.4.4", `Attempting to mix Motion versions ${nextValue.version} with 12.4.4 may not work as expected.`);
9268
9321
  }
9269
9322
  }
9270
9323
  else if (isMotionValue(prevValue)) {