@erosnicolau/animated-text
Version:
Advanced React animated text component with comprehensive animation effects
61 lines (60 loc) • 2.27 kB
JavaScript
import { FONT_PRESETS } from '../types';
// Tailwind font size mapping for scaling calculations
const FONT_SIZE_MAP = {
'text-xs': 12,
'text-sm': 14,
'text-base': 16,
'text-lg': 18,
'text-xl': 20,
'text-2xl': 24,
'text-3xl': 30,
'text-4xl': 36,
'text-5xl': 48,
'text-6xl': 60,
'text-7xl': 72,
'text-8xl': 96,
'text-9xl': 128
};
// Reverse mapping to find closest Tailwind class
const SIZE_TO_CLASS = Object.entries(FONT_SIZE_MAP).reduce((acc, [className, size]) => {
acc[size] = className;
return acc;
}, {});
const AVAILABLE_SIZES = Object.values(FONT_SIZE_MAP).sort((a, b) => a - b);
/**
* Find the closest Tailwind font size class for a given pixel size
*/
const findClosestFontClass = (targetSize) => {
const closest = AVAILABLE_SIZES.reduce((prev, curr) => Math.abs(curr - targetSize) < Math.abs(prev - targetSize) ? curr : prev);
return SIZE_TO_CLASS[closest];
};
/**
* Apply scaling to a font preset string containing responsive classes
* Example: applyScaleToPreset('text-3xl md:text-4xl lg:text-5xl', 1.2)
* Returns: 'text-4xl md:text-5xl lg:text-6xl'
*/
const applyScaleToPreset = (presetClasses, scale) => {
if (scale === 1)
return presetClasses;
return presetClasses.replace(/text-(\w+)/g, match => {
const currentSize = FONT_SIZE_MAP[match];
if (!currentSize)
return match;
const scaledSize = Math.round(currentSize * scale);
return findClosestFontClass(scaledSize);
});
};
/**
* Get font classes based on the 3-level priority system:
* Level 1: Explicit className (highest priority) - returns empty to let className win
* Level 2: Font presets (medium priority) - applies preset + scaling
* Level 3: Default fallback (lowest priority) - applies default preset when nothing specified
*/
export const getFontClasses = (hasExplicitFontClasses, fontPreset = 'section', fontScale = 1) => {
// Level 1: Explicit className font classes win - return empty to let className take precedence
if (hasExplicitFontClasses)
return '';
// Level 2 & 3: Build from preset + scale (includes default fallback)
const basePreset = FONT_PRESETS[fontPreset];
return applyScaleToPreset(basePreset, fontScale);
};