angular-movement 0.0.2 → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  import { isPlatformBrowser, DOCUMENT } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { InjectionToken, inject, PLATFORM_ID, Injectable, input, ElementRef, computed, effect, forwardRef, Directive, afterEveryRender, NgZone, signal, ViewContainerRef, TemplateRef, makeEnvironmentProviders } from '@angular/core';
3
+ import { InjectionToken, inject, PLATFORM_ID, Injectable, input, ElementRef, computed, effect, forwardRef, Directive, afterEveryRender, NgZone, signal, ViewContainerRef, TemplateRef, Renderer2, makeEnvironmentProviders } from '@angular/core';
4
4
 
5
5
  const MOVEMENT_DEFAULTS = {
6
6
  duration: 300,
@@ -51,6 +51,9 @@ function getInterpolated(arr, i1, i2, p) {
51
51
  return undefined;
52
52
  const v1 = arr[Math.min(i1, arr.length - 1)];
53
53
  const v2 = arr[Math.min(i2, arr.length - 1)];
54
+ if (typeof v1 === 'string' || typeof v2 === 'string') {
55
+ return p >= 1 ? v2 : v1;
56
+ }
54
57
  return v1 + (v2 - v1) * p;
55
58
  }
56
59
  const KNOWN_KEYS = new Set([
@@ -69,36 +72,36 @@ function buildKeyframe(frames, getVal) {
69
72
  const keyframe = {};
70
73
  const opacity = getVal(frames.opacity);
71
74
  if (opacity !== undefined) {
72
- keyframe.opacity = opacity;
75
+ keyframe.opacity = Number(opacity);
73
76
  }
74
77
  const x = getVal(frames.x);
75
78
  const y = getVal(frames.y);
76
79
  if (x !== undefined || y !== undefined) {
77
- keyframe.translate = `${x ?? 0}px ${y ?? 0}px`;
80
+ keyframe.translate = `${Number(x ?? 0)}px ${Number(y ?? 0)}px`;
78
81
  }
79
82
  const scale = getVal(frames.scale);
80
83
  if (scale !== undefined) {
81
- keyframe.scale = `${scale}`;
84
+ keyframe.scale = `${Number(scale)}`;
82
85
  }
83
86
  else {
84
87
  const scaleX = getVal(frames.scaleX);
85
88
  const scaleY = getVal(frames.scaleY);
86
89
  if (scaleX !== undefined || scaleY !== undefined) {
87
- keyframe.scale = `${scaleX ?? 1} ${scaleY ?? 1}`;
90
+ keyframe.scale = `${Number(scaleX ?? 1)} ${Number(scaleY ?? 1)}`;
88
91
  }
89
92
  }
90
93
  const rotate = getVal(frames.rotate);
91
94
  if (rotate !== undefined) {
92
- keyframe.rotate = `${rotate}deg`;
95
+ keyframe.rotate = `${Number(rotate)}deg`;
93
96
  }
94
97
  const blur = getVal(frames.blur);
95
98
  if (blur !== undefined) {
96
- keyframe.filter = `blur(${blur}px)`;
99
+ keyframe.filter = `blur(${Number(blur)}px)`;
97
100
  }
98
101
  const rotateX = getVal(frames.rotateX);
99
102
  const rotateY = getVal(frames.rotateY);
100
103
  if (rotateX !== undefined || rotateY !== undefined) {
101
- keyframe.transform = `perspective(${DEFAULT_PERSPECTIVE}) rotateX(${rotateX ?? 0}deg) rotateY(${rotateY ?? 0}deg)`;
104
+ keyframe.transform = `perspective(${DEFAULT_PERSPECTIVE}) rotateX(${Number(rotateX ?? 0)}deg) rotateY(${Number(rotateY ?? 0)}deg)`;
102
105
  }
103
106
  // Passthrough arbitrary properties for WAAPI (e.g. strokeDashoffset)
104
107
  for (const key in frames) {
@@ -241,6 +244,89 @@ const MOVE_PRESETS = {
241
244
  leave: { scale: [1, 0.95, 1] },
242
245
  loop: { scale: [1, 1.05, 1] },
243
246
  },
247
+ shake: {
248
+ enter: { opacity: DEFAULT_FADE_OPACITY, x: [0, -10, 10, -10, 10, -5, 5, -5, 5, 0] },
249
+ leave: { opacity: DEFAULT_LEAVE_OPACITY, x: [0, 10, -10, 10, -10, 5, -5, 5, -5, 0] },
250
+ },
251
+ swing: {
252
+ enter: { opacity: DEFAULT_FADE_OPACITY, rotate: [0, 15, -10, 5, -5, 0] },
253
+ leave: { opacity: DEFAULT_LEAVE_OPACITY, rotate: [0, -15, 10, -5, 5, 0] },
254
+ },
255
+ wobble: {
256
+ enter: {
257
+ opacity: DEFAULT_FADE_OPACITY,
258
+ x: [0, -25, 20, -15, 10, -5, 0],
259
+ rotate: [0, -5, 3, -3, 2, -1, 0],
260
+ },
261
+ leave: {
262
+ opacity: DEFAULT_LEAVE_OPACITY,
263
+ x: [0, 25, -20, 15, -10, 5, 0],
264
+ rotate: [0, 5, -3, 3, -2, 1, 0],
265
+ },
266
+ },
267
+ 'rubber-band': {
268
+ enter: {
269
+ opacity: DEFAULT_FADE_OPACITY,
270
+ scaleX: [1, 1.25, 0.75, 1.15, 0.95, 1.05, 1],
271
+ scaleY: [1, 0.75, 1.25, 0.85, 1.05, 0.95, 1],
272
+ },
273
+ leave: {
274
+ opacity: DEFAULT_LEAVE_OPACITY,
275
+ scaleX: [1, 1.25, 0.75, 1.15, 0.95, 1.05, 1],
276
+ scaleY: [1, 0.75, 1.25, 0.85, 1.05, 0.95, 1],
277
+ },
278
+ },
279
+ 'heart-beat': {
280
+ enter: { opacity: DEFAULT_FADE_OPACITY, scale: [1, 1.3, 1, 1.3, 1] },
281
+ leave: { opacity: DEFAULT_LEAVE_OPACITY, scale: [1, 1.3, 1, 1.3, 1] },
282
+ loop: { scale: [1, 1.3, 1, 1.3, 1] },
283
+ },
284
+ tada: {
285
+ enter: {
286
+ opacity: DEFAULT_FADE_OPACITY,
287
+ scale: [1, 0.9, 1.1, 1.1, 1.1, 1],
288
+ rotate: [0, -3, 3, -3, 3, 0],
289
+ },
290
+ leave: {
291
+ opacity: DEFAULT_LEAVE_OPACITY,
292
+ scale: [1, 0.9, 1.1, 1.1, 1.1, 1],
293
+ rotate: [0, 3, -3, 3, -3, 0],
294
+ },
295
+ },
296
+ jello: {
297
+ enter: {
298
+ opacity: DEFAULT_FADE_OPACITY,
299
+ scaleX: [1, 1.25, 0.75, 1.15, 0.95, 1.05, 1],
300
+ scaleY: [1, 0.75, 1.25, 0.85, 1.05, 0.95, 1],
301
+ },
302
+ leave: {
303
+ opacity: DEFAULT_LEAVE_OPACITY,
304
+ scaleX: [1, 1.25, 0.75, 1.15, 0.95, 1.05, 1],
305
+ scaleY: [1, 0.75, 1.25, 0.85, 1.05, 0.95, 1],
306
+ },
307
+ },
308
+ 'light-speed': {
309
+ enter: { opacity: [0, 1], x: [200, 0], scaleX: [0, 1] },
310
+ leave: { opacity: [1, 0], x: [0, 200], scaleX: [1, 0] },
311
+ },
312
+ 'roll-in': {
313
+ enter: { opacity: [0, 1], x: [-100, 0], rotate: [-120, 0] },
314
+ leave: { opacity: [1, 0], x: [0, 100], rotate: [0, 120] },
315
+ },
316
+ 'icon-draw': {
317
+ enter: { pathLength: [0, 1], opacity: [0, 1] },
318
+ leave: { pathLength: [1, 0], opacity: [1, 0] },
319
+ },
320
+ 'icon-pulse': {
321
+ enter: { scale: [1, 1.08, 1], opacity: [1, 0.85, 1] },
322
+ leave: { scale: [1, 0.92, 1], opacity: [1, 1, 1] },
323
+ loop: { scale: [1, 1.08, 1], opacity: [1, 0.85, 1] },
324
+ },
325
+ 'icon-bounce': {
326
+ enter: { y: [0, -3, 0], opacity: [1, 1, 1] },
327
+ leave: { y: [0, 0, 0], opacity: [1, 1, 1] },
328
+ loop: { y: [0, -3, 0] },
329
+ },
244
330
  none: {
245
331
  enter: { opacity: [1, 1] },
246
332
  leave: { opacity: [1, 1] },
@@ -310,6 +396,63 @@ function applyInitialStyles(el, frames) {
310
396
  function clearInitialStyles(el) {
311
397
  clearComposedStyle(el);
312
398
  }
399
+ /**
400
+ * Validates MoveSpring configuration and returns sanitized values.
401
+ * Warns in development mode for invalid values.
402
+ */
403
+ function validateSpring(spring) {
404
+ if (!spring)
405
+ return undefined;
406
+ const validated = {};
407
+ if (spring.stiffness !== undefined) {
408
+ if (spring.stiffness <= 0 && typeof ngDevMode !== 'undefined' && ngDevMode) {
409
+ console.warn('[Movement] Spring stiffness must be > 0. Using default.');
410
+ }
411
+ validated.stiffness = spring.stiffness > 0 ? spring.stiffness : 100;
412
+ }
413
+ if (spring.damping !== undefined) {
414
+ if (spring.damping < 0 && typeof ngDevMode !== 'undefined' && ngDevMode) {
415
+ console.warn('[Movement] Spring damping must be >= 0. Using default.');
416
+ }
417
+ validated.damping = spring.damping >= 0 ? spring.damping : 10;
418
+ }
419
+ if (spring.mass !== undefined) {
420
+ if (spring.mass <= 0 && typeof ngDevMode !== 'undefined' && ngDevMode) {
421
+ console.warn('[Movement] Spring mass must be > 0. Using default.');
422
+ }
423
+ validated.mass = spring.mass > 0 ? spring.mass : 1;
424
+ }
425
+ if (spring.velocity !== undefined) {
426
+ validated.velocity = spring.velocity;
427
+ }
428
+ return validated;
429
+ }
430
+ /**
431
+ * Validates scroll offset string format "elFraction viewFraction".
432
+ * Returns true if valid, warns in dev mode if invalid.
433
+ */
434
+ function isValidScrollOffset(offset) {
435
+ const parts = offset.split(' ').map(parseFloat);
436
+ if (parts.length !== 2 || parts.some(Number.isNaN)) {
437
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
438
+ console.warn(`[Movement] Invalid scroll offset: "${offset}". Expected format "elFraction viewFraction" (e.g. "0 1").`);
439
+ }
440
+ return false;
441
+ }
442
+ return true;
443
+ }
444
+ /**
445
+ * Validates drag elastic factor. Must be between 0 and 1.
446
+ */
447
+ function validateDragElastic(elastic) {
448
+ if (elastic < 0 || elastic > 1) {
449
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
450
+ console.warn(`[Movement] Drag elastic must be between 0 and 1. Got ${elastic}. Clamping to range.`);
451
+ }
452
+ return Math.max(0, Math.min(1, elastic));
453
+ }
454
+ return elastic;
455
+ }
313
456
 
314
457
  class WaapiPlayer {
315
458
  #animation = null;
@@ -323,7 +466,9 @@ class WaapiPlayer {
323
466
  onDone?.();
324
467
  return;
325
468
  }
326
- const keyframes = this.#toWAAPIKeyframes(frames);
469
+ const keyframes = Array.isArray(frames)
470
+ ? frames
471
+ : this.#toWAAPIKeyframes(frames);
327
472
  const iterations = config.iterations ?? 1;
328
473
  this.#animation = host.animate(keyframes, {
329
474
  duration: config.duration,
@@ -512,24 +657,129 @@ class SpringPlayer {
512
657
  }
513
658
  }
514
659
 
660
+ function isPropertyTransition(value) {
661
+ return (typeof value === 'object' &&
662
+ value !== null &&
663
+ ('duration' in value || 'easing' in value || 'delay' in value));
664
+ }
665
+ function composeTransitionKeyframes(frames, transition, baseConfig) {
666
+ const globalDuration = transition.duration ?? baseConfig.duration;
667
+ const globalEasing = transition.easing ?? baseConfig.easing;
668
+ const globalDelay = transition.delay ?? baseConfig.delay;
669
+ const propNames = Object.keys(frames).filter((k) => k !== 'transition');
670
+ if (propNames.length === 0)
671
+ return null;
672
+ const timings = propNames.map((prop) => {
673
+ const pt = transition[prop];
674
+ const parsed = isPropertyTransition(pt) ? pt : {};
675
+ return {
676
+ prop,
677
+ duration: parsed.duration ?? globalDuration,
678
+ easing: parsed.easing ?? globalEasing,
679
+ delay: parsed.delay ?? globalDelay,
680
+ values: frames[prop].map((v) => Number(v)),
681
+ };
682
+ });
683
+ const allSame = timings.every((t) => t.duration === timings[0].duration &&
684
+ t.easing === timings[0].easing &&
685
+ t.delay === timings[0].delay);
686
+ if (allSame) {
687
+ return null;
688
+ }
689
+ const uniqueEasings = new Set(timings.map((t) => t.easing));
690
+ let finalEasing = timings[0].easing;
691
+ if (uniqueEasings.size > 1) {
692
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
693
+ console.warn('[Movement] Per-property easing differences are not supported yet. Using global easing.');
694
+ }
695
+ finalEasing = globalEasing;
696
+ }
697
+ const totalDuration = Math.max(...timings.map((t) => t.delay + t.duration));
698
+ const totalDelay = Math.min(...timings.map((t) => t.delay));
699
+ // Collect all keyframe times
700
+ const timeSet = new Set();
701
+ for (const t of timings) {
702
+ const n = t.values.length;
703
+ for (let i = 0; i < n; i++) {
704
+ const time = t.delay + (t.duration * i) / Math.max(1, n - 1);
705
+ timeSet.add(time);
706
+ }
707
+ }
708
+ const sortedTimes = Array.from(timeSet).sort((a, b) => a - b);
709
+ const resultKeyframes = [];
710
+ for (const time of sortedTimes) {
711
+ const offset = totalDuration > totalDelay ? (time - totalDelay) / (totalDuration - totalDelay) : 0;
712
+ const kf = { offset };
713
+ for (const t of timings) {
714
+ const localTime = time - t.delay;
715
+ const n = t.values.length;
716
+ if (n === 1) {
717
+ kf[t.prop] = t.values[0];
718
+ continue;
719
+ }
720
+ if (localTime <= 0) {
721
+ kf[t.prop] = t.values[0];
722
+ }
723
+ else if (localTime >= t.duration) {
724
+ kf[t.prop] = t.values[n - 1];
725
+ }
726
+ else {
727
+ const progress = t.duration > 0 ? localTime / t.duration : 0;
728
+ const maxIdx = n - 1;
729
+ const idx = progress * maxIdx;
730
+ const i1 = Math.floor(idx);
731
+ const i2 = Math.min(Math.ceil(idx), maxIdx);
732
+ const p = idx - i1;
733
+ const v1 = t.values[i1];
734
+ const v2 = t.values[i2];
735
+ kf[t.prop] = v1 + (v2 - v1) * p;
736
+ }
737
+ }
738
+ resultKeyframes.push(kf);
739
+ }
740
+ return {
741
+ keyframes: resultKeyframes,
742
+ duration: totalDuration,
743
+ easing: finalEasing,
744
+ delay: totalDelay,
745
+ };
746
+ }
747
+
515
748
  class AnimationEngine {
516
749
  #platformId = inject(PLATFORM_ID);
517
750
  #defaults = inject(MOVEMENT_CONFIG);
518
- play(host, frames, options = {}) {
751
+ play(host, rawFrames, options = {}) {
519
752
  if (!isPlatformBrowser(this.#platformId)) {
520
753
  options.onDone?.();
521
754
  return null;
522
755
  }
756
+ const frames = this.#resolveSvgFrames(host, rawFrames);
523
757
  if (options.disabled) {
758
+ this.#prepareSvgPathDraw(host, frames);
524
759
  this.#applyFinalStyles(host, frames);
525
760
  options.onDone?.();
526
761
  return null;
527
762
  }
763
+ this.#prepareSvgPathDraw(host, frames);
528
764
  const config = options.config ?? this.#defaults;
529
- const isSpring = options.spring || config.easing === 'spring';
765
+ const spring = validateSpring(options.spring);
766
+ const isSpring = spring || config.easing === 'spring';
530
767
  const iterations = options.iterations ?? config.iterations;
768
+ // Per-property transitions only supported with WaapiPlayer (not spring)
769
+ if (options.transition && !isSpring) {
770
+ const resolved = composeTransitionKeyframes(frames, options.transition, config);
771
+ if (resolved) {
772
+ return new WaapiPlayer(host, resolved.keyframes, {
773
+ duration: resolved.duration,
774
+ easing: resolved.easing,
775
+ delay: resolved.delay,
776
+ disabled: false,
777
+ iterations,
778
+ }, options.onDone);
779
+ }
780
+ }
531
781
  if (isSpring) {
532
- return new SpringPlayer(host, frames, options.spring ?? {}, options.delay ?? config.delay, iterations, options.onDone);
782
+ return new SpringPlayer(host, frames, spring ?? {}, options.delay ?? config.delay, iterations, options.onDone);
533
783
  }
534
784
  else {
535
785
  return new WaapiPlayer(host, frames, {
@@ -544,6 +794,67 @@ class AnimationEngine {
544
794
  #applyFinalStyles(host, frames) {
545
795
  applyComposedStyle(host, composeFinalStyle(frames));
546
796
  }
797
+ #resolveSvgFrames(host, frames) {
798
+ if (!frames.pathLength && !frames.pathOffset) {
799
+ return frames;
800
+ }
801
+ const L = this.#getPathLength(host);
802
+ const resolved = { ...frames };
803
+ const pValues = frames.pathLength ? frames.pathLength.map((v) => Number(v)) : [1];
804
+ const oValues = frames.pathOffset ? frames.pathOffset.map((v) => Number(v)) : [0];
805
+ const maxLen = Math.max(pValues.length, oValues.length);
806
+ const strokeDasharray = [];
807
+ const strokeDashoffset = [];
808
+ for (let i = 0; i < maxLen; i++) {
809
+ const p = pValues[Math.min(i, pValues.length - 1)];
810
+ const o = oValues[Math.min(i, oValues.length - 1)];
811
+ strokeDasharray.push(`${p * L} ${L}`);
812
+ strokeDashoffset.push(-o * L);
813
+ }
814
+ resolved['strokeDasharray'] = strokeDasharray;
815
+ resolved['strokeDashoffset'] = strokeDashoffset;
816
+ delete resolved['pathLength'];
817
+ delete resolved['pathOffset'];
818
+ return resolved;
819
+ }
820
+ #prepareSvgPathDraw(host, frames) {
821
+ const hasPathProps = frames.strokeDashoffset || frames.strokeDasharray || frames.pathLength || frames.pathOffset;
822
+ if (!hasPathProps || !this.#isSvgGeometryElement(host)) {
823
+ return;
824
+ }
825
+ const styledHost = host;
826
+ const L = this.#getPathLength(host);
827
+ if (frames.strokeDasharray && frames.strokeDasharray.length > 0) {
828
+ styledHost.style.strokeDasharray = String(frames.strokeDasharray[0]);
829
+ }
830
+ else if (frames.strokeDashoffset || frames.pathLength || frames.pathOffset) {
831
+ styledHost.style.strokeDasharray = `${L}`;
832
+ }
833
+ if (frames.strokeDashoffset && frames.strokeDashoffset.length > 0) {
834
+ styledHost.style.strokeDashoffset = String(frames.strokeDashoffset[0]);
835
+ }
836
+ else if (frames.pathLength && frames.pathLength.length > 0) {
837
+ styledHost.style.strokeDashoffset = `${Number(frames.pathLength[0]) * L}`;
838
+ }
839
+ }
840
+ #getPathLength(host) {
841
+ if (!this.#isSvgGeometryElement(host))
842
+ return 28;
843
+ try {
844
+ return host.getTotalLength() || 28;
845
+ }
846
+ catch {
847
+ return 28;
848
+ }
849
+ }
850
+ #isSvgGeometryElement(host) {
851
+ const view = host.ownerDocument?.defaultView;
852
+ const SvgGeometryElement = view?.SVGGeometryElement;
853
+ if (typeof SvgGeometryElement === 'function' && host instanceof SvgGeometryElement) {
854
+ return true;
855
+ }
856
+ return typeof host.getTotalLength === 'function';
857
+ }
547
858
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: AnimationEngine, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
548
859
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: AnimationEngine, providedIn: 'root' });
549
860
  }
@@ -590,7 +901,7 @@ class MoveVariantsDirective {
590
901
  if (!state)
591
902
  return;
592
903
  this.#currentPlayer?.cancel();
593
- const { spring, duration, easing, delay, ...keyframesMap } = state;
904
+ const { spring, duration, easing, delay, transition, ...keyframesMap } = state;
594
905
  const keyframes = keyframesMap;
595
906
  const staggerDelay = this.#stagger?.getDelay(this.#host.nativeElement) ?? 0;
596
907
  const config = resolveMovementConfig(this.#defaults, {
@@ -603,6 +914,7 @@ class MoveVariantsDirective {
603
914
  config,
604
915
  spring: spring ?? this.moveSpring(),
605
916
  disabled: config.disabled,
917
+ transition,
606
918
  });
607
919
  });
608
920
  }
@@ -778,7 +1090,7 @@ function statesToKeyframes(from, to) {
778
1090
  for (const key of Object.keys(from)) {
779
1091
  const f = from[key];
780
1092
  const t = to[key];
781
- if (f !== undefined && t !== undefined) {
1093
+ if (typeof f === 'number' && typeof t === 'number') {
782
1094
  result[key] = [f, t];
783
1095
  }
784
1096
  }
@@ -877,13 +1189,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImpor
877
1189
  }]
878
1190
  }], propDecorators: { moveLeave: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveLeave", required: false }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }] } });
879
1191
 
1192
+ function optionalNumberAttribute$3(value) {
1193
+ if (value === undefined || value === null || value === '') {
1194
+ return undefined;
1195
+ }
1196
+ return Number(value);
1197
+ }
880
1198
  class MoveHoverDirective {
881
1199
  moveWhileHover = input.required(...(ngDevMode ? [{ debugName: "moveWhileHover" }] : /* istanbul ignore next */ []));
882
- moveDuration = input(undefined, ...(ngDevMode ? [{ debugName: "moveDuration" }] : /* istanbul ignore next */ []));
1200
+ moveDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$3 });
883
1201
  moveEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveEasing" }] : /* istanbul ignore next */ []));
884
- moveDelay = input(undefined, ...(ngDevMode ? [{ debugName: "moveDelay" }] : /* istanbul ignore next */ []));
1202
+ moveDelay = input(undefined, { ...(ngDevMode ? { debugName: "moveDelay" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$3 });
885
1203
  moveDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "moveDisabled" }] : /* istanbul ignore next */ []));
