framer-motion 12.8.2 → 12.9.1

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.
@@ -2288,13 +2288,13 @@
2288
2288
  }
2289
2289
  onPlay && onPlay();
2290
2290
  const now = this.driver.now();
2291
- if (this.holdTime !== null) {
2292
- this.startTime = now - this.holdTime;
2293
- }
2294
- else if (this.state === "finished") {
2291
+ if (this.state === "finished") {
2295
2292
  this.updateFinished();
2296
2293
  this.startTime = now;
2297
2294
  }
2295
+ else if (this.holdTime !== null) {
2296
+ this.startTime = now - this.holdTime;
2297
+ }
2298
2298
  else if (!this.startTime) {
2299
2299
  this.startTime = startTime ?? now;
2300
2300
  }
@@ -2322,7 +2322,6 @@
2322
2322
  this.holdTime = null;
2323
2323
  }
2324
2324
  finish() {
2325
- this.notifyFinished();
2326
2325
  this.teardown();
2327
2326
  this.state = "finished";
2328
2327
  const { onComplete } = this.options;
@@ -2335,6 +2334,7 @@
2335
2334
  this.teardown();
2336
2335
  }
2337
2336
  teardown() {
2337
+ this.notifyFinished();
2338
2338
  this.state = "idle";
2339
2339
  this.stopDriver();
2340
2340
  this.startTime = this.holdTime = null;
@@ -2787,7 +2787,7 @@
2787
2787
  this.isStopped = false;
2788
2788
  if (!options)
2789
2789
  return;
2790
- const { element, name, keyframes, pseudoElement, allowFlatten = false, finalKeyframe, } = options;
2790
+ const { element, name, keyframes, pseudoElement, allowFlatten = false, finalKeyframe, onComplete, } = options;
2791
2791
  this.isPseudoElement = Boolean(pseudoElement);
2792
2792
  this.allowFlatten = allowFlatten;
2793
2793
  this.options = options;
@@ -2813,8 +2813,13 @@
2813
2813
  }
2814
2814
  this.animation.cancel();
2815
2815
  }
2816
+ onComplete?.();
2816
2817
  this.notifyFinished();
2817
2818
  };
2819
+ /**
2820
+ * TODO: In a breaking change, we should replace this with `.notifyCancel()`
2821
+ */
2822
+ this.animation.oncancel = () => this.notifyFinished();
2818
2823
  }
2819
2824
  play() {
2820
2825
  if (this.isStopped)
@@ -3139,7 +3144,7 @@
3139
3144
  }
3140
3145
  onKeyframesResolved(keyframes, finalKeyframe, options, sync) {
3141
3146
  this.keyframeResolver = undefined;
3142
- const { name, type, velocity, delay, isHandoff, onUpdate, onComplete } = options;
3147
+ const { name, type, velocity, delay, isHandoff, onUpdate } = options;
3143
3148
  this.resolvedAt = time.now();
3144
3149
  /**
3145
3150
  * If we can't animate this value with the resolved keyframes
@@ -3189,12 +3194,7 @@
3189
3194
  element: resolvedOptions.motionValue.owner.current,
3190
3195
  })
3191
3196
  : new JSAnimation(resolvedOptions);
3192
- animation.finished
3193
- .then(() => {
3194
- onComplete?.();
3195
- this.notifyFinished();
3196
- })
3197
- .catch(noop);
3197
+ animation.finished.then(() => this.notifyFinished()).catch(noop);
3198
3198
  if (this.pendingTimeline) {
3199
3199
  this.stopTimeline = animation.attachTimeline(this.pendingTimeline);
3200
3200
  this.pendingTimeline = undefined;
@@ -3807,6 +3807,54 @@
3807
3807
  // "background-color"
3808
3808
  ]);
3809
3809
 
3810
+ function resolveElements(elementOrSelector, scope, selectorCache) {
3811
+ if (elementOrSelector instanceof EventTarget) {
3812
+ return [elementOrSelector];
3813
+ }
3814
+ else if (typeof elementOrSelector === "string") {
3815
+ let root = document;
3816
+ if (scope) {
3817
+ root = scope.current;
3818
+ }
3819
+ const elements = selectorCache?.[elementOrSelector] ??
3820
+ root.querySelectorAll(elementOrSelector);
3821
+ return elements ? Array.from(elements) : [];
3822
+ }
3823
+ return Array.from(elementOrSelector);
3824
+ }
3825
+
3826
+ function styleEffect(subject, values) {
3827
+ const elements = resolveElements(subject);
3828
+ const subscriptions = [];
3829
+ for (let i = 0; i < elements.length; i++) {
3830
+ const element = elements[i];
3831
+ for (const key in values) {
3832
+ const value = values[key];
3833
+ /**
3834
+ * TODO: Get specific setters for combined props (like x)
3835
+ * or values with default types (like color)
3836
+ *
3837
+ * TODO: CSS variable support
3838
+ */
3839
+ const updateStyle = () => {
3840
+ element.style[key] = value.get();
3841
+ };
3842
+ const scheduleUpdate = () => frame.render(updateStyle);
3843
+ const cancel = value.on("change", scheduleUpdate);
3844
+ scheduleUpdate();
3845
+ subscriptions.push(() => {
3846
+ cancel();
3847
+ cancelFrame(updateStyle);
3848
+ });
3849
+ }
3850
+ }
3851
+ return () => {
3852
+ for (const cancel of subscriptions) {
3853
+ cancel();
3854
+ }
3855
+ };
3856
+ }
3857
+
3810
3858
  const { schedule: microtask, cancel: cancelMicrotask } =
