@uiw/react-native
Version:
UIW for React Native
86 lines • 2.62 kB
JavaScript
import React, { useState, useMemo } from 'react';
import { Modal, Animated, TouchableOpacity, StyleSheet } from 'react-native';
import { usePrevious } from '../utils';
const styles = StyleSheet.create({
position: {
position: 'absolute',
backgroundColor: 'transparent',
top: 0,
bottom: 0,
left: 0,
right: 0,
zIndex: 9998
},
backdrop: {
backgroundColor: '#000'
},
content: {
backgroundColor: '#fff',
position: 'absolute'
}
});
const MaskLayer = (props = {}) => {
const {
maskClosable = true,
children,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
visible: _vis,
opacity = 0.6,
onDismiss,
animatedParallelShow = [],
animatedParallelHide = [],
...otherProps
} = props;
const [visible, setVisible] = useState(!!props.visible);
const preVisible = usePrevious(props.visible);
const [visibleModal, setVisibleModal] = useState(false);
const [bgOpacity] = useState(new Animated.Value(0));
useMemo(() => {
if (preVisible !== props.visible && props.visible) {
setVisible(!!props.visible);
setVisibleModal(false);
Animated.parallel([Animated.spring(bgOpacity, {
toValue: opacity,
overshootClamping: true,
useNativeDriver: true
}), ...animatedParallelShow]).start();
} else if (preVisible !== props.visible && !props.visible) {
Animated.parallel([Animated.spring(bgOpacity, {
toValue: 0,
overshootClamping: true,
useNativeDriver: true
}), ...animatedParallelHide]).start(() => {
setVisible(!!props.visible);
setVisibleModal(true);
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.visible]);
const backdropContent = <Animated.View style={[styles.position, styles.backdrop, {
opacity: bgOpacity
}]} />;
let backdrop = <TouchableOpacity activeOpacity={1} style={[styles.position]} onPress={() => onDismiss && onDismiss()}>
{backdropContent}
</TouchableOpacity>;
let isTrue = visible || false;
if (!visible && visibleModal) {
isTrue = false;
}
return <Modal transparent={true} animationType="none" {...otherProps} visible={isTrue}>
{maskClosable ? backdrop : backdropContent}
{children && React.Children.toArray(children).map(child => {
if (!React.isValidElement(child)) {
return;
}
return React.cloneElement(child, {
...child.props,
...{
style: [{
zIndex: 9999
}, child.props.style]
}
});
})}
</Modal>;
};
export default MaskLayer;