1import { useState } from "react";
2import { StyleSheet, View } from "react-native";
3import Svg, { Path } from "react-native-svg";
4
5import type { FrostedCutoutProps } from "./FrostedCutout.types";
6
7/** Fills its parent with a theme-matched tint that leaves a rounded hole clear. iOS blurs instead. */
8export function FrostedCutout(props: FrostedCutoutProps) {
9 const [width, setWidth] = useState(0);
10 const [height, setHeight] = useState(0);
11 const x = (width - props.cutoutWidth) / 2;
12 const y = props.cutoutTop;
13 const w = props.cutoutWidth;
14 const h = props.cutoutHeight;
15 const r = Math.min(props.cutoutRadius, w / 2, h / 2);
16 const hole = `M${x + r},${y} H${x + w - r} A${r},${r} 0 0 1 ${x + w},${y + r} V${y + h - r} A${r},${r} 0 0 1 ${x + w - r},${y + h} H${x + r} A${r},${r} 0 0 1 ${x},${y + h - r} V${y + r} A${r},${r} 0 0 1 ${x + r},${y} Z`;
17
18 return (
19 <View
20 pointerEvents="none"
21 style={StyleSheet.absoluteFill}
22 onLayout={(event) => {
23 setWidth(event.nativeEvent.layout.width);
24 setHeight(event.nativeEvent.layout.height);
25 }}
26 >
27 {width > 0 ? (
28 <Svg height={height} width={width}>
29 <Path
30 d={`M0,0 H${width} V${height} H0 Z ${hole}`}
31 fill={props.appearance === "light" ? "#ffffff" : "#000000"}
32 fillOpacity={0.55}
33 fillRule="evenodd"
34 />
35 </Svg>
36 ) : null}
37 </View>
38 );
39}