'use client'; import { createModal as createDrawer } from '@gluestack-ui/core/modal/creator'; import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils'; import { tva, useStyleContext, withStyleContext, } from '@gluestack-ui/utils/nativewind-utils'; import React from 'react'; import { Pressable, ScrollView, View } from 'react-native'; import Animated, { Easing, FadeIn, FadeOut, SlideInDown, SlideInLeft, SlideInRight, SlideInUp, SlideOutDown, SlideOutLeft, SlideOutRight, SlideOutUp, } from 'react-native-reanimated'; const SCOPE = 'MODAL'; const AnimatedPressable = Animated.createAnimatedComponent(Pressable); const AnimatedView = Animated.createAnimatedComponent(View); const UIDrawer = createDrawer({ Root: withStyleContext(View as any, SCOPE), Backdrop: AnimatedPressable, Content: AnimatedView, Body: ScrollView, CloseButton: Pressable, Footer: View, Header: View, }); 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-[#000]/50 web:cursor-default', }); const drawerContentStyle = tva({ base: 'bg-background shadow-hard-5 p-6 absolute', parentVariants: { size: { sm: '', md: '', lg: '', full: '', }, anchor: { left: 'h-full border-r border-border/80', right: 'h-full border-l border-border/80', top: 'w-full border-b border-border/80 rounded-b-xl', bottom: 'w-full border-t border-border/80 rounded-t-xl', }, }, parentCompoundVariants: [ { size: 'sm', anchor: 'left', class: 'sm:w-1/4 w-2/5', }, { size: 'sm', anchor: 'right', class: 'sm:w-1/4 w-2/5', }, { size: 'sm', anchor: 'top', class: 'h-1/4', }, { size: 'sm', anchor: 'bottom', class: 'h-1/4', }, { size: 'md', anchor: 'left', class: 'w-1/2', }, { size: 'md', anchor: 'right', class: 'w-1/2', }, { size: 'md', anchor: 'top', class: 'h-1/2', }, { size: 'md', anchor: 'bottom', class: 'h-1/2', }, { size: 'lg', anchor: 'left', class: 'w-3/4', }, { size: 'lg', anchor: 'right', class: 'w-3/4', }, { size: 'lg', anchor: 'top', class: 'h-3/4', }, { size: 'lg', anchor: 'bottom', class: 'h-3/4', }, { size: 'full', anchor: 'left', class: 'w-full', }, { size: 'full', anchor: 'right', class: 'w-full', }, { size: 'full', anchor: 'top', class: 'h-full', }, { size: 'full', anchor: 'bottom', class: 'h-full', }, ], }); const drawerCloseButtonStyle = tva({ base: 'z-10 rounded-sm p-2 data-[focus-visible=true]:bg-accent web:cursor-pointer web:outline-0 data-[hover=true]:bg-accent/50', }); const drawerHeaderStyle = tva({ base: 'justify-between items-center flex-row pb-4', }); const drawerBodyStyle = tva({ base: 'mt-4 mb-6 shrink-0', }); const drawerFooterStyle = tva({ base: 'flex-col-reverse gap-2 sm:flex-row sm:justify-end pt-4', }); 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 = 'md', anchor = 'left', style, ...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 { style, ...restProps } = props; // Calculate positioning classes const customClass = parentAnchor === 'left' || parentAnchor === 'right' ? `top-0 ${parentAnchor === 'left' ? 'left-0' : 'right-0'}` : `left-0 ${parentAnchor === 'top' ? 'top-0' : 'bottom-0'}`; // Select entering and exiting animations based on anchor const enteringAnimation = parentAnchor === 'left' ? SlideInLeft.duration(200).easing(Easing.in(Easing.cubic)) : parentAnchor === 'right' ? SlideInRight.duration(200) : parentAnchor === 'top' ? SlideInUp.duration(200) : SlideInDown.duration(200); const exitingAnimation = parentAnchor === 'left' ? SlideOutLeft.duration(200) : parentAnchor === 'right' ? SlideOutRight.duration(200) : parentAnchor === 'top' ? SlideOutUp.duration(200) : SlideOutDown.duration(200); 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, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, DrawerHeader };