886
1204
  moveSpring = input(undefined, ...(ngDevMode ? [{ debugName: "moveSpring" }] : /* istanbul ignore next */ []));
1205
+ moveReverseDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveReverseDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$3 });
1206
+ moveReverseEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveReverseEasing" }] : /* istanbul ignore next */ []));
887
1207
  #defaults = inject(MOVEMENT_CONFIG);
888
1208
  #documentRef = inject(DOCUMENT);
889
1209
  #host = inject((ElementRef));
@@ -928,10 +1248,22 @@ class MoveHoverDirective {
928
1248
  return;
929
1249
  let frames = resolveMoveFrames(this.moveWhileHover(), 'enter');
930
1250
  if (reverse) {
1251
+ const reverseDuration = this.moveReverseDuration();
1252
+ if (reverseDuration === 0) {
1253
+ clearComposedStyle(this.#host.nativeElement, Object.keys(frames));
1254
+ return;
1255
+ }
931
1256
  frames = reverseFrames(frames);
932
1257
  }
1258
+ const reverseConfig = reverse
1259
+ ? resolveMovementConfig({ ...this.#defaults, duration: 200, easing: 'ease-out', delay: 0 }, {
1260
+ duration: this.moveReverseDuration() ?? this.moveDuration(),
1261
+ easing: this.moveReverseEasing(),
1262
+ delay: 0,
1263
+ }, isReduced)
1264
+ : config;
933
1265
  this.#currentPlayer = this.#engine.play(this.#host.nativeElement, frames, {
934
- config,
1266
+ config: reverseConfig,
935
1267
  spring: this.moveSpring(),
936
1268
  disabled: false,
937
1269
  });
