@erosnicolau/animated-text
Version:
Advanced React animated text component with comprehensive animation effects
72 lines (71 loc) • 3.15 kB
JavaScript
import { DEFAULT_TIMING, getPhraseAnimationConfig } from '../types';
import { generateAnimationStyles } from './animationStyles';
// Phrase styling utilities
const getPhraseStyles = (phraseIndex, phraseStyles) => {
if (!phraseStyles)
return {};
let className = '';
let style = {};
phraseStyles.forEach(styleConfig => {
const { phrase, className: configClassName, style: configStyle, width, minWidth, maxWidth, height, minHeight, maxHeight, verticalAlign } = styleConfig;
const isMatch = Array.isArray(phrase) ? phrase.includes(phraseIndex) : phrase === phraseIndex;
if (isMatch) {
if (configClassName) {
className = className ? `${className} ${configClassName}` : configClassName;
}
if (configStyle) {
style = { ...style, ...configStyle };
}
// Apply layout control properties
if (width)
style.width = width;
if (minWidth)
style.minWidth = minWidth;
if (maxWidth)
style.maxWidth = maxWidth;
if (height)
style.height = height;
if (minHeight)
style.minHeight = minHeight;
if (maxHeight)
style.maxHeight = maxHeight;
if (verticalAlign)
style.verticalAlign = verticalAlign;
}
});
const result = {};
if (className)
result.className = className;
if (Object.keys(style).length > 0)
result.style = style;
return result;
};
// Get combined styles for phrase with animation
export const getPhraseWithAnimationStyles = (phraseIndex, phraseStyles, animatedItems, timingDefaults = DEFAULT_TIMING, globalVerticalAlign) => {
// Get base styling
const { className, style: baseStyle } = getPhraseStyles(phraseIndex, phraseStyles);
// Apply global vertical align if no individual vertical align is set
const finalStyle = { ...baseStyle };
if (globalVerticalAlign && !finalStyle.verticalAlign) {
finalStyle.verticalAlign = globalVerticalAlign;
}
// Get animation configuration
const animConfig = getPhraseAnimationConfig(phraseIndex, phraseStyles, timingDefaults);
// Generate animation styles
const isAnimated = animatedItems?.has(phraseIndex) ?? false;
// CRITICAL FIX: For phrase animations, delay is handled by setTimeout in useAnimationState
// So we pass 0 as CSS transition delay to avoid conflicts
const animationStyle = generateAnimationStyles(animConfig.effect, animConfig.duration, 0, // Always 0 for phrase animations - timing handled by JS timeouts
animConfig.easing, isAnimated);
// CRITICAL FIX: CSS transforms require display: inline-block for spans!
// This was the missing piece - inline elements can't be transformed properly
if (animationStyle.transform) {
animationStyle.display = 'inline-block';
}
// Combine all styles
const combinedStyle = { ...finalStyle, ...animationStyle };
return {
...(className && { className }),
style: combinedStyle
};
};