fix gluestackUI

This commit is contained in:
Patryk
2025-04-23 20:46:34 +02:00
parent b248aee33d
commit 877f232e98
62 changed files with 4571 additions and 3841 deletions

View File

@@ -1,45 +0,0 @@
import { PropsWithChildren, useState } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
const [isOpen, setIsOpen] = useState(false);
const theme = useColorScheme() ?? 'light';
return (
<ThemedView>
<TouchableOpacity
style={styles.heading}
onPress={() => setIsOpen((value) => !value)}
activeOpacity={0.8}>
<IconSymbol
name="chevron.right"
size={18}
weight="medium"
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }}
/>
<ThemedText type="defaultSemiBold">{title}</ThemedText>
</TouchableOpacity>
{isOpen && <ThemedView style={styles.content}>{children}</ThemedView>}
</ThemedView>
);
}
const styles = StyleSheet.create({
heading: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
},
content: {
marginTop: 6,
marginLeft: 24,
},
});

View File

@@ -1,24 +0,0 @@
import { Link } from 'expo-router';
import { openBrowserAsync } from 'expo-web-browser';
import { type ComponentProps } from 'react';
import { Platform } from 'react-native';
type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: string };
export function ExternalLink({ href, ...rest }: Props) {
return (
<Link
target="_blank"
{...rest}
href={href}
onPress={async (event) => {
if (Platform.OS !== 'web') {
// Prevent the default behavior of linking to the default browser on native.
event.preventDefault();
// Open the link in an in-app browser.
await openBrowserAsync(href);
}
}}
/>
);
}

View File

@@ -1,18 +0,0 @@
import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
import { PlatformPressable } from '@react-navigation/elements';
import * as Haptics from 'expo-haptics';
export function HapticTab(props: BottomTabBarButtonProps) {
return (
<PlatformPressable
{...props}
onPressIn={(ev) => {
if (process.env.EXPO_OS === 'ios') {
// Add a soft haptic feedback when pressing down on the tabs.
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}
props.onPressIn?.(ev);
}}
/>
);
}

View File

@@ -1,40 +0,0 @@
import { useEffect } from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withRepeat,
withSequence,
} from 'react-native-reanimated';
import { ThemedText } from '@/components/ThemedText';
export function HelloWave() {
const rotationAnimation = useSharedValue(0);
useEffect(() => {
rotationAnimation.value = withRepeat(
withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
4 // Run the animation 4 times
);
}, []);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotate: `${rotationAnimation.value}deg` }],
}));
return (
<Animated.View style={animatedStyle}>
<ThemedText style={styles.text}>👋</ThemedText>
</Animated.View>
);
}
const styles = StyleSheet.create({
text: {
fontSize: 28,
lineHeight: 32,
marginTop: -6,
},
});

View File

@@ -0,0 +1,58 @@
import { Box } from "@/components/ui/box";
import { Button, ButtonText } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Heading } from "@/components/ui/heading";
import { Image } from "@/components/ui/image";
import { Text } from "@/components/ui/text";
import { VStack } from "@/components/ui/vstack";
import { Icon } from "@/components/ui/icon";
export default function NoticeCard() {
return (
<Card className="p-5 rounded-lg max-w-[360px] m-3">
<Image
source={{
uri: 'https://gluestack.github.io/public-blog-video-assets/saree.png',
}}
className="mb-6 h-[240px] w-full rounded-md aspect-[4/3]"
alt="image"
/>
<Text
className="text-sm font-normal mb-2 text-typography-700"
>
Fashion Clothing
</Text>
<VStack className="mb-6">
<Heading size="md" className="mb-4">
Cotton Kurta
</Heading>
{/* <Text size="sm">
Floral embroidered notch neck thread work cotton kurta in white and
black.
</Text> */}
</VStack>
<Box
className="flex-col sm:flex-row"
>
<Button
className="px-4 py-2 mr-0 mb-3 sm:mr-3 sm:mb-0 sm:flex-1"
>
<ButtonText size="sm">Add to cart</ButtonText>
</Button>
<Button
variant="outline"
className="px-4 py-2 border-outline-300 sm:flex-1"
>
<ButtonText
size="sm"
className="text-typography-600"
>
Wishlist
</ButtonText>
{/* <Icon as={FavouriteIcon} className="text-typography-500 m-2 w-4 h-4" /> */}
</Button>
</Box>
</Card>
);
}

