gsap-react-marquee 0.1.1 → 0.1.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.
- package/dist/components/gsap-react-marquee.type.d.ts +2 -1
- package/dist/components/gsap-reactmarquee.utils.d.ts +73 -8
- package/dist/index.cjs.js +1035 -78
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +76 -10
- package/dist/index.esm.js +1035 -77
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var require$$0 = require('react');
|
|
6
6
|
var react = require('@gsap/react');
|
|
7
|
-
var gsap = require('gsap');
|
|
7
|
+
var gsap$1 = require('gsap');
|
|
8
8
|
|
|
9
9
|
var jsxRuntime = {exports: {}};
|
|
10
10
|
|
|
@@ -425,6 +425,710 @@ if (process.env.NODE_ENV === 'production') {
|
|
|
425
425
|
|
|
426
426
|
var jsxRuntimeExports = jsxRuntime.exports;
|
|
427
427
|
|
|
428
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
429
|
+
|
|
430
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); return Constructor; }
|
|
431
|
+
|
|
432
|
+
/*!
|
|
433
|
+
* Observer 3.13.0
|
|
434
|
+
* https://gsap.com
|
|
435
|
+
*
|
|
436
|
+
* @license Copyright 2008-2025, GreenSock. All rights reserved.
|
|
437
|
+
* Subject to the terms at https://gsap.com/standard-license
|
|
438
|
+
* @author: Jack Doyle, jack@greensock.com
|
|
439
|
+
*/
|
|
440
|
+
|
|
441
|
+
/* eslint-disable */
|
|
442
|
+
var gsap,
|
|
443
|
+
_coreInitted,
|
|
444
|
+
_win,
|
|
445
|
+
_doc,
|
|
446
|
+
_docEl,
|
|
447
|
+
_body,
|
|
448
|
+
_isTouch,
|
|
449
|
+
_pointerType,
|
|
450
|
+
ScrollTrigger,
|
|
451
|
+
_root,
|
|
452
|
+
_normalizer,
|
|
453
|
+
_eventTypes,
|
|
454
|
+
_context,
|
|
455
|
+
_getGSAP = function _getGSAP() {
|
|
456
|
+
return gsap || typeof window !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap;
|
|
457
|
+
},
|
|
458
|
+
_startup = 1,
|
|
459
|
+
_observers = [],
|
|
460
|
+
_scrollers = [],
|
|
461
|
+
_proxies = [],
|
|
462
|
+
_getTime = Date.now,
|
|
463
|
+
_bridge = function _bridge(name, value) {
|
|
464
|
+
return value;
|
|
465
|
+
},
|
|
466
|
+
_integrate = function _integrate() {
|
|
467
|
+
var core = ScrollTrigger.core,
|
|
468
|
+
data = core.bridge || {},
|
|
469
|
+
scrollers = core._scrollers,
|
|
470
|
+
proxies = core._proxies;
|
|
471
|
+
scrollers.push.apply(scrollers, _scrollers);
|
|
472
|
+
proxies.push.apply(proxies, _proxies);
|
|
473
|
+
_scrollers = scrollers;
|
|
474
|
+
_proxies = proxies;
|
|
475
|
+
|
|
476
|
+
_bridge = function _bridge(name, value) {
|
|
477
|
+
return data[name](value);
|
|
478
|
+
};
|
|
479
|
+
},
|
|
480
|
+
_getProxyProp = function _getProxyProp(element, property) {
|
|
481
|
+
return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
|
|
482
|
+
},
|
|
483
|
+
_isViewport = function _isViewport(el) {
|
|
484
|
+
return !!~_root.indexOf(el);
|
|
485
|
+
},
|
|
486
|
+
_addListener = function _addListener(element, type, func, passive, capture) {
|
|
487
|
+
return element.addEventListener(type, func, {
|
|
488
|
+
passive: passive !== false,
|
|
489
|
+
capture: !!capture
|
|
490
|
+
});
|
|
491
|
+
},
|
|
492
|
+
_removeListener = function _removeListener(element, type, func, capture) {
|
|
493
|
+
return element.removeEventListener(type, func, !!capture);
|
|
494
|
+
},
|
|
495
|
+
_scrollLeft = "scrollLeft",
|
|
496
|
+
_scrollTop = "scrollTop",
|
|
497
|
+
_onScroll = function _onScroll() {
|
|
498
|
+
return _normalizer && _normalizer.isPressed || _scrollers.cache++;
|
|
499
|
+
},
|
|
500
|
+
_scrollCacheFunc = function _scrollCacheFunc(f, doNotCache) {
|
|
501
|
+
var cachingFunc = function cachingFunc(value) {
|
|
502
|
+
// since reading the scrollTop/scrollLeft/pageOffsetY/pageOffsetX can trigger a layout, this function allows us to cache the value so it only gets read fresh after a "scroll" event fires (or while we're refreshing because that can lengthen the page and alter the scroll position). when "soft" is true, that means don't actually set the scroll, but cache the new value instead (useful in ScrollSmoother)
|
|
503
|
+
if (value || value === 0) {
|
|
504
|
+
_startup && (_win.history.scrollRestoration = "manual"); // otherwise the new position will get overwritten by the browser onload.
|
|
505
|
+
|
|
506
|
+
var isNormalizing = _normalizer && _normalizer.isPressed;
|
|
507
|
+
value = cachingFunc.v = Math.round(value) || (_normalizer && _normalizer.iOS ? 1 : 0); //TODO: iOS Bug: if you allow it to go to 0, Safari can start to report super strange (wildly inaccurate) touch positions!
|
|
508
|
+
|
|
509
|
+
f(value);
|
|
510
|
+
cachingFunc.cacheID = _scrollers.cache;
|
|
511
|
+
isNormalizing && _bridge("ss", value); // set scroll (notify ScrollTrigger so it can dispatch a "scrollStart" event if necessary
|
|
512
|
+
} else if (doNotCache || _scrollers.cache !== cachingFunc.cacheID || _bridge("ref")) {
|
|
513
|
+
cachingFunc.cacheID = _scrollers.cache;
|
|
514
|
+
cachingFunc.v = f();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return cachingFunc.v + cachingFunc.offset;
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
cachingFunc.offset = 0;
|
|
521
|
+
return f && cachingFunc;
|
|
522
|
+
},
|
|
523
|
+
_horizontal = {
|
|
524
|
+
s: _scrollLeft,
|
|
525
|
+
p: "left",
|
|
526
|
+
p2: "Left",
|
|
527
|
+
os: "right",
|
|
528
|
+
os2: "Right",
|
|
529
|
+
d: "width",
|
|
530
|
+
d2: "Width",
|
|
531
|
+
a: "x",
|
|
532
|
+
sc: _scrollCacheFunc(function (value) {
|
|
533
|
+
return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
|
|
534
|
+
})
|
|
535
|
+
},
|
|
536
|
+
_vertical = {
|
|
537
|
+
s: _scrollTop,
|
|
538
|
+
p: "top",
|
|
539
|
+
p2: "Top",
|
|
540
|
+
os: "bottom",
|
|
541
|
+
os2: "Bottom",
|
|
542
|
+
d: "height",
|
|
543
|
+
d2: "Height",
|
|
544
|
+
a: "y",
|
|
545
|
+
op: _horizontal,
|
|
546
|
+
sc: _scrollCacheFunc(function (value) {
|
|
547
|
+
return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
|
|
548
|
+
})
|
|
549
|
+
},
|
|
550
|
+
_getTarget = function _getTarget(t, self) {
|
|
551
|
+
return (self && self._ctx && self._ctx.selector || gsap.utils.toArray)(t)[0] || (typeof t === "string" && gsap.config().nullTargetWarn !== false ? console.warn("Element not found:", t) : null);
|
|
552
|
+
},
|
|
553
|
+
_isWithin = function _isWithin(element, list) {
|
|
554
|
+
// check if the element is in the list or is a descendant of an element in the list.
|
|
555
|
+
var i = list.length;
|
|
556
|
+
|
|
557
|
+
while (i--) {
|
|
558
|
+
if (list[i] === element || list[i].contains(element)) {
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return false;
|
|
564
|
+
},
|
|
565
|
+
_getScrollFunc = function _getScrollFunc(element, _ref) {
|
|
566
|
+
var s = _ref.s,
|
|
567
|
+
sc = _ref.sc;
|
|
568
|
+
// we store the scroller functions in an alternating sequenced Array like [element, verticalScrollFunc, horizontalScrollFunc, ...] so that we can minimize memory, maximize performance, and we also record the last position as a ".rec" property in order to revert to that after refreshing to ensure things don't shift around.
|
|
569
|
+
_isViewport(element) && (element = _doc.scrollingElement || _docEl);
|
|
570
|
+
|
|
571
|
+
var i = _scrollers.indexOf(element),
|
|
572
|
+
offset = sc === _vertical.sc ? 1 : 2;
|
|
573
|
+
|
|
574
|
+
!~i && (i = _scrollers.push(element) - 1);
|
|
575
|
+
_scrollers[i + offset] || _addListener(element, "scroll", _onScroll); // clear the cache when a scroll occurs
|
|
576
|
+
|
|
577
|
+
var prev = _scrollers[i + offset],
|
|
578
|
+
func = prev || (_scrollers[i + offset] = _scrollCacheFunc(_getProxyProp(element, s), true) || (_isViewport(element) ? sc : _scrollCacheFunc(function (value) {
|
|
579
|
+
return arguments.length ? element[s] = value : element[s];
|
|
580
|
+
})));
|
|
581
|
+
func.target = element;
|
|
582
|
+
prev || (func.smooth = gsap.getProperty(element, "scrollBehavior") === "smooth"); // only set it the first time (don't reset every time a scrollFunc is requested because perhaps it happens during a refresh() when it's disabled in ScrollTrigger.
|
|
583
|
+
|
|
584
|
+
return func;
|
|
585
|
+
},
|
|
586
|
+
_getVelocityProp = function _getVelocityProp(value, minTimeRefresh, useDelta) {
|
|
587
|
+
var v1 = value,
|
|
588
|
+
v2 = value,
|
|
589
|
+
t1 = _getTime(),
|
|
590
|
+
t2 = t1,
|
|
591
|
+
min = minTimeRefresh,
|
|
592
|
+
dropToZeroTime = Math.max(500, min * 3),
|
|
593
|
+
update = function update(value, force) {
|
|
594
|
+
var t = _getTime();
|
|
595
|
+
|
|
596
|
+
if (force || t - t1 > min) {
|
|
597
|
+
v2 = v1;
|
|
598
|
+
v1 = value;
|
|
599
|
+
t2 = t1;
|
|
600
|
+
t1 = t;
|
|
601
|
+
} else {
|
|
602
|
+
v1 += value;
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
reset = function reset() {
|
|
606
|
+
v2 = v1 = 0 ;
|
|
607
|
+
t2 = t1 = 0;
|
|
608
|
+
},
|
|
609
|
+
getVelocity = function getVelocity(latestValue) {
|
|
610
|
+
var tOld = t2,
|
|
611
|
+
vOld = v2,
|
|
612
|
+
t = _getTime();
|
|
613
|
+
|
|
614
|
+
(latestValue || latestValue === 0) && latestValue !== v1 && update(latestValue);
|
|
615
|
+
return t1 === t2 || t - t2 > dropToZeroTime ? 0 : (v1 + (vOld )) / ((t ) - tOld) * 1000;
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
return {
|
|
619
|
+
update: update,
|
|
620
|
+
reset: reset,
|
|
621
|
+
getVelocity: getVelocity
|
|
622
|
+
};
|
|
623
|
+
},
|
|
624
|
+
_getEvent = function _getEvent(e, preventDefault) {
|
|
625
|
+
preventDefault && !e._gsapAllow && e.preventDefault();
|
|
626
|
+
return e.changedTouches ? e.changedTouches[0] : e;
|
|
627
|
+
},
|
|
628
|
+
_getAbsoluteMax = function _getAbsoluteMax(a) {
|
|
629
|
+
var max = Math.max.apply(Math, a),
|
|
630
|
+
min = Math.min.apply(Math, a);
|
|
631
|
+
return Math.abs(max) >= Math.abs(min) ? max : min;
|
|
632
|
+
},
|
|
633
|
+
_setScrollTrigger = function _setScrollTrigger() {
|
|
634
|
+
ScrollTrigger = gsap.core.globals().ScrollTrigger;
|
|
635
|
+
ScrollTrigger && ScrollTrigger.core && _integrate();
|
|
636
|
+
},
|
|
637
|
+
_initCore = function _initCore(core) {
|
|
638
|
+
gsap = core || _getGSAP();
|
|
639
|
+
|
|
640
|
+
if (!_coreInitted && gsap && typeof document !== "undefined" && document.body) {
|
|
641
|
+
_win = window;
|
|
642
|
+
_doc = document;
|
|
643
|
+
_docEl = _doc.documentElement;
|
|
644
|
+
_body = _doc.body;
|
|
645
|
+
_root = [_win, _doc, _docEl, _body];
|
|
646
|
+
gsap.utils.clamp;
|
|
647
|
+
|
|
648
|
+
_context = gsap.core.context || function () {};
|
|
649
|
+
|
|
650
|
+
_pointerType = "onpointerenter" in _body ? "pointer" : "mouse"; // isTouch is 0 if no touch, 1 if ONLY touch, and 2 if it can accommodate touch but also other types like mouse/pointer.
|
|
651
|
+
|
|
652
|
+
_isTouch = Observer.isTouch = _win.matchMedia && _win.matchMedia("(hover: none), (pointer: coarse)").matches ? 1 : "ontouchstart" in _win || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ? 2 : 0;
|
|
653
|
+
_eventTypes = Observer.eventTypes = ("ontouchstart" in _docEl ? "touchstart,touchmove,touchcancel,touchend" : !("onpointerdown" in _docEl) ? "mousedown,mousemove,mouseup,mouseup" : "pointerdown,pointermove,pointercancel,pointerup").split(",");
|
|
654
|
+
setTimeout(function () {
|
|
655
|
+
return _startup = 0;
|
|
656
|
+
}, 500);
|
|
657
|
+
|
|
658
|
+
_setScrollTrigger();
|
|
659
|
+
|
|
660
|
+
_coreInitted = 1;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return _coreInitted;
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
_horizontal.op = _vertical;
|
|
667
|
+
_scrollers.cache = 0;
|
|
668
|
+
var Observer = /*#__PURE__*/function () {
|
|
669
|
+
function Observer(vars) {
|
|
670
|
+
this.init(vars);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
var _proto = Observer.prototype;
|
|
674
|
+
|
|
675
|
+
_proto.init = function init(vars) {
|
|
676
|
+
_coreInitted || _initCore(gsap) || console.warn("Please gsap.registerPlugin(Observer)");
|
|
677
|
+
ScrollTrigger || _setScrollTrigger();
|
|
678
|
+
var tolerance = vars.tolerance,
|
|
679
|
+
dragMinimum = vars.dragMinimum,
|
|
680
|
+
type = vars.type,
|
|
681
|
+
target = vars.target,
|
|
682
|
+
lineHeight = vars.lineHeight,
|
|
683
|
+
debounce = vars.debounce,
|
|
684
|
+
preventDefault = vars.preventDefault,
|
|
685
|
+
onStop = vars.onStop,
|
|
686
|
+
onStopDelay = vars.onStopDelay,
|
|
687
|
+
ignore = vars.ignore,
|
|
688
|
+
wheelSpeed = vars.wheelSpeed,
|
|
689
|
+
event = vars.event,
|
|
690
|
+
onDragStart = vars.onDragStart,
|
|
691
|
+
onDragEnd = vars.onDragEnd,
|
|
692
|
+
onDrag = vars.onDrag,
|
|
693
|
+
onPress = vars.onPress,
|
|
694
|
+
onRelease = vars.onRelease,
|
|
695
|
+
onRight = vars.onRight,
|
|
696
|
+
onLeft = vars.onLeft,
|
|
697
|
+
onUp = vars.onUp,
|
|
698
|
+
onDown = vars.onDown,
|
|
699
|
+
onChangeX = vars.onChangeX,
|
|
700
|
+
onChangeY = vars.onChangeY,
|
|
701
|
+
onChange = vars.onChange,
|
|
702
|
+
onToggleX = vars.onToggleX,
|
|
703
|
+
onToggleY = vars.onToggleY,
|
|
704
|
+
onHover = vars.onHover,
|
|
705
|
+
onHoverEnd = vars.onHoverEnd,
|
|
706
|
+
onMove = vars.onMove,
|
|
707
|
+
ignoreCheck = vars.ignoreCheck,
|
|
708
|
+
isNormalizer = vars.isNormalizer,
|
|
709
|
+
onGestureStart = vars.onGestureStart,
|
|
710
|
+
onGestureEnd = vars.onGestureEnd,
|
|
711
|
+
onWheel = vars.onWheel,
|
|
712
|
+
onEnable = vars.onEnable,
|
|
713
|
+
onDisable = vars.onDisable,
|
|
714
|
+
onClick = vars.onClick,
|
|
715
|
+
scrollSpeed = vars.scrollSpeed,
|
|
716
|
+
capture = vars.capture,
|
|
717
|
+
allowClicks = vars.allowClicks,
|
|
718
|
+
lockAxis = vars.lockAxis,
|
|
719
|
+
onLockAxis = vars.onLockAxis;
|
|
720
|
+
this.target = target = _getTarget(target) || _docEl;
|
|
721
|
+
this.vars = vars;
|
|
722
|
+
ignore && (ignore = gsap.utils.toArray(ignore));
|
|
723
|
+
tolerance = tolerance || 1e-9;
|
|
724
|
+
dragMinimum = dragMinimum || 0;
|
|
725
|
+
wheelSpeed = wheelSpeed || 1;
|
|
726
|
+
scrollSpeed = scrollSpeed || 1;
|
|
727
|
+
type = type || "wheel,touch,pointer";
|
|
728
|
+
debounce = debounce !== false;
|
|
729
|
+
lineHeight || (lineHeight = parseFloat(_win.getComputedStyle(_body).lineHeight) || 22); // note: browser may report "normal", so default to 22.
|
|
730
|
+
|
|
731
|
+
var id,
|
|
732
|
+
onStopDelayedCall,
|
|
733
|
+
dragged,
|
|
734
|
+
moved,
|
|
735
|
+
wheeled,
|
|
736
|
+
locked,
|
|
737
|
+
axis,
|
|
738
|
+
self = this,
|
|
739
|
+
prevDeltaX = 0,
|
|
740
|
+
prevDeltaY = 0,
|
|
741
|
+
passive = vars.passive || !preventDefault && vars.passive !== false,
|
|
742
|
+
scrollFuncX = _getScrollFunc(target, _horizontal),
|
|
743
|
+
scrollFuncY = _getScrollFunc(target, _vertical),
|
|
744
|
+
scrollX = scrollFuncX(),
|
|
745
|
+
scrollY = scrollFuncY(),
|
|
746
|
+
limitToTouch = ~type.indexOf("touch") && !~type.indexOf("pointer") && _eventTypes[0] === "pointerdown",
|
|
747
|
+
// for devices that accommodate mouse events and touch events, we need to distinguish.
|
|
748
|
+
isViewport = _isViewport(target),
|
|
749
|
+
ownerDoc = target.ownerDocument || _doc,
|
|
750
|
+
deltaX = [0, 0, 0],
|
|
751
|
+
// wheel, scroll, pointer/touch
|
|
752
|
+
deltaY = [0, 0, 0],
|
|
753
|
+
onClickTime = 0,
|
|
754
|
+
clickCapture = function clickCapture() {
|
|
755
|
+
return onClickTime = _getTime();
|
|
756
|
+
},
|
|
757
|
+
_ignoreCheck = function _ignoreCheck(e, isPointerOrTouch) {
|
|
758
|
+
return (self.event = e) && ignore && _isWithin(e.target, ignore) || isPointerOrTouch && limitToTouch && e.pointerType !== "touch" || ignoreCheck && ignoreCheck(e, isPointerOrTouch);
|
|
759
|
+
},
|
|
760
|
+
onStopFunc = function onStopFunc() {
|
|
761
|
+
self._vx.reset();
|
|
762
|
+
|
|
763
|
+
self._vy.reset();
|
|
764
|
+
|
|
765
|
+
onStopDelayedCall.pause();
|
|
766
|
+
onStop && onStop(self);
|
|
767
|
+
},
|
|
768
|
+
update = function update() {
|
|
769
|
+
var dx = self.deltaX = _getAbsoluteMax(deltaX),
|
|
770
|
+
dy = self.deltaY = _getAbsoluteMax(deltaY),
|
|
771
|
+
changedX = Math.abs(dx) >= tolerance,
|
|
772
|
+
changedY = Math.abs(dy) >= tolerance;
|
|
773
|
+
|
|
774
|
+
onChange && (changedX || changedY) && onChange(self, dx, dy, deltaX, deltaY); // in ScrollTrigger.normalizeScroll(), we need to know if it was touch/pointer so we need access to the deltaX/deltaY Arrays before we clear them out.
|
|
775
|
+
|
|
776
|
+
if (changedX) {
|
|
777
|
+
onRight && self.deltaX > 0 && onRight(self);
|
|
778
|
+
onLeft && self.deltaX < 0 && onLeft(self);
|
|
779
|
+
onChangeX && onChangeX(self);
|
|
780
|
+
onToggleX && self.deltaX < 0 !== prevDeltaX < 0 && onToggleX(self);
|
|
781
|
+
prevDeltaX = self.deltaX;
|
|
782
|
+
deltaX[0] = deltaX[1] = deltaX[2] = 0;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (changedY) {
|
|
786
|
+
onDown && self.deltaY > 0 && onDown(self);
|
|
787
|
+
onUp && self.deltaY < 0 && onUp(self);
|
|
788
|
+
onChangeY && onChangeY(self);
|
|
789
|
+
onToggleY && self.deltaY < 0 !== prevDeltaY < 0 && onToggleY(self);
|
|
790
|
+
prevDeltaY = self.deltaY;
|
|
791
|
+
deltaY[0] = deltaY[1] = deltaY[2] = 0;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (moved || dragged) {
|
|
795
|
+
onMove && onMove(self);
|
|
796
|
+
|
|
797
|
+
if (dragged) {
|
|
798
|
+
onDragStart && dragged === 1 && onDragStart(self);
|
|
799
|
+
onDrag && onDrag(self);
|
|
800
|
+
dragged = 0;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
moved = false;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
locked && !(locked = false) && onLockAxis && onLockAxis(self);
|
|
807
|
+
|
|
808
|
+
if (wheeled) {
|
|
809
|
+
onWheel(self);
|
|
810
|
+
wheeled = false;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
id = 0;
|
|
814
|
+
},
|
|
815
|
+
onDelta = function onDelta(x, y, index) {
|
|
816
|
+
deltaX[index] += x;
|
|
817
|
+
deltaY[index] += y;
|
|
818
|
+
|
|
819
|
+
self._vx.update(x);
|
|
820
|
+
|
|
821
|
+
self._vy.update(y);
|
|
822
|
+
|
|
823
|
+
debounce ? id || (id = requestAnimationFrame(update)) : update();
|
|
824
|
+
},
|
|
825
|
+
onTouchOrPointerDelta = function onTouchOrPointerDelta(x, y) {
|
|
826
|
+
if (lockAxis && !axis) {
|
|
827
|
+
self.axis = axis = Math.abs(x) > Math.abs(y) ? "x" : "y";
|
|
828
|
+
locked = true;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (axis !== "y") {
|
|
832
|
+
deltaX[2] += x;
|
|
833
|
+
|
|
834
|
+
self._vx.update(x, true); // update the velocity as frequently as possible instead of in the debounced function so that very quick touch-scrolls (flicks) feel natural. If it's the mouse/touch/pointer, force it so that we get snappy/accurate momentum scroll.
|
|
835
|
+
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (axis !== "x") {
|
|
839
|
+
deltaY[2] += y;
|
|
840
|
+
|
|
841
|
+
self._vy.update(y, true);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
debounce ? id || (id = requestAnimationFrame(update)) : update();
|
|
845
|
+
},
|
|
846
|
+
_onDrag = function _onDrag(e) {
|
|
847
|
+
if (_ignoreCheck(e, 1)) {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
e = _getEvent(e, preventDefault);
|
|
852
|
+
var x = e.clientX,
|
|
853
|
+
y = e.clientY,
|
|
854
|
+
dx = x - self.x,
|
|
855
|
+
dy = y - self.y,
|
|
856
|
+
isDragging = self.isDragging;
|
|
857
|
+
self.x = x;
|
|
858
|
+
self.y = y;
|
|
859
|
+
|
|
860
|
+
if (isDragging || (dx || dy) && (Math.abs(self.startX - x) >= dragMinimum || Math.abs(self.startY - y) >= dragMinimum)) {
|
|
861
|
+
dragged = isDragging ? 2 : 1; // dragged: 0 = not dragging, 1 = first drag, 2 = normal drag
|
|
862
|
+
|
|
863
|
+
isDragging || (self.isDragging = true);
|
|
864
|
+
onTouchOrPointerDelta(dx, dy);
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
_onPress = self.onPress = function (e) {
|
|
868
|
+
if (_ignoreCheck(e, 1) || e && e.button) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
self.axis = axis = null;
|
|
873
|
+
onStopDelayedCall.pause();
|
|
874
|
+
self.isPressed = true;
|
|
875
|
+
e = _getEvent(e); // note: may need to preventDefault(?) Won't side-scroll on iOS Safari if we do, though.
|
|
876
|
+
|
|
877
|
+
prevDeltaX = prevDeltaY = 0;
|
|
878
|
+
self.startX = self.x = e.clientX;
|
|
879
|
+
self.startY = self.y = e.clientY;
|
|
880
|
+
|
|
881
|
+
self._vx.reset(); // otherwise the t2 may be stale if the user touches and flicks super fast and releases in less than 2 requestAnimationFrame ticks, causing velocity to be 0.
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
self._vy.reset();
|
|
885
|
+
|
|
886
|
+
_addListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, passive, true);
|
|
887
|
+
|
|
888
|
+
self.deltaX = self.deltaY = 0;
|
|
889
|
+
onPress && onPress(self);
|
|
890
|
+
},
|
|
891
|
+
_onRelease = self.onRelease = function (e) {
|
|
892
|
+
if (_ignoreCheck(e, 1)) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
_removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
|
|
897
|
+
|
|
898
|
+
var isTrackingDrag = !isNaN(self.y - self.startY),
|
|
899
|
+
wasDragging = self.isDragging,
|
|
900
|
+
isDragNotClick = wasDragging && (Math.abs(self.x - self.startX) > 3 || Math.abs(self.y - self.startY) > 3),
|
|
901
|
+
// some touch devices need some wiggle room in terms of sensing clicks - the finger may move a few pixels.
|
|
902
|
+
eventData = _getEvent(e);
|
|
903
|
+
|
|
904
|
+
if (!isDragNotClick && isTrackingDrag) {
|
|
905
|
+
self._vx.reset();
|
|
906
|
+
|
|
907
|
+
self._vy.reset(); //if (preventDefault && allowClicks && self.isPressed) { // check isPressed because in a rare edge case, the inputObserver in ScrollTrigger may stopPropagation() on the press/drag, so the onRelease may get fired without the onPress/onDrag ever getting called, thus it could trigger a click to occur on a link after scroll-dragging it.
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
if (preventDefault && allowClicks) {
|
|
911
|
+
gsap.delayedCall(0.08, function () {
|
|
912
|
+
// some browsers (like Firefox) won't trust script-generated clicks, so if the user tries to click on a video to play it, for example, it simply won't work. Since a regular "click" event will most likely be generated anyway (one that has its isTrusted flag set to true), we must slightly delay our script-generated click so that the "real"/trusted one is prioritized. Remember, when there are duplicate events in quick succession, we suppress all but the first one. Some browsers don't even trigger the "real" one at all, so our synthetic one is a safety valve that ensures that no matter what, a click event does get dispatched.
|
|
913
|
+
if (_getTime() - onClickTime > 300 && !e.defaultPrevented) {
|
|
914
|
+
if (e.target.click) {
|
|
915
|
+
//some browsers (like mobile Safari) don't properly trigger the click event
|
|
916
|
+
e.target.click();
|
|
917
|
+
} else if (ownerDoc.createEvent) {
|
|
918
|
+
var syntheticEvent = ownerDoc.createEvent("MouseEvents");
|
|
919
|
+
syntheticEvent.initMouseEvent("click", true, true, _win, 1, eventData.screenX, eventData.screenY, eventData.clientX, eventData.clientY, false, false, false, false, 0, null);
|
|
920
|
+
e.target.dispatchEvent(syntheticEvent);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
self.isDragging = self.isGesturing = self.isPressed = false;
|
|
928
|
+
onStop && wasDragging && !isNormalizer && onStopDelayedCall.restart(true);
|
|
929
|
+
dragged && update(); // in case debouncing, we don't want onDrag to fire AFTER onDragEnd().
|
|
930
|
+
|
|
931
|
+
onDragEnd && wasDragging && onDragEnd(self);
|
|
932
|
+
onRelease && onRelease(self, isDragNotClick);
|
|
933
|
+
},
|
|
934
|
+
_onGestureStart = function _onGestureStart(e) {
|
|
935
|
+
return e.touches && e.touches.length > 1 && (self.isGesturing = true) && onGestureStart(e, self.isDragging);
|
|
936
|
+
},
|
|
937
|
+
_onGestureEnd = function _onGestureEnd() {
|
|
938
|
+
return (self.isGesturing = false) || onGestureEnd(self);
|
|
939
|
+
},
|
|
940
|
+
onScroll = function onScroll(e) {
|
|
941
|
+
if (_ignoreCheck(e)) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
var x = scrollFuncX(),
|
|
946
|
+
y = scrollFuncY();
|
|
947
|
+
onDelta((x - scrollX) * scrollSpeed, (y - scrollY) * scrollSpeed, 1);
|
|
948
|
+
scrollX = x;
|
|
949
|
+
scrollY = y;
|
|
950
|
+
onStop && onStopDelayedCall.restart(true);
|
|
951
|
+
},
|
|
952
|
+
_onWheel = function _onWheel(e) {
|
|
953
|
+
if (_ignoreCheck(e)) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
e = _getEvent(e, preventDefault);
|
|
958
|
+
onWheel && (wheeled = true);
|
|
959
|
+
var multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? _win.innerHeight : 1) * wheelSpeed;
|
|
960
|
+
onDelta(e.deltaX * multiplier, e.deltaY * multiplier, 0);
|
|
961
|
+
onStop && !isNormalizer && onStopDelayedCall.restart(true);
|
|
962
|
+
},
|
|
963
|
+
_onMove = function _onMove(e) {
|
|
964
|
+
if (_ignoreCheck(e)) {
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
var x = e.clientX,
|
|
969
|
+
y = e.clientY,
|
|
970
|
+
dx = x - self.x,
|
|
971
|
+
dy = y - self.y;
|
|
972
|
+
self.x = x;
|
|
973
|
+
self.y = y;
|
|
974
|
+
moved = true;
|
|
975
|
+
onStop && onStopDelayedCall.restart(true);
|
|
976
|
+
(dx || dy) && onTouchOrPointerDelta(dx, dy);
|
|
977
|
+
},
|
|
978
|
+
_onHover = function _onHover(e) {
|
|
979
|
+
self.event = e;
|
|
980
|
+
onHover(self);
|
|
981
|
+
},
|
|
982
|
+
_onHoverEnd = function _onHoverEnd(e) {
|
|
983
|
+
self.event = e;
|
|
984
|
+
onHoverEnd(self);
|
|
985
|
+
},
|
|
986
|
+
_onClick = function _onClick(e) {
|
|
987
|
+
return _ignoreCheck(e) || _getEvent(e, preventDefault) && onClick(self);
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
onStopDelayedCall = self._dc = gsap.delayedCall(onStopDelay || 0.25, onStopFunc).pause();
|
|
991
|
+
self.deltaX = self.deltaY = 0;
|
|
992
|
+
self._vx = _getVelocityProp(0, 50);
|
|
993
|
+
self._vy = _getVelocityProp(0, 50);
|
|
994
|
+
self.scrollX = scrollFuncX;
|
|
995
|
+
self.scrollY = scrollFuncY;
|
|
996
|
+
self.isDragging = self.isGesturing = self.isPressed = false;
|
|
997
|
+
|
|
998
|
+
_context(this);
|
|
999
|
+
|
|
1000
|
+
self.enable = function (e) {
|
|
1001
|
+
if (!self.isEnabled) {
|
|
1002
|
+
_addListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
|
|
1003
|
+
|
|
1004
|
+
type.indexOf("scroll") >= 0 && _addListener(isViewport ? ownerDoc : target, "scroll", onScroll, passive, capture);
|
|
1005
|
+
type.indexOf("wheel") >= 0 && _addListener(target, "wheel", _onWheel, passive, capture);
|
|
1006
|
+
|
|
1007
|
+
if (type.indexOf("touch") >= 0 && _isTouch || type.indexOf("pointer") >= 0) {
|
|
1008
|
+
_addListener(target, _eventTypes[0], _onPress, passive, capture);
|
|
1009
|
+
|
|
1010
|
+
_addListener(ownerDoc, _eventTypes[2], _onRelease);
|
|
1011
|
+
|
|
1012
|
+
_addListener(ownerDoc, _eventTypes[3], _onRelease);
|
|
1013
|
+
|
|
1014
|
+
allowClicks && _addListener(target, "click", clickCapture, true, true);
|
|
1015
|
+
onClick && _addListener(target, "click", _onClick);
|
|
1016
|
+
onGestureStart && _addListener(ownerDoc, "gesturestart", _onGestureStart);
|
|
1017
|
+
onGestureEnd && _addListener(ownerDoc, "gestureend", _onGestureEnd);
|
|
1018
|
+
onHover && _addListener(target, _pointerType + "enter", _onHover);
|
|
1019
|
+
onHoverEnd && _addListener(target, _pointerType + "leave", _onHoverEnd);
|
|
1020
|
+
onMove && _addListener(target, _pointerType + "move", _onMove);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
self.isEnabled = true;
|
|
1024
|
+
self.isDragging = self.isGesturing = self.isPressed = moved = dragged = false;
|
|
1025
|
+
|
|
1026
|
+
self._vx.reset();
|
|
1027
|
+
|
|
1028
|
+
self._vy.reset();
|
|
1029
|
+
|
|
1030
|
+
scrollX = scrollFuncX();
|
|
1031
|
+
scrollY = scrollFuncY();
|
|
1032
|
+
e && e.type && _onPress(e);
|
|
1033
|
+
onEnable && onEnable(self);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
return self;
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
self.disable = function () {
|
|
1040
|
+
if (self.isEnabled) {
|
|
1041
|
+
// only remove the _onScroll listener if there aren't any others that rely on the functionality.
|
|
1042
|
+
_observers.filter(function (o) {
|
|
1043
|
+
return o !== self && _isViewport(o.target);
|
|
1044
|
+
}).length || _removeListener(isViewport ? ownerDoc : target, "scroll", _onScroll);
|
|
1045
|
+
|
|
1046
|
+
if (self.isPressed) {
|
|
1047
|
+
self._vx.reset();
|
|
1048
|
+
|
|
1049
|
+
self._vy.reset();
|
|
1050
|
+
|
|
1051
|
+
_removeListener(isNormalizer ? target : ownerDoc, _eventTypes[1], _onDrag, true);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
_removeListener(isViewport ? ownerDoc : target, "scroll", onScroll, capture);
|
|
1055
|
+
|
|
1056
|
+
_removeListener(target, "wheel", _onWheel, capture);
|
|
1057
|
+
|
|
1058
|
+
_removeListener(target, _eventTypes[0], _onPress, capture);
|
|
1059
|
+
|
|
1060
|
+
_removeListener(ownerDoc, _eventTypes[2], _onRelease);
|
|
1061
|
+
|
|
1062
|
+
_removeListener(ownerDoc, _eventTypes[3], _onRelease);
|
|
1063
|
+
|
|
1064
|
+
_removeListener(target, "click", clickCapture, true);
|
|
1065
|
+
|
|
1066
|
+
_removeListener(target, "click", _onClick);
|
|
1067
|
+
|
|
1068
|
+
_removeListener(ownerDoc, "gesturestart", _onGestureStart);
|
|
1069
|
+
|
|
1070
|
+
_removeListener(ownerDoc, "gestureend", _onGestureEnd);
|
|
1071
|
+
|
|
1072
|
+
_removeListener(target, _pointerType + "enter", _onHover);
|
|
1073
|
+
|
|
1074
|
+
_removeListener(target, _pointerType + "leave", _onHoverEnd);
|
|
1075
|
+
|
|
1076
|
+
_removeListener(target, _pointerType + "move", _onMove);
|
|
1077
|
+
|
|
1078
|
+
self.isEnabled = self.isPressed = self.isDragging = false;
|
|
1079
|
+
onDisable && onDisable(self);
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
self.kill = self.revert = function () {
|
|
1084
|
+
self.disable();
|
|
1085
|
+
|
|
1086
|
+
var i = _observers.indexOf(self);
|
|
1087
|
+
|
|
1088
|
+
i >= 0 && _observers.splice(i, 1);
|
|
1089
|
+
_normalizer === self && (_normalizer = 0);
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
_observers.push(self);
|
|
1093
|
+
|
|
1094
|
+
isNormalizer && _isViewport(target) && (_normalizer = self);
|
|
1095
|
+
self.enable(event);
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
_createClass(Observer, [{
|
|
1099
|
+
key: "velocityX",
|
|
1100
|
+
get: function get() {
|
|
1101
|
+
return this._vx.getVelocity();
|
|
1102
|
+
}
|
|
1103
|
+
}, {
|
|
1104
|
+
key: "velocityY",
|
|
1105
|
+
get: function get() {
|
|
1106
|
+
return this._vy.getVelocity();
|
|
1107
|
+
}
|
|
1108
|
+
}]);
|
|
1109
|
+
|
|
1110
|
+
return Observer;
|
|
1111
|
+
}();
|
|
1112
|
+
Observer.version = "3.13.0";
|
|
1113
|
+
|
|
1114
|
+
Observer.create = function (vars) {
|
|
1115
|
+
return new Observer(vars);
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
Observer.register = _initCore;
|
|
1119
|
+
|
|
1120
|
+
Observer.getAll = function () {
|
|
1121
|
+
return _observers.slice();
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
Observer.getById = function (id) {
|
|
1125
|
+
return _observers.filter(function (o) {
|
|
1126
|
+
return o.vars.id === id;
|
|
1127
|
+
})[0];
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
_getGSAP() && gsap.registerPlugin(Observer);
|
|
1131
|
+
|
|
428
1132
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
429
1133
|
|
|
430
1134
|
const CLASS_PART_SEPARATOR = '-';
|
|
@@ -2921,134 +3625,339 @@ const twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig);
|
|
|
2921
3625
|
|
|
2922
3626
|
/**
|
|
2923
3627
|
* Utility function to merge Tailwind classes with clsx
|
|
3628
|
+
*
|
|
3629
|
+
* Combines clsx for conditional classes with tailwind-merge to handle
|
|
3630
|
+
* conflicting Tailwind classes by keeping the last occurrence.
|
|
3631
|
+
* This prevents issues like "p-4 p-2" where both would be applied.
|
|
3632
|
+
*
|
|
3633
|
+
* @param inputs - Array of class values (strings, conditionals, objects)
|
|
3634
|
+
* @returns Merged and deduplicated class string
|
|
2924
3635
|
*/
|
|
2925
3636
|
const cn = (...inputs) => {
|
|
2926
3637
|
return twMerge(clsx(inputs));
|
|
2927
3638
|
};
|
|
2928
3639
|
/**
|
|
2929
|
-
* Sets up container styles and rotation handling
|
|
3640
|
+
* Sets up container styles and rotation handling for the marquee
|
|
3641
|
+
*
|
|
3642
|
+
* This function handles the complex styling requirements for different marquee orientations:
|
|
3643
|
+
*
|
|
3644
|
+
* 1. **Basic Setup**: Applies gap spacing and rotation for vertical marquees
|
|
3645
|
+
* 2. **Vertical Mode**: Rotates container 90° and adjusts width to parent height
|
|
3646
|
+
* 3. **Rotation Alignment**: Special mode for vertical text that remains readable
|
|
3647
|
+
*
|
|
3648
|
+
* @param containerMarquee - The main container element that holds all marquee instances
|
|
3649
|
+
* @param marquees - Array of individual marquee wrapper elements
|
|
3650
|
+
* @param marqueesChildren - Array of content container elements within each marquee
|
|
3651
|
+
* @param isVertical - Boolean indicating if marquee moves up/down instead of left/right
|
|
3652
|
+
* @param props - Configuration object containing spacing and alignment options
|
|
2930
3653
|
*/
|
|
2931
3654
|
const setupContainerStyles = (containerMarquee, marquees, marqueesChildren, isVertical, props) => {
|
|
2932
3655
|
const { spacing = 16, alignRotationWithY = false } = props;
|
|
2933
|
-
|
|
3656
|
+
/**
|
|
3657
|
+
* Apply base container styling
|
|
3658
|
+
* - gap: Space between marquee elements (prevents content overlap)
|
|
3659
|
+
* - rotate: 90° rotation for vertical movement (transforms horizontal motion to vertical)
|
|
3660
|
+
*/
|
|
3661
|
+
gsap$1.set(containerMarquee, {
|
|
2934
3662
|
gap: `${spacing}px`,
|
|
2935
3663
|
rotate: isVertical ? 90 : "0",
|
|
2936
3664
|
});
|
|
3665
|
+
/**
|
|
3666
|
+
* Handle vertical marquee specific adjustments
|
|
3667
|
+
* When isVertical is true, the container is rotated 90°, so we need to:
|
|
3668
|
+
* 1. Set container width to match parent height (since it's rotated)
|
|
3669
|
+
* 2. Allow content to overflow visible bounds for smooth transitions
|
|
3670
|
+
*/
|
|
2937
3671
|
if (isVertical) {
|
|
2938
|
-
|
|
3672
|
+
const parent = containerMarquee.parentNode;
|
|
3673
|
+
gsap$1.set(containerMarquee, {
|
|
3674
|
+
width: parent.offsetHeight, // Width becomes the vertical space available
|
|
3675
|
+
});
|
|
3676
|
+
gsap$1.set(marqueesChildren, {
|
|
3677
|
+
overflow: "visible", // Prevents clipping during animation
|
|
3678
|
+
});
|
|
2939
3679
|
}
|
|
3680
|
+
/**
|
|
3681
|
+
* Handle special rotation alignment mode
|
|
3682
|
+
*
|
|
3683
|
+
* This creates a complex layout where:
|
|
3684
|
+
* - The main container is rotated for vertical movement
|
|
3685
|
+
* - Individual content is counter-rotated to remain readable
|
|
3686
|
+
* - Content is repositioned to align properly within the rotated space
|
|
3687
|
+
*
|
|
3688
|
+
* Use case: Vertical text marquee where text remains horizontally readable
|
|
3689
|
+
*/
|
|
2940
3690
|
if (alignRotationWithY && marquees.length > 0) {
|
|
2941
3691
|
const marqueeHeight = marquees[0].offsetHeight;
|
|
2942
|
-
|
|
3692
|
+
// Center align items within the container
|
|
3693
|
+
gsap$1.set(containerMarquee, {
|
|
2943
3694
|
alignItems: "center",
|
|
2944
3695
|
});
|
|
2945
|
-
|
|
2946
|
-
|
|
3696
|
+
/**
|
|
3697
|
+
* Counter-rotate content and reposition for proper alignment
|
|
3698
|
+
*
|
|
3699
|
+
* - rotate: -90° counters the container's 90° rotation
|
|
3700
|
+
* - x: Horizontal offset to center content within rotated container
|
|
3701
|
+
* - width: Set to marquee height since dimensions are swapped after rotation
|
|
3702
|
+
* - flexWrap/wordBreak/whiteSpace: Handle text flow in constrained space
|
|
3703
|
+
*/
|
|
3704
|
+
gsap$1.set(marqueesChildren, {
|
|
3705
|
+
rotate: -90, // Counter-rotate to keep text readable
|
|
3706
|
+
x: (containerMarquee.offsetWidth - spacing) / 2 - spacing, // Center horizontally
|
|
2947
3707
|
display: "flex",
|
|
2948
|
-
flexWrap: "wrap",
|
|
2949
|
-
width: marqueeHeight,
|
|
2950
|
-
wordBreak: "break-all",
|
|
2951
|
-
whiteSpace: "break-spaces",
|
|
3708
|
+
flexWrap: "wrap", // Allow text to wrap within constrained width
|
|
3709
|
+
width: marqueeHeight, // Width constraint for wrapped text
|
|
3710
|
+
wordBreak: "break-all", // Force word breaking if necessary
|
|
3711
|
+
whiteSpace: "break-spaces", // Preserve spaces while allowing breaks
|
|
3712
|
+
});
|
|
3713
|
+
/**
|
|
3714
|
+
* Adjust marquee height to fit within the rotated container
|
|
3715
|
+
* Accounts for spacing to prevent overflow
|
|
3716
|
+
*/
|
|
3717
|
+
gsap$1.set(marquees, {
|
|
3718
|
+
height: containerMarquee.offsetWidth - spacing,
|
|
2952
3719
|
});
|
|
2953
3720
|
}
|
|
2954
3721
|
};
|
|
2955
3722
|
/**
|
|
2956
|
-
* Calculates the number of duplicates needed
|
|
3723
|
+
* Calculates the number of content duplicates needed for seamless looping
|
|
3724
|
+
*
|
|
3725
|
+
* For smooth infinite scrolling, we need enough content copies to fill the visible area
|
|
3726
|
+
* plus buffer space. This prevents gaps when content loops back to the beginning.
|
|
3727
|
+
*
|
|
3728
|
+
* Algorithm:
|
|
3729
|
+
* 1. If not in fill mode, only one copy is needed (content already spans container)
|
|
3730
|
+
* 2. Determine target width (viewport height for vertical, container width for horizontal)
|
|
3731
|
+
* 3. Calculate how many copies fit in the target space, rounding up for complete coverage
|
|
3732
|
+
*
|
|
3733
|
+
* @param marqueeChildrenWidth - Width of a single content instance
|
|
3734
|
+
* @param containerMarqueeWidth - Width of the marquee container
|
|
3735
|
+
* @param isVertical - Whether the marquee scrolls vertically
|
|
3736
|
+
* @param props - Configuration object containing fill mode setting
|
|
3737
|
+
* @returns Number of content duplicates needed (minimum 1)
|
|
2957
3738
|
*/
|
|
2958
3739
|
const calculateDuplicates = (marqueeChildrenWidth, containerMarqueeWidth, isVertical, props) => {
|
|
3740
|
+
// If not filling, content presumably already spans the container
|
|
2959
3741
|
if (!props.fill)
|
|
2960
3742
|
return 1;
|
|
3743
|
+
/**
|
|
3744
|
+
* Determine the space we need to fill
|
|
3745
|
+
* - Vertical: Use viewport height (since container is rotated 90°)
|
|
3746
|
+
* - Horizontal: Use container width
|
|
3747
|
+
*/
|
|
2961
3748
|
const targetWidth = isVertical ? window.innerHeight : containerMarqueeWidth;
|
|
3749
|
+
/**
|
|
3750
|
+
* Calculate required duplicates
|
|
3751
|
+
* Math.ceil ensures we have enough copies to fully cover the target width
|
|
3752
|
+
* Even if the last copy is partially visible, it prevents gaps during looping
|
|
3753
|
+
*/
|
|
2962
3754
|
return marqueeChildrenWidth < targetWidth
|
|
2963
3755
|
? Math.ceil(targetWidth / marqueeChildrenWidth)
|
|
2964
|
-
: 1;
|
|
3756
|
+
: 1; // If content is already larger than target, one copy suffices
|
|
2965
3757
|
};
|
|
2966
3758
|
/**
|
|
2967
|
-
* Determines the minimum width for marquee elements
|
|
3759
|
+
* Determines the minimum width for marquee elements based on content and container
|
|
3760
|
+
*
|
|
3761
|
+
* This function ensures marquee elements have appropriate dimensions for their content
|
|
3762
|
+
* and container context, handling different modes and orientations.
|
|
3763
|
+
*
|
|
3764
|
+
* Width determination logic:
|
|
3765
|
+
* 1. **Fill mode**: Auto width lets content size naturally
|
|
3766
|
+
* 2. **Rotation alignment**: Use content height as width (rotated dimensions)
|
|
3767
|
+
* 3. **Undersized content**: Stretch to 100% to fill container
|
|
3768
|
+
* 4. **Oversized content**: Use actual content width for overflow scrolling
|
|
3769
|
+
*
|
|
3770
|
+
* @param marqueesChildren - Array of content elements for dimension measurement
|
|
3771
|
+
* @param totalWidth - Combined width of all content elements
|
|
3772
|
+
* @param containerMarqueeWidth - Available container width
|
|
3773
|
+
* @param props - Configuration object containing fill and alignment settings
|
|
3774
|
+
* @returns CSS width value (string with units or number for pixels)
|
|
2968
3775
|
*/
|
|
2969
3776
|
const getMinWidth = (marqueesChildren, totalWidth, containerMarqueeWidth, props) => {
|
|
2970
3777
|
const { fill = false, alignRotationWithY = false } = props;
|
|
3778
|
+
// Fill mode: Let content size itself naturally
|
|
2971
3779
|
if (fill)
|
|
2972
3780
|
return "auto";
|
|
3781
|
+
/**
|
|
3782
|
+
* Rotation alignment mode: Use height as width
|
|
3783
|
+
* Since content is rotated 90°, height becomes the effective width
|
|
3784
|
+
*/
|
|
2973
3785
|
if (alignRotationWithY && marqueesChildren.length > 0) {
|
|
2974
3786
|
return `${marqueesChildren[0].offsetHeight}px`;
|
|
2975
3787
|
}
|
|
3788
|
+
/**
|
|
3789
|
+
* Content smaller than container: Stretch to fill
|
|
3790
|
+
* Prevents awkward gaps in the marquee display
|
|
3791
|
+
*/
|
|
2976
3792
|
if (totalWidth < containerMarqueeWidth)
|
|
2977
3793
|
return "100%";
|
|
3794
|
+
/**
|
|
3795
|
+
* Content larger than container: Use actual content width
|
|
3796
|
+
* Allows content to overflow and scroll properly
|
|
3797
|
+
*/
|
|
2978
3798
|
return `${totalWidth}px`;
|
|
2979
3799
|
};
|
|
2980
|
-
/**
|
|
2981
|
-
* Creates a simple infinite marquee animation
|
|
2982
|
-
*/
|
|
2983
|
-
const simpleAnimation = (marquees, marqueeChildrenDimension, isReverse, props) => {
|
|
2984
|
-
const { spacing = 16, speed = 100, loop = -1 } = props;
|
|
2985
|
-
const tween = gsap.to(marquees, {
|
|
2986
|
-
xPercent: (_, el) => {
|
|
2987
|
-
const w = parseFloat(String(gsap.getProperty(el, "width", "px")));
|
|
2988
|
-
const xPercent = ((w + spacing) / w) * 100;
|
|
2989
|
-
return -xPercent;
|
|
2990
|
-
},
|
|
2991
|
-
duration: (marqueeChildrenDimension - spacing) / speed,
|
|
2992
|
-
repeat: loop,
|
|
2993
|
-
ease: "none",
|
|
2994
|
-
});
|
|
2995
|
-
tween.play();
|
|
2996
|
-
if (isReverse) {
|
|
2997
|
-
tween.totalTime(tween.rawTime() + tween.duration() * 100);
|
|
2998
|
-
tween.reverse();
|
|
2999
|
-
}
|
|
3000
|
-
};
|
|
3001
3800
|
/**
|
|
3002
3801
|
* Creates a complex fill-based marquee animation with seamless looping
|
|
3802
|
+
*
|
|
3803
|
+
* This is the core animation engine that creates smooth, continuous scrolling.
|
|
3804
|
+
* It handles the complex math required for seamless looping by calculating
|
|
3805
|
+
* precise positions and durations for each content element.
|
|
3806
|
+
*
|
|
3807
|
+
* Animation Strategy:
|
|
3808
|
+
* 1. **Position Calculation**: Convert pixel positions to percentages for responsive scaling
|
|
3809
|
+
* 2. **Seamless Looping**: Calculate track length and loop points to prevent gaps
|
|
3810
|
+
* 3. **Staggered Animation**: Each element starts at different times for smooth flow
|
|
3811
|
+
* 4. **Direction Handling**: Support forward and reverse directions with proper timing
|
|
3812
|
+
*
|
|
3813
|
+
* Technical Details:
|
|
3814
|
+
* - Uses xPercent for percentage-based positioning (responsive to element width changes)
|
|
3815
|
+
* - Creates two-part animation: main movement + seamless loop reset
|
|
3816
|
+
* - Calculates precise durations based on distance and speed for consistent motion
|
|
3817
|
+
*
|
|
3818
|
+
* @param elementsToAnimate - Array of DOM elements to animate (content or containers)
|
|
3819
|
+
* @param startX - Starting X position reference point
|
|
3820
|
+
* @param tl - GSAP timeline to add animations to
|
|
3821
|
+
* @param isReverse - Whether animation should play in reverse direction
|
|
3822
|
+
* @param props - Configuration object with spacing, speed, delay, and other settings
|
|
3003
3823
|
*/
|
|
3004
|
-
const
|
|
3005
|
-
const { spacing = 16, speed = 100 } = props;
|
|
3006
|
-
|
|
3007
|
-
const
|
|
3008
|
-
const
|
|
3009
|
-
|
|
3010
|
-
|
|
3824
|
+
const coreAnimation = (elementsToAnimate, startX, tl, isReverse, props) => {
|
|
3825
|
+
const { spacing = 16, speed = 100, delay = 0, paused = false, alignRotationWithY = false, } = props;
|
|
3826
|
+
// Arrays to store calculated values for each element
|
|
3827
|
+
const widths = []; // Element widths in pixels
|
|
3828
|
+
const xPercents = []; // Current positions as percentages
|
|
3829
|
+
const latestPos = elementsToAnimate.length - 1; // Index of last element
|
|
3830
|
+
/**
|
|
3831
|
+
* Initialize positions and calculate percentage values
|
|
3832
|
+
*
|
|
3833
|
+
* GSAP's xPercent property positions elements relative to their own width:
|
|
3834
|
+
* - 0% = element's left edge at current x position
|
|
3835
|
+
* - -100% = element's right edge at current x position
|
|
3836
|
+
* - 100% = element positioned one full width to the right
|
|
3837
|
+
*
|
|
3838
|
+
* This approach makes animations responsive to width changes
|
|
3839
|
+
*/
|
|
3840
|
+
gsap$1.set(elementsToAnimate, {
|
|
3011
3841
|
xPercent: (i, el) => {
|
|
3012
|
-
|
|
3842
|
+
// Get element width and store for later calculations
|
|
3843
|
+
const w = (widths[i] = parseFloat(String(gsap$1.getProperty(el, "width", "px"))));
|
|
3844
|
+
/**
|
|
3845
|
+
* Calculate current position as percentage of element width
|
|
3846
|
+
* Combines pixel position with any existing percentage offset
|
|
3847
|
+
*/
|
|
3013
3848
|
xPercents[i] =
|
|
3014
|
-
(parseFloat(String(gsap.getProperty(el, "x", "px"))) / w) * 100 +
|
|
3015
|
-
Number(gsap.getProperty(el, "xPercent"));
|
|
3849
|
+
(parseFloat(String(gsap$1.getProperty(el, "x", "px"))) / w) * 100 +
|
|
3850
|
+
Number(gsap$1.getProperty(el, "xPercent"));
|
|
3016
3851
|
return xPercents[i];
|
|
3017
3852
|
},
|
|
3018
3853
|
});
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3854
|
+
// Reset x position to 0 since we're now using xPercent for positioning
|
|
3855
|
+
gsap$1.set(elementsToAnimate, { x: 0 });
|
|
3856
|
+
/**
|
|
3857
|
+
* Calculate total track length for seamless looping
|
|
3858
|
+
*
|
|
3859
|
+
* Track length is the total distance content travels before looping back.
|
|
3860
|
+
* It includes:
|
|
3861
|
+
* - Distance from start to last element's left edge
|
|
3862
|
+
* - Last element's offset percentage in pixels
|
|
3863
|
+
* - Last element's full width
|
|
3864
|
+
* - Spacing gap after last element
|
|
3865
|
+
*
|
|
3866
|
+
* This ensures smooth transitions when content loops back to beginning
|
|
3867
|
+
*/
|
|
3868
|
+
const trackLength = elementsToAnimate[latestPos].offsetLeft +
|
|
3022
3869
|
(xPercents[latestPos] / 100) * widths[latestPos] -
|
|
3023
3870
|
startX +
|
|
3024
|
-
|
|
3871
|
+
elementsToAnimate[latestPos].offsetWidth +
|
|
3025
3872
|
spacing;
|
|
3026
|
-
|
|
3027
|
-
|
|
3873
|
+
/**
|
|
3874
|
+
* Create staggered animation for each element
|
|
3875
|
+
*
|
|
3876
|
+
* Each element gets a two-part animation:
|
|
3877
|
+
* 1. Main movement: From start position to loop point
|
|
3878
|
+
* 2. Reset movement: From end of track back to start (seamless loop)
|
|
3879
|
+
*/
|
|
3880
|
+
elementsToAnimate.forEach((item, i) => {
|
|
3881
|
+
// Current position in pixels
|
|
3028
3882
|
const curX = (xPercents[i] / 100) * widths[i];
|
|
3883
|
+
// Distance from element to animation start point
|
|
3029
3884
|
const distanceToStart = item.offsetLeft + curX - startX;
|
|
3030
|
-
|
|
3885
|
+
/**
|
|
3886
|
+
* Calculate distance to complete loop point
|
|
3887
|
+
*
|
|
3888
|
+
* For rotation alignment mode, use height instead of width
|
|
3889
|
+
* since the element dimensions are effectively swapped
|
|
3890
|
+
*/
|
|
3891
|
+
const distanceToLoop = alignRotationWithY
|
|
3892
|
+
? distanceToStart + item.offsetHeight - spacing
|
|
3893
|
+
: distanceToStart + widths[i];
|
|
3894
|
+
/**
|
|
3895
|
+
* Part 1: Main animation - move from current position to loop point
|
|
3896
|
+
*
|
|
3897
|
+
* - Target: Position where element should loop back
|
|
3898
|
+
* - Duration: Based on distance and speed for consistent motion
|
|
3899
|
+
* - Start time: 0 (all elements start simultaneously but from different positions)
|
|
3900
|
+
*/
|
|
3031
3901
|
tl.to(item, {
|
|
3032
3902
|
xPercent: ((curX - distanceToLoop) / widths[i]) * 100,
|
|
3033
3903
|
duration: distanceToLoop / speed,
|
|
3034
|
-
}, 0
|
|
3904
|
+
}, 0 // Start immediately
|
|
3905
|
+
).fromTo(item, {
|
|
3906
|
+
/**
|
|
3907
|
+
* Part 2 Start: Position element at end of track
|
|
3908
|
+
* This creates the illusion of seamless continuation
|
|
3909
|
+
*/
|
|
3035
3910
|
xPercent: ((curX - distanceToLoop + trackLength) / widths[i]) * 100,
|
|
3036
3911
|
}, {
|
|
3912
|
+
/**
|
|
3913
|
+
* Part 2 End: Move back to original start position
|
|
3914
|
+
* Completes the seamless loop cycle
|
|
3915
|
+
*/
|
|
3037
3916
|
xPercent: xPercents[i],
|
|
3038
3917
|
duration: (curX - distanceToLoop + trackLength - curX) / speed,
|
|
3039
|
-
immediateRender: false,
|
|
3040
|
-
}, distanceToLoop / speed
|
|
3918
|
+
immediateRender: false, // Don't render start position immediately
|
|
3919
|
+
}, distanceToLoop / speed // Start after main animation completes
|
|
3920
|
+
);
|
|
3041
3921
|
});
|
|
3042
|
-
//
|
|
3043
|
-
tl.
|
|
3922
|
+
// Apply initial delay before starting animations
|
|
3923
|
+
tl.delay(delay);
|
|
3924
|
+
/**
|
|
3925
|
+
* Handle reverse direction animations
|
|
3926
|
+
*
|
|
3927
|
+
* For reverse marquees (right/down directions):
|
|
3928
|
+
* 1. Set timeline to end position
|
|
3929
|
+
* 2. Pause to prevent immediate playback
|
|
3930
|
+
* 3. Use delayed call to start reverse playback after initial delay
|
|
3931
|
+
* 4. Set up reverse completion handler for continuous looping
|
|
3932
|
+
*/
|
|
3044
3933
|
if (isReverse) {
|
|
3045
|
-
|
|
3046
|
-
|
|
3934
|
+
// If paused is requested, just pause and return
|
|
3935
|
+
if (paused) {
|
|
3936
|
+
tl.pause();
|
|
3937
|
+
return;
|
|
3938
|
+
}
|
|
3939
|
+
// Position timeline at end and pause
|
|
3940
|
+
tl.progress(1).pause();
|
|
3941
|
+
/**
|
|
3942
|
+
* Start reverse playback after delay
|
|
3943
|
+
* This creates the proper reverse scrolling effect
|
|
3944
|
+
*/
|
|
3945
|
+
gsap$1.delayedCall(delay, () => {
|
|
3946
|
+
tl.reverse(); // Start playing backwards
|
|
3947
|
+
/**
|
|
3948
|
+
* Handle seamless looping in reverse direction
|
|
3949
|
+
* When reverse completes, restart from end position
|
|
3950
|
+
* This prevents new delay in continuous reverse scrolling
|
|
3951
|
+
*/
|
|
3952
|
+
tl.eventCallback("onReverseComplete", () => {
|
|
3953
|
+
tl.totalTime(tl.rawTime() + tl.duration() * 100);
|
|
3954
|
+
});
|
|
3955
|
+
});
|
|
3047
3956
|
}
|
|
3048
3957
|
};
|
|
3049
3958
|
|
|
3050
3959
|
const GSAPReactMarquee = require$$0.forwardRef((props, ref) => {
|
|
3051
|
-
const { children, className, dir = "left", loop = -1, paused = false, fill = false,
|
|
3960
|
+
const { children, className, dir = "left", loop = -1, paused = false, fill = false, followScrollDir = false, scrollSpeed = 2.5, } = props;
|
|
3052
3961
|
const rootRef = require$$0.useRef(null) || ref;
|
|
3053
3962
|
const containerRef = rootRef;
|
|
3054
3963
|
const marqueeRef = require$$0.useRef(null);
|
|
@@ -3059,14 +3968,14 @@ const GSAPReactMarquee = require$$0.forwardRef((props, ref) => {
|
|
|
3059
3968
|
if (!(marqueeRef === null || marqueeRef === void 0 ? void 0 : marqueeRef.current) || !containerRef.current)
|
|
3060
3969
|
return;
|
|
3061
3970
|
const containerMarquee = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current;
|
|
3062
|
-
const marquees = gsap.utils.toArray(containerMarquee.querySelectorAll(".gsap-react-marquee"));
|
|
3063
|
-
const marqueesChildren = gsap.utils.toArray(containerMarquee.querySelectorAll(".gsap-react-marquee .gsap-react-marquee-content"));
|
|
3971
|
+
const marquees = gsap$1.utils.toArray(containerMarquee.querySelectorAll(".gsap-react-marquee"));
|
|
3972
|
+
const marqueesChildren = gsap$1.utils.toArray(containerMarquee.querySelectorAll(".gsap-react-marquee .gsap-react-marquee-content"));
|
|
3064
3973
|
const marquee = marqueeRef.current;
|
|
3065
3974
|
if (!marquee || !marqueesChildren)
|
|
3066
3975
|
return;
|
|
3067
|
-
const tl = gsap.timeline({
|
|
3068
|
-
repeat: loop,
|
|
3976
|
+
const tl = gsap$1.timeline({
|
|
3069
3977
|
paused: paused,
|
|
3978
|
+
repeat: loop,
|
|
3070
3979
|
defaults: { ease: "none" },
|
|
3071
3980
|
onReverseComplete() {
|
|
3072
3981
|
// start the animation from the end, when scrolling in reverse (up)
|
|
@@ -3077,29 +3986,78 @@ const GSAPReactMarquee = require$$0.forwardRef((props, ref) => {
|
|
|
3077
3986
|
setupContainerStyles(containerMarquee, marquees, marqueesChildren, isVertical, props);
|
|
3078
3987
|
// Calculate dimensions and duplicates
|
|
3079
3988
|
const containerMarqueeWidth = containerMarquee.offsetWidth;
|
|
3080
|
-
const marqueeHeight = marquees[0].offsetHeight;
|
|
3081
3989
|
const marqueeChildrenWidth = marqueesChildren[0].offsetWidth;
|
|
3082
3990
|
const startX = marqueesChildren[0].offsetLeft;
|
|
3991
|
+
// Clamp scrollSpeed to valid range (1.1 to 4.0)
|
|
3992
|
+
const clampedScrollSpeed = Math.min(4, Math.max(1.1, scrollSpeed));
|
|
3083
3993
|
setMarqueeDuplicates(calculateDuplicates(marqueeChildrenWidth, containerMarqueeWidth, isVertical, props));
|
|
3084
3994
|
// Calculate total width and set marquee styles
|
|
3085
|
-
const totalWidth = gsap.utils
|
|
3995
|
+
const totalWidth = gsap$1.utils
|
|
3086
3996
|
.toArray(marquee.children)
|
|
3087
3997
|
.map((child) => child.offsetWidth)
|
|
3088
3998
|
.reduce((a, b) => a + b, 0);
|
|
3089
|
-
gsap.set(marquees, {
|
|
3999
|
+
gsap$1.set(marquees, {
|
|
3090
4000
|
minWidth: getMinWidth(marqueesChildren, totalWidth, containerMarqueeWidth, props),
|
|
3091
4001
|
flex: fill ? "0 0 auto" : "1",
|
|
3092
4002
|
});
|
|
3093
4003
|
// Create appropriate animation based on fill setting
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
4004
|
+
coreAnimation(fill ? marqueesChildren : marquees, startX, tl, isReverse, props);
|
|
4005
|
+
/**
|
|
4006
|
+
* GSAP Observer for scroll-based speed control
|
|
4007
|
+
*
|
|
4008
|
+
* This creates an interactive experience where users can control
|
|
4009
|
+
* the marquee speed and direction through mouse wheel scrolling.
|
|
4010
|
+
*
|
|
4011
|
+
* Behavior:
|
|
4012
|
+
* - Scroll down: Increases speed in normal direction
|
|
4013
|
+
* - Scroll up: Increases speed in reverse direction or slows normal direction
|
|
4014
|
+
* - Speed changes are smoothly animated with acceleration and deceleration phases
|
|
4015
|
+
* - ScrollSpeed multiplier is applied and clamped to valid range
|
|
4016
|
+
*/
|
|
4017
|
+
Observer.create({
|
|
4018
|
+
onChangeY(self) {
|
|
4019
|
+
if (!followScrollDir)
|
|
4020
|
+
return;
|
|
4021
|
+
let factor = clampedScrollSpeed * (isReverse ? -1 : 1);
|
|
4022
|
+
if (self.deltaY < 0) {
|
|
4023
|
+
factor *= -1;
|
|
4024
|
+
}
|
|
4025
|
+
/**
|
|
4026
|
+
* Create smooth speed transition animation
|
|
4027
|
+
*
|
|
4028
|
+
* Phase 1: Quick acceleration to new speed (0.2s)
|
|
4029
|
+
* - timeScale: Controls timeline playback speed (higher = faster)
|
|
4030
|
+
* - factor * 2.5: Initial speed boost for responsive feel
|
|
4031
|
+
* - overwrite: Cancels any previous speed animations
|
|
4032
|
+
*
|
|
4033
|
+
* Phase 2: Gradual deceleration to sustained speed (1s delay + 1s duration)
|
|
4034
|
+
* - factor / 2.5: Settle to a more moderate sustained speed
|
|
4035
|
+
* - "+=0.3": Wait 0.3 seconds before starting deceleration
|
|
4036
|
+
*/
|
|
4037
|
+
gsap$1
|
|
4038
|
+
.timeline({
|
|
4039
|
+
defaults: {
|
|
4040
|
+
ease: "none",
|
|
4041
|
+
},
|
|
4042
|
+
})
|
|
4043
|
+
.to(tl, {
|
|
4044
|
+
timeScale: factor * 2.5,
|
|
4045
|
+
duration: 0.2,
|
|
4046
|
+
overwrite: true,
|
|
4047
|
+
})
|
|
4048
|
+
.to(tl, { timeScale: factor / 2.5, duration: 1 }, "+=0.3");
|
|
4049
|
+
},
|
|
4050
|
+
});
|
|
4051
|
+
}, {
|
|
4052
|
+
dependencies: [marqueeDuplicates],
|
|
4053
|
+
});
|
|
4054
|
+
/**
|
|
4055
|
+
* Generate cloned marquee elements for seamless looping
|
|
4056
|
+
*
|
|
4057
|
+
* Creates multiple copies of the content based on calculated duplicates.
|
|
4058
|
+
* Each clone maintains the same structure and styling as the original.
|
|
4059
|
+
* Memoized to prevent unnecessary re-renders when dependencies haven't changed.
|
|
4060
|
+
*/
|
|
3103
4061
|
const clonedMarquees = require$$0.useMemo(() => {
|
|
3104
4062
|
if (!Number.isFinite(marqueeDuplicates) || marqueeDuplicates <= 0)
|
|
3105
4063
|
return null;
|
|
@@ -3111,9 +4069,8 @@ GSAPReactMarquee.displayName = "GSAPReactMarquee";
|
|
|
3111
4069
|
|
|
3112
4070
|
exports.calculateDuplicates = calculateDuplicates;
|
|
3113
4071
|
exports.cn = cn;
|
|
4072
|
+
exports.coreAnimation = coreAnimation;
|
|
3114
4073
|
exports.default = GSAPReactMarquee;
|
|
3115
|
-
exports.fillAnimation = fillAnimation;
|
|
3116
4074
|
exports.getMinWidth = getMinWidth;
|
|
3117
4075
|
exports.setupContainerStyles = setupContainerStyles;
|
|
3118
|
-
exports.simpleAnimation = simpleAnimation;
|
|
3119
4076
|
//# sourceMappingURL=index.cjs.js.map
|