Open History to see the last commit
1import { useId, useState } from "react";
2import { Platform, View } from "react-native";
3import { FormSheet, ScreenStack } from "react-native-screens";
4import { useResolveClassNames } from "uniwind";
5
6import { nativeHeaderScrollEdgeEffects } from "../../native/StackHeader";
7import { formSheetDetents } from "../../native/sheet-surface";
8import { NativeHeader, NativeScreen } from "../../native/ThemedScreenStack";
9
10const HEADER_SCROLL_EDGE_EFFECTS = nativeHeaderScrollEdgeEffects(Platform.OS, Platform.Version);
11
12export type { SheetProps } from "./Sheet.types";
13import type { SheetProps } from "./Sheet.types";
14
15/** Native presentation. Scrollable children use automatic insets beneath the iOS header. */
16export function Sheet(props: SheetProps) {
17 const containerStyle = useResolveClassNames("bg-sheet");
18 const screenId = useId();
19 const [isOpen, setIsOpen] = useState(true);
20 const close = () => {
21 if (!props.dismissDisabled) setIsOpen(false);
22 };
23
24 return (
25 <FormSheet
26 isOpen={isOpen}
27 detents={formSheetDetents(0.5, 0.9)}
28 prefersGrabberVisible
29 preventNativeDismiss={props.dismissDisabled}
30 // The header holds the close button, so the Duo needs no rail inside this sheet.
31 prefersHorizontalBars
32 nativeContainerStyle={containerStyle}
33 onDismiss={props.onClose}
34 onNativeDismiss={props.onClose}
35 >
36 {/* Flex children are not bounded by the FormSheet host, so pin to its edges. */}
37 <View collapsable={false} className="absolute inset-0 bg-sheet">
38 <ScreenStack style={{ flex: 1 }}>
39 <NativeScreen
40 activityState={2}
41 enabled
42 isNativeStack
43 screenId={`app-sheet-${screenId}`}
44 scrollEdgeEffects={HEADER_SCROLL_EDGE_EFFECTS}
45 className="flex-1 bg-sheet"
46 >
47 {props.children}
48 <NativeHeader
49 backgroundColor="rgba(0,0,0,0)"
50 tintColorClassName="accent-foreground"
51 hideBackButton
52 hideShadow={false}
53 title={props.title}
54 titleColorClassName="accent-foreground"
55 titleFontSize={18}
56 titleFontWeight="800"
57 translucent
58 headerRightBarButtonItems={[
59 {
60 type: "button",
61 icon: { name: "xmark", type: "sfSymbol" },
62 accessibilityLabel: `Close ${props.title}`,
63 identifier: `app-sheet-close-${screenId}`,
64 disabled: props.dismissDisabled,
65 onPress: close,
66 },
67 ]}
68 />
69 </NativeScreen>
70 </ScreenStack>
71 </View>
72 </FormSheet>
73 );
74}