View File

@@ -1,82 +0,0 @@
import type { PropsWithChildren, ReactElement } from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
interpolate,
useAnimatedRef,
useAnimatedStyle,
useScrollViewOffset,
} from 'react-native-reanimated';
import { ThemedView } from '@/components/ThemedView';
import { useBottomTabOverflow } from '@/components/ui/TabBarBackground';
import { useColorScheme } from '@/hooks/useColorScheme';
const HEADER_HEIGHT = 250;
type Props = PropsWithChildren<{
headerImage: ReactElement;
headerBackgroundColor: { dark: string; light: string };
}>;
export default function ParallaxScrollView({
children,
headerImage,
headerBackgroundColor,
}: Props) {
const colorScheme = useColorScheme() ?? 'light';
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef);
const bottom = useBottomTabOverflow();
const headerAnimatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: interpolate(
scrollOffset.value,
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
),
},
{
scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
},
],
};
});
return (
<ThemedView style={styles.container}>
<Animated.ScrollView
ref={scrollRef}
scrollEventThrottle={16}
scrollIndicatorInsets={{ bottom }}
contentContainerStyle={{ paddingBottom: bottom }}>
<Animated.View
style={[
styles.header,
{ backgroundColor: headerBackgroundColor[colorScheme] },
headerAnimatedStyle,
]}>
{headerImage}
</Animated.View>
<ThemedView style={styles.content}>{children}</ThemedView>
</Animated.ScrollView>
</ThemedView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
height: HEADER_HEIGHT,
overflow: 'hidden',
},
content: {
flex: 1,
padding: 32,
gap: 16,
overflow: 'hidden',
},
});

View File

@@ -1,60 +0,0 @@
import { Text, type TextProps, StyleSheet } from 'react-native';
import { useThemeColor } from '@/hooks/useThemeColor';
export type ThemedTextProps = TextProps & {
lightColor?: string;
darkColor?: string;
type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
};
export function ThemedText({
style,
lightColor,
darkColor,
type = 'default',
...rest
}: ThemedTextProps) {
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
return (
<Text
style={[
{ color },
type === 'default' ? styles.default : undefined,
type === 'title' ? styles.title : undefined,
type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined,
type === 'subtitle' ? styles.subtitle : undefined,
type === 'link' ? styles.link : undefined,
style,
]}
{...rest}
/>
);
}
const styles = StyleSheet.create({
default: {
fontSize: 16,
lineHeight: 24,
},
defaultSemiBold: {
fontSize: 16,
lineHeight: 24,
fontWeight: '600',
},
title: {
fontSize: 32,
fontWeight: 'bold',
lineHeight: 32,
},
subtitle: {
fontSize: 20,
fontWeight: 'bold',
},
link: {
lineHeight: 30,
fontSize: 16,
color: '#0a7ea4',
},
});

View File

@@ -1,14 +0,0 @@
import { View, type ViewProps } from 'react-native';
import { useThemeColor } from '@/hooks/useThemeColor';
export type ThemedViewProps = ViewProps & {
lightColor?: string;
darkColor?: string;
};
export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
return <View style={[{ backgroundColor }, style]} {...otherProps} />;
}

View File

@@ -1,10 +0,0 @@
import * as React from 'react';
import renderer from 'react-test-renderer';
import { ThemedText } from '../ThemedText';
it(`renders correctly`, () => {
const tree = renderer.create(<ThemedText>Snapshot test!</ThemedText>).toJSON();
expect(tree).toMatchSnapshot();
});

