react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
82 lines (81 loc) • 3.17 kB
JavaScript
'use strict';
import { has } from "./utils.js";
import { WorkletEventHandler } from "../WorkletEventHandler.js";
import { findNodeHandle } from '../platformFunctions/findNodeHandle';
export class NativeEventsManager {
#managedComponent;
#componentOptions;
#eventViewTag = -1;
constructor(component, options) {
this.#managedComponent = component;
this.#componentOptions = options;
this.#eventViewTag = this.getEventViewTag();
}
attachEvents() {
executeForEachEventHandler(this.#managedComponent.props, (key, handler) => {
handler.registerForEvents(this.#eventViewTag, key);
});
}
detachEvents() {
executeForEachEventHandler(this.#managedComponent.props, (_key, handler) => {
handler.unregisterFromEvents(this.#eventViewTag);
});
}
updateEvents(prevProps) {
const computedEventTag = this.getEventViewTag();
// If the event view tag changes, we need to completely re-mount all events
if (this.#eventViewTag !== computedEventTag) {
// Remove all bindings from previous props that ran on the old viewTag
executeForEachEventHandler(prevProps, (_key, handler) => {
handler.unregisterFromEvents(this.#eventViewTag);
});
// We don't need to unregister from current (new) props, because their events weren't registered yet
// Replace the view tag
this.#eventViewTag = computedEventTag;
// Attach the events with a new viewTag
this.attachEvents();
return;
}
executeForEachEventHandler(prevProps, (key, prevHandler) => {
const newProp = this.#managedComponent.props[key];
if (!newProp) {
// Prop got deleted
prevHandler.unregisterFromEvents(this.#eventViewTag);
} else if (isWorkletEventHandler(newProp) && newProp.workletEventHandler !== prevHandler) {
// Prop got changed
prevHandler.unregisterFromEvents(this.#eventViewTag);
newProp.workletEventHandler.registerForEvents(this.#eventViewTag);
}
});
executeForEachEventHandler(this.#managedComponent.props, (key, handler) => {
if (!prevProps[key]) {
// Prop got added
handler.registerForEvents(this.#eventViewTag);
}
});
}
getEventViewTag() {
// Get the tag for registering events - since the event emitting view can be nested inside the main component
const componentAnimatedRef = this.#managedComponent._component;
let newTag;
if (componentAnimatedRef.getScrollableNode) {
const scrollableNode = componentAnimatedRef.getScrollableNode();
newTag = findNodeHandle(scrollableNode) ?? -1;
} else {
newTag = findNodeHandle(this.#componentOptions?.setNativeProps ? this.#managedComponent : componentAnimatedRef) ?? -1;
}
return newTag;
}
}
function isWorkletEventHandler(prop) {
return has('workletEventHandler', prop) && prop.workletEventHandler instanceof WorkletEventHandler;
}
function executeForEachEventHandler(props, callback) {
for (const key in props) {
const prop = props[key];
if (isWorkletEventHandler(prop)) {
callback(key, prop.workletEventHandler);
}
}
}
//# sourceMappingURL=NativeEventsManager.js.map