gsap-react-marquee 0.1.0 → 0.1.3

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/index.d.ts CHANGED
@@ -111,14 +111,10 @@ declare const calculateDuplicates: (marqueeChildrenWidth: number, containerMarqu
111
111
  * Determines the minimum width for marquee elements
112
112
  */
113
113
  declare const getMinWidth: (marqueesChildren: HTMLElement[], totalWidth: number, containerMarqueeWidth: number, props: GSAPReactMarqueeProps) => string | number;
114
- /**
115
- * Creates a simple infinite marquee animation
116
- */
117
- declare const simpleAnimation: (marquees: HTMLElement[], marqueeChildrenDimension: number, isReverse: boolean, props: GSAPReactMarqueeProps) => void;
118
114
  /**
119
115
  * Creates a complex fill-based marquee animation with seamless looping
120
116
  */
121
- declare const fillAnimation: (marqueesChildren: HTMLElement[], startX: number, tl: gsap.core.Timeline, isReverse: boolean, props: GSAPReactMarqueeProps) => void;
117
+ declare const coreAnimation: (elementsToAnimate: HTMLElement[], startX: number, tl: gsap.core.Timeline, isReverse: boolean, props: GSAPReactMarqueeProps) => void;
122
118
 
123
- export { GSAPReactMarquee, calculateDuplicates, cn, fillAnimation, getMinWidth, setupContainerStyles, simpleAnimation };
119
+ export { calculateDuplicates, cn, coreAnimation, GSAPReactMarquee as default, getMinWidth, setupContainerStyles };
124
120
  export type { GSAPReactMarqueeProps };
package/dist/index.esm.js CHANGED
@@ -2931,7 +2931,13 @@ const setupContainerStyles = (containerMarquee, marquees, marqueesChildren, isVe
2931
2931
  rotate: isVertical ? 90 : "0",
2932
2932
  });
2933
2933
  if (isVertical) {
2934
- gsap.set(containerMarquee, { width: window.innerHeight });
2934
+ const parent = containerMarquee.parentNode;
2935
+ gsap.set(containerMarquee, {
2936
+ width: parent.offsetHeight,
2937
+ });
2938
+ gsap.set(marqueesChildren, {
2939
+ overflow: "visible",
2940
+ });
2935
2941
  }
2936
2942
  if (alignRotationWithY && marquees.length > 0) {
2937
2943
  const marqueeHeight = marquees[0].offsetHeight;
@@ -2940,12 +2946,16 @@ const setupContainerStyles = (containerMarquee, marquees, marqueesChildren, isVe
2940
2946
  });
2941
2947
  gsap.set(marqueesChildren, {
2942
2948
  rotate: -90,
2949
+ x: (containerMarquee.offsetWidth - spacing) / 2 - spacing,
2943
2950
  display: "flex",
2944
2951
  flexWrap: "wrap",
2945
2952
  width: marqueeHeight,
2946
2953
  wordBreak: "break-all",
2947
2954
  whiteSpace: "break-spaces",
2948
2955
  });
2956
+ gsap.set(marquees, {
2957
+ height: containerMarquee.offsetWidth - spacing,
2958
+ });
2949
2959
  }
2950
2960
  };
2951
2961
  /**
@@ -2973,37 +2983,16 @@ const getMinWidth = (marqueesChildren, totalWidth, containerMarqueeWidth, props)
2973
2983
  return "100%";
2974
2984
  return `${totalWidth}px`;
2975
2985
  };
2976
- /**
2977
- * Creates a simple infinite marquee animation
2978
- */
2979
- const simpleAnimation = (marquees, marqueeChildrenDimension, isReverse, props) => {
2980
- const { spacing = 16, speed = 100, loop = -1 } = props;
2981
- const tween = gsap.to(marquees, {
2982
- xPercent: (_, el) => {
2983
- const w = parseFloat(String(gsap.getProperty(el, "width", "px")));
2984
- const xPercent = ((w + spacing) / w) * 100;
2985
- return -xPercent;
2986
- },
2987
- duration: (marqueeChildrenDimension - spacing) / speed,
2988
- repeat: loop,
2989
- ease: "none",
2990
- });
2991
- tween.play();
2992
- if (isReverse) {
2993
- tween.totalTime(tween.rawTime() + tween.duration() * 100);
2994
- tween.reverse();
2995
- }
2996
- };
2997
2986
  /**
2998
2987
  * Creates a complex fill-based marquee animation with seamless looping
2999
2988
  */