View File

@@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Text
style={
[
{
"color": "#11181C",
},
{
"fontSize": 16,
"lineHeight": 24,
},
undefined,
undefined,
undefined,
undefined,
undefined,
]
}
>
Snapshot test!
</Text>
`;

View File

@@ -1,32 +0,0 @@
import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
import { StyleProp, ViewStyle } from 'react-native';
export function IconSymbol({
name,
size = 24,
color,
style,
weight = 'regular',
}: {
name: SymbolViewProps['name'];
size?: number;
color: string;
style?: StyleProp<ViewStyle>;
weight?: SymbolWeight;
}) {
return (
<SymbolView
weight={weight}
tintColor={color}
resizeMode="scaleAspectFit"
name={name}
style={[
{
width: size,
height: size,
},
style,
]}
/>
);
}

View File

@@ -1,43 +0,0 @@
// This file is a fallback for using MaterialIcons on Android and web.
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { SymbolWeight } from 'expo-symbols';
import React from 'react';
import { OpaqueColorValue, StyleProp, ViewStyle } from 'react-native';
// Add your SFSymbol to MaterialIcons mappings here.
const MAPPING = {
// See MaterialIcons here: https://icons.expo.fyi
// See SF Symbols in the SF Symbols app on Mac.
'house.fill': 'home',
'paperplane.fill': 'send',
'chevron.left.forwardslash.chevron.right': 'code',
'chevron.right': 'chevron-right',
} as Partial<
Record<
import('expo-symbols').SymbolViewProps['name'],
React.ComponentProps<typeof MaterialIcons>['name']
>
>;
export type IconSymbolName = keyof typeof MAPPING;
/**
* An icon component that uses native SFSymbols on iOS, and MaterialIcons on Android and web. This ensures a consistent look across platforms, and optimal resource usage.
*
* Icon `name`s are based on SFSymbols and require manual mapping to MaterialIcons.
*/
export function IconSymbol({
name,
size = 24,
color,
style,
}: {
name: IconSymbolName;
size?: number;
color: string | OpaqueColorValue;
style?: StyleProp<ViewStyle>;
weight?: SymbolWeight;
}) {
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
}

View File

@@ -1,22 +0,0 @@
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { BlurView } from 'expo-blur';
import { StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function BlurTabBarBackground() {
return (
<BlurView
// System chrome material automatically adapts to the system's theme
// and matches the native tab bar appearance on iOS.
tint="systemChromeMaterial"
intensity={100}
style={StyleSheet.absoluteFill}
/>
);
}
export function useBottomTabOverflow() {
const tabHeight = useBottomTabBarHeight();
const { bottom } = useSafeAreaInsets();
return tabHeight - bottom;
}

View File

@@ -1,6 +0,0 @@
// This is a shim for web and Android where the tab bar is generally opaque.
export default undefined;
export function useBottomTabOverflow() {
return 0;
}

View File

@@ -0,0 +1,19 @@
import React from 'react';
import { View, ViewProps } from 'react-native';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { boxStyle } from './styles';
type IBoxProps = ViewProps &
VariantProps<typeof boxStyle> & { className?: string };
const Box = React.forwardRef<React.ComponentRef<typeof View>, IBoxProps>(
function Box({ className, ...props }, ref) {
return (
<View ref={ref} {...props} className={boxStyle({ class: className })} />
);
}
);
Box.displayName = 'Box';
export { Box };

View File

@@ -0,0 +1,19 @@
import React from 'react';
import { boxStyle } from './styles';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
type IBoxProps = React.ComponentPropsWithoutRef<'div'> &
VariantProps<typeof boxStyle> & { className?: string };
const Box = React.forwardRef<HTMLDivElement, IBoxProps>(function Box(
{ className, ...props },
ref
) {
return (
<div ref={ref} className={boxStyle({ class: className })} {...props} />
);
});
Box.displayName = 'Box';
export { Box };

View File

@@ -0,0 +1,10 @@
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb';
const baseStyle = isWeb
? 'flex flex-col relative z-0 box-border border-0 list-none min-w-0 min-h-0 bg-transparent items-stretch m-0 p-0 text-decoration-none'
: '';
export const boxStyle = tva({
base: baseStyle,
});

View File

@@ -0,0 +1,26 @@
import React from 'react';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { View, ViewProps } from 'react-native';
import { cardStyle } from './styles';
type ICardProps = ViewProps &
VariantProps<typeof cardStyle> & { className?: string };
const Card = React.forwardRef<React.ComponentRef<typeof View>, ICardProps>(
function Card(
{ className, size = 'md', variant = 'elevated', ...props },
ref
) {
return (
<View
className={cardStyle({ size, variant, class: className })}
{...props}
ref={ref}
/>
);
}
);
Card.displayName = 'Card';
export { Card };

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { cardStyle } from './styles';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
type ICardProps = React.ComponentPropsWithoutRef<'div'> &
VariantProps<typeof cardStyle>;
const Card = React.forwardRef<HTMLDivElement, ICardProps>(function Card(
{ className, size = 'md', variant = 'elevated', ...props },
ref
) {
return (
<div
className={cardStyle({ size, variant, class: className })}
{...props}
ref={ref}
/>
);
});
Card.displayName = 'Card';
export { Card };

View File

@@ -0,0 +1,20 @@
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb';
const baseStyle = isWeb ? 'flex flex-col relative z-0' : '';
export const cardStyle = tva({
base: baseStyle,
variants: {
size: {
sm: 'p-3 rounded',
md: 'p-4 rounded-md',
lg: 'p-6 rounded-xl',
},
variant: {
elevated: 'bg-background-0',
outline: 'border border-outline-200 ',
ghost: 'rounded-none',
filled: 'bg-background-50',
},
},
});

View File

@@ -4,7 +4,8 @@ import { View, ViewProps } from 'react-native';
import { OverlayProvider } from '@gluestack-ui/overlay';
import { ToastProvider } from '@gluestack-ui/toast';
import { useColorScheme } from 'nativewind';
import { ModeType } from './types';
export type ModeType = 'light' | 'dark' | 'system';
export function GluestackUIProvider({
mode = 'light',

View File

@@ -5,7 +5,8 @@ import { OverlayProvider } from '@gluestack-ui/overlay';
import { ToastProvider } from '@gluestack-ui/toast';
import { setFlushStyles } from '@gluestack-ui/nativewind-utils/flush';
import { script } from './script';
import { ModeType } from './types';
export type ModeType = 'light' | 'dark' | 'system';
const variableStyleTagId = 'nativewind-style';
const createStyle = (styleTagId: string) => {

View File

@@ -1 +0,0 @@
export type ModeType = 'light' | 'dark' | 'system';

View File

@@ -0,0 +1,220 @@
import React, { forwardRef, memo } from 'react';
import { H1, H2, H3, H4, H5, H6 } from '@expo/html-elements';
import { headingStyle } from './styles';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { cssInterop } from 'nativewind';
type IHeadingProps = VariantProps<typeof headingStyle> &
React.ComponentPropsWithoutRef<typeof H1> & {
as?: React.ElementType;
};
cssInterop(H1, { className: 'style' });
cssInterop(H2, { className: 'style' });
cssInterop(H3, { className: 'style' });
cssInterop(H4, { className: 'style' });
cssInterop(H5, { className: 'style' });
cssInterop(H6, { className: 'style' });
const MappedHeading = memo(
forwardRef<React.ComponentRef<typeof H1>, IHeadingProps>(
function MappedHeading(
{
size,
className,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
...props
},
ref
) {
switch (size) {
case '5xl':
case '4xl':
case '3xl':
return (
<H1
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
case '2xl':
return (
<H2
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
case 'xl':
return (
<H3
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
case 'lg':
return (
<H4
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
case 'md':
return (
<H5
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
case 'sm':
case 'xs':
return (
<H6
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
default:
return (
<H4
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
// @ts-expect-error : type issue
ref={ref}
/>
);
}
}
)
);
const Heading = memo(
forwardRef<React.ComponentRef<typeof H1>, IHeadingProps>(function Heading(
{ className, size = 'lg', as: AsComp, ...props },
ref
) {
const {
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
} = props;
if (AsComp) {
return (
<AsComp
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
/>
);
}
return (
<MappedHeading className={className} size={size} ref={ref} {...props} />
);
})
);
Heading.displayName = 'Heading';
export { Heading };

View File

@@ -0,0 +1,202 @@
import React, { forwardRef, memo } from 'react';
import { headingStyle } from './styles';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
type IHeadingProps = VariantProps<typeof headingStyle> &
React.ComponentPropsWithoutRef<'h1'> & {
as?: React.ElementType;
};
const MappedHeading = memo(
forwardRef<HTMLHeadingElement, IHeadingProps>(function MappedHeading(
{
size,
className,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
...props
},
ref
) {
switch (size) {
case '5xl':
case '4xl':
case '3xl':
return (
<h1
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
case '2xl':
return (
<h2
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
case 'xl':
return (
<h3
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
case 'lg':
return (
<h4
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
case 'md':
return (
<h5
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
case 'sm':
case 'xs':
return (
<h6
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
default:
return (
<h4
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
}
})
);
const Heading = memo(
forwardRef<HTMLHeadingElement, IHeadingProps>(function Heading(
{ className, size = 'lg', as: AsComp, ...props },
ref
) {
const {
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
} = props;
if (AsComp) {
return (
<AsComp
className={headingStyle({
size,
isTruncated,
bold,
underline,
strikeThrough,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
}
return (
<MappedHeading className={className} size={size} ref={ref} {...props} />
);
})
);
Heading.displayName = 'Heading';
export { Heading };

View File

@@ -0,0 +1,43 @@
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb';
const baseStyle = isWeb
? 'font-sans tracking-sm bg-transparent border-0 box-border display-inline list-none margin-0 padding-0 position-relative text-start no-underline whitespace-pre-wrap word-wrap-break-word'
: '';
export const headingStyle = tva({
base: `text-typography-900 font-bold font-heading tracking-sm my-0 ${baseStyle}`,
variants: {
isTruncated: {
true: 'truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
size: {
'5xl': 'text-6xl',
'4xl': 'text-5xl',
'3xl': 'text-4xl',
'2xl': 'text-3xl',
'xl': 'text-2xl',
'lg': 'text-xl',
'md': 'text-lg',
'sm': 'text-base',
'xs': 'text-sm',
},
},
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
'use client';
import React from 'react';
import { createImage } from '@gluestack-ui/image';
import { Platform, Image as RNImage } from 'react-native';
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
const imageStyle = tva({
base: 'max-w-full',
variants: {
size: {
'2xs': 'h-6 w-6',
'xs': 'h-10 w-10',
'sm': 'h-16 w-16',
'md': 'h-20 w-20',
'lg': 'h-24 w-24',
'xl': 'h-32 w-32',
'2xl': 'h-64 w-64',
'full': 'h-full w-full',
'none': '',
},
},
});
const UIImage = createImage({ Root: RNImage });
type ImageProps = VariantProps<typeof imageStyle> &
React.ComponentProps<typeof UIImage>;
const Image = React.forwardRef<
React.ComponentRef<typeof UIImage>,
ImageProps & { className?: string }
>(function Image({ size = 'md', className, ...props }, ref) {
return (
<UIImage
className={imageStyle({ size, class: className })}
{...props}
ref={ref}
// @ts-expect-error : web only
style={
Platform.OS === 'web'
? { height: 'revert-layer', width: 'revert-layer' }
: undefined
}
/>
);
});
Image.displayName = 'Image';
export { Image };

View File

@@ -0,0 +1,48 @@
import React from 'react';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { Text as RNText } from 'react-native';
import { textStyle } from './styles';
type ITextProps = React.ComponentProps<typeof RNText> &
VariantProps<typeof textStyle>;
const Text = React.forwardRef<React.ComponentRef<typeof RNText>, ITextProps>(
function Text(
{
className,
isTruncated,
bold,
underline,
strikeThrough,
size = 'md',
sub,
italic,
highlight,
...props
},
ref
) {
return (
<RNText
className={textStyle({
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
}
);
Text.displayName = 'Text';
export { Text };

View File

@@ -0,0 +1,45 @@
import React from 'react';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { textStyle } from './styles';
type ITextProps = React.ComponentProps<'span'> & VariantProps<typeof textStyle>;
const Text = React.forwardRef<React.ComponentRef<'span'>, ITextProps>(
function Text(
{
className,
isTruncated,
bold,
underline,
strikeThrough,
size = 'md',
sub,
italic,
highlight,
...props
}: { className?: string } & ITextProps,
ref
) {
return (
<span
className={textStyle({
isTruncated,
bold,
underline,
strikeThrough,
size,
sub,
italic,
highlight,
class: className,
})}
{...props}
ref={ref}
/>
);
}
);
Text.displayName = 'Text';
export { Text };

View File

@@ -0,0 +1,47 @@
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb';
const baseStyle = isWeb
? 'font-sans tracking-sm my-0 bg-transparent border-0 box-border display-inline list-none margin-0 padding-0 position-relative text-start no-underline whitespace-pre-wrap word-wrap-break-word'
: '';
export const textStyle = tva({
base: `text-typography-700 font-body ${baseStyle}`,
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});

View File

@@ -0,0 +1,24 @@
import React from 'react';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { View } from 'react-native';
import { vstackStyle } from './styles';
type IVStackProps = React.ComponentProps<typeof View> &
VariantProps<typeof vstackStyle>;
const VStack = React.forwardRef<React.ComponentRef<typeof View>, IVStackProps>(
function VStack({ className, space, reversed, ...props }, ref) {
return (
<View
className={vstackStyle({ space, reversed, class: className })}
{...props}
ref={ref}
/>
);
}
);
VStack.displayName = 'VStack';
export { VStack };

View File

@@ -0,0 +1,23 @@
import React from 'react';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { vstackStyle } from './styles';
type IVStackProps = React.ComponentProps<'div'> &
VariantProps<typeof vstackStyle>;
const VStack = React.forwardRef<React.ComponentRef<'div'>, IVStackProps>(
function VStack({ className, space, reversed, ...props }, ref) {
return (
<div
className={vstackStyle({ space, reversed, class: className })}
{...props}
ref={ref}
/>
);
}
);
VStack.displayName = 'VStack';
export { VStack };

View File

@@ -0,0 +1,25 @@
import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb';
import { tva } from '@gluestack-ui/nativewind-utils/tva';
const baseStyle = isWeb
? 'flex flex-col relative z-0 box-border border-0 list-none min-w-0 min-h-0 bg-transparent items-stretch m-0 p-0 text-decoration-none'
: '';
export const vstackStyle = tva({
base: `flex-col ${baseStyle}`,
variants: {
space: {
'xs': 'gap-1',
'sm': 'gap-2',
'md': 'gap-3',
'lg': 'gap-4',
'xl': 'gap-5',
'2xl': 'gap-6',
'3xl': 'gap-7',
'4xl': 'gap-8',
},
reversed: {
true: 'flex-col-reverse',
},
},
});