@erosnicolau/animated-text
Version:
Advanced React animated text component with comprehensive animation effects
87 lines (86 loc) • 6.36 kB
JavaScript
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import React, { useMemo, useState } from 'react';
import { DEFAULT_GROUP_CONFIG } from '../types';
import { AnimatedTextGroupProvider } from './AnimatedTextGroupProvider';
import ConfigModal from './ConfigModal';
const AnimatedTextGroup = ({ children, className = '', style, showReplay = DEFAULT_GROUP_CONFIG.showReplay, showConfig = DEFAULT_GROUP_CONFIG.showConfig, groupId: propGroupId, groupStartDelay = DEFAULT_GROUP_CONFIG.groupStartDelay, staggerDelay = DEFAULT_GROUP_CONFIG.staggerDelay, groupEasing, coordinationMode = DEFAULT_GROUP_CONFIG.coordinationMode, reduceMotionMode = DEFAULT_GROUP_CONFIG.reduceMotionMode, intersectionConfig: _intersectionConfig, batchUpdates: _batchUpdates = DEFAULT_GROUP_CONFIG.batchUpdates, debugMode = DEFAULT_GROUP_CONFIG.debugMode, highlightGroup = DEFAULT_GROUP_CONFIG.highlightGroup, logTiming = DEFAULT_GROUP_CONFIG.logTiming, dependencies: _dependencies, onGroupStart, onGroupComplete, onChildStart, onChildComplete }) => {
// Stable groupId - generate once and keep it
const [groupId] = useState(() => propGroupId || `group-${Math.random().toString(36).substr(2, 9)}`);
// Group replay state
const [groupReplayKey, setGroupReplayKey] = useState(0);
const [showConfigModal, setShowConfigModal] = useState(false);
// Child button visibility state - hidden by default when in a group
const [showChildButtons, setShowChildButtons] = useState(false);
// Handle group replay
const handleGroupReplay = () => {
setGroupReplayKey(prev => prev + 1);
// Debug logging to verify replay functionality
if (debugMode && logTiming) {
console.log(`[AnimatedTextGroup:${groupId}] Group replay triggered, new key:`, groupReplayKey + 1);
}
};
// Handle child button visibility toggle
const handleToggleChildButtons = () => {
setShowChildButtons(prev => !prev);
if (debugMode && logTiming) {
console.log(`[AnimatedTextGroup:${groupId}] Child buttons visibility toggled:`, !showChildButtons);
}
};
// Handle group config
const handleShowConfig = () => {
setShowConfigModal(true);
};
// Compute container classes with debug highlighting
const containerClasses = useMemo(() => {
let classes = className;
if (highlightGroup && debugMode) {
classes += ' ring-2 ring-blue-500 ring-opacity-50 relative';
}
// Add class to hide child buttons when toggled off
if (!showChildButtons) {
classes += ' hide-child-buttons';
}
return classes;
}, [className, highlightGroup, debugMode, showChildButtons]);
// Compute container styles
const containerStyles = useMemo(() => {
return {
...style,
// Always add position relative when buttons are shown OR when debug highlighting is enabled
...((showReplay || showConfig || (highlightGroup && debugMode)) && {
position: 'relative'
})
};
}, [style, showReplay, showConfig, highlightGroup, debugMode]);
// Generate group configuration for modal
const groupConfig = useMemo(() => ({
groupId,
coordinationMode,
groupStartDelay,
staggerDelay,
groupEasing,
reduceMotionMode,
debugMode,
logTiming,
showReplay,
showConfig,
children: React.Children.count(children)
}), [
groupId,
coordinationMode,
groupStartDelay,
staggerDelay,
groupEasing,
reduceMotionMode,
debugMode,
logTiming,
showReplay,
showConfig,
children
]);
return (_jsx(AnimatedTextGroupProvider, { groupId: groupId, groupReplayKey: groupReplayKey, coordinationMode: coordinationMode, groupStartDelay: groupStartDelay, staggerDelay: staggerDelay, ...(groupEasing && { groupEasing }), debugMode: debugMode, reduceMotionMode: reduceMotionMode, isShowReplay: showReplay, isShowConfig: showConfig, ...(onGroupStart && { onGroupStart }), ...(onGroupComplete && { onGroupComplete }), ...(onChildStart && { onChildStart }), ...(onChildComplete && { onChildComplete }), logTiming: logTiming, children: _jsxs("div", { className: containerClasses, style: containerStyles, "data-animated-group": groupId, role: debugMode ? 'group' : undefined, "aria-label": debugMode ? `Animated text group: ${groupId}` : undefined, children: [debugMode && highlightGroup && (_jsxs("div", { className: "absolute top-0 left-0 bg-blue-500 text-white text-xs px-2 py-1 rounded-br opacity-75 pointer-events-none z-50", children: ["Group: ", groupId, " | Mode: ", coordinationMode] })), (showReplay || showConfig) && (_jsxs("div", { className: "absolute top-4 right-4 flex gap-2 z-40", children: [_jsx("button", { onClick: handleToggleChildButtons, className: "w-8 h-8 bg-white bg-opacity-90 hover:bg-opacity-100 text-gray-800 rounded-full flex items-center justify-center text-sm transition-all duration-200 hover:scale-110 backdrop-blur-sm border border-gray-200 shadow-md", title: showChildButtons ? 'Hide child buttons' : 'Show child buttons', children: showChildButtons ? '👁' : '🙈' }), showReplay && (_jsx("button", { onClick: handleGroupReplay, className: "w-8 h-8 bg-white bg-opacity-90 hover:bg-opacity-100 text-gray-800 rounded-full flex items-center justify-center text-xs transition-all duration-200 hover:scale-110 backdrop-blur-sm border border-gray-200 shadow-md", title: "Replay group animations", "aria-label": "Replay all animations in this group", children: "\u21BB" })), showConfig && (_jsx("button", { onClick: handleShowConfig, className: "w-8 h-8 bg-white bg-opacity-90 hover:bg-opacity-100 text-gray-800 rounded-full flex items-center justify-center text-xs transition-all duration-200 hover:scale-110 backdrop-blur-sm border border-gray-200 shadow-md", title: "Show group configuration", "aria-label": "Show configuration for this animation group", children: "\u2699" }))] })), children, showConfig && (_jsx(ConfigModal, { isOpen: showConfigModal, onClose: () => setShowConfigModal(false), componentProps: {
groupConfig,
isGroup: true
} }))] }) }));
};
export default AnimatedTextGroup;