import React, {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState
} from "https://esm.sh/react@19.0.0";
import ReactDOM from "https://esm.sh/react-dom@19.0.0/client";
import gsap from "https://esm.sh/gsap";
import { useGSAP } from "https://esm.sh/@gsap/react?deps=react@19.0.0";
gsap.registerPlugin(useGSAP);
console.clear();
function Box({ children, addAnimation, index }) {
const el = useRef();
useGSAP(() => {
console.log("Box effect");
const animation = gsap.to(el.current, { x: -200 });
addAnimation(animation, index);
}, [addAnimation, index]);
return (
<div className="box gradient-green" ref={el}>
{children}
</div>
);
}
function Circle({ children, addAnimation, index, rotation }) {
const el = useRef();
useGSAP(() => {
console.log("Circle effect");
const animation = gsap.to(el.current, { rotate: rotation, x: 200 });
addAnimation(animation, index);
}, [addAnimation, index]);
return <div className="circle gradient-blue" ref={el}>{children}</div>;
}
function App() {
const [tl, setTl] = useState();
const { contextSafe} = useGSAP(() => {
console.log("App effect (create timeline)");
const tl = gsap.timeline();
setTl(tl);
});
const addAnimation = useCallback((animation, index) => {
tl && tl.add(animation, index * 0.1);
},[tl]);
const toggleTimeline = contextSafe(() => {
console.log("toggle")
tl && tl.reversed(!tl.reversed())
});
return (
<div className="app">
<button onClick={toggleTimeline}>Toggle</button>
<Box addAnimation={addAnimation} index={0}>Box</Box>
<Circle addAnimation={addAnimation} index={1} rotation="360">Circle</Circle>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
View Compiled