motion 11.11.16 → 11.12.0

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.
@@ -281,7 +281,7 @@
281
281
  * This will be replaced by the build step with the latest version number.
282
282
  * When MotionValues are provided to motion components, warn if versions are mixed.
283
283
  */
284
- this.version = "11.11.16";
284
+ this.version = "11.12.0";
285
285
  /**
286
286
  * Tracks whether this value can output a velocity. Currently this is only true
287
287
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -649,6 +649,34 @@
649
649
  }
650
650
  }
651
651
 
652
+ /*
653
+ Progress within given range
654
+
655
+ Given a lower limit and an upper limit, we return the progress
656
+ (expressed as a number 0-1) represented by the given value, and
657
+ limit that progress to within 0-1.
658
+
659
+ @param [number]: Lower limit
660
+ @param [number]: Upper limit
661
+ @param [number]: Value to find progress within given range
662
+ @return [number]: Progress of value within range as expressed 0-1
663
+ */
664
+ const progress = (from, to, value) => {
665
+ const toFromDifference = to - from;
666
+ return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
667
+ };
668
+
669
+ const generateLinearEasing = (easing, duration, // as milliseconds
670
+ resolution = 10 // as milliseconds
671
+ ) => {
672
+ let points = "";
673
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
674
+ for (let i = 0; i < numPoints; i++) {
675
+ points += easing(progress(0, numPoints - 1, i)) + ", ";
676
+ }
677
+ return `linear(${points.substring(0, points.length - 2)})`;
678
+ };
679
+
652
680
  /**
653
681
  * Converts seconds to milliseconds
654
682
  *
@@ -687,21 +715,43 @@
687
715
  return v;
688
716
  };
689
717
 
718
+ const springDefaults = {
719
+ // Default spring physics
720
+ stiffness: 100,
721
+ damping: 10,
722
+ mass: 1.0,
723
+ velocity: 0.0,
724
+ // Default duration/bounce-based options
725
+ duration: 800, // in ms
726
+ bounce: 0.3,
727
+ visualDuration: 0.3, // in seconds
728
+ // Rest thresholds
729
+ restSpeed: {
730
+ granular: 0.01,
731
+ default: 2,
732
+ },
733
+ restDelta: {
734
+ granular: 0.005,
735
+ default: 0.5,
736
+ },
737
+ // Limits
738
+ minDuration: 0.01, // in seconds
739
+ maxDuration: 10.0, // in seconds
740
+ minDamping: 0.05,
741
+ maxDamping: 1,
742
+ };
743
+
690
744
  const safeMin = 0.001;
691
- const minDuration = 0.01;
692
- const maxDuration$1 = 10.0;
693
- const minDamping = 0.05;
694
- const maxDamping = 1;
695
- function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }) {
745
+ function findSpring({ duration = springDefaults.duration, bounce = springDefaults.bounce, velocity = springDefaults.velocity, mass = springDefaults.mass, }) {
696
746
  let envelope;
697
747
  let derivative;
698
- exports.warning(duration <= secondsToMilliseconds(maxDuration$1), "Spring duration must be 10 seconds or less");
748
+ exports.warning(duration <= secondsToMilliseconds(springDefaults.maxDuration), "Spring duration must be 10 seconds or less");
699
749
  let dampingRatio = 1 - bounce;
700
750
  /**
701
751
  * Restrict dampingRatio and duration to within acceptable ranges.
702
752
  */