@@ -940,7 +1272,7 @@ class MoveHoverDirective {
940
1272
  this.#currentPlayer?.cancel();
941
1273
  }
942
1274
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveHoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
943
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveHoverDirective, isStandalone: true, selector: "[moveWhileHover]", inputs: { moveWhileHover: { classPropertyName: "moveWhileHover", publicName: "moveWhileHover", isSignal: true, isRequired: true, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchEnd()" } }, ngImport: i0 });
1275
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveHoverDirective, isStandalone: true, selector: "[moveWhileHover]", inputs: { moveWhileHover: { classPropertyName: "moveWhileHover", publicName: "moveWhileHover", isSignal: true, isRequired: true, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null }, moveReverseDuration: { classPropertyName: "moveReverseDuration", publicName: "moveReverseDuration", isSignal: true, isRequired: false, transformFunction: null }, moveReverseEasing: { classPropertyName: "moveReverseEasing", publicName: "moveReverseEasing", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchEnd()" } }, ngImport: i0 });
944
1276
  }
945
1277
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveHoverDirective, decorators: [{
946
1278
  type: Directive,
@@ -954,15 +1286,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImpor
954
1286
  '(touchcancel)': 'onTouchEnd()',
955
1287
  },
956
1288
  }]
957
- }], propDecorators: { moveWhileHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveWhileHover", required: true }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }] } });
1289
+ }], propDecorators: { moveWhileHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveWhileHover", required: true }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }], moveReverseDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseDuration", required: false }] }], moveReverseEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseEasing", required: false }] }] } });
958
1290
 
