| 1 | import { useId, useState, type ReactNode } from "react"; |
| 2 | import { Platform, View } from "react-native"; |
| 3 | import { FormSheet, Screen, ScreenStack, ScreenStackHeaderConfig } from "react-native-screens"; |
| 4 | import { useResolveClassNames, withUniwind } from "uniwind"; |
| 5 | |
| 6 | import { AndroidSheetHeader } from "./AndroidScreenHeader"; |
| 7 | import { nativeHeaderScrollEdgeEffects } from "../native/StackHeader"; |
| 8 | |
| 9 | const HEADER_SCROLL_EDGE_EFFECTS = nativeHeaderScrollEdgeEffects(Platform.OS, Platform.Version); |
| 10 | const NativeScreen = withUniwind(Screen); |
| 11 | const NativeHeader = withUniwind(ScreenStackHeaderConfig, { |
| 12 | color: { fromClassName: "tintColorClassName", styleProperty: "accentColor" }, |
| 13 | titleColor: { fromClassName: "titleColorClassName", styleProperty: "accentColor" }, |
| 14 | }); |
| 15 | |
| 16 | /** Native presentation for local context whose owner supplies its dismissal callback. */ |
| 17 | export function AppSheet(props: { |
| 18 | readonly title: string; |
| 19 | readonly children: ReactNode; |
| 20 | readonly onClose: () => void; |
| 21 | }) { |
| 22 | const containerStyle = useResolveClassNames("bg-sheet"); |
| 23 | const screenId = useId(); |
| 24 | const [isOpen, setIsOpen] = useState(true); |
| 25 | const close = () => setIsOpen(false); |
| 26 | |
| 27 | return ( |
| 28 | <FormSheet |
| 29 | isOpen={isOpen} |
| 30 | detents={[0.5, 0.9]} |
| 31 | prefersGrabberVisible |
| 32 | nativeContainerStyle={containerStyle} |
| 33 | onDismiss={props.onClose} |
| 34 | onNativeDismiss={props.onClose} |
| 35 | > |
| 36 | <View collapsable={false} className="flex-1 bg-sheet"> |
| 37 | {Platform.OS === "ios" ? ( |
| 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 | title: "Done", |
| 62 | variant: "done", |
| 63 | accessibilityLabel: `Close ${props.title}`, |
| 64 | identifier: `app-sheet-done-${screenId}`, |
| 65 | onPress: close, |
| 66 | }, |
| 67 | ]} |
| 68 | /> |
| 69 | </NativeScreen> |
| 70 | </ScreenStack> |
| 71 | ) : ( |
| 72 | <> |
| 73 | <AndroidSheetHeader title={props.title} onBack={close} /> |
| 74 | {props.children} |
| 75 | </> |
| 76 | )} |
| 77 | </View> |
| 78 | </FormSheet> |
| 79 | ); |
| 80 | } |