'use client'; import React from 'react'; import { createAccordion } from '@gluestack-ui/accordion'; import { View, Pressable, Text, Platform, TextProps } from 'react-native'; import { tva } from '@gluestack-ui/nativewind-utils/tva'; import type { VariantProps } from '@gluestack-ui/nativewind-utils'; import { withStyleContext, useStyleContext, } from '@gluestack-ui/nativewind-utils/withStyleContext'; import { H3 } from '@expo/html-elements'; import { cssInterop } from 'nativewind'; import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'; const SCOPE = 'ACCORDION'; /** Styles */ const accordionStyle = tva({ base: 'w-full', variants: { variant: { filled: 'bg-white shadow-hard-2', unfilled: '', }, size: { sm: '', md: '', lg: '', }, }, }); const accordionItemStyle = tva({ base: '', parentVariants: { variant: { filled: 'bg-background-0', unfilled: 'bg-transparent', }, }, }); const accordionTitleTextStyle = tva({ base: 'text-typography-900 font-bold flex-1 text-left', parentVariants: { size: { sm: 'text-sm', md: 'text-base', lg: 'text-lg', }, }, }); const accordionIconStyle = tva({ base: 'text-typography-900 fill-none', parentVariants: { size: { '2xs': 'h-3 w-3', 'xs': 'h-3.5 w-3.5', 'sm': 'h-4 w-4', 'md': 'h-[18px] w-[18px]', 'lg': 'h-5 w-5', 'xl': 'h-6 w-6', }, }, }); const accordionContentTextStyle = tva({ base: 'text-typography-700 font-normal', parentVariants: { size: { sm: 'text-sm', md: 'text-base', lg: 'text-lg', }, }, }); const accordionHeaderStyle = tva({ base: 'mx-0 my-0', }); const accordionContentStyle = tva({ base: 'pt-1 pb-3 px-4', }); const accordionTriggerStyle = tva({ base: 'w-full flex-row justify-between items-center web:outline-none focus:outline-none data-[disabled=true]:opacity-40 data-[disabled=true]:cursor-not-allowed data-[focus-visible=true]:bg-background-50 py-3 px-4', }); const Root = withStyleContext(View, SCOPE); const Header = ( Platform.OS === 'web' ? H3 : View ) as React.ComponentType; /** Creator */ const UIAccordion = createAccordion({ Root: Root, Item: View, Header: Header, Trigger: Pressable, Icon: UIIcon, TitleText: Text, ContentText: Text, Content: View, }); cssInterop(PrimitiveIcon, { className: { target: 'style', nativeStyleToProp: { height: true, width: true, fill: true, color: 'classNameColor', stroke: true, }, }, }); cssInterop(H3, { className: { target: 'style', }, }); type IAccordionProps = React.ComponentPropsWithoutRef & VariantProps; type IAccordionItemProps = React.ComponentPropsWithoutRef< typeof UIAccordion.Item > & VariantProps; type IAccordionContentProps = React.ComponentPropsWithoutRef< typeof UIAccordion.Content > & VariantProps; type IAccordionContentTextProps = React.ComponentPropsWithoutRef< typeof UIAccordion.ContentText > & VariantProps; type IAccordionIconProps = VariantProps & React.ComponentPropsWithoutRef & { as?: React.ElementType; height?: number; width?: number; }; type IAccordionHeaderProps = React.ComponentPropsWithoutRef< typeof UIAccordion.Header > & VariantProps; type IAccordionTriggerProps = React.ComponentPropsWithoutRef< typeof UIAccordion.Trigger > & VariantProps; type IAccordionTitleTextProps = React.ComponentPropsWithoutRef< typeof UIAccordion.TitleText > & VariantProps; /** Components */ const Accordion = React.forwardRef< React.ComponentRef, IAccordionProps >(({ className, variant = 'filled', size = 'md', ...props }, ref) => { return ( ); }); const AccordionItem = React.forwardRef< React.ComponentRef, IAccordionItemProps >(({ className, ...props }, ref) => { const { variant } = useStyleContext(SCOPE); return ( ); }); const AccordionContent = React.forwardRef< React.ComponentRef, IAccordionContentProps >(function AccordionContent({ className, ...props }, ref) { return ( ); }); const AccordionContentText = React.forwardRef< React.ComponentRef, IAccordionContentTextProps >(function AccordionContentText({ className, ...props }, ref) { const { size } = useStyleContext(SCOPE); return ( ); }); const AccordionIcon = React.forwardRef< React.ComponentRef, IAccordionIconProps >(function AccordionIcon({ size, className, ...props }, ref) { const { size: parentSize } = useStyleContext(SCOPE); if (typeof size === 'number') { return ( ); } else if ( (props.height !== undefined || props.width !== undefined) && size === undefined ) { return ( ); } return ( ); }); const AccordionHeader = React.forwardRef< React.ComponentRef, IAccordionHeaderProps >(function AccordionHeader({ className, ...props }, ref) { return ( ); }); const AccordionTrigger = React.forwardRef< React.ComponentRef, IAccordionTriggerProps >(function AccordionTrigger({ className, ...props }, ref) { return ( ); }); const AccordionTitleText = React.forwardRef< React.ComponentRef, IAccordionTitleTextProps >(function AccordionTitleText({ className, ...props }, ref) { const { size } = useStyleContext(SCOPE); return ( ); }); Accordion.displayName = 'Accordion'; AccordionItem.displayName = 'AccordionItem'; AccordionHeader.displayName = 'AccordionHeader'; AccordionTrigger.displayName = 'AccordionTrigger'; AccordionTitleText.displayName = 'AccordionTitleText'; AccordionContentText.displayName = 'AccordionContentText'; AccordionIcon.displayName = 'AccordionIcon'; AccordionContent.displayName = 'AccordionContent'; export { Accordion, AccordionItem, AccordionHeader, AccordionTrigger, AccordionTitleText, AccordionContentText, AccordionIcon, AccordionContent, };