3811
3859
  /* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
3812
3860
 
@@ -3843,22 +3891,6 @@
3843
3891
  }
3844
3892
  }
3845
3893
 
3846
- function resolveElements(elementOrSelector, scope, selectorCache) {
3847
- if (elementOrSelector instanceof EventTarget) {
3848
- return [elementOrSelector];
3849
- }
3850
- else if (typeof elementOrSelector === "string") {
3851
- let root = document;
3852
- if (scope) {
3853
- root = scope.current;
3854
- }
3855
- const elements = selectorCache?.[elementOrSelector] ??
3856
- root.querySelectorAll(elementOrSelector);
3857
- return elements ? Array.from(elements) : [];
3858
- }
3859
- return Array.from(elementOrSelector);
3860
- }
3861
-
3862
3894
  function setupGesture(elementOrSelector, options) {
3863
3895
  const elements = resolveElements(elementOrSelector);
3864
3896
  const gestureAbortController = new AbortController();
@@ -4233,7 +4265,7 @@
4233
4265
  * This will be replaced by the build step with the latest version number.
4234
4266
  * When MotionValues are provided to motion components, warn if versions are mixed.
4235
4267
  */
4236
- this.version = "12.8.1";
4268
+ this.version = "12.9.1";
4237
4269
  /**
4238
4270
  * Tracks whether this value can output a velocity. Currently this is only true
4239
4271
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -4259,12 +4291,12 @@
4259
4291
  this.prev = this.current;
4260
4292
  this.setCurrent(v);
4261
4293
  // Update update subscribers
4262
- if (this.current !== this.prev && this.events.change) {
4263
- this.events.change.notify(this.current);
4294
+ if (this.current !== this.prev) {
4295
+ this.events.change?.notify(this.current);
4264
4296
  }
4265
4297
  // Update render subscribers
4266
- if (render && this.events.renderRequest) {
4267
- this.events.renderRequest.notify(this.current);
4298
+ if (render) {
4299
+ this.events.renderRequest?.notify(this.current);
4268
4300
  }
4269
4301
  };
4270
4302
  this.hasAnimated = false;
@@ -7576,7 +7608,7 @@
7576
7608
  * and warn against mismatches.
7577
7609
  */
7578
7610
  {
7579
- warnOnce(nextValue.version === "12.8.2", `Attempting to mix Motion versions ${nextValue.version} with 12.8.2 may not work as expected.`);
7611
+ warnOnce(nextValue.version === "12.9.1", `Attempting to mix Motion versions ${nextValue.version} with 12.9.1 may not work as expected.`);
7580
7612
  }
7581
7613
  }
7582
7614
  else if (isMotionValue(prevValue)) {
@@ -8715,6 +8747,17 @@
8715
8747
  delay,
8716
8748
  ...getValueTransition$1(transition || {}, key),
8717
8749
  };
8750
+ /**
8751
+ * If the value is already at the defined target, skip the animation.
8752
+ */
8753
+ const currentValue = value.get();
8754
+ if (currentValue !== undefined &&
8755
+ !value.isAnimating &&
8756
+ !Array.isArray(valueTarget) &&
8757
+ valueTarget === currentValue &&
8758
+ !valueTransition.velocity) {
8759
+ continue;
8760
+ }
8718
8761
  /**
8719
8762
  * If this is the first time a value is being animated, check
8720
8763
  * to see if we're handling off from an existing animation.
@@ -13773,6 +13816,7 @@
13773
13816
  exports.startWaapiAnimation = startWaapiAnimation;
13774
13817
  exports.statsBuffer = statsBuffer;
13775
13818
  exports.steps = steps;
13819
+ exports.styleEffect = styleEffect;
13776
13820
  exports.supportedWaapiEasing = supportedWaapiEasing;
13777
13821
  exports.supportsBrowserAnimation = supportsBrowserAnimation;
13778
13822
  exports.supportsFlags = supportsFlags;