fixed positioning for presentations
This commit is contained in:
parent
7dd3384a46
commit
e1ff820629
@ -9,9 +9,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import UiElementRenderer from './UiElements/UiElementRenderer';
|
import UiElementRenderer from './UiElements/UiElementRenderer';
|
||||||
import { useElementEffects } from '../hooks/useElementEffects';
|
import { useElementEffects } from '../hooks/useElementEffects';
|
||||||
import { useAppearAnimation } from '../hooks/useAppearAnimation';
|
|
||||||
import {
|
import {
|
||||||
buildTransitionStyle,
|
buildTransitionStyle,
|
||||||
|
buildAppearAnimationStyle,
|
||||||
hasAnyEffects,
|
hasAnyEffects,
|
||||||
extractEffectProperties,
|
extractEffectProperties,
|
||||||
} from '../lib/elementEffects';
|
} from '../lib/elementEffects';
|
||||||
@ -57,20 +57,11 @@ const RuntimeElement: React.FC<RuntimeElementProps> = ({
|
|||||||
element as unknown as Record<string, unknown>,
|
element as unknown as Record<string, unknown>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use appear animation hook (removes animation after completion to unlock properties)
|
// Use effects hook for interactive states
|
||||||
const { animationStyle, onAnimationEnd, hasAnimationEnded } =
|
|
||||||
useAppearAnimation(
|
|
||||||
effectProperties,
|
|
||||||
element.id, // Reset animation when element changes
|
|
||||||
);
|
|
||||||
|
|
||||||
// Use effects hook for interactive states with animation coordination
|
|
||||||
const { effectStyle, eventHandlers, onPersistClick } = useElementEffects(
|
const { effectStyle, eventHandlers, onPersistClick } = useElementEffects(
|
||||||
effectProperties,
|
effectProperties,
|
||||||
{
|
{
|
||||||
resetKey: element.id, // Reset reveal on element change
|
resetKey: element.id, // Reset reveal on element change
|
||||||
appearAnimationCompleted:
|
|
||||||
hasAnimationEnded || !effectProperties.appearAnimation,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -80,36 +71,33 @@ const RuntimeElement: React.FC<RuntimeElementProps> = ({
|
|||||||
onClick(); // Original navigation action
|
onClick(); // Original navigation action
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build base position style
|
// Build base position style (outer div - handles positioning + animation)
|
||||||
let positionStyle: React.CSSProperties = {
|
let positionStyle: React.CSSProperties = {
|
||||||
left: `${xPercent}%`,
|
left: `${xPercent}%`,
|
||||||
top: `${yPercent}%`,
|
top: `${yPercent}%`,
|
||||||
transform: `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''}`,
|
transform: `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Merge transform if effect style has transform
|
// Add appear animation to outer div
|
||||||
if (effectStyle.transform) {
|
// Animation stays on outer div to keep positioning hack working
|
||||||
// Preserve the translate and rotation, add effect transform
|
if (effectProperties.appearAnimation) {
|
||||||
positionStyle.transform = `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''} ${effectStyle.transform}`;
|
positionStyle = {
|
||||||
// Remove transform from effectStyle to avoid double application
|
...positionStyle,
|
||||||
const { transform, ...restEffectStyle } = effectStyle;
|
...buildAppearAnimationStyle(effectProperties),
|
||||||
positionStyle = { ...positionStyle, ...restEffectStyle };
|
};
|
||||||
} else {
|
|
||||||
positionStyle = { ...positionStyle, ...effectStyle };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add transition if element has any effects
|
// Build inner wrapper style for hover/focus/active effects
|
||||||
|
// Using separate div so animation on outer div doesn't block these effects
|
||||||
|
let innerEffectStyle: React.CSSProperties = {};
|
||||||
if (hasAnyEffects(effectProperties)) {
|
if (hasAnyEffects(effectProperties)) {
|
||||||
const transitionStyle = buildTransitionStyle(effectProperties);
|
innerEffectStyle = {
|
||||||
positionStyle = { ...positionStyle, ...transitionStyle };
|
...effectStyle,
|
||||||
|
...buildTransitionStyle(effectProperties),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if appear animation uses transform (slide/scale need separate wrapper)
|
// Render content
|
||||||
const needsAnimationWrapper =
|
|
||||||
effectProperties.appearAnimation &&
|
|
||||||
effectProperties.appearAnimation !== 'fade';
|
|
||||||
|
|
||||||
// Render content (with or without animation wrapper)
|
|
||||||
const content = (
|
const content = (
|
||||||
<UiElementRenderer
|
<UiElementRenderer
|
||||||
element={element}
|
element={element}
|
||||||
@ -121,41 +109,25 @@ const RuntimeElement: React.FC<RuntimeElementProps> = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
// For fade animation (opacity only), apply to positioning div
|
// Check if we need the inner wrapper for effects
|
||||||
// For slide/scale (uses transform), use separate wrapper to avoid conflict
|
const needsEffectWrapper = hasAnyEffects(effectProperties);
|
||||||
if (needsAnimationWrapper) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className='absolute cursor-pointer'
|
|
||||||
style={positionStyle}
|
|
||||||
onClick={handleClick}
|
|
||||||
tabIndex={0}
|
|
||||||
{...eventHandlers}
|
|
||||||
>
|
|
||||||
<div style={animationStyle} onAnimationEnd={onAnimationEnd}>
|
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fade or no animation: apply animation to positioning div
|
|
||||||
const combinedStyle = effectProperties.appearAnimation
|
|
||||||
? { ...positionStyle, ...animationStyle }
|
|
||||||
: positionStyle;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='absolute cursor-pointer'
|
className='absolute cursor-pointer'
|
||||||
style={combinedStyle}
|
style={positionStyle}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onAnimationEnd={
|
{...(!needsEffectWrapper ? eventHandlers : {})}
|
||||||
effectProperties.appearAnimation ? onAnimationEnd : undefined
|
|
||||||
}
|
|
||||||
{...eventHandlers}
|
|
||||||
>
|
>
|
||||||
{content}
|
{needsEffectWrapper ? (
|
||||||
|
// Inner wrapper handles hover/focus/active effects independently from animation
|
||||||
|
<div style={innerEffectStyle} {...eventHandlers}>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
content
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user