UNPKG

react-native-navigation-bottom-sheet

Version:

A performant customizable bottom sheet component made on top of wix react-native-navigation library.

178 lines (156 loc) 4.55 kB
/** -------------------------------------------- */ /** Utility functions */ /** -------------------------------------------- */ import Animated from "react-native-reanimated"; import type { AnimationConfig } from './types'; const magic = { damping: 50, mass: 0.3, stiffness: 121.6, overshootClamping: true, restSpeedThreshold: 0.3, restDisplacementThreshold: 0.3, deceleration: 0.996, bouncyFactor: 1, velocityFactor: 0.9, toss: 0.4, coefForTranslatingVelocities: 5, } let { damping, mass, stiffness, overshootClamping, restSpeedThreshold, restDisplacementThreshold, deceleration, velocityFactor } = magic const { set, cond, multiply, decay, lessThan, timing, block, min, max, eq, Value, spring, abs, sub, clockRunning, startClock, stopClock, greaterOrEq, } = Animated export function overrideConfig(config: AnimationConfig) { damping = config.damping ? config.damping : damping; mass = config.mass ? config.mass : mass; stiffness = config.stiffness ? config.stiffness : stiffness; deceleration = config.deceleration ? config.deceleration : deceleration; mass = config.mass ? config.mass : mass; velocityFactor = config.velocityFactor ? config.velocityFactor : velocityFactor; restSpeedThreshold = config.restSpeedThreshold ? config.restSpeedThreshold : restSpeedThreshold; restDisplacementThreshold = config.restDisplacementThreshold ? config.restDisplacementThreshold : restDisplacementThreshold; } /** * Converts snap points with percentage to fixed numbers. */ export const normalizeSnapPoints = ( snapPoints: ReadonlyArray<number | string>, containerHeight: number, ) => snapPoints.map(snapPoint => { return typeof snapPoint === 'number' ? snapPoint : (Number(snapPoint.split('%')[0]) * containerHeight) / 100; }); export function runDecay( clock: Animated.Clock, value: Animated.Value<number>, velocity: Animated.Node<number>, contentHeight: Animated.Value<number> ) { const state = { finished: new Value(0), velocity: new Value(0), position: new Value(0), time: new Value(0), } const config = { deceleration } const resultScroll = max(min(state.position, 0), multiply(contentHeight, -1)); return block([ cond(clockRunning(clock), 0, [ set(state.finished, 0), set(state.velocity, multiply(velocity, velocityFactor)), set(state.position, value), set(state.time, 0), startClock(clock), ]), // cond(lessThan(abs(sub(resultScroll, multiply(contentHeight, -1))), 0.1), [set(state.finished, 1), stopClock(clock)]), // cond(lessThan(abs(resultScroll), 0.1), [set(state.finished, 1), stopClock(clock)]), cond(clockRunning(clock), [ cond(state.finished, 0, set(value, resultScroll)), decay(clock, state, config), ]), /* cond(greaterOrEq(state.position, 0), [set(state.finished, 1), stopClock(clock)]), cond(lessThan(state.position, multiply(contentHeight, -1)), [set(state.finished, 1), stopClock(clock)]), */ cond(state.finished, [stopClock(clock)]), resultScroll, ]); } export function runSpring( clock: Animated.Clock, start: Animated.Value<number>, end: Animated.Node<number>, velocity: Animated.Value<number>, updateWhenFinished: Animated.Node<number>, wasRun: Animated.Value<number>, valueToUpdate: Animated.Value<number>, ) { const state = { finished: new Value(0), velocity: new Value(0), position: new Value(0), time: new Value(0), }; const config: Animated.SpringConfig = { damping, mass, stiffness, overshootClamping, restSpeedThreshold, restDisplacementThreshold, toValue: new Value(0), }; return block([ cond( clockRunning(clock), [ // if the clock is already running we update the toValue, in case a new dest has been passed in set(config.toValue as Animated.Value<number>, end), ], [ // if the clock isn't running we reset all the animation params and start the clock // set(forcedFlag, 0), set(state.finished, 0), set(state.position, start), set(state.velocity, velocity), set(state.time, 0), set(config.toValue as Animated.Value<number>, end), startClock(clock), ], ), spring(clock, state, config), cond(state.finished, [stopClock(clock), set(wasRun, 0), updateWhenFinished]), set(valueToUpdate, state.position), state.position, ]); }