react-native-action-toast
Version:
A premium, customizable toast notification system for React Native with action buttons, beautiful animations, and Expo compatibility
274 lines (271 loc) • 10.7 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var react_native_1 = require("react-native");
var MaterialIcons_1 = __importDefault(require("react-native-vector-icons/MaterialIcons"));
var react_native_linear_gradient_1 = require("react-native-linear-gradient");
var WINDOW_WIDTH = react_native_1.Dimensions.get("window").width;
var TOAST_WIDTH = Math.min(WINDOW_WIDTH - 40, 400);
var ActionToast = function (_a) {
var _b;
var title = _a.title, message = _a.message, _c = _a.duration, duration = _c === void 0 ? 4000 : _c, _d = _a.position, position = _d === void 0 ? "bottom" : _d, _e = _a.actionButtons, actionButtons = _e === void 0 ? [] : _e, titleStyle = _a.titleStyle, messageStyle = _a.messageStyle, containerStyle = _a.containerStyle, icon = _a.icon, onDismiss = _a.onDismiss, onHide = _a.onHide, _f = _a.swipeable, swipeable = _f === void 0 ? true : _f, _g = _a.animationDuration, animationDuration = _g === void 0 ? 500 : _g, backgroundColor = _a.backgroundColor, _h = _a.gradientColors, gradientColors = _h === void 0 ? ["#4c669f", "#3b5998", "#192f6a"] : _h;
var animatedValue = react_1.default.useRef(new react_native_1.Animated.Value(0)).current;
var _j = react_1.default.useState(true), isVisible = _j[0], setIsVisible = _j[1];
var pan = react_1.default.useRef(new react_native_1.Animated.ValueXY()).current;
var opacity = react_1.default.useRef(new react_native_1.Animated.Value(0)).current;
// Spring animation values
var translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: position === "top"
? [-100, 40]
: position === "bottom"
? [100, -40]
: [0, 0],
});
var scale = animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0.8, 1.05, 1],
});
(0, react_1.useEffect)(function () {
// Entry animation
react_native_1.Animated.parallel([
react_native_1.Animated.spring(animatedValue, {
toValue: 1,
useNativeDriver: true,
friction: 8,
tension: 40,
}),
react_native_1.Animated.timing(opacity, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}),
]).start();
// Auto-dismiss timer
var timer = setTimeout(function () {
hideToast();
}, duration);
return function () { return clearTimeout(timer); };
}, []);
var hideToast = function () {
if (!isVisible)
return;
setIsVisible(false);
react_native_1.Animated.parallel([
react_native_1.Animated.spring(animatedValue, {
toValue: 0,
useNativeDriver: true,
friction: 10,
}),
react_native_1.Animated.timing(opacity, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}),
]).start(function () {
onHide();
onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss();
});
};
var handleActionPress = function (btn, e) {
btn.onPress(e);
hideToast();
};
var renderActionButton = function (button, index) {
var isPrimary = index === 0 && actionButtons.length > 1;
var buttonBgColor = button.backgroundColor
? button.backgroundColor
: isPrimary
? "rgba(255,255,255,0.9)"
: "rgba(255,255,255,0.2)";
return (<react_native_1.TouchableOpacity key={"action-".concat(index)} onPress={function (e) { return handleActionPress(button, e); }} activeOpacity={0.7} style={[
styles.actionButton,
{ backgroundColor: buttonBgColor },
button.buttonStyle,
]}>
{button.iconPosition === "left" && button.icon && (<react_native_1.View style={styles.buttonIcon}>{button.icon}</react_native_1.View>)}
<react_native_1.Text style={[
styles.actionButtonText,
isPrimary ? styles.primaryActionText : styles.secondaryActionText,
button.textStyle,
]}>
{button.text}
</react_native_1.Text>
{button.iconPosition === "right" && button.icon && (<react_native_1.View style={styles.buttonIcon}>{button.icon}</react_native_1.View>)}
</react_native_1.TouchableOpacity>);
};
if (!isVisible)
return null;
return (<react_native_1.Animated.View style={[
styles.container,
(_b = {
opacity: opacity,
transform: __spreadArray([
{ translateY: translateY },
{ scale: scale }
], pan.getTranslateTransform(), true)
},
_b[position] = position === "top" ? 0 : 20,
_b),
containerStyle,
]}>
<react_native_linear_gradient_1.LinearGradient colors={backgroundColor
? [backgroundColor, backgroundColor]
: gradientColors} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={styles.gradient}>
<react_native_1.View style={styles.content}>
{icon && (<react_native_1.View style={styles.iconContainer}>
{typeof icon === "string" ? (<MaterialIcons_1.default name={icon} size={24} color="#fff"/>) : (icon)}
</react_native_1.View>)}
<react_native_1.View style={styles.textContainer}>
{title && (<react_native_1.Text style={[styles.title, titleStyle]} numberOfLines={1} ellipsizeMode="tail">
{title}
</react_native_1.Text>)}
<react_native_1.Text style={[styles.message, messageStyle]} numberOfLines={2} ellipsizeMode="tail">
{message}
</react_native_1.Text>
</react_native_1.View>
{swipeable && (<react_native_1.TouchableOpacity onPress={hideToast} style={styles.closeButton} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
<MaterialIcons_1.default name="close" size={20} color="rgba(255,255,255,0.7)"/>
</react_native_1.TouchableOpacity>)}
</react_native_1.View>
{actionButtons.length > 0 && (<react_native_1.View style={[
styles.actionsContainer,
actionButtons.length > 1 && styles.multipleActions,
]}>
{actionButtons.map(renderActionButton)}
</react_native_1.View>)}
</react_native_linear_gradient_1.LinearGradient>
</react_native_1.Animated.View>);
};
var styles = react_native_1.StyleSheet.create({
container: {
position: "absolute",
width: TOAST_WIDTH,
alignSelf: "center",
borderRadius: 14,
shadowColor: "#000",
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.2,
shadowRadius: 10,
elevation: 10,
overflow: "hidden",
zIndex: 9999,
},
gradient: {
padding: 16,
},
content: {
flexDirection: "row",
alignItems: "center",
marginBottom: 8,
},
iconContainer: {
marginRight: 12,
justifyContent: "center",
alignItems: "center",
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: "rgba(255,255,255,0.2)",
},
textContainer: {
flex: 1,
},
title: {
fontSize: 16,
fontWeight: "600",
color: "#fff",
marginBottom: 4,
},
message: {
fontSize: 14,
lineHeight: 20,
color: "rgba(255,255,255,0.9)",
},
closeButton: {
padding: 4,
marginLeft: 8,
},
actionsContainer: {
flexDirection: "row",
justifyContent: "flex-end",
marginTop: 8,
},
multipleActions: {
justifyContent: "space-between",
},
actionButton: {
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 8,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
},
primaryAction: {
backgroundColor: "rgba(255,255,255,0.9)",
},
secondaryAction: {
backgroundColor: "rgba(255,255,255,0.2)",
},
actionButtonText: {
fontSize: 14,
fontWeight: "500",
},
primaryActionText: {
color: "#4c669f",
},
secondaryActionText: {
color: "#fff",
},
buttonIcon: {
marginHorizontal: 4,
},
});
exports.default = ActionToast;
//# sourceMappingURL=ActionToast.js.map