react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
80 lines (77 loc) • 3.87 kB
JavaScript
'use strict';
import { getCompoundComponentName, getPropsBuilder, IS_ANDROID } from "../../../common/index.js";
import { filterCSSAndStyleProperties, splitCSSCallbacks } from "../../utils/index.js";
import { setViewStyle } from "../proxy.js";
import CSSAnimationsManager from "./CSSAnimationsManager.js";
import CSSCallbacksManager from "./CSSCallbacksManager.js";
import CSSPseudoStylesManager from "./CSSPseudoStylesManager.js";
import CSSTransitionsManager from "./CSSTransitionsManager.js";
export default class CSSManager {
cssCallbacksManager = null;
/**
* True if the previous update had CSS transition props attached. On the next
* update we still need to build `normalizedStyle` only on Android to revert
* props applied during the transition to correct current values. (fixes
* https://github.com/software-mansion/react-native-reanimated/issues/9218).
*/
hadTransitionLastUpdate = false;
constructor({
shadowNodeWrapper,
viewTag,
reactViewName = 'RCTView'
}, componentDisplayName = '') {
const tag = this.viewTag = viewTag;
const wrapper = shadowNodeWrapper;
const compoundComponentName = getCompoundComponentName(reactViewName, componentDisplayName);
this.propsBuilder = getPropsBuilder(compoundComponentName);
this.cssAnimationsManager = new CSSAnimationsManager(wrapper, tag, compoundComponentName);
this.cssTransitionsManager = new CSSTransitionsManager(wrapper, tag);
this.cssPseudoStylesManager = new CSSPseudoStylesManager(wrapper, tag, this.propsBuilder, compoundComponentName);
}
update(style, props = {}) {
const [animationProperties, transitionProperties, pseudoStylesBySelector, filteredStyle] = filterCSSAndStyleProperties(style);
const hasAnimation = animationProperties !== null;
const hasTransition = transitionProperties !== null;
const [animationCallbacks, transitionCallbacks] = splitCSSCallbacks(props);
// Synced before either manager runs so a cancel emitted while detaching
// still reaches the user.
const {
animationEventMask,
transitionEventMask
} = this.syncCallbacks(animationCallbacks, transitionCallbacks);
const normalizedStyle = hasAnimation || hasTransition || IS_ANDROID && this.hadTransitionLastUpdate ? this.propsBuilder.build(filteredStyle) : undefined;
const transitionDetached = this.cssTransitionsManager.update(transitionProperties, normalizedStyle, transitionEventMask);
// Record the committed style as the base so animations and (on Android) a
// detaching transition can revert to it instead of interpolator defaults.
if (normalizedStyle && (hasAnimation || IS_ANDROID && transitionDetached)) {
setViewStyle(this.viewTag, normalizedStyle);
}
this.cssAnimationsManager.update(animationProperties, animationEventMask);
this.cssPseudoStylesManager.update(pseudoStylesBySelector, transitionProperties);
this.hadTransitionLastUpdate = hasTransition;
}
unmountCleanup() {
this.cssCallbacksManager?.retire();
this.cssAnimationsManager.unmountCleanup();
this.cssTransitionsManager.unmountCleanup();
this.cssPseudoStylesManager.unmountCleanup();
}
syncCallbacks(animationCallbacks, transitionCallbacks) {
if (!this.cssCallbacksManager) {
if (!animationCallbacks && !transitionCallbacks) {
return {
animationEventMask: 0,
transitionEventMask: 0
};
}
this.cssCallbacksManager = new CSSCallbacksManager(this.viewTag);
}
this.cssCallbacksManager.syncAnimationCallbacks(animationCallbacks);
this.cssCallbacksManager.syncTransitionCallbacks(transitionCallbacks);
return {
animationEventMask: this.cssCallbacksManager.getAnimationEventMask(),
transitionEventMask: this.cssCallbacksManager.getTransitionEventMask()
};
}
}
//# sourceMappingURL=CSSManager.js.map