Created
December 22, 2020 08:19
-
-
Save jfrolich/0ac86f998e5fa51a87d18e2c0f59958d to your computer and use it in GitHub Desktop.
Reanimated2 Bindings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Extrapolate = { | |
type t | |
@bs.scope(("default", "Extrapolate")) @bs.module("react-native-reanimated") | |
external extend: t = "EXTEND" | |
@bs.scope(("default", "Extrapolate")) @bs.module("react-native-reanimated") | |
external clamp: t = "CLAMP" | |
@bs.scope(("default", "Extrapolate")) @bs.module("react-native-reanimated") | |
external identity: t = "IDENTITY" | |
} | |
module Value = { | |
type t | |
module Interpolation = { | |
type config = { | |
inputRange: array<float>, | |
outputRange: array<float>, | |
} | |
type dynamicConfig = { | |
inputRange: array<t>, | |
outputRange: array<t>, | |
} | |
type dynamicConfigFull = { | |
inputRange: array<t>, | |
outputRange: array<t>, | |
extrapolateLeft: Extrapolate.t, | |
extrapolateRight: Extrapolate.t, | |
} | |
type configFull = { | |
inputRange: array<float>, | |
outputRange: array<float>, | |
extrapolateLeft: Extrapolate.t, | |
extrapolateRight: Extrapolate.t, | |
} | |
} | |
@bs.scope("default") @bs.module("react-native-reanimated") @bs.new | |
external make: float => t = "Value" | |
external makeFromValue: t => t = "Value" | |
external toAnimated: float => t = "%identity" | |
external intToAnimated: int => t = "%identity" | |
external boolToAnimated: bool => t = "%identity" | |
@bs.send external set: (t, t) => unit = "setValue" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolate: (t, Interpolation.config) => t = "interpolateNode" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolateDynamic: (t, Interpolation.dynamicConfig) => t = "interpolateNode" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolateFull: (t, Interpolation.configFull) => t = "interpolateNode" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolateDynamicFull: (t, Interpolation.dynamicConfigFull) => t = "interpolateNode" | |
let setInitial = (value: t, initialValue: float): t => { | |
Obj.magic(value)["__Custom_InitialValue"] = initialValue | |
value | |
} | |
} | |
module Clock = { | |
type t | |
@bs.scope("default") @bs.module("react-native-reanimated") @bs.new | |
external make: unit => t = "Clock" | |
external toValue: t => Value.t = "%identity" | |
} | |
type springConfig = { | |
mass: float, | |
stiffness: float, | |
damping: float, | |
overshootClamping: bool, | |
restSpeedThreshold: float, | |
restDisplacementThreshold: float, | |
toValue: Value.t, | |
} | |
type springState = { | |
finished: Value.t, | |
velocity: Value.t, | |
position: Value.t, | |
time: Value.t, | |
} | |
module SpringUtils = { | |
@bs.scope(("default", "SpringUtils")) @bs.module("react-native-reanimated") | |
external makeDefaultConfig: unit => springConfig = "makeDefaultConfig" | |
} | |
module InterpolatedValue = { | |
type t | |
external toFloat: t => float = "%identity" | |
} | |
// copied and modified from reason-react-native | |
module Event = { | |
type contentOffset = {y: option<Value.t>} | |
type nativeEventMapping = { | |
translationX: option<Value.t>, | |
velocityX: option<Value.t>, | |
state: option<Value.t>, | |
contentOffset: option<contentOffset>, | |
x: option<Value.t>, | |
} | |
type mapping = {nativeEvent: nativeEventMapping} | |
let defaultContentOffset = {y: None} | |
let defaultEvent = { | |
translationX: None, | |
velocityX: None, | |
state: None, | |
contentOffset: None, | |
x: None, | |
} | |
} | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external spring: (Clock.t, springState, springConfig) => Value.t = "spring" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external block: array<Value.t> => Value.t = "block" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external cond: (Value.t, Value.t, Value.t) => Value.t = "cond" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external add: (Value.t, Value.t) => Value.t = "add" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external not__: Value.t => Value.t = "not" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external absolute: Value.t => Value.t = "abs" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external greaterThan: (Value.t, Value.t) => Value.t = "greaterThan" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external greaterOrEq: (Value.t, Value.t) => Value.t = "greaterOrEq" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external lessThan: (Value.t, Value.t) => Value.t = "lessThan" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external lessOrEq: (Value.t, Value.t) => Value.t = "lessOrEq" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external sub: (Value.t, Value.t) => Value.t = "sub" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external eq: (Value.t, Value.t) => Value.t = "eq" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external neq: (Value.t, Value.t) => Value.t = "neq" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external color: (Value.t, Value.t, Value.t, Value.t) => Value.t = "color" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external maximum: (Value.t, Value.t) => Value.t = "max" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external minimum: (Value.t, Value.t) => Value.t = "min" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external round: Value.t => Value.t = "round" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external divide: (Value.t, Value.t) => Value.t = "divide" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external multiply: (Value.t, Value.t) => Value.t = "multiply" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external onChange: (Value.t, Value.t) => Value.t = "onChange" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external cond1: (Value.t, Value.t) => Value.t = "cond" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external startClock: Clock.t => Value.t = "startClock" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external stopClock: Clock.t => Value.t = "stopClock" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external clockRunning: Clock.t => Value.t = "clockRunning" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external set: (Value.t, Value.t) => Value.t = "set" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external modulo: (Value.t, Value.t) => Value.t = "modulo" | |
type callFn = array<InterpolatedValue.t> => unit | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external call: (array<Value.t>, callFn) => Value.t = "call" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external or_: (Value.t, Value.t) => Value.t = "or" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external debug: (string, Value.t) => Value.t = "debug" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external and_: (Value.t, Value.t) => Value.t = "and" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external and3: (Value.t, Value.t, Value.t) => Value.t = "and" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external and4: (Value.t, Value.t, Value.t, Value.t) => Value.t = "and" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external and5: (Value.t, Value.t, Value.t, Value.t, Value.t) => Value.t = "and" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external concat: (Value.t, string) => Value.t = "concat" | |
type arg = unit => Value.t | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external useCode1: (arg, array<'a>) => unit = "useCode" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external createAnimatedComponent: 'a => 'a = "createAnimatedComponent" | |
type pressEventRet = ReactNative.Event.pressEvent => unit | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external pressEvent: array<Event.mapping> => pressEventRet = "event" | |
type scrollEventRet = ReactNative.Event.scrollEvent => unit | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external scrollEvent: array<Event.mapping> => scrollEventRet = "event" | |
type gestureEventRet = RNGestureHandler.Event.gestureEvent => unit | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external gestureEvent: array<Event.mapping> => gestureEventRet = "event" | |
module StyleProp = { | |
// methods to allow use of Animated values with Style props | |
// these methods should not be used to get the current value | |
// for angle, Color.t, and size expressed as percentage, | |
// interpolated values are needed where the outputRange is | |
// an appropriate array of strings | |
external float: Value.t => float = "%identity" | |
external int: Value.t => int = "%identity" | |
external unsafeAngle: Value.t => ReactNative.Style.angle = "%identity" | |
let angle: Value.t => ReactNative.Style.angle = angle => concat(angle, "deg")->unsafeAngle | |
external size: Value.t => ReactNative.Style.size = "%identity" | |
external margin: Value.t => ReactNative.Style.margin = "%identity" | |
external color: Value.t => ReactNative.Color.t = "%identity" | |
} | |
let interpolateColorNode = (t, (r, g, b, a), (r', g', b', a')) => { | |
let a = Belt.Option.getWithDefault(a, 1.) | |
let a' = Belt.Option.getWithDefault(a', 1.) | |
color( | |
round( | |
Value.interpolateFull( | |
t, | |
{ | |
inputRange: [0., 1.], | |
outputRange: [r', r], | |
extrapolateLeft: Extrapolate.clamp, | |
extrapolateRight: Extrapolate.clamp, | |
}, | |
), | |
), | |
round( | |
Value.interpolateFull( | |
t, | |
{ | |
inputRange: [0., 1.], | |
outputRange: [g', g], | |
extrapolateLeft: Extrapolate.clamp, | |
extrapolateRight: Extrapolate.clamp, | |
}, | |
), | |
), | |
round( | |
Value.interpolateFull( | |
t, | |
{ | |
inputRange: [0., 1.], | |
outputRange: [b', b], | |
extrapolateLeft: Extrapolate.clamp, | |
extrapolateRight: Extrapolate.clamp, | |
}, | |
), | |
), | |
Value.interpolateFull( | |
t, | |
{ | |
inputRange: [0., 1.], | |
outputRange: [a', a], | |
extrapolateLeft: Extrapolate.clamp, | |
extrapolateRight: Extrapolate.clamp, | |
}, | |
), | |
)->StyleProp.color | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
/////////////////////// V2 | |
/////////////////////////////////////////////////////////////////////////////// | |
// this is version two. Everything above still works with version 2, but the | |
// below is the new API. Will build this while building features. | |
// once the API surface looks good, we can finalize and contribute the whole | |
// to open-source | |
module AnimationObject = { | |
// phantom type. An animation object can wrap a specific type, we need to | |
// parameterize it to make sure the types are sound. | |
type t<'a> | |
// everything that accepts an animation object also accepts the original value | |
// so to have a single type we can just cast to identity | |
external make: 'a => t<'a> = "%identity" | |
} | |
module SharedValue = { | |
type t<'a> = {mutable value: 'a} | |
} | |
module AnimatedStyle = { | |
type t | |
type transform | |
type offset | |
@bs.obj | |
external offset: (~height: AnimationObject.t<float>, ~width: AnimationObject.t<float>) => offset = | |
"" | |
@bs.obj | |
external perspective: (~perspective: AnimationObject.t<float>) => transform = "" | |
@bs.obj | |
external rotate: (~rotate: AnimationObject.t<ReactNative.Style.angle>) => transform = "" | |
@bs.obj | |
external rotateX: (~rotateX: AnimationObject.t<ReactNative.Style.angle>) => transform = "" | |
@bs.obj | |
external rotateZ: (~rotateZ: AnimationObject.t<ReactNative.Style.angle>) => transform = "" | |
@bs.obj external scale: (~scale: AnimationObject.t<float>) => transform = "" | |
@bs.obj external scaleX: (~scaleX: AnimationObject.t<float>) => transform = "" | |
@bs.obj external scaleY: (~scaleY: AnimationObject.t<float>) => transform = "" | |
@bs.obj | |
external translateX: (~translateX: AnimationObject.t<float>) => transform = "" | |
@bs.obj | |
external translateY: (~translateY: AnimationObject.t<float>) => transform = "" | |
@bs.obj | |
external skewX: (~skewX: AnimationObject.t<ReactNative.Style.angle>) => transform = "" | |
@bs.obj | |
external skewY: (~skewY: AnimationObject.t<ReactNative.Style.angle>) => transform = "" | |
// normal styles are also valid animated styles | |
external make: ReactNative.Style.t => t = "%identity" | |
// tried to iomplement most styles that are "animatable" | |
// can be expanded to have more. | |
@bs.obj | |
external style: ( | |
~overlayColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~tintColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~color: AnimationObject.t<ReactNative.Color.t>=?, | |
~fontSize: AnimationObject.t<float>=?, | |
~letterSpacing: AnimationObject.t<float>=?, | |
~lineHeight: AnimationObject.t<float>=?, | |
~textDecorationColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~textShadowColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~textShadowRadius: AnimationObject.t<float>=?, | |
~textShadowOffset: offset=?, | |
~backgroundColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderBottomColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderBottomEndRadius: AnimationObject.t<float>=?, | |
~borderBottomLeftRadius: AnimationObject.t<float>=?, | |
~borderBottomRightRadius: AnimationObject.t<float>=?, | |
~borderBottomStartRadius: AnimationObject.t<float>=?, | |
~borderBottomWidth: AnimationObject.t<float>=?, | |
~borderColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderEndColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderEndWidth: AnimationObject.t<float>=?, | |
~borderLeftColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderLeftWidth: AnimationObject.t<float>=?, | |
~borderRadius: AnimationObject.t<float>=?, | |
~borderRightColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderRightWidth: AnimationObject.t<float>=?, | |
~borderStartColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderStartWidth: AnimationObject.t<float>=?, | |
~borderTopColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~borderTopEndRadius: AnimationObject.t<float>=?, | |
~borderTopLeftRadius: AnimationObject.t<float>=?, | |
~borderTopRightRadius: AnimationObject.t<float>=?, | |
~borderTopStartRadius: AnimationObject.t<float>=?, | |
~borderTopWidth: AnimationObject.t<float>=?, | |
~borderWidth: AnimationObject.t<float>=?, | |
~elevation: AnimationObject.t<float>=?, | |
~opacity: AnimationObject.t<float>=?, | |
~transform: array<transform>=?, | |
~shadowColor: AnimationObject.t<ReactNative.Color.t>=?, | |
~shadowOffset: offset=?, | |
~shadowOpacity: AnimationObject.t<float>=?, | |
~shadowRadius: AnimationObject.t<float>=?, | |
~aspectRatio: AnimationObject.t<float>=?, | |
~bottom: AnimationObject.t<ReactNative.Style.size>=?, | |
~_end: AnimationObject.t<ReactNative.Style.size>=?, | |
~flex: AnimationObject.t<float>=?, | |
~flexBasis: AnimationObject.t<ReactNative.Style.margin>=?, | |
~flexGrow: AnimationObject.t<float>=?, | |
~flexShrink: AnimationObject.t<float>=?, | |
~height: AnimationObject.t<ReactNative.Style.size>=?, | |
~left: AnimationObject.t<ReactNative.Style.size>=?, | |
~margin: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginBottom: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginEnd: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginHorizontal: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginLeft: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginRight: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginStart: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginTop: AnimationObject.t<ReactNative.Style.margin>=?, | |
~marginVertical: AnimationObject.t<ReactNative.Style.margin>=?, | |
~maxHeight: AnimationObject.t<ReactNative.Style.size>=?, | |
~maxWidth: AnimationObject.t<ReactNative.Style.size>=?, | |
~minHeight: AnimationObject.t<ReactNative.Style.size>=?, | |
~minWidth: AnimationObject.t<ReactNative.Style.size>=?, | |
~padding: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingBottom: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingEnd: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingHorizontal: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingLeft: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingRight: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingStart: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingTop: AnimationObject.t<ReactNative.Style.size>=?, | |
~paddingVertical: AnimationObject.t<ReactNative.Style.size>=?, | |
~right: AnimationObject.t<ReactNative.Style.size>=?, | |
~start: AnimationObject.t<ReactNative.Style.size>=?, | |
~top: AnimationObject.t<ReactNative.Style.size>=?, | |
~width: AnimationObject.t<ReactNative.Style.size>=?, | |
unit, | |
) => t = "" | |
} | |
type springOptions = { | |
damping: float, | |
mass: float, | |
stiffness: float, | |
overshootClamping: bool, | |
restDisplacementThreshold: float, | |
restSpeedThreshold: float, | |
} | |
let defaultSpringOptions = { | |
damping: 10., | |
mass: 1., | |
stiffness: 100., | |
overshootClamping: false, | |
restDisplacementThreshold: 0.001, | |
restSpeedThreshold: 0.001, | |
} | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolateColor: ( | |
float, | |
array<float>, | |
array<ReactNative.Color.t>, | |
) => ReactNative.Color.t = "interpolateColor" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external withSpring: (float, springOptions) => AnimationObject.t<float> = "withSpring" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external withSpringColor: ( | |
ReactNative.Color.t, | |
springOptions, | |
) => AnimationObject.t<ReactNative.Color.t> = "withSpring" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external useSharedValue: ('a, ~shouldRebuild: bool=?) => SharedValue.t<'a> = "useSharedValue" | |
type animatedStyleArg = unit => AnimatedStyle.t | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external useAnimatedStyle: animatedStyleArg => ReactNative.Style.t = "useAnimatedStyle" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external useAnimatedStyle1: (animatedStyleArg, array<'a>) => ReactNative.Style.t = | |
"useAnimatedStyle" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolate2: ( | |
float, | |
(float, float), | |
(float, float), | |
~extrapolate: Extrapolate.t=?, | |
unit, | |
) => float = "interpolate" | |
@bs.scope("default") @bs.module("react-native-reanimated") | |
external interpolate3: ( | |
float, | |
(float, float, float), | |
(float, float, float), | |
~extrapolate: Extrapolate.t=?, | |
unit, | |
) => float = "interpolate" | |
// you can assign an animated object to a shared value. | |
// it will perform some magic, so that the value will not actually be changed | |
// the type will also not change, it will just animate the value over time | |
// so it's not actually assignment. So we need a helper function for this. | |
let assignAnimatedObject = ( | |
sharedValue: SharedValue.t<'a>, | |
animatedObject: AnimationObject.t<'a>, | |
) => sharedValue.value = Obj.magic(animatedObject) | |
type scrollEventFn = ReactNative.Event.scrollEvent => unit | |
@scope("default") @module("react-native-reanimated") | |
external useAnimatedScrollHandler: scrollEventFn => scrollEventFn = "useAnimatedScrollHandler" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment