You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
7.7 KiB
331 lines
7.7 KiB
'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<TextProps>;
|
|
|
|
/** 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<typeof UIAccordion> &
|
|
VariantProps<typeof accordionStyle>;
|
|
|
|
type IAccordionItemProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.Item
|
|
> &
|
|
VariantProps<typeof accordionItemStyle>;
|
|
|
|
type IAccordionContentProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.Content
|
|
> &
|
|
VariantProps<typeof accordionContentStyle>;
|
|
|
|
type IAccordionContentTextProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.ContentText
|
|
> &
|
|
VariantProps<typeof accordionContentTextStyle>;
|
|
|
|
type IAccordionIconProps = VariantProps<typeof accordionIconStyle> &
|
|
React.ComponentPropsWithoutRef<typeof UIAccordion.Icon> & {
|
|
as?: React.ElementType;
|
|
height?: number;
|
|
width?: number;
|
|
};
|
|
|
|
type IAccordionHeaderProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.Header
|
|
> &
|
|
VariantProps<typeof accordionHeaderStyle>;
|
|
|
|
type IAccordionTriggerProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.Trigger
|
|
> &
|
|
VariantProps<typeof accordionTriggerStyle>;
|
|
|
|
type IAccordionTitleTextProps = React.ComponentPropsWithoutRef<
|
|
typeof UIAccordion.TitleText
|
|
> &
|
|
VariantProps<typeof accordionTitleTextStyle>;
|
|
|
|
/** Components */
|
|
|
|
const Accordion = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion>,
|
|
IAccordionProps
|
|
>(({ className, variant = 'filled', size = 'md', ...props }, ref) => {
|
|
return (
|
|
<UIAccordion
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionStyle({ variant, class: className })}
|
|
context={{ variant, size }}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionItem = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.Item>,
|
|
IAccordionItemProps
|
|
>(({ className, ...props }, ref) => {
|
|
const { variant } = useStyleContext(SCOPE);
|
|
return (
|
|
<UIAccordion.Item
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionItemStyle({
|
|
parentVariants: { variant },
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionContent = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.Content>,
|
|
IAccordionContentProps
|
|
>(function AccordionContent({ className, ...props }, ref) {
|
|
return (
|
|
<UIAccordion.Content
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionContentStyle({
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionContentText = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.ContentText>,
|
|
IAccordionContentTextProps
|
|
>(function AccordionContentText({ className, ...props }, ref) {
|
|
const { size } = useStyleContext(SCOPE);
|
|
return (
|
|
<UIAccordion.ContentText
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionContentTextStyle({
|
|
parentVariants: { size },
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionIcon = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.Icon>,
|
|
IAccordionIconProps
|
|
>(function AccordionIcon({ size, className, ...props }, ref) {
|
|
const { size: parentSize } = useStyleContext(SCOPE);
|
|
|
|
if (typeof size === 'number') {
|
|
return (
|
|
<UIAccordion.Icon
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionIconStyle({ class: className })}
|
|
size={size}
|
|
/>
|
|
);
|
|
} else if (
|
|
(props.height !== undefined || props.width !== undefined) &&
|
|
size === undefined
|
|
) {
|
|
return (
|
|
<UIAccordion.Icon
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionIconStyle({ class: className })}
|
|
/>
|
|
);
|
|
}
|
|
return (
|
|
<UIAccordion.Icon
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionIconStyle({
|
|
size,
|
|
class: className,
|
|
parentVariants: { size: parentSize },
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionHeader = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.Header>,
|
|
IAccordionHeaderProps
|
|
>(function AccordionHeader({ className, ...props }, ref) {
|
|
return (
|
|
<UIAccordion.Header
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionHeaderStyle({
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
const AccordionTrigger = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.Trigger>,
|
|
IAccordionTriggerProps
|
|
>(function AccordionTrigger({ className, ...props }, ref) {
|
|
return (
|
|
<UIAccordion.Trigger
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionTriggerStyle({
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
const AccordionTitleText = React.forwardRef<
|
|
React.ComponentRef<typeof UIAccordion.TitleText>,
|
|
IAccordionTitleTextProps
|
|
>(function AccordionTitleText({ className, ...props }, ref) {
|
|
const { size } = useStyleContext(SCOPE);
|
|
return (
|
|
<UIAccordion.TitleText
|
|
ref={ref}
|
|
{...props}
|
|
className={accordionTitleTextStyle({
|
|
parentVariants: { size },
|
|
class: className,
|
|
})}
|
|
/>
|
|
);
|
|
});
|
|
|
|
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,
|
|
};
|