UNPKG

@ontech7/react-native-dialog

Version:

Simple and lightweight dialog component for React Native, structure similar to shadcn/ui, with dimezis background blur. Compatible with Android & iOS.

117 lines (116 loc) 4.11 kB
import React, { useEffect, useRef, useState } from "react"; import { Animated, Easing, StyleSheet, TouchableWithoutFeedback, View, } from "react-native"; import { useDialogStyles } from "./DialogProvider"; import { Portal } from "./components/Portal"; export function Dialog({ open = true, onPressOut, tint = "dark", animation = true, duration = 200, delay = 0, slideFrom = "none", BlurComponent, style, children, ...props }) { const { container } = useDialogStyles(); const [mounted, setMounted] = useState(open); const progress = useRef(new Animated.Value(open ? 1 : 0)).current; useEffect(() => { if (!animation) { progress.setValue(open ? 1 : 0); setMounted(open); return; } if (open) { setMounted(true); Animated.timing(progress, { toValue: 1, duration, delay, easing: Easing.out(Easing.ease), useNativeDriver: true, }).start(); } else { Animated.timing(progress, { toValue: 0, duration, easing: Easing.in(Easing.ease), useNativeDriver: true, }).start(({ finished }) => { if (finished) { setMounted(false); } }); } }, [open]); const dialogAnimStyle = (() => { if (!animation) { return { opacity: open ? 1 : 0 }; } if (slideFrom === "none") { return { opacity: progress }; } if (slideFrom === "center") { const scale = progress.interpolate({ inputRange: [0, 1], outputRange: [0.95, 1], }); return { opacity: progress, transform: [{ scale }], }; } const translateValue = slideFrom === "bottom" || slideFrom === "right" ? 30 : -30; const translate = progress.interpolate({ inputRange: [0, 1], outputRange: [translateValue, 0], }); return { opacity: progress, transform: [ slideFrom === "top" || slideFrom === "bottom" ? { translateY: translate } : { translateX: translate }, ], }; })(); if (!mounted) { return null; } const transparencyBackground = tint === "dark" ? BlurComponent ? "#0003" : "#0008" : BlurComponent ? "#fff3" : "#fff8"; const BlurComp = (BlurComponent ?? View); return (React.createElement(Portal, null, React.createElement(BlurComp /* expo-blur */ , { /* expo-blur */ intensity: 25, tint: tint, experimentalBlurMethod: "dimezisBlurView", blurReducedFactor: 8, /* sbaiahmed1/react-native-blur */ blurAmount: 30, blurType: tint, reducedTransparencyFallbackColor: transparencyBackground, /* @react-native-community/blur */ downsampleFactor: 8, style: StyleSheet.absoluteFillObject }), React.createElement(Animated.View, { style: [ StyleSheet.absoluteFillObject, { backgroundColor: transparencyBackground }, { opacity: progress }, ] }), React.createElement(TouchableWithoutFeedback, { onPress: onPressOut }, React.createElement(View, { style: styles.container }, React.createElement(Animated.View, { ...props, style: [styles.dialog, dialogAnimStyle, container, style] }, children))))); } const styles = StyleSheet.create({ container: { position: "absolute", justifyContent: "center", alignItems: "center", top: 0, left: 0, width: "100%", height: "100%", zIndex: 1000, }, dialog: { maxWidth: "80%", width: "100%", backgroundColor: "#fff", borderRadius: 12, }, });