create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
255 lines (236 loc) • 9.77 kB
Flow
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import NativeAnimatedNonTurboModule from './NativeAnimatedModule';
import NativeAnimatedTurboModule from './NativeAnimatedTurboModule';
import NativeEventEmitter from '../NativeEventEmitter';
import Platform from '../../../exports/Platform';
import type { EventConfig } from './AnimatedEvent';
import type { EventMapping, AnimatedNodeConfig, AnimatingNodeConfig } from './NativeAnimatedModule';
import type { AnimationConfig, EndCallback } from './animations/Animation';
import type { InterpolationConfigType } from './nodes/AnimatedInterpolation';
import invariant from 'fbjs/lib/invariant'; // TODO T69437152 @petetheheat - Delete this fork when Fabric ships to 100%.
const NativeAnimatedModule = Platform.OS === 'ios' && global.RN$Bridgeless ? NativeAnimatedTurboModule : NativeAnimatedNonTurboModule;
let __nativeAnimatedNodeTagCount = 1;
/* used for animated nodes */
let __nativeAnimationIdCount = 1;
/* used for started animations */
let nativeEventEmitter;
let waitingForQueuedOperations = new Set();
let queueOperations = false;
let queue: Array<() => void> = [];
/**
* Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
* the native module methods
*/
const API = {
getValue: function (tag: number, saveValueCallback: (value: number) => void): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
if (NativeAnimatedModule.getValue) {
NativeAnimatedModule.getValue(tag, saveValueCallback);
}
},
setWaitingForIdentifier: function (id: string): void {
waitingForQueuedOperations.add(id);
queueOperations = true;
},
unsetWaitingForIdentifier: function (id: string): void {
waitingForQueuedOperations.delete(id);
if (waitingForQueuedOperations.size === 0) {
queueOperations = false;
API.disableQueue();
}
},
disableQueue: function (): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
if (Platform.OS === 'android') {
NativeAnimatedModule.startOperationBatch();
}
for (let q = 0, l = queue.length; q < l; q++) {
queue[q]();
}
queue.length = 0;
if (Platform.OS === 'android') {
NativeAnimatedModule.finishOperationBatch();
}
},
queueOperation: (fn: (() => void)): void => {
if (queueOperations) {
queue.push(fn);
} else {
fn();
}
},
createAnimatedNode: function (tag: number, config: AnimatedNodeConfig): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.createAnimatedNode(tag, config));
},
startListeningToAnimatedNodeValue: function (tag: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.startListeningToAnimatedNodeValue(tag));
},
stopListeningToAnimatedNodeValue: function (tag: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag));
},
connectAnimatedNodes: function (parentTag: number, childTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag));
},
disconnectAnimatedNodes: function (parentTag: number, childTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag));
},
startAnimatingNode: function (animationId: number, nodeTag: number, config: AnimatingNodeConfig, endCallback: EndCallback): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.startAnimatingNode(animationId, nodeTag, config, endCallback));
},
stopAnimation: function (animationId: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.stopAnimation(animationId));
},
setAnimatedNodeValue: function (nodeTag: number, value: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value));
},
setAnimatedNodeOffset: function (nodeTag: number, offset: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset));
},
flattenAnimatedNodeOffset: function (nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag));
},
extractAnimatedNodeOffset: function (nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag));
},
connectAnimatedNodeToView: function (nodeTag: number, viewTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag));
},
disconnectAnimatedNodeFromView: function (nodeTag: number, viewTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag));
},
restoreDefaultValues: function (nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available'); // Backwards compat with older native runtimes, can be removed later.
if (NativeAnimatedModule.restoreDefaultValues != null) {
API.queueOperation(() => NativeAnimatedModule.restoreDefaultValues(nodeTag));
}
},
dropAnimatedNode: function (tag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.dropAnimatedNode(tag));
},
addAnimatedEventToView: function (viewTag: number, eventName: string, eventMapping: EventMapping) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.addAnimatedEventToView(viewTag, eventName, eventMapping));
},
removeAnimatedEventFromView(viewTag: number, eventName: string, animatedNodeTag: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
API.queueOperation(() => NativeAnimatedModule.removeAnimatedEventFromView(viewTag, eventName, animatedNodeTag));
}
};
/**
* Styles allowed by the native animated implementation.
*
* In general native animated implementation should support any numeric property that doesn't need
* to be updated through the shadow view hierarchy (all non-layout properties).
*/
const SUPPORTED_STYLES = {
opacity: true,
transform: true,
borderRadius: true,
borderBottomEndRadius: true,
borderBottomLeftRadius: true,
borderBottomRightRadius: true,
borderBottomStartRadius: true,
borderTopEndRadius: true,
borderTopLeftRadius: true,
borderTopRightRadius: true,
borderTopStartRadius: true,
elevation: true,
zIndex: true,
/* ios styles */
shadowOpacity: true,
shadowRadius: true,
/* legacy android transform properties */
scaleX: true,
scaleY: true,
translateX: true,
translateY: true
};
const SUPPORTED_TRANSFORMS = {
translateX: true,
translateY: true,
scale: true,
scaleX: true,
scaleY: true,
rotate: true,
rotateX: true,
rotateY: true,
rotateZ: true,
perspective: true
};
const SUPPORTED_INTERPOLATION_PARAMS = {
inputRange: true,
outputRange: true,
extrapolate: true,
extrapolateRight: true,
extrapolateLeft: true
};
declare function addWhitelistedStyleProp(prop: string): void;
declare function addWhitelistedTransformProp(prop: string): void;
declare function addWhitelistedInterpolationParam(param: string): void;
declare function validateTransform(configs: Array<{
type: 'animated',
property: string,
nodeTag: ?number,
...
} | {
type: 'static',
property: string,
value: number | string,
...
}>): void;
declare function validateStyles(styles: {
[key: string]: ?number,
...
}): void;
declare function validateInterpolation(config: InterpolationConfigType): void;
declare function generateNewNodeTag(): number;
declare export function generateNewAnimationId(): number;
declare function assertNativeAnimatedModule(): void;
let _warnedMissingNativeAnimated = false;
declare export function shouldUseNativeDriver(config: { ...AnimationConfig,
...
} | EventConfig): boolean;
declare function transformDataType(value: number | string): number | string;
export default {
API,
addWhitelistedStyleProp,
addWhitelistedTransformProp,
addWhitelistedInterpolationParam,
validateStyles,
validateTransform,
validateInterpolation,
generateNewNodeTag,
generateNewAnimationId,
assertNativeAnimatedModule,
shouldUseNativeDriver,
transformDataType,
// $FlowExpectedError - unsafe getter lint suppresion
get nativeEventEmitter(): NativeEventEmitter {
if (!nativeEventEmitter) {
nativeEventEmitter = new NativeEventEmitter(NativeAnimatedModule);
}
return nativeEventEmitter;
}
};