@snooper/rn-scroll-bottom-sheet
Version:
Cross platform scrollable bottom sheet with virtualization support, running at 60 FPS and fully implemented in JS land
508 lines (404 loc) • 30.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.ScrollBottomSheet = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
var _reactNativeGestureHandler = require("react-native-gesture-handler");
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const FlatListComponentType = 'FlatList';
const ScrollViewComponentType = 'ScrollView';
const SectionListComponentType = 'SectionList';
const {
height: windowHeight
} = _reactNative.Dimensions.get('window');
const DRAG_TOSS = 0.05;
const IOS_NORMAL_DECELERATION_RATE = 0.998;
const ANDROID_NORMAL_DECELERATION_RATE = 0.985;
const DEFAULT_ANIMATION_DURATION = 250;
const DEFAULT_EASING = _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.linear);
const imperativeScrollOptions = {
[FlatListComponentType]: {
method: 'scrollToIndex',
args: {
index: 0,
viewPosition: 0,
viewOffset: 1000,
animated: true
}
},
[ScrollViewComponentType]: {
method: 'scrollTo',
args: {
x: 0,
y: 0,
animated: true
}
},
[SectionListComponentType]: {
method: 'scrollToLocation',
args: {
itemIndex: 0,
sectionIndex: 0,
viewPosition: 0,
viewOffset: 1000,
animated: true
}
}
};
class ScrollBottomSheet extends _react.Component {
/**
* Gesture Handler references
*/
/**
* ScrollView prop
*/
/**
* Pan gesture handler events for drawer handle and content
*/
/**
* Main Animated Value that drives the top position of the UI drawer at any point in time
*/
/**
* Animated value that keeps track of the position: 0 => closed, 1 => opened
*/
/**
* Flag to indicate imperative snapping
*/
/**
* Manual snapping amount
*/
/**
* Keeps track of the current index
*/
/**
* Deceleration rate of the scroll component. This is used only on Android to
* compensate the unexpected glide it gets sometimes.
*/
constructor(props) {
super(props);
_defineProperty(this, "masterDrawer", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "drawerHandleRef", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "overlayComponentRef", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "drawerContentRef", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "scrollComponentRef", /*#__PURE__*/_react.default.createRef());
_defineProperty(this, "onScrollBeginDrag", void 0);
_defineProperty(this, "onHandleGestureEvent", void 0);
_defineProperty(this, "onDrawerGestureEvent", void 0);
_defineProperty(this, "translateY", void 0);
_defineProperty(this, "position", void 0);
_defineProperty(this, "isManuallySetValue", new _reactNativeReanimated.Value(0));
_defineProperty(this, "manualYOffset", new _reactNativeReanimated.Value(0));
_defineProperty(this, "nextSnapIndex", void 0);
_defineProperty(this, "decelerationRate", void 0);
_defineProperty(this, "prevSnapIndex", -1);
_defineProperty(this, "dragY", new _reactNativeReanimated.Value(0));
_defineProperty(this, "prevDragY", new _reactNativeReanimated.Value(0));
_defineProperty(this, "tempDestSnapPoint", new _reactNativeReanimated.Value(0));
_defineProperty(this, "isAndroid", new _reactNativeReanimated.Value(Number(_reactNative.Platform.OS === 'android')));
_defineProperty(this, "animationClock", new _reactNativeReanimated.Clock());
_defineProperty(this, "animationPosition", new _reactNativeReanimated.Value(0));
_defineProperty(this, "animationFinished", new _reactNativeReanimated.Value(0));
_defineProperty(this, "animationFrameTime", new _reactNativeReanimated.Value(0));
_defineProperty(this, "velocityY", new _reactNativeReanimated.Value(0));
_defineProperty(this, "lastStartScrollY", new _reactNativeReanimated.Value(0));
_defineProperty(this, "prevTranslateYOffset", void 0);
_defineProperty(this, "translationY", void 0);
_defineProperty(this, "destSnapPoint", new _reactNativeReanimated.Value(0));
_defineProperty(this, "lastSnap", void 0);
_defineProperty(this, "dragWithHandle", new _reactNativeReanimated.Value(0));
_defineProperty(this, "scrollUpAndPullDown", new _reactNativeReanimated.Value(0));
_defineProperty(this, "didGestureFinish", void 0);
_defineProperty(this, "didScrollUpAndPullDown", void 0);
_defineProperty(this, "setTranslationY", void 0);
_defineProperty(this, "extraOffset", void 0);
_defineProperty(this, "calculateNextSnapPoint", void 0);
_defineProperty(this, "scrollComponent", void 0);
_defineProperty(this, "convertPercentageToDp", str => Number(str.split('%')[0]) * (windowHeight - this.props.topInset) / 100);
_defineProperty(this, "getNormalisedSnapPoints", () => {
return this.props.snapPoints.map(p => {
if (typeof p === 'string') {
return this.convertPercentageToDp(p);
} else if (typeof p === 'number') {
return p;
}
throw new Error("Invalid type for value ".concat(p, ": ").concat(typeof p, ". It should be either a percentage string or a number"));
});
});
_defineProperty(this, "getScrollComponent", () => {
switch (this.props.componentType) {
case 'FlatList':
return _reactNative.FlatList;
case 'ScrollView':
return _reactNative.ScrollView;
case 'SectionList':
return _reactNative.SectionList;
default:
throw new Error('Component type not supported: it should be one of `FlatList`, `ScrollView` or `SectionList`');
}
});
_defineProperty(this, "snapTo", index => {
const snapPoints = this.getNormalisedSnapPoints();
this.isManuallySetValue.setValue(1);
this.manualYOffset.setValue(snapPoints[index]);
this.nextSnapIndex.setValue(index);
});
const {
initialSnapIndex,
animationConfig
} = props;
const animationDuration = (animationConfig === null || animationConfig === void 0 ? void 0 : animationConfig.duration) || DEFAULT_ANIMATION_DURATION;
const ScrollComponent = this.getScrollComponent(); // @ts-ignore
this.scrollComponent = _reactNativeReanimated.default.createAnimatedComponent(ScrollComponent);
const _snapPoints = this.getNormalisedSnapPoints();
const openPosition = _snapPoints[0];
const closedPosition = _snapPoints[_snapPoints.length - 1];
const initialSnap = _snapPoints[initialSnapIndex];
this.nextSnapIndex = new _reactNativeReanimated.Value(initialSnapIndex);
const initialDecelerationRate = _reactNative.Platform.select({
android: props.initialSnapIndex === 0 ? ANDROID_NORMAL_DECELERATION_RATE : 0,
ios: IOS_NORMAL_DECELERATION_RATE
});
this.decelerationRate = new _reactNativeReanimated.Value(initialDecelerationRate);
const handleGestureState = new _reactNativeReanimated.Value(-1);
const handleOldGestureState = new _reactNativeReanimated.Value(-1);
const drawerGestureState = new _reactNativeReanimated.Value(-1);
const drawerOldGestureState = new _reactNativeReanimated.Value(-1);
const lastSnapInRange = new _reactNativeReanimated.Value(1);
this.prevTranslateYOffset = new _reactNativeReanimated.Value(initialSnap);
this.translationY = new _reactNativeReanimated.Value(initialSnap);
this.lastSnap = new _reactNativeReanimated.Value(initialSnap);
this.onHandleGestureEvent = (0, _reactNativeReanimated.event)([{
nativeEvent: {
translationY: this.dragY,
oldState: handleOldGestureState,
state: handleGestureState,
velocityY: this.velocityY
}
}]);
this.onDrawerGestureEvent = (0, _reactNativeReanimated.event)([{
nativeEvent: {
translationY: this.dragY,
oldState: drawerOldGestureState,
state: drawerGestureState,
velocityY: this.velocityY
}
}]);
this.onScrollBeginDrag = (0, _reactNativeReanimated.event)([{
nativeEvent: {
contentOffset: {
y: this.lastStartScrollY
}
}
}]);
const didHandleGestureBegin = (0, _reactNativeReanimated.eq)(handleGestureState, _reactNativeGestureHandler.State.ACTIVE);
const isAnimationInterrupted = (0, _reactNativeReanimated.and)((0, _reactNativeReanimated.or)((0, _reactNativeReanimated.eq)(handleGestureState, _reactNativeGestureHandler.State.BEGAN), (0, _reactNativeReanimated.eq)(drawerGestureState, _reactNativeGestureHandler.State.BEGAN)), (0, _reactNativeReanimated.clockRunning)(this.animationClock));
this.didGestureFinish = (0, _reactNativeReanimated.or)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.eq)(handleOldGestureState, _reactNativeGestureHandler.State.ACTIVE), (0, _reactNativeReanimated.eq)(handleGestureState, _reactNativeGestureHandler.State.END)), (0, _reactNativeReanimated.and)((0, _reactNativeReanimated.eq)(drawerOldGestureState, _reactNativeGestureHandler.State.ACTIVE), (0, _reactNativeReanimated.eq)(drawerGestureState, _reactNativeGestureHandler.State.END))); // Function that determines if the last snap point is in the range {snapPoints}
// In the case of interruptions in the middle of an animation, we'll get
// lastSnap values outside the range
const isLastSnapPointInRange = (i = 0) => i === _snapPoints.length ? lastSnapInRange : (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.lastSnap, _snapPoints[i]), [(0, _reactNativeReanimated.set)(lastSnapInRange, 1)], isLastSnapPointInRange(i + 1));
const scrollY = [(0, _reactNativeReanimated.set)(lastSnapInRange, 0), isLastSnapPointInRange(), (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.or)(didHandleGestureBegin, (0, _reactNativeReanimated.and)(this.isManuallySetValue, (0, _reactNativeReanimated.not)((0, _reactNativeReanimated.eq)(this.manualYOffset, _snapPoints[0])))), [(0, _reactNativeReanimated.set)(this.dragWithHandle, 1), 0]), (0, _reactNativeReanimated.cond)( // This is to account for a continuous scroll on the drawer from a snap point
// Different than top, bringing the drawer to the top position, so that if we
// change scroll direction without releasing the gesture, it doesn't pull down the drawer again
(0, _reactNativeReanimated.and)((0, _reactNativeReanimated.eq)(this.dragWithHandle, 1), (0, _reactNativeReanimated.greaterThan)(_snapPoints[0], (0, _reactNativeReanimated.add)(this.lastSnap, this.dragY)), (0, _reactNativeReanimated.and)((0, _reactNativeReanimated.not)((0, _reactNativeReanimated.eq)(this.lastSnap, _snapPoints[0])), lastSnapInRange)), [(0, _reactNativeReanimated.set)(this.lastSnap, _snapPoints[0]), (0, _reactNativeReanimated.set)(this.dragWithHandle, 0), this.lastStartScrollY], (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.dragWithHandle, 1), 0, this.lastStartScrollY))];
this.didScrollUpAndPullDown = (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.greaterOrEq)(this.dragY, this.lastStartScrollY), (0, _reactNativeReanimated.greaterThan)(this.lastStartScrollY, 0)), (0, _reactNativeReanimated.set)(this.scrollUpAndPullDown, 1));
this.setTranslationY = (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.not)(this.dragWithHandle), (0, _reactNativeReanimated.not)((0, _reactNativeReanimated.greaterOrEq)(this.dragY, this.lastStartScrollY))), (0, _reactNativeReanimated.set)(this.translationY, (0, _reactNativeReanimated.sub)(this.dragY, this.lastStartScrollY)), (0, _reactNativeReanimated.set)(this.translationY, this.dragY));
this.extraOffset = (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.scrollUpAndPullDown, 1), this.lastStartScrollY, 0);
const endOffsetY = (0, _reactNativeReanimated.add)(this.lastSnap, this.translationY, (0, _reactNativeReanimated.multiply)(DRAG_TOSS, this.velocityY));
this.calculateNextSnapPoint = (i = 0) => i === _snapPoints.length ? this.tempDestSnapPoint : (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.greaterThan)((0, _reactNativeReanimated.abs)((0, _reactNativeReanimated.sub)(this.tempDestSnapPoint, endOffsetY)), (0, _reactNativeReanimated.abs)((0, _reactNativeReanimated.sub)((0, _reactNativeReanimated.add)(_snapPoints[i], this.extraOffset), endOffsetY))), [(0, _reactNativeReanimated.set)(this.tempDestSnapPoint, (0, _reactNativeReanimated.add)(_snapPoints[i], this.extraOffset)), (0, _reactNativeReanimated.set)(this.nextSnapIndex, i), this.calculateNextSnapPoint(i + 1)], this.calculateNextSnapPoint(i + 1));
const runTiming = ({
clock,
from,
to,
position,
finished,
frameTime
}) => {
const state = {
finished,
position,
time: new _reactNativeReanimated.Value(0),
frameTime
};
const animationParams = {
duration: animationDuration,
easing: (animationConfig === null || animationConfig === void 0 ? void 0 : animationConfig.easing) || DEFAULT_EASING
};
const config = _objectSpread({
toValue: new _reactNativeReanimated.Value(0)
}, animationParams);
return [(0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.not)((0, _reactNativeReanimated.clockRunning)(clock)), (0, _reactNativeReanimated.not)((0, _reactNativeReanimated.eq)(finished, 1))), [// If the clock isn't running, we reset all the animation params and start the clock
(0, _reactNativeReanimated.set)(state.finished, 0), (0, _reactNativeReanimated.set)(state.time, 0), (0, _reactNativeReanimated.set)(state.position, from), (0, _reactNativeReanimated.set)(state.frameTime, 0), (0, _reactNativeReanimated.set)(config.toValue, to), (0, _reactNativeReanimated.startClock)(clock)]), // We run the step here that is going to update position
(0, _reactNativeReanimated.timing)(clock, state, config), (0, _reactNativeReanimated.cond)(state.finished, [(0, _reactNativeReanimated.call)([this.nextSnapIndex], ([value]) => {
if (value !== this.prevSnapIndex) {
var _this$props$onSettle, _this$props;
(_this$props$onSettle = (_this$props = this.props).onSettle) === null || _this$props$onSettle === void 0 ? void 0 : _this$props$onSettle.call(_this$props, value);
}
this.prevSnapIndex = value;
}), // Resetting appropriate values
(0, _reactNativeReanimated.set)(drawerOldGestureState, _reactNativeGestureHandler.State.END), (0, _reactNativeReanimated.set)(handleOldGestureState, _reactNativeGestureHandler.State.END), (0, _reactNativeReanimated.set)(this.prevTranslateYOffset, state.position), (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.scrollUpAndPullDown, 1), [(0, _reactNativeReanimated.set)(this.prevTranslateYOffset, (0, _reactNativeReanimated.sub)(this.prevTranslateYOffset, this.lastStartScrollY)), (0, _reactNativeReanimated.set)(this.lastStartScrollY, 0), (0, _reactNativeReanimated.set)(this.scrollUpAndPullDown, 0)]), (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.destSnapPoint, _snapPoints[0]), [(0, _reactNativeReanimated.set)(this.dragWithHandle, 0)]), (0, _reactNativeReanimated.set)(this.isManuallySetValue, 0), (0, _reactNativeReanimated.set)(this.manualYOffset, 0), (0, _reactNativeReanimated.stopClock)(clock), this.prevTranslateYOffset], // We made the block return the updated position,
state.position)];
};
const translateYOffset = (0, _reactNativeReanimated.cond)(isAnimationInterrupted, [// set(prevTranslateYOffset, animationPosition) should only run if we are
// interrupting an animation when the drawer is currently in a different
// position than the top
(0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.or)(this.dragWithHandle, (0, _reactNativeReanimated.greaterOrEq)((0, _reactNativeReanimated.abs)(this.prevDragY), this.lastStartScrollY)), (0, _reactNativeReanimated.set)(this.prevTranslateYOffset, this.animationPosition)), (0, _reactNativeReanimated.set)(this.animationFinished, 1), (0, _reactNativeReanimated.set)(this.translationY, 0), // Resetting appropriate values
(0, _reactNativeReanimated.set)(drawerOldGestureState, _reactNativeGestureHandler.State.END), (0, _reactNativeReanimated.set)(handleOldGestureState, _reactNativeGestureHandler.State.END), // By forcing that frameTime exceeds duration, it has the effect of stopping the animation
(0, _reactNativeReanimated.set)(this.animationFrameTime, (0, _reactNativeReanimated.add)(animationDuration, 1000)), (0, _reactNativeReanimated.stopClock)(this.animationClock), this.prevTranslateYOffset], (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.or)(this.didGestureFinish, this.isManuallySetValue, (0, _reactNativeReanimated.clockRunning)(this.animationClock)), [runTiming({
clock: this.animationClock,
from: (0, _reactNativeReanimated.cond)(this.isManuallySetValue, this.prevTranslateYOffset, (0, _reactNativeReanimated.add)(this.prevTranslateYOffset, this.translationY)),
to: this.destSnapPoint,
position: this.animationPosition,
finished: this.animationFinished,
frameTime: this.animationFrameTime
})], [(0, _reactNativeReanimated.set)(this.animationFrameTime, 0), (0, _reactNativeReanimated.set)(this.animationFinished, 0), // @ts-ignore
this.prevTranslateYOffset]));
this.translateY = (0, _reactNativeReanimated.interpolate)((0, _reactNativeReanimated.add)(translateYOffset, this.dragY, (0, _reactNativeReanimated.multiply)(scrollY, -1)), {
inputRange: [openPosition, closedPosition],
outputRange: [openPosition, closedPosition],
extrapolate: _reactNativeReanimated.Extrapolate.CLAMP
});
this.position = (0, _reactNativeReanimated.interpolate)(this.translateY, {
inputRange: [openPosition, closedPosition],
outputRange: [1, 0],
extrapolate: _reactNativeReanimated.Extrapolate.CLAMP
});
}
render() {
const _this$props2 = this.props,
{
renderHandle,
snapPoints,
initialSnapIndex,
componentType,
onSettle,
animatedPosition,
containerStyle,
renderOverlappingComponent
} = _this$props2,
rest = _objectWithoutProperties(_this$props2, ["renderHandle", "snapPoints", "initialSnapIndex", "componentType", "onSettle", "animatedPosition", "containerStyle", "renderOverlappingComponent"]);
const AnimatedScrollableComponent = this.scrollComponent;
const normalisedSnapPoints = this.getNormalisedSnapPoints();
const initialSnap = normalisedSnapPoints[initialSnapIndex];
const Content = /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
style: [_reactNative.StyleSheet.absoluteFillObject, containerStyle, // @ts-ignore
{
transform: [{
translateY: this.translateY
}]
}]
}, /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.PanGestureHandler, {
ref: this.drawerHandleRef,
shouldCancelWhenOutside: false,
simultaneousHandlers: this.masterDrawer,
onGestureEvent: this.onHandleGestureEvent,
onHandlerStateChange: this.onHandleGestureEvent
}, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, null, renderHandle())), /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.PanGestureHandler, {
ref: this.drawerContentRef,
simultaneousHandlers: [this.scrollComponentRef, this.masterDrawer],
shouldCancelWhenOutside: false,
onGestureEvent: this.onDrawerGestureEvent,
onHandlerStateChange: this.onDrawerGestureEvent
}, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
style: styles.container
}, /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.NativeViewGestureHandler, {
ref: this.scrollComponentRef,
waitFor: this.masterDrawer,
simultaneousHandlers: this.drawerContentRef
}, /*#__PURE__*/_react.default.createElement(AnimatedScrollableComponent, _extends({
overScrollMode: "never",
bounces: false
}, rest, {
ref: this.props.innerRef // @ts-ignore
,
decelerationRate: this.decelerationRate,
onScrollBeginDrag: this.onScrollBeginDrag,
scrollEventThrottle: 1,
contentContainerStyle: [rest.contentContainerStyle, {
paddingBottom: this.getNormalisedSnapPoints()[0]
}]
}))))), /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.PanGestureHandler, {
ref: this.overlayComponentRef,
shouldCancelWhenOutside: false,
simultaneousHandlers: this.masterDrawer,
onGestureEvent: this.onHandleGestureEvent,
onHandlerStateChange: this.onHandleGestureEvent
}, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, null, renderOverlappingComponent())), this.props.animatedPosition && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
exec: (0, _reactNativeReanimated.onChange)(this.position, (0, _reactNativeReanimated.set)(this.props.animatedPosition, this.position))
}), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
exec: (0, _reactNativeReanimated.onChange)(this.dragY, (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.not)((0, _reactNativeReanimated.eq)(this.dragY, 0)), (0, _reactNativeReanimated.set)(this.prevDragY, this.dragY)))
}), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
exec: (0, _reactNativeReanimated.onChange)(this.didGestureFinish, (0, _reactNativeReanimated.cond)(this.didGestureFinish, [this.didScrollUpAndPullDown, this.setTranslationY, (0, _reactNativeReanimated.set)(this.tempDestSnapPoint, (0, _reactNativeReanimated.add)(normalisedSnapPoints[0], this.extraOffset)), (0, _reactNativeReanimated.set)(this.nextSnapIndex, 0), (0, _reactNativeReanimated.set)(this.destSnapPoint, this.calculateNextSnapPoint()), (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.greaterThan)(this.dragY, this.lastStartScrollY), this.isAndroid, (0, _reactNativeReanimated.not)(this.dragWithHandle)), (0, _reactNativeReanimated.call)([], () => {
var _this$props3, _this$props3$data;
// This prevents the scroll glide from happening on Android when pulling down with inertia.
// It's not perfect, but does the job for now
const {
method,
args
} = imperativeScrollOptions[this.props.componentType];
if (this.props.componentType === 'FlatList' && (((_this$props3 = this.props) === null || _this$props3 === void 0 ? void 0 : (_this$props3$data = _this$props3.data) === null || _this$props3$data === void 0 ? void 0 : _this$props3$data.length) || 0) > 0 || this.props.componentType === 'SectionList' && this.props.sections.length > 0 || this.props.componentType === 'ScrollView') {
var _this$props$innerRef$;
// @ts-ignore
(_this$props$innerRef$ = this.props.innerRef.current) === null || _this$props$innerRef$ === void 0 ? void 0 : _this$props$innerRef$.getNode()[method](args);
}
})), (0, _reactNativeReanimated.set)(this.dragY, 0), (0, _reactNativeReanimated.set)(this.velocityY, 0), (0, _reactNativeReanimated.set)(this.lastSnap, (0, _reactNativeReanimated.sub)(this.destSnapPoint, (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.scrollUpAndPullDown, 1), this.lastStartScrollY, 0))), (0, _reactNativeReanimated.call)([this.lastSnap], ([value]) => {
var _this$masterDrawer, _this$masterDrawer$cu;
// This is the TapGHandler trick
// @ts-ignore
(_this$masterDrawer = this.masterDrawer) === null || _this$masterDrawer === void 0 ? void 0 : (_this$masterDrawer$cu = _this$masterDrawer.current) === null || _this$masterDrawer$cu === void 0 ? void 0 : _this$masterDrawer$cu.setNativeProps({
maxDeltaY: value - this.getNormalisedSnapPoints()[0]
});
}), (0, _reactNativeReanimated.set)(this.decelerationRate, (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.isAndroid, 1), (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.eq)(this.lastSnap, normalisedSnapPoints[0]), ANDROID_NORMAL_DECELERATION_RATE, 0), IOS_NORMAL_DECELERATION_RATE))]))
}), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
exec: (0, _reactNativeReanimated.onChange)(this.isManuallySetValue, [(0, _reactNativeReanimated.cond)(this.isManuallySetValue, [(0, _reactNativeReanimated.set)(this.destSnapPoint, this.manualYOffset), (0, _reactNativeReanimated.set)(this.animationFinished, 0), (0, _reactNativeReanimated.set)(this.lastSnap, this.manualYOffset), (0, _reactNativeReanimated.call)([this.lastSnap], ([value]) => {
var _this$masterDrawer2, _this$masterDrawer2$c;
// This is the TapGHandler trick
// @ts-ignore
(_this$masterDrawer2 = this.masterDrawer) === null || _this$masterDrawer2 === void 0 ? void 0 : (_this$masterDrawer2$c = _this$masterDrawer2.current) === null || _this$masterDrawer2$c === void 0 ? void 0 : _this$masterDrawer2$c.setNativeProps({
maxDeltaY: value - this.getNormalisedSnapPoints()[0]
});
})], [(0, _reactNativeReanimated.set)(this.nextSnapIndex, 0)])])
})); // On Android, having an intermediary view with pointerEvents="box-none", breaks the
// waitFor logic
if (_reactNative.Platform.OS === 'android') {
return /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.TapGestureHandler, {
maxDurationMs: 100000,
ref: this.masterDrawer,
maxDeltaY: initialSnap - this.getNormalisedSnapPoints()[0],
shouldCancelWhenOutside: false
}, Content);
} // On iOS, We need to wrap the content on a view with PointerEvents box-none
// So that we can start scrolling automatically when reaching the top without
// Stopping the gesture
return /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.TapGestureHandler, {
maxDurationMs: 100000,
ref: this.masterDrawer,
maxDeltaY: initialSnap - this.getNormalisedSnapPoints()[0]
}, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: _reactNative.StyleSheet.absoluteFillObject,
pointerEvents: "box-none"
}, Content));
}
}
exports.ScrollBottomSheet = ScrollBottomSheet;
_defineProperty(ScrollBottomSheet, "defaultProps", {
topInset: 0,
innerRef: /*#__PURE__*/_react.default.createRef()
});
var _default = ScrollBottomSheet;
exports.default = _default;
const styles = _reactNative.StyleSheet.create({
container: {
flex: 1
}
});
//# sourceMappingURL=index.js.map