UNPKG

sonner-native

Version:

An opinionated toast component for React Native. A port of @emilkowalski's sonner.

181 lines (171 loc) 6.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ToastSwipeHandler = void 0; var React = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeGestureHandler = require("react-native-gesture-handler"); var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated")); var _context = require("./context.js"); var _easings = require("./easings.js"); var _jsxRuntime = require("react/jsx-runtime"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const { width: WINDOW_WIDTH } = _reactNative.Dimensions.get('window'); const ToastSwipeHandler = ({ children, onRemove, style, onBegin, onFinalize, enabled, unstyled, important, position: positionProps, onPress }) => { const translate = (0, _reactNativeReanimated.useSharedValue)(0); const { swipeToDismissDirection: direction, gap, position: positionCtx } = (0, _context.useToastContext)(); const position = positionProps || positionCtx; const pan = _reactNativeGestureHandler.Gesture.Pan().onBegin(() => { 'worklet'; if (!enabled) { return; } (0, _reactNativeReanimated.runOnJS)(onBegin)(); }).onChange(event => { 'worklet'; if (!enabled) { return; } if (direction === 'left' && event.translationX < 0) { translate.value = event.translationX; } else if (direction === 'up') { const isBottomPosition = position === 'bottom-center'; const rawTranslation = event.translationY * (isBottomPosition ? -1 : 1); // Define correct and wrong directions based on position const isCorrectDirection = rawTranslation < 0; // negative means correct dismissal direction const isWrongDirection = rawTranslation > 0; // positive means wrong direction if (isCorrectDirection) { // Allow full movement in correct direction translate.value = rawTranslation; } else if (isWrongDirection) { translate.value = elasticResistance(rawTranslation); } } }).onFinalize(() => { 'worklet'; if (!enabled) { return; } if (direction === 'left') { const threshold = -WINDOW_WIDTH * 0.25; const shouldDismiss = translate.value < threshold; if (Math.abs(translate.value) < 16) { translate.value = (0, _reactNativeReanimated.withTiming)(0, { easing: _reactNativeReanimated.Easing.elastic(0.8) }); return; } if (shouldDismiss) { translate.value = (0, _reactNativeReanimated.withTiming)(-WINDOW_WIDTH, { easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease) }, isDone => { if (isDone) { (0, _reactNativeReanimated.runOnJS)(onRemove)(); } }); } else { translate.value = (0, _reactNativeReanimated.withTiming)(0, { easing: _reactNativeReanimated.Easing.elastic(0.8) }); } } else if (direction === 'up') { const threshold = -16; const shouldDismiss = translate.value < threshold; const isWrongDirection = translate.value > 0; // If dragged in wrong direction, always spring back if (isWrongDirection) { translate.value = (0, _reactNativeReanimated.withTiming)(0, { easing: _reactNativeReanimated.Easing.elastic(0.8), duration: 400 }); } else if (Math.abs(translate.value) < 16) { translate.value = (0, _reactNativeReanimated.withTiming)(0, { easing: _reactNativeReanimated.Easing.elastic(0.8) }); } else if (shouldDismiss) { translate.value = (0, _reactNativeReanimated.withTiming)(-WINDOW_WIDTH, { easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease) }, isDone => { if (isDone) { (0, _reactNativeReanimated.runOnJS)(onRemove)(); } }); } else { translate.value = (0, _reactNativeReanimated.withTiming)(0, { easing: _reactNativeReanimated.Easing.elastic(0.8) }); } } (0, _reactNativeReanimated.runOnJS)(onFinalize)(); }); const tap = _reactNativeGestureHandler.Gesture.Tap().onEnd(() => { 'worklet'; if (onPress) { (0, _reactNativeReanimated.runOnJS)(onPress)(); } }); const isAndroid = _reactNative.Platform.OS === 'android'; const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { const aStyle = { transform: [direction === 'left' ? { translateX: translate.value } : { translateY: translate.value * (position === 'bottom-center' ? -1 : 1) }] }; if (isAndroid) { aStyle.opacity = 1; } else { aStyle.opacity = (0, _reactNativeReanimated.interpolate)(translate.value, [0, direction === 'left' ? -WINDOW_WIDTH : -60], [1, 0]); } return aStyle; }, [direction, translate]); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, { gesture: _reactNativeGestureHandler.Gesture.Race(tap, pan), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { style: [animatedStyle, unstyled ? undefined : { justifyContent: 'center', marginBottom: gap }, { width: '100%' }, _reactNative.Platform.OS === 'android' ? { opacity: 1 } : {}, style], layout: _reactNativeReanimated.LinearTransition.easing(_easings.easeInOutCircFn), "aria-live": important ? 'assertive' : 'polite' // https://reactnative.dev/docs/accessibility#aria-live-android , children: children }) }); }; // Apply progressive elastic resistance (Apple-style) // This function provides diminishing returns as the drag distance increases exports.ToastSwipeHandler = ToastSwipeHandler; function elasticResistance(distance) { 'worklet'; // Base resistance factor const baseResistance = 0.4; // Progressive dampening - the further you drag, the more resistance const progressiveFactor = 1 / (1 + distance * 0.02); return distance * baseResistance * progressiveFactor; } //# sourceMappingURL=gestures.js.map