1291
+ function optionalNumberAttribute$2(value) {
1292
+ if (value === undefined || value === null || value === '') {
1293
+ return undefined;
1294
+ }
1295
+ return Number(value);
1296
+ }
959
1297
  class MoveTapDirective {
960
1298
  moveWhileTap = input.required(...(ngDevMode ? [{ debugName: "moveWhileTap" }] : /* istanbul ignore next */ []));
961
- moveDuration = input(undefined, ...(ngDevMode ? [{ debugName: "moveDuration" }] : /* istanbul ignore next */ []));
1299
+ moveDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$2 });
962
1300
  moveEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveEasing" }] : /* istanbul ignore next */ []));
963
- moveDelay = input(undefined, ...(ngDevMode ? [{ debugName: "moveDelay" }] : /* istanbul ignore next */ []));
1301
+ moveDelay = input(undefined, { ...(ngDevMode ? { debugName: "moveDelay" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$2 });
964
1302
  moveDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "moveDisabled" }] : /* istanbul ignore next */ []));
965
1303
  moveSpring = input(undefined, ...(ngDevMode ? [{ debugName: "moveSpring" }] : /* istanbul ignore next */ []));
1304
+ moveReverseDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveReverseDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$2 });
1305
+ moveReverseEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveReverseEasing" }] : /* istanbul ignore next */ []));
966
1306
  #defaults = inject(MOVEMENT_CONFIG);
967
1307
  #documentRef = inject(DOCUMENT);
968
1308
  #host = inject((ElementRef));
@@ -994,10 +1334,22 @@ class MoveTapDirective {
994
1334
  return;
995
1335
  let frames = resolveMoveFrames(this.moveWhileTap(), 'enter');
996
1336
  if (reverse) {
1337
+ const reverseDuration = this.moveReverseDuration();
1338
+ if (reverseDuration === 0) {
1339
+ clearComposedStyle(this.#host.nativeElement, Object.keys(frames));
1340
+ return;
1341
+ }
997
1342
  frames = reverseFrames(frames);
998
1343
  }
1344
+ const reverseConfig = reverse
1345
+ ? resolveMovementConfig({ ...this.#defaults, duration: 200, easing: 'ease-out', delay: 0 }, {
1346
+ duration: this.moveReverseDuration() ?? this.moveDuration(),
1347
+ easing: this.moveReverseEasing(),
1348
+ delay: 0,
1349
+ }, isReduced)
1350
+ : config;
999
1351
  this.#currentPlayer = this.#engine.play(this.#host.nativeElement, frames, {
1000
- config,
1352
+ config: reverseConfig,
1001
1353
  spring: this.moveSpring(),
1002
1354
  disabled: false,
1003
1355
  });
@@ -1006,7 +1358,7 @@ class MoveTapDirective {
1006
1358
  this.#currentPlayer?.cancel();
1007
1359
  }
