廓形仪rn版本-技术调研
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

'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,
};