* The Modal component is a simple way to present content above an enclosing view. * To render the `Modal` above other components, you'll need to wrap it with the [`Portal`](./Portal) component. * Note that this modal is NOT accessible by default; if you need an accessible modal, please use the Rea
({
dismissable = true,
dismissableBackButton = dismissable,
visible = false,
overlayAccessibilityLabel = 'Close modal',
onDismiss = () => {},
children,
contentContainerStyle,
style,
theme: themeOverrides,
testID = 'modal',
}: Props)
| 101 | * ``` |
| 102 | */ |
| 103 | function Modal({ |
| 104 | dismissable = true, |
| 105 | dismissableBackButton = dismissable, |
| 106 | visible = false, |
| 107 | overlayAccessibilityLabel = 'Close modal', |
| 108 | onDismiss = () => {}, |
| 109 | children, |
| 110 | contentContainerStyle, |
| 111 | style, |
| 112 | theme: themeOverrides, |
| 113 | testID = 'modal', |
| 114 | }: Props) { |
| 115 | const theme = useInternalTheme(themeOverrides); |
| 116 | const onDismissCallback = useLatestCallback(onDismiss); |
| 117 | const { scale } = theme.animation; |
| 118 | const { top, bottom } = useSafeAreaInsets(); |
| 119 | const opacity = useAnimatedValue(visible ? 1 : 0); |
| 120 | const [visibleInternal, setVisibleInternal] = React.useState(visible); |
| 121 | |
| 122 | const showModalAnimation = React.useCallback(() => { |
| 123 | Animated.timing(opacity, { |
| 124 | toValue: 1, |
| 125 | duration: scale * DEFAULT_DURATION, |
| 126 | easing: Easing.out(Easing.cubic), |
| 127 | useNativeDriver: true, |
| 128 | }).start(); |
| 129 | }, [opacity, scale]); |
| 130 | |
| 131 | const hideModalAnimation = React.useCallback(() => { |
| 132 | Animated.timing(opacity, { |
| 133 | toValue: 0, |
| 134 | duration: scale * DEFAULT_DURATION, |
| 135 | easing: Easing.out(Easing.cubic), |
| 136 | useNativeDriver: true, |
| 137 | }).start(({ finished }) => { |
| 138 | if (!finished) { |
| 139 | return; |
| 140 | } |
| 141 | |
| 142 | setVisibleInternal(false); |
| 143 | }); |
| 144 | }, [opacity, scale]); |
| 145 | |
| 146 | React.useEffect(() => { |
| 147 | if (visibleInternal === visible) { |
| 148 | return; |
| 149 | } |
| 150 | |
| 151 | if (!visibleInternal && visible) { |
| 152 | setVisibleInternal(true); |
| 153 | return showModalAnimation(); |
| 154 | } |
| 155 | |
| 156 | if (visibleInternal && !visible) { |
| 157 | return hideModalAnimation(); |
| 158 | } |
| 159 | }, [visible, showModalAnimation, hideModalAnimation, visibleInternal]); |
| 160 |
nothing calls this directly
no test coverage detected
searching dependent graphs…