'use client'; import React from 'react'; import { createModal as createDrawer } from '@gluestack-ui/modal'; import { Pressable, View, ScrollView, Dimensions, ViewStyle, } from 'react-native'; import { Motion, AnimatePresence, createMotionAnimatedComponent, MotionComponentProps, } from '@legendapp/motion'; import { tva } from '@gluestack-ui/nativewind-utils/tva'; import { withStyleContext, useStyleContext, } from '@gluestack-ui/nativewind-utils/withStyleContext'; import { cssInterop } from 'nativewind'; import type { VariantProps } from '@gluestack-ui/nativewind-utils'; type IAnimatedPressableProps = React.ComponentProps & MotionComponentProps; const AnimatedPressable = createMotionAnimatedComponent( Pressable ) as React.ComponentType; const SCOPE = 'MODAL'; const screenWidth = Dimensions.get('window').width; const screenHeight = Dimensions.get('window').height; const sizes: { [key: string]: number } = { sm: 0.25, md: 0.5, lg: 0.75, full: 1, }; type IMotionViewProps = React.ComponentProps & MotionComponentProps; const MotionView = Motion.View as React.ComponentType; const UIDrawer = createDrawer({ Root: withStyleContext(View, SCOPE), Backdrop: AnimatedPressable, Content: MotionView, Body: ScrollView, CloseButton: Pressable, Footer: View, Header: View, AnimatePresence: AnimatePresence, }); cssInterop(AnimatedPressable, { className: 'style' }); cssInterop(MotionView, { className: 'style' }); const drawerStyle = tva({ base: 'w-full h-full web:pointer-events-none relative', variants: { size: { sm: '', md: '', lg: '', full: '', }, anchor: { left: 'items-start', right: 'items-end', top: 'justify-start', bottom: 'justify-end', }, }, }); const drawerBackdropStyle = tva({ base: 'absolute left-0 top-0 right-0 bottom-0 bg-background-dark web:cursor-default', }); const drawerContentStyle = tva({ base: 'bg-background-0 overflow-scroll border-outline-100 p-6 absolute', parentVariants: { size: { sm: 'w-1/4', md: 'w-1/2', lg: 'w-3/4', full: 'w-full', }, anchor: { left: 'h-full border-r', right: 'h-full border-l', top: 'w-full border-b', bottom: 'w-full border-t', }, }, parentCompoundVariants: [ { anchor: 'top', size: 'sm', class: 'h-1/4', }, { anchor: 'top', size: 'md', class: 'h-1/2', }, { anchor: 'top', size: 'lg', class: 'h-3/4', }, { anchor: 'top', size: 'full', class: 'h-full', }, { anchor: 'bottom', size: 'sm', class: 'h-1/4', }, { anchor: 'bottom', size: 'md', class: 'h-1/2', }, { anchor: 'bottom', size: 'lg', class: 'h-3/4', }, { anchor: 'bottom', size: 'full', class: 'h-full', }, ], }); const drawerCloseButtonStyle = tva({ base: 'z-10 rounded data-[focus-visible=true]:web:bg-background-100 web:outline-0 cursor-pointer', }); const drawerHeaderStyle = tva({ base: 'justify-between items-center flex-row', }); const drawerBodyStyle = tva({ base: 'mt-4 mb-6 shrink-0', }); const drawerFooterStyle = tva({ base: 'flex-row justify-end items-center', }); type IDrawerProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerBackdropProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerContentProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerHeaderProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerBodyProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerFooterProps = React.ComponentProps & VariantProps & { className?: string }; type IDrawerCloseButtonProps = React.ComponentProps< typeof UIDrawer.CloseButton > & VariantProps & { className?: string }; const Drawer = React.forwardRef< React.ComponentRef, IDrawerProps >(function Drawer({ className, size = 'sm', anchor = 'left', ...props }, ref) { return ( ); }); const DrawerBackdrop = React.forwardRef< React.ComponentRef, IDrawerBackdropProps >(function DrawerBackdrop({ className, ...props }, ref) { return ( ); }); const DrawerContent = React.forwardRef< React.ComponentRef, IDrawerContentProps >(function DrawerContent({ className, ...props }, ref) { const { size: parentSize, anchor: parentAnchor } = useStyleContext(SCOPE); const drawerHeight = screenHeight * (sizes[parentSize] || sizes.md); const drawerWidth = screenWidth * (sizes[parentSize] || sizes.md); const isHorizontal = parentAnchor === 'left' || parentAnchor === 'right'; const initialObj = isHorizontal ? { x: parentAnchor === 'left' ? -drawerWidth : drawerWidth } : { y: parentAnchor === 'top' ? -drawerHeight : drawerHeight }; const animateObj = isHorizontal ? { x: 0 } : { y: 0 }; const exitObj = isHorizontal ? { x: parentAnchor === 'left' ? -drawerWidth : drawerWidth } : { y: parentAnchor === 'top' ? -drawerHeight : drawerHeight }; const customClass = isHorizontal ? `top-0 ${parentAnchor === 'left' ? 'left-0' : 'right-0'}` : `left-0 ${parentAnchor === 'top' ? 'top-0' : 'bottom-0'}`; return ( ); }); const DrawerHeader = React.forwardRef< React.ComponentRef, IDrawerHeaderProps >(function DrawerHeader({ className, ...props }, ref) { return ( ); }); const DrawerBody = React.forwardRef< React.ComponentRef, IDrawerBodyProps >(function DrawerBody({ className, ...props }, ref) { return ( ); }); const DrawerFooter = React.forwardRef< React.ComponentRef, IDrawerFooterProps >(function DrawerFooter({ className, ...props }, ref) { return ( ); }); const DrawerCloseButton = React.forwardRef< React.ComponentRef, IDrawerCloseButtonProps >(function DrawerCloseButton({ className, ...props }, ref) { return ( ); }); Drawer.displayName = 'Drawer'; DrawerBackdrop.displayName = 'DrawerBackdrop'; DrawerContent.displayName = 'DrawerContent'; DrawerHeader.displayName = 'DrawerHeader'; DrawerBody.displayName = 'DrawerBody'; DrawerFooter.displayName = 'DrawerFooter'; DrawerCloseButton.displayName = 'DrawerCloseButton'; export { Drawer, DrawerBackdrop, DrawerContent, DrawerCloseButton, DrawerHeader, DrawerBody, DrawerFooter, };