1008
1360
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTapDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1009
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveTapDirective, isStandalone: true, selector: "[moveWhileTap]", inputs: { moveWhileTap: { classPropertyName: "moveWhileTap", publicName: "moveWhileTap", isSignal: true, isRequired: true, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointerdown": "onPointerDown()", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "pointerleave": "onPointerUp()" } }, ngImport: i0 });
1361
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveTapDirective, isStandalone: true, selector: "[moveWhileTap]", inputs: { moveWhileTap: { classPropertyName: "moveWhileTap", publicName: "moveWhileTap", isSignal: true, isRequired: true, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null }, moveReverseDuration: { classPropertyName: "moveReverseDuration", publicName: "moveReverseDuration", isSignal: true, isRequired: false, transformFunction: null }, moveReverseEasing: { classPropertyName: "moveReverseEasing", publicName: "moveReverseEasing", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointerdown": "onPointerDown()", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "pointerleave": "onPointerUp()" } }, ngImport: i0 });
1010
1362
  }
1011
1363
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTapDirective, decorators: [{
1012
1364
  type: Directive,
@@ -1019,7 +1371,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImpor
1019
1371
  '(pointerleave)': 'onPointerUp()',
1020
1372
  },
1021
1373
  }]
1022
- }], propDecorators: { moveWhileTap: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveWhileTap", required: true }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }] } });
1374
+ }], propDecorators: { moveWhileTap: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveWhileTap", required: true }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }], moveReverseDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseDuration", required: false }] }], moveReverseEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseEasing", required: false }] }] } });
1023
1375
 
