2424
2525'use client' ;
2626
27- import React , { useCallback , useEffect , useRef , useState } from 'react' ;
27+ import React , { PropsWithChildren , useCallback , useEffect , useRef , useState } from 'react' ;
2828import { AnimatePresence , motion , LayoutGroup } from 'framer-motion' ;
2929import { cn } from '@/lib/utils' ;
3030
31- const FlipWords = ( { words, duration = 3000 , className} : { className ?: string ; duration ?: number ; words : string [ ] } ) => {
31+ export interface FlipWordsProps {
32+ className ?: string ;
33+ duration ?: number ;
34+ words : string [ ] ;
35+ }
36+
37+ const FlipWords = ( { words, duration = 3000 , className, children} : PropsWithChildren < FlipWordsProps > ) => {
3238 const [ currentWord , setCurrentWord ] = useState ( words [ 0 ] ) ;
3339 const [ isAnimating , setIsAnimating ] = useState < boolean > ( false ) ;
3440
35- // thanks for the fix Julian - https://github.com/Julian-AT
3641 const startAnimation = useCallback ( ( ) => {
3742 const word = words [ words . indexOf ( currentWord ) + 1 ] || words [ 0 ] ;
3843 setCurrentWord ( word ) ;
@@ -47,67 +52,69 @@ const FlipWords = ({words, duration = 3000, className}: {className?: string; dur
4752 } , [ isAnimating , duration , startAnimation ] ) ;
4853
4954 return (
50- < AnimatePresence
51- onExitComplete = { ( ) => {
52- setIsAnimating ( false ) ;
53- } }
54- >
55- < motion . div
56- initial = { {
57- opacity : 0 ,
58- y : 10 ,
59- } }
60- animate = { {
61- opacity : 1 ,
62- y : 0 ,
63- } }
64- transition = { {
65- type : 'spring' ,
66- stiffness : 100 ,
67- damping : 10 ,
68- } }
69- exit = { {
70- opacity : 0 ,
71- y : - 40 ,
72- x : 40 ,
73- filter : 'blur(8px)' ,
74- scale : 2 ,
75- position : 'absolute' ,
55+ < >
56+ < AnimatePresence
57+ onExitComplete = { ( ) => {
58+ setIsAnimating ( false ) ;
7659 } }
77- className = { cn ( 'z-10 inline-block relative text-left px-2' , className ) }
78- key = { currentWord }
7960 >
80- { /* edit suggested by Sajal: https://x.com/DewanganSajal */ }
81- { currentWord . split ( ' ' ) . map ( ( word , wordIndex ) => (
82- < motion . span
83- key = { word + wordIndex }
84- initial = { { opacity : 0 , y : 10 , filter : 'blur(8px)' } }
85- animate = { { opacity : 1 , y : 0 , filter : 'blur(0px)' } }
86- transition = { {
87- delay : wordIndex * 0.3 ,
88- duration : 0.3 ,
89- } }
90- className = "inline-block whitespace-nowrap"
91- >
92- { word . split ( '' ) . map ( ( letter , letterIndex ) => (
93- < motion . span
94- key = { word + letterIndex }
95- initial = { { opacity : 0 , y : 10 , filter : 'blur(8px)' } }
96- animate = { { opacity : 1 , y : 0 , filter : 'blur(0px)' } }
97- transition = { {
98- delay : wordIndex * 0.3 + letterIndex * 0.05 ,
99- duration : 0.2 ,
100- } }
101- className = "inline-block"
102- >
103- { letter }
104- </ motion . span >
105- ) ) }
106- < span className = "inline-block" > </ span >
107- </ motion . span >
108- ) ) }
109- </ motion . div >
110- </ AnimatePresence >
61+ < motion . div
62+ initial = { {
63+ opacity : 0 ,
64+ y : 10 ,
65+ } }
66+ animate = { {
67+ opacity : 1 ,
68+ y : 0 ,
69+ } }
70+ transition = { {
71+ type : 'spring' ,
72+ stiffness : 100 ,
73+ damping : 10 ,
74+ } }
75+ exit = { {
76+ opacity : 0 ,
77+ y : - 40 ,
78+ x : 40 ,
79+ filter : 'blur(8px)' ,
80+ scale : 2 ,
81+ position : 'absolute' ,
82+ } }
83+ className = { cn ( 'z-10 inline-block relative text-left px-2' , className ) }
84+ key = { currentWord }
85+ >
86+ { currentWord . split ( ' ' ) . map ( ( word , wordIndex ) => (
87+ < motion . span
88+ key = { word + wordIndex }
89+ initial = { { opacity : 0 , y : 10 , filter : 'blur(8px)' } }
90+ animate = { { opacity : 1 , y : 0 , filter : 'blur(0px)' } }
91+ transition = { {
92+ delay : wordIndex * 0.3 ,
93+ duration : 0.3 ,
94+ } }
95+ className = "inline-block whitespace-nowrap"
96+ >
97+ { word . split ( '' ) . map ( ( letter , letterIndex ) => (
98+ < motion . span
99+ key = { word + letterIndex }
100+ initial = { { opacity : 0 , y : 10 , filter : 'blur(8px)' } }
101+ animate = { { opacity : 1 , y : 0 , filter : 'blur(0px)' } }
102+ transition = { {
103+ delay : wordIndex * 0.3 + letterIndex * 0.05 ,
104+ duration : 0.2 ,
105+ } }
106+ className = "inline-block"
107+ >
108+ { letter }
109+ </ motion . span >
110+ ) ) }
111+ < span className = "inline-block" > </ span >
112+ </ motion . span >
113+ ) ) }
114+ </ motion . div >
115+ { children }
116+ </ AnimatePresence >
117+ </ >
111118 ) ;
112119} ;
113120
0 commit comments