703
- dampingRatio = clamp(minDamping, maxDamping, dampingRatio);
704
- duration = clamp(minDuration, maxDuration$1, millisecondsToSeconds(duration));
753
+ dampingRatio = clamp(springDefaults.minDamping, springDefaults.maxDamping, dampingRatio);
754
+ duration = clamp(springDefaults.minDuration, springDefaults.maxDuration, millisecondsToSeconds(duration));
705
755
  if (dampingRatio < 1) {
706
756
  /**
707
757
  * Underdamped spring
@@ -745,8 +795,8 @@
745
795
  duration = secondsToMilliseconds(duration);
746
796
  if (isNaN(undampedFreq)) {
747
797
  return {
748
- stiffness: 100,
749
- damping: 10,
798
+ stiffness: springDefaults.stiffness,
799
+ damping: springDefaults.damping,
750
800
  duration,
751
801
  };
752
802
  }
@@ -771,6 +821,22 @@
771
821
  return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
772
822
  }
773
823
 
824
+ /**
825
+ * Implement a practical max duration for keyframe generation
826
+ * to prevent infinite loops
827
+ */
828
+ const maxGeneratorDuration = 20000;
829
+ function calcGeneratorDuration(generator) {
830
+ let duration = 0;
831
+ const timeStep = 50;
832
+ let state = generator.next(duration);
833
+ while (!state.done && duration < maxGeneratorDuration) {
834
+ duration += timeStep;
835
+ state = generator.next(duration);
836
+ }
837
+ return duration >= maxGeneratorDuration ? Infinity : duration;
838
+ }
839
+
774
840
  const durationKeys = ["duration", "bounce"];
775
841
  const physicsKeys = ["stiffness", "damping", "mass"];
776
842
  function isSpringType(options, keys) {
@@ -778,29 +844,51 @@
778
844
  }
779
845
  function getSpringOptions(options) {
780
846
  let springOptions = {
781
- velocity: 0.0,
782
- stiffness: 100,
783
- damping: 10,
784
- mass: 1.0,
847
+ velocity: springDefaults.velocity,
848
+ stiffness: springDefaults.stiffness,
849
+ damping: springDefaults.damping,
850
+ mass: springDefaults.mass,
785
851
  isResolvedFromDuration: false,
786
852
  ...options,
787
853
  };
788
854
  // stiffness/damping/mass overrides duration/bounce
789
855
  if (!isSpringType(options, physicsKeys) &&
790
856
  isSpringType(options, durationKeys)) {
791
- const derived = findSpring(options);
792
- springOptions = {
793
- ...springOptions,
794
- ...derived,
795
- mass: 1.0,
796
- };
797
- springOptions.isResolvedFromDuration = true;
857
+ if (options.visualDuration) {
858
+ const visualDuration = options.visualDuration;
859
+ const root = (2 * Math.PI) / (visualDuration * 1.2);
860
+ const stiffness = root * root;
861
+ const damping = 2 * clamp(0.05, 1, 1 - options.bounce) * Math.sqrt(stiffness);
862
+ springOptions = {
863
+ ...springOptions,
864
+ mass: springDefaults.mass,
865
+ stiffness,
866
+ damping,
867
+ };
868
+ }
869
+ else {
870
+ const derived = findSpring(options);
871
+ springOptions = {
872
+ ...springOptions,
873
+ ...derived,
874
+ mass: springDefaults.mass,
875
+ };
876
+ springOptions.isResolvedFromDuration = true;
877
+ }
798
878
  }
799
879
  return springOptions;
800
880
  }
801
- function spring({ keyframes, restDelta, restSpeed, ...options }) {
802
- const origin = keyframes[0];
803
- const target = keyframes[keyframes.length - 1];
881
+ function spring(optionsOrVisualDuration = springDefaults.visualDuration, bounce = springDefaults.bounce) {
882
+ const options = typeof optionsOrVisualDuration !== "object"
883
+ ? {
884
+ visualDuration: optionsOrVisualDuration,
885
+ keyframes: [0, 1],
886
+ bounce,
887
+ }
888
+ : optionsOrVisualDuration;
889
+ let { restSpeed, restDelta } = options;
890
+ const origin = options.keyframes[0];
891
+ const target = options.keyframes[options.keyframes.length - 1];
804
892
  /**
805
893
  * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
806
894
  * to reduce GC during animation.
@@ -822,8 +910,12 @@
822
910
  * ratio between feeling good and finishing as soon as changes are imperceptible.
823
911
  */
824
912
  const isGranularScale = Math.abs(initialDelta) < 5;
825
- restSpeed || (restSpeed = isGranularScale ? 0.01 : 2);
826
- restDelta || (restDelta = isGranularScale ? 0.005 : 0.5);
913
+ restSpeed || (restSpeed = isGranularScale
914
+ ? springDefaults.restSpeed.granular
915
+ : springDefaults.restSpeed.default);
916
+ restDelta || (restDelta = isGranularScale
917
+ ? springDefaults.restDelta.granular
918
+ : springDefaults.restDelta.default);
827
919
  let resolveSpring;
828
920
  if (dampingRatio < 1) {
829
921
  const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
@@ -864,7 +956,7 @@
864
956
  dampedAngularFreq);
865
957
  };
866
958
  }
867
- return {
959
+ const generator = {
868
960
  calculatedDuration: isResolvedFromDuration ? duration || null : null,
869
961
  next: (t) => {
870
962
  const current = resolveSpring(t);
@@ -892,23 +984,13 @@
892
984
  state.value = state.done ? target : current;
893
985
  return state;
894
986
  },
987
+ toString: () => {
988
+ const calculatedDuration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
989
+ const easing = generateLinearEasing((progress) => generator.next(calculatedDuration * progress).value, calculatedDuration, 30);
990
+ return calculatedDuration + "ms " + easing;
991
+ },
895
992
  };
896
- }
897
-
898
- /**
899
- * Implement a practical max duration for keyframe generation
900
- * to prevent infinite loops
901
- */
902
- const maxGeneratorDuration = 20000;
903
- function calcGeneratorDuration(generator) {
904
- let duration = 0;
905
- const timeStep = 50;
906
- let state = generator.next(duration);
907
- while (!state.done && duration < maxGeneratorDuration) {
908
- duration += timeStep;
909
- state = generator.next(duration);
910
- }
911
- return duration >= maxGeneratorDuration ? Infinity : duration;
993
+ return generator;
912
994
  }
913
995
 
914
996
  /**
@@ -949,23 +1031,6 @@
949
1031
  return from + (to - from) * progress;
950
1032
  };
951
1033
 
952
- /*
953
- Progress within given range
954
-
955
- Given a lower limit and an upper limit, we return the progress
956
- (expressed as a number 0-1) represented by the given value, and
957
- limit that progress to within 0-1.
958
-
959
- @param [number]: Lower limit
960
- @param [number]: Upper limit
961
- @param [number]: Value to find progress within given range
962
- @return [number]: Progress of value within range as expressed 0-1
963
- */
964
- const progress = (from, to, value) => {
965
- const toFromDifference = to - from;
966
- return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
967
- };
968
-
969
1034
  function fillOffset(offset, remaining) {
970
1035
  const min = offset[offset.length - 1];
971
1036
  for (let i = 1; i <= remaining; i++) {
@@ -3324,18 +3389,6 @@
3324
3389
  // "background-color"
3325
3390
  ]);
3326
3391
 
3327
- // Create a linear easing point for every 10 ms
3328
- const resolution = 10;
3329
- const generateLinearEasing = (easing, duration // as milliseconds
3330
- ) => {
3331
- let points = "";
3332
- const numPoints = Math.max(Math.round(duration / resolution), 2);
3333
- for (let i = 0; i < numPoints; i++) {
3334
- points += easing(progress(0, numPoints - 1, i)) + ", ";
3335
- }
3336
- return `linear(${points.substring(0, points.length - 2)})`;
3337
- };
3338
-
3339
3392
  /**
3340
3393
  * Add the ability for test suites to manually set support flags
3341
3394
  * to better test more environments.
@@ -4105,7 +4158,7 @@
4105
4158
  * and warn against mismatches.
4106
4159
  */
4107
4160
  {
4108
- warnOnce(nextValue.version === "11.11.16", `Attempting to mix Motion versions ${nextValue.version} with 11.11.16 may not work as expected.`);
4161
+ warnOnce(nextValue.version === "11.12.0", `Attempting to mix Motion versions ${nextValue.version} with 11.12.0 may not work as expected.`);
4109
4162
  }
4110
4163
  }
4111
4164
  else if (isMotionValue(prevValue)) {
@@ -5253,6 +5306,7 @@
5253
5306
  valueKeyframes = [valueKeyframes];
5254
5307
  }
5255
5308
  hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
5309
+ // TODO: Replace this with toString()?
5256
5310
  if (isGenerator(options.type)) {
5257
5311
  const generatorOptions = createGeneratorEasing(options, 100, options.type);
5258
5312
  options.ease = supportsLinearEasing()
@@ -5391,7 +5445,7 @@
5391
5445
  for (const valueName in keyframes) {
5392
5446
  const valueKeyframes = keyframes[valueName];
5393
5447
  const valueOptions = {
5394
- ...getValueTransition(options, valueName),
5448
+ ...getValueTransition(elementTransition, valueName),
5395
5449
  };
5396
5450
  valueOptions.duration = valueOptions.duration
5397
5451
  ? secondsToMilliseconds(valueOptions.duration)