UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

55 lines (54 loc) 2.35 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ import React, { useEffect } from 'react'; import clsx from 'clsx'; import { useTextRevealAnimationLines } from './useTextRevealAnimationLines'; import styles from './TextRevealAnimation.module.css'; export function TextRevealAnimation({ children, ...rest }) { const [animationStarted, setAnimationStarted] = React.useState(false); const [hasAnimationCompleted, setHasAnimationCompleted] = React.useState(false); const { ref, lines } = useTextRevealAnimationLines(children.toString() || ''); const onLineAnimationEnd = (i) => { if (lines && i === lines.length - 1) { setHasAnimationCompleted(true); } }; useEffect(() => { const el = ref.current; const observer = new IntersectionObserver(entries => { for (const entry of entries) { if (entry.isIntersecting) { setAnimationStarted(true); if (el) { observer.unobserve(el); } } } }, { threshold: 1, rootMargin: '0px 0px -10% 0px', }); if (el) { observer.observe(el); } return () => { if (el) { observer.unobserve(el); } }; }, [ref]); if (typeof children !== 'string' && (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test')) { console.warn('Children passed to TextRevealAnimation must be a string'); return null; } return (_jsx("span", { ref: ref, ...rest, children: lines?.map((line, i) => (_jsxs(React.Fragment, { children: [_jsx("span", { className: clsx(styles.TextRevealAnimation, animationStarted && styles['TextRevealAnimation--visible'], animationStarted && (hasAnimationCompleted ? styles['TextRevealAnimation'] : styles['TextRevealAnimation--animated'])), style: { '--animation-delay': `${220 + i * 200}ms`, }, onAnimationEnd: () => onLineAnimationEnd(i), children: line }), ' '] }, line))) })); }