3000
- const fillAnimation = (marqueesChildren, startX, tl, isReverse, props) => {
3001
- const { spacing = 16, speed = 100 } = props;
2989
+ const coreAnimation = (elementsToAnimate, startX, tl, isReverse, props) => {
2990
+ const { spacing = 16, speed = 100, delay = 0, paused = false, alignRotationWithY = false, } = props;
3002
2991
  const widths = [];
3003
2992
  const xPercents = [];
3004
- const latestPos = marqueesChildren.length - 1;
2993
+ const latestPos = elementsToAnimate.length - 1;
3005
2994
  // Set initial positions and calculate percentages
3006
- gsap.set(marqueesChildren, {
2995
+ gsap.set(elementsToAnimate, {
3007
2996
  xPercent: (i, el) => {
3008
2997
  const w = (widths[i] = parseFloat(String(gsap.getProperty(el, "width", "px"))));
3009
2998
  xPercents[i] =
@@ -3012,18 +3001,20 @@ const fillAnimation = (marqueesChildren, startX, tl, isReverse, props) => {
3012
3001
  return xPercents[i];
3013
3002
  },
3014
3003
  });
3015
- gsap.set(marqueesChildren, { x: 0 });
3016
- // Calculate the total track length for seamless looping
3017
- const trackLength = marqueesChildren[latestPos].offsetLeft +
3004
+ gsap.set(elementsToAnimate, { x: 0 });
3005
+ //Calculate the total track length for seamless looping
3006
+ const trackLength = elementsToAnimate[latestPos].offsetLeft +
3018
3007
  (xPercents[latestPos] / 100) * widths[latestPos] -
3019
3008
  startX +
3020
- marqueesChildren[latestPos].offsetWidth +
3009
+ elementsToAnimate[latestPos].offsetWidth +
3021
3010
  spacing;
3022
3011
  // Create animation timeline for each element
3023
- marqueesChildren.forEach((item, i) => {
3012
+ elementsToAnimate.forEach((item, i) => {
3024
3013
  const curX = (xPercents[i] / 100) * widths[i];
3025
3014
  const distanceToStart = item.offsetLeft + curX - startX;
3026
- const distanceToLoop = distanceToStart + widths[i];
3015
+ const distanceToLoop = alignRotationWithY
3016
+ ? distanceToStart + item.offsetHeight - spacing
3017
+ : distanceToStart + widths[i];
3027
3018
  tl.to(item, {
3028
3019
  xPercent: ((curX - distanceToLoop) / widths[i]) * 100,
3029
3020
  duration: distanceToLoop / speed,
@@ -3035,16 +3026,24 @@ const fillAnimation = (marqueesChildren, startX, tl, isReverse, props) => {
3035
3026
  immediateRender: false,
3036
3027
  }, distanceToLoop / speed);
3037
3028
  });
3038
- // Pre-render for performance optimization
3039
- tl.progress(1, true).progress(0, true);
3029
+ tl.delay(delay);
3040
3030
  if (isReverse) {
3041
- tl.totalTime(tl.rawTime() + tl.duration() * 100);
3042
- tl.reverse();
3031
+ if (paused) {
3032
+ tl.pause();
3033
+ return;
3034
+ }
3035
+ tl.progress(1).pause();
3036
+ gsap.delayedCall(delay, () => {
3037
+ tl.reverse();
3038
+ tl.eventCallback("onReverseComplete", () => {
3039
+ tl.totalTime(tl.rawTime() + tl.duration() * 100);
3040
+ });
3041
+ });
3043
3042
  }
3044
3043
  };
3045
3044
 
3046
3045
  const GSAPReactMarquee = forwardRef((props, ref) => {
3047
- const { children, className, dir = "left", loop = -1, paused = false, fill = false, alignRotationWithY, } = props;
3046
+ const { children, className, dir = "left", loop = -1, paused = false, fill = false, } = props;
3048
3047
  const rootRef = useRef(null) || ref;
3049
3048
  const containerRef = rootRef;
3050
3049
  const marqueeRef = useRef(null);
@@ -3061,8 +3060,8 @@ const GSAPReactMarquee = forwardRef((props, ref) => {
3061
3060
  if (!marquee || !marqueesChildren)
3062
3061
  return;
3063
3062
  const tl = gsap.timeline({
3064
- repeat: loop,
3065
3063
  paused: paused,
3064
+ repeat: loop,
3066
3065
  defaults: { ease: "none" },
3067
3066
  onReverseComplete() {
3068
3067
  // start the animation from the end, when scrolling in reverse (up)
@@ -3073,7 +3072,7 @@ const GSAPReactMarquee = forwardRef((props, ref) => {
3073
3072
  setupContainerStyles(containerMarquee, marquees, marqueesChildren, isVertical, props);
3074
3073
  // Calculate dimensions and duplicates
3075
3074
  const containerMarqueeWidth = containerMarquee.offsetWidth;
3076
- const marqueeHeight = marquees[0].offsetHeight;
3075
+ // const marqueeHeight = marquees[0].offsetHeight;
3077
3076
  const marqueeChildrenWidth = marqueesChildren[0].offsetWidth;
3078
3077
  const startX = marqueesChildren[0].offsetLeft;
3079
3078
  setMarqueeDuplicates(calculateDuplicates(marqueeChildrenWidth, containerMarqueeWidth, isVertical, props));
@@ -3087,15 +3086,10 @@ const GSAPReactMarquee = forwardRef((props, ref) => {
3087
3086
  flex: fill ? "0 0 auto" : "1",
3088
3087
  });
3089
3088
  // Create appropriate animation based on fill setting
3090
- if (fill) {
3091
- fillAnimation(marqueesChildren, startX, tl, isReverse, props);
3092
- }
3093
- else {
3094
- simpleAnimation(marquees, isVertical && alignRotationWithY
3095
- ? marqueeHeight
3096
- : marqueeChildrenWidth, isReverse, props);
3097
- }
3098
- }, { dependencies: [marqueeDuplicates] });
3089
+ coreAnimation(fill ? marqueesChildren : marquees, startX, tl, isReverse, props);
3090
+ }, {
3091
+ dependencies: [marqueeDuplicates],
3092
+ });
3099
3093
  const clonedMarquees = useMemo(() => {
3100
3094
  if (!Number.isFinite(marqueeDuplicates) || marqueeDuplicates <= 0)
3101
3095
  return null;
@@ -3105,5 +3099,5 @@ const GSAPReactMarquee = forwardRef((props, ref) => {
3105
3099
  });
3106
3100
  GSAPReactMarquee.displayName = "GSAPReactMarquee";
3107
3101
 
3108
- export { GSAPReactMarquee, calculateDuplicates, cn, fillAnimation, getMinWidth, setupContainerStyles, simpleAnimation };
3102
+ export { calculateDuplicates, cn, coreAnimation, GSAPReactMarquee as default, getMinWidth, setupContainerStyles };
3109
3103
  //# sourceMappingURL=index.esm.js.map