/** * RuntimeElement Component * * Renders a single UI element with interactive effects at runtime. * Handles hover, focus, and active states for element effects. */ import React from 'react'; import { useElementEffects } from '../hooks/useElementEffects'; import { buildElementStyle } from '../lib/elementStyles'; import { buildTransitionStyle, buildAppearAnimationStyle, hasAnyEffects, type ElementEffectProperties, } from '../lib/elementEffects'; interface RuntimeElementProps { element: any; onClick: () => void; children: React.ReactNode; } const RuntimeElement: React.FC = ({ element, onClick, children, }) => { const xPercent = element.xPercent ?? 0; const yPercent = element.yPercent ?? 0; const rotation = element.rotation ?? 0; // Extract effect properties from element const effectProperties: Partial = { appearAnimation: element.appearAnimation, appearAnimationDuration: element.appearAnimationDuration, appearAnimationEasing: element.appearAnimationEasing, hoverScale: element.hoverScale, hoverOpacity: element.hoverOpacity, hoverBackgroundColor: element.hoverBackgroundColor, hoverColor: element.hoverColor, hoverBoxShadow: element.hoverBoxShadow, hoverTransitionDuration: element.hoverTransitionDuration, focusScale: element.focusScale, focusOpacity: element.focusOpacity, focusOutline: element.focusOutline, focusBoxShadow: element.focusBoxShadow, activeScale: element.activeScale, activeOpacity: element.activeOpacity, activeBackgroundColor: element.activeBackgroundColor, }; // Use effects hook for interactive states const { effectStyle, eventHandlers } = useElementEffects(effectProperties); // Build base element style const baseStyle: React.CSSProperties = { left: `${xPercent}%`, top: `${yPercent}%`, transform: `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''}`, ...buildElementStyle(element), }; // Merge transform if effect style has transform let mergedStyle: React.CSSProperties = { ...baseStyle }; // Handle transform merging - effect transform overrides base (except for position) if (effectStyle.transform) { // Preserve the translate and rotation, add effect transform mergedStyle.transform = `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''} ${effectStyle.transform}`; // Remove transform from effectStyle to avoid double application const { transform, ...restEffectStyle } = effectStyle; mergedStyle = { ...mergedStyle, ...restEffectStyle }; } else { mergedStyle = { ...mergedStyle, ...effectStyle }; } // Add transition if element has any effects if (hasAnyEffects(effectProperties)) { const transitionStyle = buildTransitionStyle(effectProperties); mergedStyle = { ...mergedStyle, ...transitionStyle }; } // Add appear animation if configured if (effectProperties.appearAnimation) { const animationStyle = buildAppearAnimationStyle(effectProperties); mergedStyle = { ...mergedStyle, ...animationStyle }; } return (
{children}
); }; export default RuntimeElement;