98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
import React from "react";
|
|
import { View, ScrollView, Platform, KeyboardAvoidingView } from "react-native";
|
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
|
|
interface ScreenWrapProps {
|
|
children: React.ReactNode;
|
|
/** Whether the content should scroll (default: true) */
|
|
scrollable?: boolean;
|
|
/** Background color class (default: "bg-background") */
|
|
bgClass?: string;
|
|
/** Additional className for the container */
|
|
className?: string;
|
|
/** Which edges to apply safe area (default: ['top', 'left', 'right']) */
|
|
edges?: ('top' | 'bottom' | 'left' | 'right')[];
|
|
/** Whether to add keyboard avoiding behavior (default: false) */
|
|
keyboardAvoiding?: boolean;
|
|
/** Padding for content area (default: "px-5") */
|
|
paddingClass?: string;
|
|
/** Whether to apply max-width constraint for web (default: true) */
|
|
maxWidth?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Consistent screen wrapper that handles:
|
|
* - Safe area insets
|
|
* - Max-width constraint for web (prevents content from stretching too wide)
|
|
* - Consistent padding
|
|
* - Optional scrolling
|
|
* - Optional keyboard avoiding behavior
|
|
*/
|
|
export function ScreenWrap({
|
|
children,
|
|
scrollable = true,
|
|
bgClass = "bg-background",
|
|
className = "",
|
|
edges = ['top', 'left', 'right'],
|
|
keyboardAvoiding = false,
|
|
paddingClass = "px-5",
|
|
maxWidth = true,
|
|
}: ScreenWrapProps) {
|
|
const content = (
|
|
<View className={`flex-1 w-full ${maxWidth ? 'max-w-2xl' : ''} mx-auto ${paddingClass}`}>
|
|
{children}
|
|
</View>
|
|
);
|
|
|
|
const scrollContent = scrollable ? (
|
|
<ScrollView
|
|
className="flex-1"
|
|
contentContainerStyle={{ flexGrow: 1 }}
|
|
showsVerticalScrollIndicator={false}
|
|
keyboardShouldPersistTaps="handled"
|
|
>
|
|
{content}
|
|
</ScrollView>
|
|
) : content;
|
|
|
|
const keyboardContent = keyboardAvoiding ? (
|
|
<KeyboardAvoidingView
|
|
className="flex-1"
|
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
|
|
>
|
|
{scrollContent}
|
|
</KeyboardAvoidingView>
|
|
) : scrollContent;
|
|
|
|
return (
|
|
<SafeAreaView className={`flex-1 ${bgClass} ${className}`} edges={edges}>
|
|
{keyboardContent}
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Simpler wrapper for screens that don't need scrolling
|
|
* Just provides safe area and max-width constraint
|
|
*/
|
|
export function ScreenContainer({
|
|
children,
|
|
bgClass = "bg-background",
|
|
className = "",
|
|
edges = ['top', 'left', 'right'],
|
|
paddingClass = "px-5",
|
|
maxWidth = true,
|
|
}: Omit<ScreenWrapProps, 'scrollable' | 'keyboardAvoiding'>) {
|
|
return (
|
|
<SafeAreaView className={`flex-1 ${bgClass} ${className}`} edges={edges}>
|
|
<View className={`flex-1 w-full ${maxWidth ? 'max-w-2xl' : ''} mx-auto ${paddingClass}`}>
|
|
{children}
|
|
</View>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
export default ScreenWrap;
|
|
|