@nexara/nativeflow
Version:
Beautiful, responsive, and customizable UI components for React Native – built for performance and seamless experiences.
119 lines (118 loc) • 3.6 kB
JavaScript
;
import React, { cloneElement, forwardRef, useEffect, useId, useImperativeHandle, useRef, useState } from 'react';
import { Keyboard, BackHandler, StyleSheet, Animated } from 'react-native';
import { dialogSizes } from "../../constants/index.js";
import Portal from "../Portal/Portal.js";
import { useTheme } from "../../hooks/index.js";
import { verticalScale } from "../../helpers/index.js";
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
const Dialog = /*#__PURE__*/forwardRef(({
variant = 'classic',
size = 'lg',
fullScreen,
backdropColor,
portalKey,
onClose,
containerStyle,
children
}, ref) => {
const uniqueId = useId();
const [dialogVisible, setDialogVisible] = useState(false);
const scale = useRef(new Animated.Value(0.9)).current;
const opacity = useRef(new Animated.Value(0)).current;
const theme = useTheme();
useEffect(() => {
Animated.timing(opacity, {
toValue: dialogVisible ? 1 : 0,
duration: 300,
useNativeDriver: true
}).start();
Animated.spring(scale, {
toValue: dialogVisible ? 1 : 0.9,
damping: 10,
stiffness: 90,
useNativeDriver: true
}).start();
}, [dialogVisible]);
useEffect(() => {
const handler = BackHandler.addEventListener('hardwareBackPress', hardwareBackPress);
return () => handler.remove();
}, [dialogVisible]);
const hardwareBackPress = () => {
onClose?.();
setDialogVisible(false);
return dialogVisible;
};
useImperativeHandle(ref, () => ({
open: () => setDialogVisible(true),
close: () => setDialogVisible(false)
}));
const backdropAnimatedStyles = {
opacity: opacity,
backgroundColor: backdropColor ?? theme?.colors.background.backdrop
};
const modalContAnimatedStyles = {
transform: [{
scale
}],
opacity: opacity
};
const dynamicModalContStyles = {
minHeight: fullScreen ? '100%' : 'auto',
maxHeight: fullScreen ? '100%' : '80%',
width: `${dialogSizes[size]}%`,
backgroundColor: theme?.colors.background.elevated,
borderColor: theme?.colors.border.default,
borderRadius: verticalScale(40)
};
const renderChildrenWithVariant = () => {
return React.Children.map(children, child => {
if (/*#__PURE__*/React.isValidElement(child)) {
return /*#__PURE__*/cloneElement(child, {
variant
});
}
return child;
});
};
const handleStartShouldSetResponder = () => {
Keyboard.dismiss();
onClose?.();
setDialogVisible(false);
return true;
};
return /*#__PURE__*/_jsx(_Fragment, {
children: /*#__PURE__*/_jsx(Portal, {
name: portalKey ?? `dialog-${uniqueId}`,
children: /*#__PURE__*/_jsx(Animated.View, {
style: [STYLES.BACKDROP_CONT, backdropAnimatedStyles],
pointerEvents: dialogVisible ? 'auto' : 'none',
onStartShouldSetResponder: handleStartShouldSetResponder,
children: /*#__PURE__*/_jsx(Animated.View, {
style: [STYLES.MODAL_CONT, dynamicModalContStyles, modalContAnimatedStyles, containerStyle],
onStartShouldSetResponder: () => true,
children: renderChildrenWithVariant()
})
})
})
});
});
export default Dialog;
const STYLES = StyleSheet.create({
BACKDROP_CONT: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
justifyContent: 'center',
alignItems: 'center'
},
MODAL_CONT: {
// backgroundColor: '#fff',
borderRadius: 5,
borderWidth: 1
// borderColor: '#d4d4d4'
}
});
//# sourceMappingURL=Dialog.js.map