UNPKG

@erosnicolau/animated-text

Version:

Advanced React animated text component with comprehensive animation effects

87 lines (86 loc) 6.36 kB
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;