1024
1376
  class MoveStaggerDirective {
1025
1377
  moveStagger = input.required(...(ngDevMode ? [{ debugName: "moveStagger" }] : /* istanbul ignore next */ []));
@@ -1035,9 +1387,14 @@ class MoveStaggerDirective {
1035
1387
  if (!this.#children.has(el))
1036
1388
  return 0;
1037
1389
  const list = Array.from(this.#children).sort((a, b) => {
1038
- // Unreliable on detached elements, but they are in DOM when sorting
1390
+ if (a === b)
1391
+ return 0;
1039
1392
  const pos = a.compareDocumentPosition(b);
1040
- return pos & Node.DOCUMENT_POSITION_PRECEDING ? 1 : -1;
1393
+ if (pos & Node.DOCUMENT_POSITION_PRECEDING)
1394
+ return 1;
1395
+ if (pos & Node.DOCUMENT_POSITION_FOLLOWING)
1396
+ return -1;
1397
+ return 0;
1041
1398
  });
1042
1399
  const index = list.indexOf(el);
1043
1400
  if (index === -1)
@@ -1416,6 +1773,11 @@ class MoveScrollDirective {
1416
1773
  const view = this.#documentRef.defaultView;
1417
1774
  if (!view)
1418
1775
  return;
1776
+ // Validate scroll offsets
1777
+ const offsets = this.moveScrollOffset();
1778
+ if (!isValidScrollOffset(offsets[0]) || !isValidScrollOffset(offsets[1])) {
1779
+ return;
1780
+ }
1419
1781
  this.#player = this.#engine.play(this.#host.nativeElement, keyframes, {
1420
1782
  config: { duration: 1000, easing: 'linear', delay: 0, disabled: false, iterations: 1 },
1421
1783
  });
@@ -1658,7 +2020,9 @@ class MoveDragDirective {
1658
2020
  return;
1659
2021
  this.#isDragging = true;
1660
2022
  this.#pointerId = e.pointerId;
1661
- this.#host.nativeElement.setPointerCapture(e.pointerId);
2023
+ if (typeof this.#host.nativeElement.setPointerCapture === 'function') {
2024
+ this.#host.nativeElement.setPointerCapture(e.pointerId);
2025
+ }
1662
2026
  this.#player?.cancel();
1663
2027
  // read bounds cleanly before next render
1664
2028
  this.#dragBounds = this.resolveBounds();
@@ -1679,7 +2043,9 @@ class MoveDragDirective {
1679
2043
  if (!this.#isDragging || e.pointerId !== this.#pointerId)
1680
2044
  return;
1681
2045
  this.#isDragging = false;
1682
- this.#host.nativeElement.releasePointerCapture(e.pointerId);
2046
+ if (typeof this.#host.nativeElement.releasePointerCapture === 'function') {
2047
+ this.#host.nativeElement.releasePointerCapture(e.pointerId);
2048
+ }
1683
2049
  this.#pointerId = null;
1684
2050
  this.#host.nativeElement.style.touchAction = '';
1685
2051
  this.#host.nativeElement.style.userSelect = '';
@@ -1708,7 +2074,7 @@ class MoveDragDirective {
1708
2074
  let x = this.#_x;
1709
2075
  let y = this.#_y;
1710
2076
  if (this.#dragBounds) {
1711
- const elastic = this.moveDragElastic();
2077
+ const elastic = validateDragElastic(this.moveDragElastic());
1712
2078
  if (this.#dragBounds.left !== undefined && x < this.#dragBounds.left) {
1713
2079
  x = this.#dragBounds.left - (this.#dragBounds.left - x) * elastic;
1714
2080
  }
@@ -1742,7 +2108,7 @@ class MoveDragDirective {
1742
2108
  // Find the currently visible coordinates (which include elasticity)
1743
2109
  let currentVisX = this.#_x;
1744
2110
  let currentVisY = this.#_y;
1745
- const elastic = this.moveDragElastic();
2111
+ const elastic = validateDragElastic(this.moveDragElastic());
1746
2112
  if (this.#dragBounds.left !== undefined && this.#_x < this.#dragBounds.left) {
1747
2113
  currentVisX = this.#dragBounds.left - (this.#dragBounds.left - this.#_x) * elastic;
1748
2114
  }
@@ -1768,6 +2134,19 @@ class MoveDragDirective {
1768
2134
  }
1769
2135
  }
1770
2136
  ngOnDestroy() {
2137
+ if (this.#pointerId !== null) {
2138
+ try {
2139
+ if (typeof this.#host.nativeElement.releasePointerCapture === 'function') {
2140
+ this.#host.nativeElement.releasePointerCapture(this.#pointerId);
2141
+ }
2142
+ }
2143
+ catch {
2144
+ // Element may already be detached
2145
+ }
2146
+ this.#pointerId = null;
2147
+ }
2148
+ this.#host.nativeElement.style.touchAction = '';
2149
+ this.#host.nativeElement.style.userSelect = '';
1771
2150
  this.#player?.cancel();
1772
2151
  }
1773
2152
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -1888,6 +2267,7 @@ class MoveTextDirective {
1888
2267
  #platformId = inject(PLATFORM_ID);
1889
2268
  #host = inject((ElementRef));
1890
2269
  #engine = inject(AnimationEngine);
2270
+ #renderer = inject(Renderer2);
1891
2271
  #players = [];
1892
2272
  #spans = [];
1893
2273
  #observer = null;
@@ -1948,21 +2328,24 @@ class MoveTextDirective {
1948
2328
  #splitText() {
1949
2329
  const el = this.#host.nativeElement;
1950
2330
  const text = (el.textContent ?? '').trim();
1951
- el.innerHTML = '';
1952
- el.setAttribute('aria-label', text);
2331
+ // Clear existing content safely via Renderer2
2332
+ while (el.firstChild) {
2333
+ this.#renderer.removeChild(el, el.firstChild);
2334
+ }
2335
+ this.#renderer.setAttribute(el, 'aria-label', text);
1953
2336
  const byChars = this.moveTextSplit() === 'chars';
1954
2337
  if (byChars) {
1955
2338
  // Split character by character, preserving spaces as text nodes
1956
2339
  [...text].forEach((char) => {
1957
2340
  if (char === ' ') {
1958
- el.appendChild(this.#documentRef.createTextNode(' '));
2341
+ this.#renderer.appendChild(el, this.#documentRef.createTextNode(' '));
1959
2342
  return;
1960
2343
  }
1961
- const span = this.#documentRef.createElement('span');
1962
- span.setAttribute('aria-hidden', 'true');
1963
- span.style.display = 'inline-block';
1964
- span.textContent = char;
1965
- el.appendChild(span);
2344
+ const span = this.#renderer.createElement('span');
2345
+ this.#renderer.setAttribute(span, 'aria-hidden', 'true');
2346
+ this.#renderer.setStyle(span, 'display', 'inline-block');
2347
+ this.#renderer.setProperty(span, 'textContent', char);
2348
+ this.#renderer.appendChild(el, span);
1966
2349
  this.#spans.push(span);
1967
2350
  });
1968
2351
  }
@@ -1970,12 +2353,12 @@ class MoveTextDirective {
1970
2353
  // Split word by word
1971
2354
  const words = text.split(/\s+/);
1972
2355
  words.forEach((word, index) => {
1973
- const span = this.#documentRef.createElement('span');
1974
- span.setAttribute('aria-hidden', 'true');
1975
- span.style.display = 'inline-block';
1976
- span.style.whiteSpace = 'pre';
1977
- span.textContent = index < words.length - 1 ? word + ' ' : word;
1978
- el.appendChild(span);
2356
+ const span = this.#renderer.createElement('span');
2357
+ this.#renderer.setAttribute(span, 'aria-hidden', 'true');
2358
+ this.#renderer.setStyle(span, 'display', 'inline-block');
2359
+ this.#renderer.setStyle(span, 'white-space', 'pre');
2360
+ this.#renderer.setProperty(span, 'textContent', index < words.length - 1 ? word + ' ' : word);
2361
+ this.#renderer.appendChild(el, span);
1979
2362
  this.#spans.push(span);
1980
2363
  });
1981
2364
  }
@@ -1983,6 +2366,8 @@ class MoveTextDirective {
1983
2366
  ngOnDestroy() {
1984
2367
  this.#observer?.disconnect();
1985
2368
  this.#players.forEach((p) => p.cancel());
2369
+ this.#players = [];
2370
+ this.#spans = [];
1986
2371
  }
1987
2372
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1988
2373
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveTextDirective, isStandalone: true, selector: "[moveText]", inputs: { moveText: { classPropertyName: "moveText", publicName: "moveText", isSignal: true, isRequired: false, transformFunction: null }, moveTextSplit: { classPropertyName: "moveTextSplit", publicName: "moveTextSplit", isSignal: true, isRequired: false, transformFunction: null }, moveTextStagger: { classPropertyName: "moveTextStagger", publicName: "moveTextStagger", isSignal: true, isRequired: false, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
@@ -2270,6 +2655,283 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImpor
2270
2655
  }]
2271
2656
  }], propDecorators: { moveLoop: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveLoop", required: false }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }] } });
2272
2657
 
2658
+ function optionalNumberAttribute$1(value) {
2659
+ if (value === undefined || value === null || value === '') {
2660
+ return undefined;
2661
+ }
2662
+ return Number(value);
2663
+ }
2664
+ class MoveTargetDirective {
2665
+ moveTarget = input.required(...(ngDevMode ? [{ debugName: "moveTarget" }] : /* istanbul ignore next */ []));
2666
+ moveFrames = input.required(...(ngDevMode ? [{ debugName: "moveFrames" }] : /* istanbul ignore next */ []));
2667
+ moveDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$1 });
2668
+ moveEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveEasing" }] : /* istanbul ignore next */ []));
2669
+ moveDelay = input(undefined, { ...(ngDevMode ? { debugName: "moveDelay" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$1 });
2670
+ moveSpring = input(undefined, ...(ngDevMode ? [{ debugName: "moveSpring" }] : /* istanbul ignore next */ []));
2671
+ moveDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "moveDisabled" }] : /* istanbul ignore next */ []));
2672
+ moveReverseDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveReverseDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute$1 });
2673
+ moveReverseEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveReverseEasing" }] : /* istanbul ignore next */ []));
2674
+ moveTransition = input(undefined, ...(ngDevMode ? [{ debugName: "moveTransition" }] : /* istanbul ignore next */ []));
2675
+ #defaults = inject(MOVEMENT_CONFIG);
2676
+ #documentRef = inject(DOCUMENT);
2677
+ #host = inject((ElementRef));
2678
+ #engine = inject(AnimationEngine);
2679
+ #currentPlayer = null;
2680
+ #hasPlayedForward = false;
2681
+ #targetEffect = effect(() => {
2682
+ const active = this.moveTarget();
2683
+ const frames = this.moveFrames();
2684
+ if (active) {
2685
+ this.#playForward(frames);
2686
+ this.#hasPlayedForward = true;
2687
+ return;
2688
+ }
2689
+ if (this.#hasPlayedForward) {
2690
+ this.#playReverse(frames);
2691
+ }
2692
+ }, ...(ngDevMode ? [{ debugName: "#targetEffect" }] : /* istanbul ignore next */ []));
2693
+ #playForward(frames) {
2694
+ this.#currentPlayer?.cancel();
2695
+ const isReduced = prefersReducedMotion(this.#documentRef);
2696
+ const config = resolveMovementConfig(this.#defaults, {
2697
+ duration: this.moveDuration(),
2698
+ easing: this.moveEasing(),
2699
+ delay: this.moveDelay(),
2700
+ disabled: this.moveDisabled(),
2701
+ }, isReduced);
2702
+ this.#currentPlayer = this.#engine.play(this.#host.nativeElement, frames, {
2703
+ config,
2704
+ spring: this.moveSpring(),
2705
+ disabled: config.disabled,
2706
+ transition: this.moveTransition(),
2707
+ });
2708
+ }
2709
+ #playReverse(frames) {
2710
+ this.#currentPlayer?.cancel();
2711
+ const isReduced = prefersReducedMotion(this.#documentRef);
2712
+ const config = resolveMovementConfig({ ...this.#defaults, duration: 200, easing: 'ease-out', delay: 0 }, {
2713
+ duration: this.moveReverseDuration() ?? this.moveDuration(),
2714
+ easing: this.moveReverseEasing(),
2715
+ delay: 0,
2716
+ disabled: this.moveDisabled(),
2717
+ }, isReduced);
2718
+ this.#currentPlayer = this.#engine.play(this.#host.nativeElement, reverseFrames(frames), {
2719
+ config,
2720
+ spring: this.moveSpring(),
2721
+ disabled: config.disabled,
2722
+ transition: this.moveTransition(),
2723
+ });
2724
+ }
2725
+ ngOnDestroy() {
2726
+ this.#targetEffect.destroy();
2727
+ this.#currentPlayer?.cancel();
2728
+ }
2729
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTargetDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2730
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveTargetDirective, isStandalone: true, selector: "[moveTarget]", inputs: { moveTarget: { classPropertyName: "moveTarget", publicName: "moveTarget", isSignal: true, isRequired: true, transformFunction: null }, moveFrames: { classPropertyName: "moveFrames", publicName: "moveFrames", isSignal: true, isRequired: true, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveReverseDuration: { classPropertyName: "moveReverseDuration", publicName: "moveReverseDuration", isSignal: true, isRequired: false, transformFunction: null }, moveReverseEasing: { classPropertyName: "moveReverseEasing", publicName: "moveReverseEasing", isSignal: true, isRequired: false, transformFunction: null }, moveTransition: { classPropertyName: "moveTransition", publicName: "moveTransition", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
2731
+ }
2732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTargetDirective, decorators: [{
2733
+ type: Directive,
2734
+ args: [{
2735
+ selector: '[moveTarget]',
2736
+ standalone: true,
2737
+ }]
2738
+ }], propDecorators: { moveTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveTarget", required: true }] }], moveFrames: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveFrames", required: true }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveReverseDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseDuration", required: false }] }], moveReverseEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseEasing", required: false }] }], moveTransition: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveTransition", required: false }] }] } });
2739
+
2740
+ function optionalNumberAttribute(value) {
2741
+ if (value === undefined || value === null || value === '') {
2742
+ return undefined;
2743
+ }
2744
+ return Number(value);
2745
+ }
2746
+ class MoveTriggerDirective {
2747
+ moveTrigger = input.required(...(ngDevMode ? [{ debugName: "moveTrigger" }] : /* istanbul ignore next */ []));
2748
+ moveFrames = input.required(...(ngDevMode ? [{ debugName: "moveFrames" }] : /* istanbul ignore next */ []));
2749
+ moveResetFrames = input(undefined, ...(ngDevMode ? [{ debugName: "moveResetFrames" }] : /* istanbul ignore next */ []));
2750
+ moveResetState = input('clear', ...(ngDevMode ? [{ debugName: "moveResetState" }] : /* istanbul ignore next */ []));
2751
+ moveDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute });
2752
+ moveEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveEasing" }] : /* istanbul ignore next */ []));
2753
+ moveDelay = input(undefined, { ...(ngDevMode ? { debugName: "moveDelay" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute });
2754
+ moveSpring = input(undefined, ...(ngDevMode ? [{ debugName: "moveSpring" }] : /* istanbul ignore next */ []));
2755
+ moveDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "moveDisabled" }] : /* istanbul ignore next */ []));
2756
+ moveReverseDuration = input(undefined, { ...(ngDevMode ? { debugName: "moveReverseDuration" } : /* istanbul ignore next */ {}), transform: optionalNumberAttribute });
2757
+ moveReverseEasing = input(undefined, ...(ngDevMode ? [{ debugName: "moveReverseEasing" }] : /* istanbul ignore next */ []));
2758
+ #defaults = inject(MOVEMENT_CONFIG);
2759
+ #documentRef = inject(DOCUMENT);
2760
+ #host = inject((ElementRef));
2761
+ #engine = inject(AnimationEngine);
2762
+ #currentPlayer = null;
2763
+ #hasPlayedForward = false;
2764
+ #triggerEffect = effect(() => {
2765
+ const active = this.moveTrigger();
2766
+ const frames = this.moveFrames();
2767
+ if (active) {
2768
+ this.#playForward(frames);
2769
+ this.#hasPlayedForward = true;
2770
+ return;
2771
+ }
2772
+ if (this.#hasPlayedForward) {
2773
+ this.#playReset(frames);
2774
+ }
2775
+ }, ...(ngDevMode ? [{ debugName: "#triggerEffect" }] : /* istanbul ignore next */ []));
2776
+ play(frames) {
2777
+ const targetFrames = frames ?? this.moveFrames();
2778
+ this.#playForward(targetFrames);
2779
+ this.#hasPlayedForward = true;
2780
+ return this.#currentPlayer?.finished ?? Promise.resolve();
2781
+ }
2782
+ reset() {
2783
+ this.#currentPlayer?.cancel();
2784
+ const frames = this.moveFrames();
2785
+ this.#applyReset(frames);
2786
+ }
2787
+ set(state) {
2788
+ this.#currentPlayer?.cancel();
2789
+ applyComposedStyle(this.#host.nativeElement, state);
2790
+ }
2791
+ #playForward(frames) {
2792
+ this.#currentPlayer?.cancel();
2793
+ const isReduced = prefersReducedMotion(this.#documentRef);
2794
+ const config = resolveMovementConfig(this.#defaults, {
2795
+ duration: this.moveDuration(),
2796
+ easing: this.moveEasing(),
2797
+ delay: this.moveDelay(),
2798
+ disabled: this.moveDisabled(),
2799
+ }, isReduced);
2800
+ this.#currentPlayer = this.#engine.play(this.#host.nativeElement, frames, {
2801
+ config,
2802
+ spring: this.moveSpring(),
2803
+ disabled: config.disabled,
2804
+ });
2805
+ }
2806
+ #playReset(frames) {
2807
+ this.#currentPlayer?.cancel();
2808
+ const resetFrames = this.moveResetFrames();
2809
+ if (resetFrames) {
2810
+ const isReduced = prefersReducedMotion(this.#documentRef);
2811
+ const config = resolveMovementConfig({ ...this.#defaults, duration: 200, easing: 'ease-out', delay: 0 }, {
2812
+ duration: this.moveReverseDuration() ?? this.moveDuration(),
2813
+ easing: this.moveReverseEasing(),
2814
+ delay: 0,
2815
+ disabled: this.moveDisabled(),
2816
+ }, isReduced);
2817
+ this.#currentPlayer = this.#engine.play(this.#host.nativeElement, resetFrames, {
2818
+ config,
2819
+ spring: this.moveSpring(),
2820
+ disabled: config.disabled,
2821
+ });
2822
+ return;
2823
+ }
2824
+ const reverseDuration = this.moveReverseDuration();
2825
+ if (reverseDuration === 0) {
2826
+ this.#applyReset(frames);
2827
+ return;
2828
+ }
2829
+ const isReduced = prefersReducedMotion(this.#documentRef);
2830
+ const config = resolveMovementConfig({ ...this.#defaults, duration: 200, easing: 'ease-out', delay: 0 }, {
2831
+ duration: reverseDuration ?? this.moveDuration(),
2832
+ easing: this.moveReverseEasing(),
2833
+ delay: 0,
2834
+ disabled: this.moveDisabled(),
2835
+ }, isReduced);
2836
+ if (config.disabled) {
2837
+ this.#applyReset(frames);
2838
+ return;
2839
+ }
2840
+ // For triggers, reverse is typically not desired; we reset to initial/clear.
2841
+ // We apply the initial style of the forward frames to restore state.
2842
+ this.#applyReset(frames);
2843
+ }
2844
+ #applyReset(frames) {
2845
+ const mode = this.moveResetState();
2846
+ const host = this.#host.nativeElement;
2847
+ if (mode === 'clear') {
2848
+ clearComposedStyle(host, Object.keys(frames));
2849
+ return;
2850
+ }
2851
+ if (mode === 'initial') {
2852
+ clearComposedStyle(host, Object.keys(frames));
2853
+ applyComposedStyle(host, composeInitialStyle(frames));
2854
+ return;
2855
+ }
2856
+ if (mode === 'final') {
2857
+ clearComposedStyle(host, Object.keys(frames));
2858
+ applyComposedStyle(host, composeFinalStyle(frames));
2859
+ }
2860
+ }
2861
+ ngOnDestroy() {
2862
+ this.#triggerEffect.destroy();
2863
+ this.#currentPlayer?.cancel();
2864
+ const frames = this.moveFrames();
2865
+ if (frames) {
2866
+ clearComposedStyle(this.#host.nativeElement, Object.keys(frames));
2867
+ }
2868
+ }
2869
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2870
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: MoveTriggerDirective, isStandalone: true, selector: "[moveTrigger]", inputs: { moveTrigger: { classPropertyName: "moveTrigger", publicName: "moveTrigger", isSignal: true, isRequired: true, transformFunction: null }, moveFrames: { classPropertyName: "moveFrames", publicName: "moveFrames", isSignal: true, isRequired: true, transformFunction: null }, moveResetFrames: { classPropertyName: "moveResetFrames", publicName: "moveResetFrames", isSignal: true, isRequired: false, transformFunction: null }, moveResetState: { classPropertyName: "moveResetState", publicName: "moveResetState", isSignal: true, isRequired: false, transformFunction: null }, moveDuration: { classPropertyName: "moveDuration", publicName: "moveDuration", isSignal: true, isRequired: false, transformFunction: null }, moveEasing: { classPropertyName: "moveEasing", publicName: "moveEasing", isSignal: true, isRequired: false, transformFunction: null }, moveDelay: { classPropertyName: "moveDelay", publicName: "moveDelay", isSignal: true, isRequired: false, transformFunction: null }, moveSpring: { classPropertyName: "moveSpring", publicName: "moveSpring", isSignal: true, isRequired: false, transformFunction: null }, moveDisabled: { classPropertyName: "moveDisabled", publicName: "moveDisabled", isSignal: true, isRequired: false, transformFunction: null }, moveReverseDuration: { classPropertyName: "moveReverseDuration", publicName: "moveReverseDuration", isSignal: true, isRequired: false, transformFunction: null }, moveReverseEasing: { classPropertyName: "moveReverseEasing", publicName: "moveReverseEasing", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["moveTrigger"], ngImport: i0 });
2871
+ }
2872
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: MoveTriggerDirective, decorators: [{
2873
+ type: Directive,
2874
+ args: [{
2875
+ selector: '[moveTrigger]',
2876
+ standalone: true,
2877
+ exportAs: 'moveTrigger',
2878
+ }]
2879
+ }], propDecorators: { moveTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveTrigger", required: true }] }], moveFrames: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveFrames", required: true }] }], moveResetFrames: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveResetFrames", required: false }] }], moveResetState: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveResetState", required: false }] }], moveDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDuration", required: false }] }], moveEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveEasing", required: false }] }], moveDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDelay", required: false }] }], moveSpring: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveSpring", required: false }] }], moveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveDisabled", required: false }] }], moveReverseDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseDuration", required: false }] }], moveReverseEasing: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveReverseEasing", required: false }] }] } });
2880
+
2881
+ /**
2882
+ * Returns keyframes for a path-drawing animation.
2883
+ * Ideal for SVG `<path>`, `<circle>`, `<line>`, etc.
2884
+ *
2885
+ * @example
2886
+ * ```html
2887
+ * <path [moveTarget]="animate()" [moveFrames]="movePathDraw({ opacity: [0, 1] })" moveDuration="700" />
2888
+ * ```
2889
+ */
2890
+ function movePathDraw(overrides) {
2891
+ return {
2892
+ pathLength: [0, 1],
2893
+ opacity: [0, 1],
2894
+ ...overrides,
2895
+ };
2896
+ }
2897
+ /**
2898
+ * Returns keyframes for a subtle pulse animation on an icon.
2899
+ */
2900
+ function moveIconPulse(overrides) {
2901
+ return {
2902
+ scale: [1, 1.08, 1],
2903
+ opacity: [1, 0.85, 1],
2904
+ ...overrides,
2905
+ };
2906
+ }
2907
+ /**
2908
+ * Returns keyframes for a subtle bounce animation on an icon.
2909
+ */
2910
+ function moveIconBounce(overrides) {
2911
+ return {
2912
+ y: [0, -3, 0],
2913
+ ...overrides,
2914
+ };
2915
+ }
2916
+ /**
2917
+ * Returns keyframes for a subtle shake animation on an icon.
2918
+ */
2919
+ function moveIconShake(overrides) {
2920
+ return {
2921
+ rotate: [0, -8, 8, -8, 8, 0],
2922
+ ...overrides,
2923
+ };
2924
+ }
2925
+ /**
2926
+ * Returns keyframes for a subtle rotate animation on an icon.
2927
+ */
2928
+ function moveIconRotate(overrides) {
2929
+ return {
2930
+ rotate: [0, 15, 0],
2931
+ ...overrides,
2932
+ };
2933
+ }
2934
+
2273
2935
  function provideMovement(config = {}) {
2274
2936
  return makeEnvironmentProviders([
2275
2937
  {
@@ -2301,6 +2963,8 @@ const MOVEMENT_DIRECTIVES = [
2301
2963
  MoveParallaxDirective,
2302
2964
  MoveAnimationDirective,
2303
2965
  MoveLoopDirective,
2966
+ MoveTargetDirective,
2967
+ MoveTriggerDirective,
2304
2968
  ];
2305
2969
 
2306
2970
  /*
@@ -2311,5 +2975,5 @@ const MOVEMENT_DIRECTIVES = [
2311
2975
  * Generated bundle index. Do not edit.
2312
2976
  */
2313
2977
 
2314
- export { AnimationEngine, MOVEMENT_CONFIG, MOVEMENT_DEFAULTS, MOVEMENT_DIRECTIVES, MOVE_PRESENCE_PARENT, MOVE_PRESETS, MOVE_STAGGER_PARENT, MOVE_VARIANTS_PARENT, MoveAnimateDirective, MoveAnimationDirective, MoveDragDirective, MoveEnterDirective, MoveFocusDirective, MoveHoverDirective, MoveInViewDirective, MoveLayoutDirective, MoveLeaveDirective, MoveLoopDirective, MoveParallaxDirective, MovePresenceDirective, MoveScrollDirective, MoveSmoothScrollDirective, MoveStaggerDirective, MoveTapDirective, MoveTextDirective, MoveVariantsDirective, SmoothScrollService, SpringPlayer, WaapiPlayer, applyInitialStyles, clearInitialStyles, prefersReducedMotion, provideMovement, resolveMoveFrames, resolveMovementConfig, reverseFrames };
2978
+ export { AnimationEngine, MOVEMENT_CONFIG, MOVEMENT_DEFAULTS, MOVEMENT_DIRECTIVES, MOVE_PRESENCE_PARENT, MOVE_PRESETS, MOVE_STAGGER_PARENT, MOVE_VARIANTS_PARENT, MoveAnimateDirective, MoveAnimationDirective, MoveDragDirective, MoveEnterDirective, MoveFocusDirective, MoveHoverDirective, MoveInViewDirective, MoveLayoutDirective, MoveLeaveDirective, MoveLoopDirective, MoveParallaxDirective, MovePresenceDirective, MoveScrollDirective, MoveSmoothScrollDirective, MoveStaggerDirective, MoveTapDirective, MoveTargetDirective, MoveTextDirective, MoveTriggerDirective, MoveVariantsDirective, SmoothScrollService, SpringPlayer, WaapiPlayer, applyInitialStyles, clearComposedStyle, clearInitialStyles, composeTransitionKeyframes, isValidScrollOffset, moveIconBounce, moveIconPulse, moveIconRotate, moveIconShake, movePathDraw, prefersReducedMotion, provideMovement, resolveMoveFrames, resolveMovementConfig, reverseFrames, validateDragElastic, validateSpring };
2315
2979
  //# sourceMappingURL=angular-movement.mjs.map