parent
c31fb48123
commit
77b250a52f
@ -0,0 +1,66 @@
|
|||||||
|
import LoginForm from "@/components/form/LoginForm";
|
||||||
|
import Button from "@/components/ui/Button";
|
||||||
|
import Screen from "@/components/ui/Screen";
|
||||||
|
import Text from "@/components/ui/Text";
|
||||||
|
import { Feather } from "@expo/vector-icons";
|
||||||
|
import { Link } from "expo-router";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function LoginPage() {
|
||||||
|
interface ISocialNetworkButtons {
|
||||||
|
icon: any;
|
||||||
|
}
|
||||||
|
const socialNetworkButtons: ISocialNetworkButtons[] = [
|
||||||
|
{ icon: "instagram" },
|
||||||
|
{ icon: "facebook" },
|
||||||
|
{ icon: "linkedin" },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Screen>
|
||||||
|
<View className="justify-center gap-4 h-full">
|
||||||
|
<View className="gap-2">
|
||||||
|
<Text position="center" size="3xl" weight="bold">
|
||||||
|
Connexion à Optifit
|
||||||
|
</Text>
|
||||||
|
<Text position="center" size="xl">
|
||||||
|
Personnalise ton expérience du sport avec Optifit, ton nouveau coach
|
||||||
|
IA.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<LoginForm />
|
||||||
|
<View className="flex-row justify-center gap-4">
|
||||||
|
{socialNetworkButtons.map((socialNetworkButton) => (
|
||||||
|
<Button
|
||||||
|
className="w-[4.5rem] h-[4.5rem]"
|
||||||
|
key={socialNetworkButton.icon}
|
||||||
|
size="xl"
|
||||||
|
style="outline"
|
||||||
|
>
|
||||||
|
<Feather
|
||||||
|
name={socialNetworkButton.icon}
|
||||||
|
size={26}
|
||||||
|
color={"black"}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
<View className="gap-2">
|
||||||
|
<Text position="center">
|
||||||
|
Tu n'as pas encore de compte ?{" "}
|
||||||
|
<Link href="/sign-in">
|
||||||
|
<Text weight="bold" isLink={true}>
|
||||||
|
Inscris-toi !
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
</Text>
|
||||||
|
<Link href="/reset-password">
|
||||||
|
<Text position="center" weight="bold" isLink={true}>
|
||||||
|
Mot de passe oublié ?
|
||||||
|
</Text>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Screen>
|
||||||
|
);
|
||||||
|
}
|
@ -1,89 +0,0 @@
|
|||||||
import Screen from "@/components/ui/Screen";
|
|
||||||
import CustomText from "@/components/ui/Text";
|
|
||||||
import { Link } from "expo-router";
|
|
||||||
import { View } from "react-native";
|
|
||||||
|
|
||||||
const socialNetworkButtons: ISocialNetworkButtons[] = [
|
|
||||||
{ icon: "instagram" },
|
|
||||||
{ icon: "facebook" },
|
|
||||||
{ icon: "linkedin" },
|
|
||||||
];
|
|
||||||
|
|
||||||
interface ISocialNetworkButtons {
|
|
||||||
icon: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function LoginPage() {
|
|
||||||
return (
|
|
||||||
<Screen>
|
|
||||||
<View className="flex flex-col gap-4">
|
|
||||||
<View className="flex flex-col gap-2">
|
|
||||||
<CustomText center={true} size="3xl" bold={true}>
|
|
||||||
Connexion à Optifit
|
|
||||||
</CustomText>
|
|
||||||
<CustomText center={true} size="lg">
|
|
||||||
Personnalise ton expérience du sport avec Optifit, ton nouveau coach
|
|
||||||
IA.
|
|
||||||
</CustomText>
|
|
||||||
</View>
|
|
||||||
{/* <LoginForm /> */}
|
|
||||||
<View className="flex flex-col gap-2">
|
|
||||||
<CustomText center={true}>
|
|
||||||
Tu n'as pas encore de compte ?
|
|
||||||
<Link href="/(auth)/sign-in">
|
|
||||||
<CustomText bold={true} isLink={true}>
|
|
||||||
{" "}
|
|
||||||
Inscris-toi !
|
|
||||||
</CustomText>
|
|
||||||
</Link>
|
|
||||||
</CustomText>
|
|
||||||
<Link href="/reset-password">
|
|
||||||
<CustomText center={true} bold={true} isLink={true}>
|
|
||||||
Mot de passe oublié ?
|
|
||||||
</CustomText>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Screen>
|
|
||||||
|
|
||||||
// <Screen>
|
|
||||||
// <Box className="h-full justify-center">
|
|
||||||
// <VStack space="2xl">
|
|
||||||
// <VStack space="sm">
|
|
||||||
// <Heading className="text-center" size="3xl">
|
|
||||||
// Connexion à Optifit
|
|
||||||
// </Heading>
|
|
||||||
// <Text size="lg" className="text-center">
|
|
||||||
// Personnalise ton expérience du sport avec Optifit, ton nouveau
|
|
||||||
// coach IA.
|
|
||||||
// </Text>
|
|
||||||
// </VStack>
|
|
||||||
// <LoginForm />
|
|
||||||
// <ButtonGroup className="justify-center" flexDirection="row">
|
|
||||||
// {socialNetworkButtons.map((socialNetworkButton) => (
|
|
||||||
// <Button
|
|
||||||
// key={socialNetworkButton.icon}
|
|
||||||
// size="xl"
|
|
||||||
// variant="outline"
|
|
||||||
// action="primary"
|
|
||||||
// >
|
|
||||||
// <Feather name={socialNetworkButton.icon} size={27} />
|
|
||||||
// </Button>
|
|
||||||
// ))}
|
|
||||||
// </ButtonGroup>
|
|
||||||
// <VStack>
|
|
||||||
// <HStack className="justify-center items-center" space="xs">
|
|
||||||
// <Text>Tu n'as pas encore de compte ?</Text>
|
|
||||||
// <Link href="/(auth)/sign-in">
|
|
||||||
// <LinkText bold={true}>Inscris-toi !</LinkText>
|
|
||||||
// </Link>
|
|
||||||
// </HStack>
|
|
||||||
// <Link className="text-center" href="/reset-password">
|
|
||||||
// <LinkText bold={true}>Mot de passe oublié ?</LinkText>
|
|
||||||
// </Link>
|
|
||||||
// </VStack>
|
|
||||||
// </VStack>
|
|
||||||
// </Box>
|
|
||||||
// </Screen>
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,68 @@
|
|||||||
|
import Button from "@/components/ui/Button";
|
||||||
|
import Screen from "@/components/ui/Screen";
|
||||||
|
import Text from "@/components/ui/Text";
|
||||||
|
import TextInput from "@/components/form/FormInput";
|
||||||
|
import BackButton from "@/components/BackButton";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import React from "react";
|
||||||
|
import CodeSent from "@/components/modals/CodeSent";
|
||||||
|
import FormError from "@/components/form/FormError";
|
||||||
|
import { EMPTY_FIELD, INVALID_EMAIL } from "@/components/Errors";
|
||||||
|
import { isEmail } from "validator";
|
||||||
|
|
||||||
|
export default function ResetPasswordWithEmail() {
|
||||||
|
const [isModalVisible, setIsModalVisible] = React.useState(false);
|
||||||
|
const [email, setEmail] = React.useState("");
|
||||||
|
const [error, setError] = React.useState("");
|
||||||
|
const [isFormValid, setIsFormValid] = React.useState(true);
|
||||||
|
|
||||||
|
const validateForm = () => {
|
||||||
|
setError("");
|
||||||
|
setIsFormValid(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const invalidateForm = (error: string) => {
|
||||||
|
setError(error);
|
||||||
|
setIsFormValid(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
if (email != "") {
|
||||||
|
if (isEmail(email)) {
|
||||||
|
validateForm();
|
||||||
|
setIsModalVisible(true);
|
||||||
|
} else {
|
||||||
|
invalidateForm(INVALID_EMAIL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invalidateForm(EMPTY_FIELD);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Screen>
|
||||||
|
<CodeSent
|
||||||
|
email={email}
|
||||||
|
onPress={() => setIsModalVisible(false)}
|
||||||
|
visible={isModalVisible}
|
||||||
|
/>
|
||||||
|
<BackButton icon="close" />
|
||||||
|
<View className="gap-4">
|
||||||
|
<Text size="3xl" weight="bold">
|
||||||
|
Recevoir un code par email
|
||||||
|
</Text>
|
||||||
|
<TextInput
|
||||||
|
beforeIcon="mail"
|
||||||
|
placeholder="Test@Optifit.com"
|
||||||
|
onChangeText={setEmail}
|
||||||
|
value={email}
|
||||||
|
label={"Adresse mail"}
|
||||||
|
/>
|
||||||
|
<FormError isVisible={!isFormValid}>{error}</FormError>
|
||||||
|
<Button onPress={onSubmit} afterIcon="arrowright">
|
||||||
|
Recevoir le code
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</Screen>
|
||||||
|
);
|
||||||
|
}
|
@ -1,67 +1,49 @@
|
|||||||
// import {Text} from "@/components/ui/text";
|
import BackButton from "@/components/BackButton";
|
||||||
// import {
|
import { AntDesignIconNames } from "@/components/Icons";
|
||||||
// Button,
|
import Button from "@/components/ui/Button";
|
||||||
// ButtonGroup,
|
import Screen from "@/components/ui/Screen";
|
||||||
// ButtonIcon,
|
import Text from "@/components/ui/Text";
|
||||||
// ButtonText,
|
import { Link } from "expo-router";
|
||||||
// } from "@/components/ui/button";
|
import { View } from "react-native";
|
||||||
// import {VStack} from "@/components/ui/vstack";
|
|
||||||
// import React from "react";
|
|
||||||
// import {
|
|
||||||
// ArrowRightIcon,
|
|
||||||
// LockIcon,
|
|
||||||
// MailIcon,
|
|
||||||
// MessageCircleIcon,
|
|
||||||
// } from "@/components/ui/icon";
|
|
||||||
// import BackButton from "@/components/BackButton";
|
|
||||||
// import Screen from "@/components/Screen";
|
|
||||||
// import {Heading} from "@/components/ui/heading";
|
|
||||||
// import {Link} from "expo-router";
|
|
||||||
// import {SafeAreaView} from "react-native";
|
|
||||||
|
|
||||||
// const resetButtons: IResetButton[] = [
|
export default function ResetPasswordPage() {
|
||||||
// {icon: MailIcon, text: "Envoyer par email"},
|
interface IResetButton {
|
||||||
// {icon: LockIcon, text: "Envoyer par 2FA"},
|
icon: AntDesignIconNames;
|
||||||
// {icon: MessageCircleIcon, text: "Envoyer par SMS"},
|
text: string;
|
||||||
// ];
|
}
|
||||||
|
|
||||||
// interface IResetButton {
|
const resetButtons: IResetButton[] = [
|
||||||
// icon: React.ElementType;
|
{ icon: "mail", text: "Envoyer par email" },
|
||||||
// text: string;
|
{ icon: "lock", text: "Envoyer par 2FA" },
|
||||||
// }
|
{ icon: "message1", text: "Envoyer par SMS" },
|
||||||
|
];
|
||||||
|
|
||||||
// export default function ResetPasswordPage() {
|
return (
|
||||||
// return (
|
<Screen>
|
||||||
// <SafeAreaView>
|
<BackButton />
|
||||||
// <Screen>
|
<View className="gap-4">
|
||||||
// <BackButton link={"/login"}/>
|
<View className="gap-2">
|
||||||
// <VStack space="2xl">
|
<Text className="text-center" size="3xl" weight="bold">
|
||||||
// <VStack space="sm">
|
Réinitialisation de ton mot de passe
|
||||||
// <Heading className="text-center" size="3xl">
|
</Text>
|
||||||
// Réinitialisation de ton mot de passe
|
<Text size="lg" className="text-center">
|
||||||
// </Heading>
|
Selectionne une méthode pour recevoir ton code temporaire !
|
||||||
// <Text size="lg" className="text-center">
|
</Text>
|
||||||
// Selectionne une méthode pour recevoir ton code temporaire
|
</View>
|
||||||
// </Text>
|
<View className="gap-4">
|
||||||
// </VStack>
|
{resetButtons.map((resetButton) => (
|
||||||
// <ButtonGroup space="xl">
|
<Button
|
||||||
// {resetButtons.map((resetButton) => (
|
key={resetButton.text}
|
||||||
// <Link key={resetButton.text} href={"/sign-in"} asChild>
|
size="2xl"
|
||||||
// <Button
|
style="secondary"
|
||||||
// className="justify-between"
|
beforeIcon={resetButton.icon}
|
||||||
// size="2xl"
|
afterIcon="arrowright"
|
||||||
// action="primary"
|
>
|
||||||
// variant="outline"
|
<Link href="/reset-password-with-email">{resetButton.text}</Link>
|
||||||
// >
|
</Button>
|
||||||
// <ButtonIcon as={resetButton.icon}/>
|
))}
|
||||||
// <ButtonText>{resetButton.text}</ButtonText>
|
</View>
|
||||||
// <ButtonIcon as={ArrowRightIcon}/>
|
</View>
|
||||||
// </Button>
|
</Screen>
|
||||||
// </Link>
|
);
|
||||||
// ))}
|
}
|
||||||
// </ButtonGroup>
|
|
||||||
// </VStack>
|
|
||||||
// </Screen>
|
|
||||||
// </SafeAreaView>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
@ -1,36 +1,31 @@
|
|||||||
// import { Text } from "@/components/ui/text";
|
import SigninForm from "@/components/form/SigninForm";
|
||||||
// import { VStack } from "@/components/ui/vstack";
|
import Screen from "@/components/ui/Screen";
|
||||||
// import { Box } from "@/components/ui/box";
|
import Text from "@/components/ui/Text";
|
||||||
// import { HStack } from "@/components/ui/hstack";
|
import { Link } from "expo-router";
|
||||||
// import React from "react";
|
import { View } from "react-native";
|
||||||
// import SigninForm from "@/components/form/SigninForm";
|
|
||||||
// import Screen from "@/components/Screen";
|
|
||||||
// import { Heading } from "@/components/ui/heading";
|
|
||||||
// import { Link } from "expo-router";
|
|
||||||
// import { LinkText } from "@/components/ui/link";
|
|
||||||
|
|
||||||
// export default function SigninPage() {
|
export default function SigninPage() {
|
||||||
// return (
|
return (
|
||||||
// <Screen>
|
<Screen>
|
||||||
// <Box className="h-full justify-center">
|
<View className="justify-center h-full gap-4">
|
||||||
// <VStack space="2xl">
|
<View className="gap-2">
|
||||||
// <VStack space="sm">
|
<Text position="center" size="3xl" weight="bold">
|
||||||
// <Heading className="text-center" size="2xl">
|
Inscris-toi gratuitement
|
||||||
// Inscris-toi gratuitement
|
</Text>
|
||||||
// </Heading>
|
<Text size="xl" position="center">
|
||||||
// <Text size="lg" className="text-center">
|
Génère un programme personnalisé en quelques clics et 1 minute !
|
||||||
// Génère un programme personnalisé en quelques clics et 1 minute !
|
</Text>
|
||||||
// </Text>
|
</View>
|
||||||
// </VStack>
|
<SigninForm />
|
||||||
// <SigninForm />
|
<Text position="center">
|
||||||
// <HStack className="justify-center items-center" space="xs">
|
Tu as déjà un compte ?{" "}
|
||||||
// <Text>Tu as déjà un compte ?</Text>
|
<Link href="/log-in">
|
||||||
// <Link href="/sign-in">
|
<Text isLink={true} weight="bold">
|
||||||
// <LinkText bold={true}>Connectes-toi !</LinkText>
|
Connectes-toi !
|
||||||
// </Link>
|
</Text>
|
||||||
// </HStack>
|
</Link>
|
||||||
// </VStack>
|
</Text>
|
||||||
// </Box>
|
</View>
|
||||||
// </Screen>
|
</Screen>
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
@ -1,13 +1,24 @@
|
|||||||
import {SafeAreaView, Text, View} from "react-native";
|
import { SafeAreaView, Text, View } from "react-native";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import Button from "@/components/ui/Button";
|
||||||
|
import { useSession } from "@/ctx";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
|
||||||
export default function ProfileScreen() {
|
export default function ProfileScreen() {
|
||||||
|
const { signOut } = useSession();
|
||||||
|
|
||||||
|
const disconnect = () => {
|
||||||
|
signOut();
|
||||||
|
router.replace("/log-in");
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
<View>
|
<View>
|
||||||
<Text className="m-7 font-extrabold">Welcome Screen </Text>
|
<Text className="m-7 font-extrabold">Welcome Screen </Text>
|
||||||
<Text>We will do it soon</Text>
|
<Text>We will do it soon</Text>
|
||||||
</View>
|
</View>
|
||||||
|
<Button onPress={disconnect}>Se déconnecter</Button>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import Text from "@/components/ui/Text";
|
||||||
|
import { View } from "react-native";
|
||||||
|
|
||||||
|
export default function Loading() {
|
||||||
|
return (
|
||||||
|
<View className="justify-center items-center h-full">
|
||||||
|
<Text size="3xl" weight="bold">
|
||||||
|
Chargement en cours
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
@ -1,23 +1,29 @@
|
|||||||
|
import { router } from "expo-router";
|
||||||
|
import Button from "./ui/Button";
|
||||||
|
import { TouchableOpacityProps } from "react-native";
|
||||||
import { AntDesign } from "@expo/vector-icons";
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
import { Button, ButtonActions } from "./ui/Button";
|
import React from "react";
|
||||||
import { Href, Link } from "expo-router";
|
import { AntDesignIconNames } from "./Icons";
|
||||||
|
|
||||||
type props = {
|
interface Props extends TouchableOpacityProps {
|
||||||
icon?: any;
|
icon?: AntDesignIconNames;
|
||||||
link: Href;
|
}
|
||||||
action?: ButtonActions;
|
|
||||||
};
|
export default React.forwardRef<any, Props>(
|
||||||
|
(props, ref): React.ReactElement => {
|
||||||
|
const { icon, onPress } = props;
|
||||||
|
const defaultOnPress = () => {
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
export default function BackButton({ icon, link, action }: props) {
|
|
||||||
return (
|
return (
|
||||||
<Button className="h-16 w-16 mb-4" action={action ?? "secondary"}>
|
<Button
|
||||||
<Link href={link}>
|
className="h-16 w-16 mb-4"
|
||||||
<AntDesign
|
onPress={onPress ?? defaultOnPress}
|
||||||
name={icon ?? "arrowleft"}
|
{...ref}
|
||||||
size={30}
|
>
|
||||||
color={action == "primary" ? "white" : "black"}
|
<AntDesign name={icon ?? "arrowleft"} size={24} />
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
export type Size = "xs" | "md" | "lg" | "xl" | "2xl" | "3xl";
|
||||||
|
export type Color = "black" | "white" | "orange" | "red";
|
||||||
|
export type Weight = "thin" | "normal" | "bold" | "extrabold";
|
||||||
|
export type Position = "left" | "center" | "right";
|
||||||
|
|
||||||
|
export function toTextSize(size: Size): string {
|
||||||
|
switch (size) {
|
||||||
|
case "xs":
|
||||||
|
return "text-xs";
|
||||||
|
case "md":
|
||||||
|
return "text-md";
|
||||||
|
case "lg":
|
||||||
|
return "text-lg";
|
||||||
|
case "xl":
|
||||||
|
return "text-xl";
|
||||||
|
case "2xl":
|
||||||
|
return "text-2xl";
|
||||||
|
case "3xl":
|
||||||
|
return "text-3xl";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toTextColor(color: Color): string {
|
||||||
|
switch (color) {
|
||||||
|
case "black":
|
||||||
|
return "text-black";
|
||||||
|
case "white":
|
||||||
|
return "text-white";
|
||||||
|
case "orange":
|
||||||
|
return "text-orange-500";
|
||||||
|
case "red":
|
||||||
|
return "text-red-500";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toTextWeight(weight: Weight): string {
|
||||||
|
switch (weight) {
|
||||||
|
case "thin":
|
||||||
|
return "font-thin";
|
||||||
|
case "normal":
|
||||||
|
return "font-normal";
|
||||||
|
case "bold":
|
||||||
|
return "font-bold";
|
||||||
|
case "extrabold":
|
||||||
|
return "font-extrabold";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toTextPosition(position: Position): string {
|
||||||
|
switch (position) {
|
||||||
|
case "left":
|
||||||
|
return "text-left";
|
||||||
|
case "center":
|
||||||
|
return "text-center";
|
||||||
|
case "right":
|
||||||
|
return "text-right";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export const EMPTY_FIELD = "Un des champs est vide !";
|
||||||
|
export const INVALID_EMAIL = "Adresse mail invalide !";
|
||||||
|
export const NOT_MATCHING_PASSWORD = "Les mots de passe sont différents";
|
@ -0,0 +1,3 @@
|
|||||||
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
|
|
||||||
|
export type AntDesignIconNames = keyof typeof AntDesign.glyphMap;
|
@ -1,19 +1,29 @@
|
|||||||
import {
|
import React from "react";
|
||||||
FormControlError,
|
import { View } from "react-native";
|
||||||
FormControlErrorIcon,
|
import Text, { ExtendedTextProps } from "../ui/Text";
|
||||||
FormControlErrorText,
|
import { MaterialIcons } from "@expo/vector-icons";
|
||||||
} from "../ui/form-control";
|
|
||||||
import { AlertCircleIcon } from "../ui/icon";
|
|
||||||
|
|
||||||
type props = { text: string };
|
interface Props extends ExtendedTextProps {
|
||||||
|
isVisible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.forwardRef<any, Props>(
|
||||||
|
(props, ref): React.ReactElement => {
|
||||||
|
const { isVisible, ...rest } = props;
|
||||||
|
|
||||||
export default function FormError({ text }: props) {
|
const buildClassName = (): string => {
|
||||||
return (
|
return (
|
||||||
<FormControlError className="mb-2 border-[1px] border-red-500 p-4 rounded-3xl bg-red-100 gap-2">
|
"flex-row items-center gap-2 bg-red-300 p-4 border-2 border-red-500 rounded-3xl" +
|
||||||
<FormControlErrorIcon as={AlertCircleIcon} />
|
" " +
|
||||||
<FormControlErrorText className="text-black font-bold">
|
(isVisible ? "block" : "hidden")
|
||||||
{text}
|
|
||||||
</FormControlErrorText>
|
|
||||||
</FormControlError>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className={buildClassName()} {...ref}>
|
||||||
|
<MaterialIcons name="error" size={24} color={"red"} />
|
||||||
|
<Text position="center" weight="bold" {...rest} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { TextInput, TextInputProps, View } from "react-native";
|
||||||
|
import { AntDesignIconNames } from "../Icons";
|
||||||
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
|
import Text from "../ui/Text";
|
||||||
|
export interface FormInputProps extends TextInputProps {
|
||||||
|
afterIcon?: AntDesignIconNames;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
interface Props extends FormInputProps {
|
||||||
|
beforeIcon: AntDesignIconNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.forwardRef<any, Props>(
|
||||||
|
(props, ref): React.ReactElement => {
|
||||||
|
const {
|
||||||
|
onBlur,
|
||||||
|
onChangeText,
|
||||||
|
value,
|
||||||
|
beforeIcon,
|
||||||
|
afterIcon,
|
||||||
|
label,
|
||||||
|
placeholder,
|
||||||
|
onPress,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className="gap-2">
|
||||||
|
<Text weight="bold">{label}</Text>
|
||||||
|
<View className="flex-row items-center gap-2 px-4 py-2 bg-gray-200 rounded-3xl">
|
||||||
|
<AntDesign name={beforeIcon} size={24} />
|
||||||
|
<TextInput
|
||||||
|
className="grow"
|
||||||
|
placeholder={placeholder}
|
||||||
|
onBlur={onBlur}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
value={value}
|
||||||
|
{...ref}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
{afterIcon != null ? (
|
||||||
|
<AntDesign name={afterIcon} size={24} onPress={onPress} />
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
@ -1,75 +1,72 @@
|
|||||||
import React from "react";
|
import { View, ViewProps } from "react-native";
|
||||||
import { Text } from "react-native";
|
import TextInput from "./FormInput";
|
||||||
import Button from "../ui/Button";
|
import Button from "../ui/Button";
|
||||||
export default function LoginForm() {
|
import PasswordTextInput from "./SecretTextInput";
|
||||||
const REQUIRED_ERROR = "Au moins un des champs requis est vide !";
|
import React from "react";
|
||||||
const [emailValue, setEmailValue] = React.useState("");
|
import { EMPTY_FIELD, INVALID_EMAIL } from "../Errors";
|
||||||
const [isEmailInvalid, setIsEmailInvalid] = React.useState(false);
|
import FormError from "./FormError";
|
||||||
const [passwordValue, setPasswordValue] = React.useState("");
|
import { isEmail } from "validator";
|
||||||
const [isPasswordInvalid, setIsPasswordInvalid] = React.useState(false);
|
import { useSession } from "@/ctx";
|
||||||
const [isFormInvalid, setIsFormInvalid] = React.useState(false);
|
import { router } from "expo-router";
|
||||||
const handleSubmit = () => {
|
|
||||||
//check for empty fields
|
export default React.forwardRef<any, ViewProps>(
|
||||||
setIsEmailInvalid(emailValue == "");
|
(props, ref): React.ReactElement => {
|
||||||
setIsPasswordInvalid(passwordValue == "");
|
const { ...rest } = props;
|
||||||
setIsFormInvalid(isEmailInvalid || isPasswordInvalid);
|
const [email, setEmail] = React.useState("");
|
||||||
|
const [password, setPassword] = React.useState("");
|
||||||
|
const [error, setError] = React.useState("");
|
||||||
|
const [isFormValid, setIsFormValid] = React.useState(true);
|
||||||
|
const { signIn } = useSession();
|
||||||
|
|
||||||
|
const validateForm = () => {
|
||||||
|
setError("");
|
||||||
|
setIsFormValid(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const invalidateForm = (error: string) => {
|
||||||
|
setError(error);
|
||||||
|
setIsFormValid(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
if (email != "") {
|
||||||
|
if (isEmail(email)) {
|
||||||
|
if (password != "") {
|
||||||
|
validateForm();
|
||||||
|
signIn();
|
||||||
|
router.replace("/HomeScreen");
|
||||||
|
} else {
|
||||||
|
invalidateForm(EMPTY_FIELD);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invalidateForm(INVALID_EMAIL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invalidateForm(EMPTY_FIELD);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl className="gap-4" isInvalid={isFormInvalid}>
|
<View className="gap-4" {...ref} {...rest}>
|
||||||
<FormControl isInvalid={isEmailInvalid}>
|
<View className="gap-4">
|
||||||
<FormControlLabel>
|
<TextInput
|
||||||
<FormControlLabelText bold={true}>Adresse mail</FormControlLabelText>
|
beforeIcon="mail"
|
||||||
</FormControlLabel>
|
placeholder="Test@Optifit.com"
|
||||||
<Input variant="outline" size="xl">
|
onChangeText={setEmail}
|
||||||
<InputIcon color="black" as={MailIcon} />
|
value={email}
|
||||||
<InputField
|
label={"Adresse mail"}
|
||||||
value={emailValue}
|
|
||||||
onChangeText={setEmailValue}
|
|
||||||
placeholder="Test@optifit.com"
|
|
||||||
/>
|
/>
|
||||||
</Input>
|
<PasswordTextInput
|
||||||
</FormControl>
|
label="Mot de passe"
|
||||||
<FormControl isInvalid={isPasswordInvalid}>
|
onChangeText={setPassword}
|
||||||
<FormControlLabel>
|
value={password}
|
||||||
<FormControlLabelText bold={true}>Mot de passe</FormControlLabelText>
|
/>
|
||||||
</FormControlLabel>
|
</View>
|
||||||
<PasswordField value={passwordValue} onChangeText={setPasswordValue} />
|
<FormError isVisible={!isFormValid}>{error}</FormError>
|
||||||
</FormControl>
|
<Button onPress={onSubmit} afterIcon="arrowright">
|
||||||
<VStack>
|
Se connecter
|
||||||
<FormError text={REQUIRED_ERROR} />
|
|
||||||
<Button size="xl" onPress={handleSubmit}>
|
|
||||||
<ButtonText>Se connecter</ButtonText>
|
|
||||||
<ButtonIcon as={ArrowRightIcon} />
|
|
||||||
</Button>
|
|
||||||
</VStack>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl className="gap-4">
|
|
||||||
<FormControl>
|
|
||||||
<FormControlLabel>
|
|
||||||
<FormControlLabelText bold={true}>Adresse mail</FormControlLabelText>
|
|
||||||
</FormControlLabel>
|
|
||||||
<Input variant="outline" size="xl">
|
|
||||||
<InputIcon color="black" as={MailIcon} />
|
|
||||||
<InputField placeholder="Test@optifit.com" />
|
|
||||||
</Input>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormControlLabel>
|
|
||||||
<FormControlLabelText bold={true}>Mot de passe</FormControlLabelText>
|
|
||||||
</FormControlLabel>
|
|
||||||
<PasswordField />
|
|
||||||
</FormControl>
|
|
||||||
<VStack>
|
|
||||||
<FormError text={"REQUIRED_ERROR"} />
|
|
||||||
<Button size="xl">
|
|
||||||
<ButtonText>Se connecter</ButtonText>
|
|
||||||
<ButtonIcon as={ArrowRightIcon} />
|
|
||||||
</Button>
|
</Button>
|
||||||
</VStack>
|
</View>
|
||||||
</FormControl>
|
|
||||||
<Link href={"/sign-in"} asChild>
|
|
||||||
<Button title="Se connecter"/>
|
|
||||||
</Link>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import { LockIcon, EyeIcon, EyeOffIcon } from "../ui/icon";
|
|
||||||
import { Input, InputIcon, InputField, InputSlot } from "../ui/input";
|
|
||||||
import { VariantProps } from "@gluestack-ui/nativewind-utils";
|
|
||||||
|
|
||||||
type props = React.ComponentProps<typeof Input> &
|
|
||||||
VariantProps<typeof InputField>;
|
|
||||||
|
|
||||||
export default function PasswordField({ value, onChangeText }: props) {
|
|
||||||
const [showPassword, setShowPassword] = React.useState(false);
|
|
||||||
const handleState = () => {
|
|
||||||
setShowPassword((showState) => {
|
|
||||||
return !showState;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Input variant="outline" size="xl">
|
|
||||||
<InputIcon color="black" as={LockIcon} />
|
|
||||||
<InputField
|
|
||||||
value={value}
|
|
||||||
onChangeText={onChangeText}
|
|
||||||
type={showPassword ? "text" : "password"}
|
|
||||||
placeholder="⋆⋆⋆⋆⋆⋆⋆⋆⋆⋆⋆⋆"
|
|
||||||
/>
|
|
||||||
<InputSlot className="pr-3" onPress={handleState}>
|
|
||||||
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon} />
|
|
||||||
</InputSlot>
|
|
||||||
</Input>
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,29 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import FormInput, { FormInputProps } from "./FormInput";
|
||||||
|
|
||||||
|
export default React.forwardRef<any, FormInputProps>(
|
||||||
|
(props, ref): React.ReactElement => {
|
||||||
|
const { onBlur, onChangeText, value, label, ...rest } = props;
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
|
const toggleShowPassword = () => {
|
||||||
|
setShowPassword(!showPassword);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormInput
|
||||||
|
label={label}
|
||||||
|
beforeIcon="lock"
|
||||||
|
afterIcon={showPassword ? "eye" : "eyeo"}
|
||||||
|
placeholder="⋆⋆⋆⋆⋆⋆⋆⋆⋆⋆"
|
||||||
|
onBlur={onBlur}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
value={value}
|
||||||
|
onPress={toggleShowPassword}
|
||||||
|
secureTextEntry={!showPassword}
|
||||||
|
{...ref}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
@ -1,125 +1,82 @@
|
|||||||
import { Button, ButtonText, ButtonIcon } from "../ui/Button";
|
import { View, ViewProps } from "react-native";
|
||||||
import {
|
import TextInput from "./FormInput";
|
||||||
FormControl,
|
import Button from "../ui/Button";
|
||||||
FormControlLabel,
|
|
||||||
FormControlLabelText,
|
|
||||||
} from "../ui/form-control";
|
|
||||||
import { MailIcon, ArrowRightIcon } from "../ui/icon";
|
|
||||||
import { Input, InputIcon, InputField } from "../ui/input";
|
|
||||||
import { VStack } from "../ui/vstack";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import PasswordTextInput from "./SecretTextInput";
|
||||||
|
import { isEmail } from "validator";
|
||||||
|
import { EMPTY_FIELD, INVALID_EMAIL, NOT_MATCHING_PASSWORD } from "../Errors";
|
||||||
import FormError from "./FormError";
|
import FormError from "./FormError";
|
||||||
import PasswordField from "./PasswordField";
|
|
||||||
|
|
||||||
export default function SigninForm() {
|
export default React.forwardRef<any, ViewProps>(
|
||||||
const REQUIRED = "Au moins un des champs requis est vide !";
|
(props, ref): React.ReactElement => {
|
||||||
const INVALID_EMAIL = "Adresse mail invalide !";
|
const { ...rest } = props;
|
||||||
// TODO Définir ce qu'est un mdp valide
|
const [email, setEmail] = React.useState("");
|
||||||
const INVALID_PASSWORD = "Mot de passe invalide !";
|
const [password, setPassword] = React.useState("");
|
||||||
const NOT_MATCHING_PASSWORD = "Les mots de passe ne correspondent pas !";
|
const [confirmPassword, setConfirmPassword] = React.useState("");
|
||||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
const [error, setError] = React.useState("");
|
||||||
|
const [isFormValid, setIsFormValid] = React.useState(true);
|
||||||
|
|
||||||
const [emailValue, setEmailValue] = React.useState("");
|
const validateForm = () => {
|
||||||
const [isEmailInvalid, setIsEmailInvalid] = React.useState(false);
|
setError("");
|
||||||
const [passwordValue, setPasswordValue] = React.useState("");
|
setIsFormValid(true);
|
||||||
const [isPasswordInvalid, setIsPasswordInvalid] = React.useState(false);
|
};
|
||||||
const [passwordConfirmValue, setPasswordConfirmValue] = React.useState("");
|
|
||||||
const [isPasswordConfirmInvalid, setIsPasswordConfirmInvalid] =
|
|
||||||
React.useState(false);
|
|
||||||
const [isFormInvalid, setIsFormInvalid] = React.useState(false);
|
|
||||||
const [formError, setFormError] = React.useState("");
|
|
||||||
|
|
||||||
function validateForm() {
|
|
||||||
setFormError("");
|
|
||||||
setIsFormInvalid(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalidateForm(error: string) {
|
const invalidateForm = (error: string) => {
|
||||||
setFormError(error);
|
setError(error);
|
||||||
setIsFormInvalid(true);
|
setIsFormValid(false);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const onSubmit = () => {
|
||||||
//check for valid email block
|
if (email != "") {
|
||||||
if (emailValue != "") {
|
if (isEmail(email)) {
|
||||||
if (emailRegex.test(emailValue)) {
|
if (password != "") {
|
||||||
setIsEmailInvalid(false);
|
if (confirmPassword != "") {
|
||||||
|
if (confirmPassword == password) {
|
||||||
|
validateForm();
|
||||||
|
console.log("tmp");
|
||||||
} else {
|
} else {
|
||||||
setIsEmailInvalid(true);
|
invalidateForm(NOT_MATCHING_PASSWORD);
|
||||||
invalidateForm(INVALID_EMAIL);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsEmailInvalid(true);
|
invalidateForm(EMPTY_FIELD);
|
||||||
invalidateForm(REQUIRED);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO : check for valid password block
|
|
||||||
if (passwordValue != "") {
|
|
||||||
setIsPasswordInvalid(false);
|
|
||||||
} else {
|
} else {
|
||||||
setIsPasswordInvalid(true);
|
invalidateForm(EMPTY_FIELD);
|
||||||
invalidateForm(REQUIRED);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check for valid password confirmation
|
|
||||||
if (passwordConfirmValue != "") {
|
|
||||||
if (passwordConfirmValue == passwordValue) {
|
|
||||||
setIsPasswordConfirmInvalid(false);
|
|
||||||
validateForm();
|
|
||||||
} else {
|
} else {
|
||||||
setIsPasswordConfirmInvalid(true);
|
invalidateForm(INVALID_EMAIL);
|
||||||
invalidateForm(NOT_MATCHING_PASSWORD);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setIsPasswordConfirmInvalid(true);
|
invalidateForm(EMPTY_FIELD);
|
||||||
invalidateForm(REQUIRED);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl className="gap-4" isInvalid={isFormInvalid}>
|
<View className="gap-4" {...ref} {...rest}>
|
||||||
<FormControl isInvalid={isEmailInvalid}>
|
<View className="gap-4">
|
||||||
<FormControlLabel>
|
<TextInput
|
||||||
<FormControlLabelText bold={true}>Adresse mail</FormControlLabelText>
|
beforeIcon="mail"
|
||||||
</FormControlLabel>
|
placeholder="Test@Optifit.com"
|
||||||
<Input variant="outline" size="xl">
|
onChangeText={setEmail}
|
||||||
<InputIcon color="black" as={MailIcon} />
|
value={email}
|
||||||
<InputField
|
label={"Adresse mail"}
|
||||||
value={emailValue}
|
/>
|
||||||
onChangeText={setEmailValue}
|
<PasswordTextInput
|
||||||
placeholder="Test@optifit.com"
|
onChangeText={setPassword}
|
||||||
|
value={password}
|
||||||
|
label={"Mot de passe"}
|
||||||
/>
|
/>
|
||||||
</Input>
|
<PasswordTextInput
|
||||||
</FormControl>
|
onChangeText={setConfirmPassword}
|
||||||
<FormControl isInvalid={isPasswordInvalid}>
|
value={confirmPassword}
|
||||||
<FormControlLabel>
|
label={"Confirmation du mot de passe"}
|
||||||
<FormControlLabelText bold={true}>Mot de passe</FormControlLabelText>
|
|
||||||
</FormControlLabel>
|
|
||||||
<PasswordField value={passwordValue} onChangeText={setPasswordValue} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl isInvalid={isPasswordConfirmInvalid}>
|
|
||||||
<FormControlLabel>
|
|
||||||
<FormControlLabelText bold={true}>
|
|
||||||
Confirmation du mot de passe
|
|
||||||
</FormControlLabelText>
|
|
||||||
</FormControlLabel>
|
|
||||||
<PasswordField
|
|
||||||
value={passwordConfirmValue}
|
|
||||||
onChangeText={setPasswordConfirmValue}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</View>
|
||||||
<VStack>
|
<FormError isVisible={!isFormValid}>{error}</FormError>
|
||||||
<FormError text={formError} />
|
<Button onPress={onSubmit} afterIcon="arrowright">
|
||||||
<Button size="xl" onPress={handleSubmit}>
|
S'inscrire
|
||||||
<ButtonText>S'inscrire</ButtonText>
|
|
||||||
<ButtonIcon as={ArrowRightIcon} />
|
|
||||||
</Button>
|
</Button>
|
||||||
</VStack>
|
</View>
|
||||||
</FormControl>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { PropsWithChildren } from "react";
|
import { View, ViewProps } from "react-native";
|
||||||
import { View } from "react-native";
|
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
type props = PropsWithChildren;
|
export default React.forwardRef<any, ViewProps>(
|
||||||
|
(props, ref): React.ReactElement => {
|
||||||
export default function Screen({ children }: props) {
|
const { children, ...rest } = props;
|
||||||
return (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView className={"h-full p-4"} {...ref} {...rest}>
|
||||||
<View className={"h-full pl-2 pr-2"}>{children}</View>
|
<View>{children}</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
@ -1,27 +1,62 @@
|
|||||||
import { PropsWithChildren } from "react";
|
import React from "react";
|
||||||
import { Text } from "react-native";
|
import { Text, TextProps } from "react-native";
|
||||||
|
import {
|
||||||
|
Color,
|
||||||
|
Position,
|
||||||
|
Size,
|
||||||
|
toTextColor,
|
||||||
|
toTextPosition,
|
||||||
|
toTextSize,
|
||||||
|
toTextWeight,
|
||||||
|
Weight,
|
||||||
|
} from "../Constants";
|
||||||
|
|
||||||
type props = PropsWithChildren & {
|
export interface ExtendedTextProps extends TextProps {
|
||||||
center?: boolean;
|
position?: Position;
|
||||||
color?: string;
|
color?: Color;
|
||||||
size?: string;
|
size?: Size;
|
||||||
bold?: boolean;
|
weight?: Weight;
|
||||||
isLink?: boolean;
|
isLink?: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
const CustomText = ({ children, center, color, size, bold, isLink }: props) => {
|
export default React.forwardRef<any, ExtendedTextProps>(
|
||||||
const className =
|
(props, ref): React.ReactElement => {
|
||||||
"text-" +
|
const {
|
||||||
(size ?? "md") +
|
position,
|
||||||
|
color,
|
||||||
|
size,
|
||||||
|
weight,
|
||||||
|
isLink,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const buildClassName = () => {
|
||||||
|
const textSize = toTextSize(size ?? "lg");
|
||||||
|
const textColor = toTextColor(color ?? "black");
|
||||||
|
const textWeight = toTextWeight(weight ?? "normal");
|
||||||
|
const textPosition = toTextPosition(position ?? "left");
|
||||||
|
|
||||||
|
return (
|
||||||
|
textSize +
|
||||||
|
" " +
|
||||||
|
textPosition +
|
||||||
" " +
|
" " +
|
||||||
(center ? "text-center" : "") +
|
textColor +
|
||||||
" " +
|
" " +
|
||||||
("text-" + (color ?? "black ")) +
|
textWeight +
|
||||||
" " +
|
" " +
|
||||||
(bold ? "font-bold" : "") +
|
(isLink ? "text-orange-500 underline" : "") +
|
||||||
" " +
|
" " +
|
||||||
(isLink ? "text-orange-500 underline" : "");
|
className
|
||||||
return <Text className={className}>{children}</Text>;
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CustomText;
|
return (
|
||||||
|
<Text className={buildClassName()} {...ref} {...rest}>
|
||||||
|
{children}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
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.ElementRef<typeof View>, IBoxProps>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<View ref={ref} {...props} className={boxStyle({ class: className })} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Box.displayName = "Box";
|
|
||||||
export { Box };
|
|
@ -1,18 +0,0 @@
|
|||||||
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>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div ref={ref} className={boxStyle({ class: className })} {...props} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Box.displayName = 'Box';
|
|
||||||
export { Box };
|
|
@ -1,10 +0,0 @@
|
|||||||
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,
|
|
||||||
});
|
|
@ -1,432 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import React = require("react");
|
|
||||||
import { ActivityIndicator, Pressable, Text, View } from "react-native";
|
|
||||||
|
|
||||||
const SCOPE = "BUTTON";
|
|
||||||
|
|
||||||
const Root = withStyleContext(Pressable, SCOPE);
|
|
||||||
|
|
||||||
const UIButton = createButton({
|
|
||||||
Root: Root,
|
|
||||||
Text,
|
|
||||||
Group: View,
|
|
||||||
Spinner: ActivityIndicator,
|
|
||||||
Icon: UIIcon,
|
|
||||||
});
|
|
||||||
|
|
||||||
cssInterop(PrimitiveIcon, {
|
|
||||||
className: {
|
|
||||||
target: "style",
|
|
||||||
nativeStyleToProp: {
|
|
||||||
height: true,
|
|
||||||
width: true,
|
|
||||||
fill: true,
|
|
||||||
color: "classNameColor",
|
|
||||||
stroke: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonStyle = tva({
|
|
||||||
base: "group/button rounded-3xl bg-primary-500 flex-row items-center justify-center data-[focus-visible=true]:web:outline-none data-[focus-visible=true]:web:ring-2 data-[disabled=true]:opacity-40 gap-2",
|
|
||||||
variants: {
|
|
||||||
action: {
|
|
||||||
primary:
|
|
||||||
"bg-primary-500 data-[hover=true]:bg-primary-600 data-[active=true]:bg-primary-700 border-primary-300 data-[hover=true]:border-primary-400 data-[active=true]:border-primary-500 data-[focus-visible=true]:web:ring-indicator-info",
|
|
||||||
secondary:
|
|
||||||
"bg-secondary-500 border-secondary-300 data-[hover=true]:bg-secondary-600 data-[hover=true]:border-secondary-400 data-[active=true]:bg-secondary-700 data-[active=true]:border-secondary-700 data-[focus-visible=true]:web:ring-indicator-info",
|
|
||||||
positive:
|
|
||||||
"bg-success-500 border-success-300 data-[hover=true]:bg-success-600 data-[hover=true]:border-success-400 data-[active=true]:bg-success-700 data-[active=true]:border-success-500 data-[focus-visible=true]:web:ring-indicator-info",
|
|
||||||
negative:
|
|
||||||
"bg-error-500 border-error-300 data-[hover=true]:bg-error-600 data-[hover=true]:border-error-400 data-[active=true]:bg-error-700 data-[active=true]:border-error-500 data-[focus-visible=true]:web:ring-indicator-info",
|
|
||||||
default:
|
|
||||||
"bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
variant: {
|
|
||||||
link: "px-0",
|
|
||||||
outline:
|
|
||||||
"bg-transparent border data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
solid: "",
|
|
||||||
},
|
|
||||||
|
|
||||||
size: {
|
|
||||||
xs: "h-8",
|
|
||||||
sm: "h-9",
|
|
||||||
md: "h-10",
|
|
||||||
lg: "h-11",
|
|
||||||
xl: "p-4 h-16",
|
|
||||||
"2xl": "p-6 h-20",
|
|
||||||
"3xl": "p-8 h-24",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
compoundVariants: [
|
|
||||||
{
|
|
||||||
action: "primary",
|
|
||||||
variant: "link",
|
|
||||||
class:
|
|
||||||
"px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "secondary",
|
|
||||||
variant: "link",
|
|
||||||
class:
|
|
||||||
"px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "positive",
|
|
||||||
variant: "link",
|
|
||||||
class:
|
|
||||||
"px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "negative",
|
|
||||||
variant: "link",
|
|
||||||
class:
|
|
||||||
"px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "primary",
|
|
||||||
variant: "outline",
|
|
||||||
class:
|
|
||||||
"bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "secondary",
|
|
||||||
variant: "outline",
|
|
||||||
class:
|
|
||||||
"bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "positive",
|
|
||||||
variant: "outline",
|
|
||||||
class:
|
|
||||||
"bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "negative",
|
|
||||||
variant: "outline",
|
|
||||||
class:
|
|
||||||
"bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonTextStyle = tva({
|
|
||||||
base: "text-typography-0 font-semibold web:select-none",
|
|
||||||
parentVariants: {
|
|
||||||
action: {
|
|
||||||
primary:
|
|
||||||
"text-primary-600 data-[hover=true]:text-primary-600 data-[active=true]:text-primary-700",
|
|
||||||
secondary:
|
|
||||||
"text-typography-500 data-[hover=true]:text-typography-600 data-[active=true]:text-typography-700",
|
|
||||||
positive:
|
|
||||||
"text-success-600 data-[hover=true]:text-success-600 data-[active=true]:text-success-700",
|
|
||||||
negative:
|
|
||||||
"text-error-600 data-[hover=true]:text-error-600 data-[active=true]:text-error-700",
|
|
||||||
},
|
|
||||||
variant: {
|
|
||||||
link: "underline data-[hover=true]:underline data-[active=true]:underline text-orange-400",
|
|
||||||
outline: "",
|
|
||||||
solid:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
xs: "text-xs",
|
|
||||||
sm: "text-sm",
|
|
||||||
md: "text-base",
|
|
||||||
lg: "text-lg",
|
|
||||||
xl: "text-xl",
|
|
||||||
"2xl": "text-2xl",
|
|
||||||
"3xl": "text-3xl",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parentCompoundVariants: [
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "primary",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "secondary",
|
|
||||||
class:
|
|
||||||
"text-typography-800 data-[hover=true]:text-typography-800 data-[active=true]:text-typography-800",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "positive",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "negative",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "outline",
|
|
||||||
action: "primary",
|
|
||||||
class:
|
|
||||||
"text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "outline",
|
|
||||||
action: "secondary",
|
|
||||||
class:
|
|
||||||
"text-typography-500 data-[hover=true]:text-primary-600 data-[active=true]:text-typography-700",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "outline",
|
|
||||||
action: "positive",
|
|
||||||
class:
|
|
||||||
"text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "outline",
|
|
||||||
action: "negative",
|
|
||||||
class:
|
|
||||||
"text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonIconStyle = tva({
|
|
||||||
base: "fill-none",
|
|
||||||
parentVariants: {
|
|
||||||
variant: {
|
|
||||||
link: "data-[hover=true]:underline data-[active=true]:underline",
|
|
||||||
outline: "",
|
|
||||||
solid:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
xs: "h-3.5 w-3.5",
|
|
||||||
sm: "h-4 w-4",
|
|
||||||
md: "h-[18px] w-[18px]",
|
|
||||||
lg: "h-[18px] w-[18px]",
|
|
||||||
xl: "h-5 w-5",
|
|
||||||
"2xl": "h-8 w-8",
|
|
||||||
"3xl": "h-10 w-10",
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
primary:
|
|
||||||
"text-primary-600 data-[hover=true]:text-primary-600 data-[active=true]:text-primary-700",
|
|
||||||
secondary:
|
|
||||||
"text-typography-500 data-[hover=true]:text-typography-600 data-[active=true]:text-typography-700",
|
|
||||||
positive:
|
|
||||||
"text-success-600 data-[hover=true]:text-success-600 data-[active=true]:text-success-700",
|
|
||||||
|
|
||||||
negative:
|
|
||||||
"text-error-600 data-[hover=true]:text-error-600 data-[active=true]:text-error-700",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parentCompoundVariants: [
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "primary",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "secondary",
|
|
||||||
class:
|
|
||||||
"text-typography-800 data-[hover=true]:text-typography-800 data-[active=true]:text-typography-800",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "positive",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
variant: "solid",
|
|
||||||
action: "negative",
|
|
||||||
class:
|
|
||||||
"text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttonGroupStyle = tva({
|
|
||||||
base: "",
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
isAttached: {
|
|
||||||
true: "gap-0",
|
|
||||||
},
|
|
||||||
flexDirection: {
|
|
||||||
row: "flex-row",
|
|
||||||
column: "flex-col",
|
|
||||||
"row-reverse": "flex-row-reverse",
|
|
||||||
"column-reverse": "flex-col-reverse",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
type IButtonProps = Omit<
|
|
||||||
React.ComponentPropsWithoutRef<typeof UIButton>,
|
|
||||||
"context"
|
|
||||||
> &
|
|
||||||
VariantProps<typeof buttonStyle> & { className?: string };
|
|
||||||
|
|
||||||
const Button = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIButton>,
|
|
||||||
IButtonProps
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{ className, variant = "solid", size = "md", action = "primary", ...props },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<UIButton
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={buttonStyle({ variant, size, action, class: className })}
|
|
||||||
context={{ variant, size, action }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
type IButtonTextProps = React.ComponentPropsWithoutRef<typeof UIButton.Text> &
|
|
||||||
VariantProps<typeof buttonTextStyle> & { className?: string };
|
|
||||||
|
|
||||||
const ButtonText = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIButton.Text>,
|
|
||||||
IButtonTextProps
|
|
||||||
>(({ className, variant, size, action, ...props }, ref) => {
|
|
||||||
const {
|
|
||||||
variant: parentVariant,
|
|
||||||
size: parentSize,
|
|
||||||
action: parentAction,
|
|
||||||
} = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<UIButton.Text
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={buttonTextStyle({
|
|
||||||
parentVariants: {
|
|
||||||
variant: parentVariant,
|
|
||||||
size: parentSize,
|
|
||||||
action: parentAction,
|
|
||||||
},
|
|
||||||
variant,
|
|
||||||
size,
|
|
||||||
action,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const ButtonSpinner = UIButton.Spinner;
|
|
||||||
|
|
||||||
type IButtonIcon = React.ComponentPropsWithoutRef<typeof UIButton.Icon> &
|
|
||||||
VariantProps<typeof buttonIconStyle> & {
|
|
||||||
className?: string | undefined;
|
|
||||||
as?: React.ElementType;
|
|
||||||
height?: number;
|
|
||||||
width?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ButtonIcon = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIButton.Icon>,
|
|
||||||
IButtonIcon
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const {
|
|
||||||
variant: parentVariant,
|
|
||||||
size: parentSize,
|
|
||||||
action: parentAction,
|
|
||||||
} = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
if (typeof size === "number") {
|
|
||||||
return (
|
|
||||||
<UIButton.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={buttonIconStyle({ class: className })}
|
|
||||||
size={size}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
(props.height !== undefined || props.width !== undefined) &&
|
|
||||||
size === undefined
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<UIButton.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={buttonIconStyle({ class: className })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<UIButton.Icon
|
|
||||||
{...props}
|
|
||||||
className={buttonIconStyle({
|
|
||||||
parentVariants: {
|
|
||||||
size: parentSize,
|
|
||||||
variant: parentVariant,
|
|
||||||
action: parentAction,
|
|
||||||
},
|
|
||||||
size,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IButtonGroupProps = React.ComponentPropsWithoutRef<typeof UIButton.Group> &
|
|
||||||
VariantProps<typeof buttonGroupStyle>;
|
|
||||||
|
|
||||||
const ButtonGroup = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIButton.Group>,
|
|
||||||
IButtonGroupProps
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
className,
|
|
||||||
space = "md",
|
|
||||||
isAttached = false,
|
|
||||||
flexDirection = "column",
|
|
||||||
...props
|
|
||||||
},
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<UIButton.Group
|
|
||||||
className={buttonGroupStyle({
|
|
||||||
class: className,
|
|
||||||
space,
|
|
||||||
isAttached,
|
|
||||||
flexDirection,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Button.displayName = "Button";
|
|
||||||
ButtonText.displayName = "ButtonText";
|
|
||||||
ButtonSpinner.displayName = "ButtonSpinner";
|
|
||||||
ButtonIcon.displayName = "ButtonIcon";
|
|
||||||
ButtonGroup.displayName = "ButtonGroup";
|
|
||||||
|
|
||||||
export { Button, ButtonText, ButtonSpinner, ButtonIcon, ButtonGroup };
|
|
||||||
export type ButtonActions = keyof typeof buttonStyle.variants.action;
|
|
@ -1,23 +0,0 @@
|
|||||||
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.ElementRef<typeof View>, ICardProps>(
|
|
||||||
({ className, size = 'md', variant = 'elevated', ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
className={cardStyle({ size, variant, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Card.displayName = 'Card';
|
|
||||||
|
|
||||||
export { Card };
|
|
@ -1,22 +0,0 @@
|
|||||||
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>(
|
|
||||||
({ className, size = 'md', variant = 'elevated', ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={cardStyle({ size, variant, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Card.displayName = 'Card';
|
|
||||||
|
|
||||||
export { Card };
|
|
@ -1,20 +0,0 @@
|
|||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,468 +0,0 @@
|
|||||||
'use client';
|
|
||||||
import { Text, View } from 'react-native';
|
|
||||||
import React from 'react';
|
|
||||||
import { createFormControl } from '@gluestack-ui/form-control';
|
|
||||||
import { tva } from '@gluestack-ui/nativewind-utils/tva';
|
|
||||||
import {
|
|
||||||
withStyleContext,
|
|
||||||
useStyleContext,
|
|
||||||
} from '@gluestack-ui/nativewind-utils/withStyleContext';
|
|
||||||
import { cssInterop } from 'nativewind';
|
|
||||||
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
|
|
||||||
import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon';
|
|
||||||
|
|
||||||
const SCOPE = 'FORM_CONTROL';
|
|
||||||
|
|
||||||
const formControlStyle = tva({
|
|
||||||
base: 'flex flex-col',
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
sm: '',
|
|
||||||
md: '',
|
|
||||||
lg: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlErrorIconStyle = tva({
|
|
||||||
base: 'text-error-700 fill-none',
|
|
||||||
variants: {
|
|
||||||
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 formControlErrorStyle = tva({
|
|
||||||
base: 'flex flex-row justify-start items-center mt-1 gap-1',
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlErrorTextStyle = tva({
|
|
||||||
base: 'text-error-700',
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlHelperStyle = tva({
|
|
||||||
base: 'flex flex-row justify-start items-center mt-1',
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlHelperTextStyle = tva({
|
|
||||||
base: 'text-typography-500',
|
|
||||||
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-xs',
|
|
||||||
'md': 'text-sm',
|
|
||||||
'lg': 'text-base',
|
|
||||||
'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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlLabelStyle = tva({
|
|
||||||
base: 'flex flex-row justify-start items-center mb-1',
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlLabelTextStyle = tva({
|
|
||||||
base: 'font-medium text-typography-900',
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const formControlLabelAstrickStyle = tva({
|
|
||||||
base: 'font-medium text-typography-900',
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlLabelAstrickProps = React.ComponentPropsWithoutRef<
|
|
||||||
typeof Text
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlLabelAstrickStyle>;
|
|
||||||
|
|
||||||
const FormControlLabelAstrick = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Text>,
|
|
||||||
IFormControlLabelAstrickProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
ref={ref}
|
|
||||||
className={formControlLabelAstrickStyle({
|
|
||||||
parentVariants: { size: parentSize },
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const UIFormControl = createFormControl({
|
|
||||||
Root: withStyleContext(View, SCOPE),
|
|
||||||
Error: View,
|
|
||||||
ErrorText: Text,
|
|
||||||
ErrorIcon: UIIcon,
|
|
||||||
Label: View,
|
|
||||||
LabelText: Text,
|
|
||||||
LabelAstrick: FormControlLabelAstrick,
|
|
||||||
Helper: View,
|
|
||||||
HelperText: Text,
|
|
||||||
});
|
|
||||||
|
|
||||||
cssInterop(PrimitiveIcon, {
|
|
||||||
className: {
|
|
||||||
target: 'style',
|
|
||||||
nativeStyleToProp: {
|
|
||||||
height: true,
|
|
||||||
width: true,
|
|
||||||
fill: true,
|
|
||||||
color: true,
|
|
||||||
stroke: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlProps = React.ComponentProps<typeof UIFormControl> &
|
|
||||||
VariantProps<typeof formControlStyle>;
|
|
||||||
|
|
||||||
const FormControl = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl>,
|
|
||||||
IFormControlProps
|
|
||||||
>(({ className, size = 'md', ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIFormControl
|
|
||||||
ref={ref}
|
|
||||||
className={formControlStyle({ size, class: className })}
|
|
||||||
{...props}
|
|
||||||
context={{ size }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlErrorProps = React.ComponentProps<typeof UIFormControl.Error> &
|
|
||||||
VariantProps<typeof formControlErrorStyle>;
|
|
||||||
|
|
||||||
const FormControlError = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Error>,
|
|
||||||
IFormControlErrorProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIFormControl.Error
|
|
||||||
ref={ref}
|
|
||||||
className={formControlErrorStyle({ class: className })}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlErrorTextProps = React.ComponentProps<
|
|
||||||
typeof UIFormControl.Error.Text
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlErrorTextStyle>;
|
|
||||||
|
|
||||||
const FormControlErrorText = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Error.Text>,
|
|
||||||
IFormControlErrorTextProps
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
return (
|
|
||||||
<UIFormControl.Error.Text
|
|
||||||
className={formControlErrorTextStyle({
|
|
||||||
parentVariants: { size: parentSize },
|
|
||||||
size,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlErrorIconProps = React.ComponentProps<
|
|
||||||
typeof UIFormControl.Error.Icon
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlErrorIconStyle> & {
|
|
||||||
height?: number;
|
|
||||||
width?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormControlErrorIcon = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Error.Icon>,
|
|
||||||
IFormControlErrorIconProps
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
if (typeof size === 'number') {
|
|
||||||
return (
|
|
||||||
<UIFormControl.Error.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={formControlErrorIconStyle({ class: className })}
|
|
||||||
size={size}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
(props.height !== undefined || props.width !== undefined) &&
|
|
||||||
size === undefined
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<UIFormControl.Error.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={formControlErrorIconStyle({ class: className })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<UIFormControl.Error.Icon
|
|
||||||
className={formControlErrorIconStyle({
|
|
||||||
parentVariants: { size: parentSize },
|
|
||||||
size,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlLabelProps = React.ComponentProps<typeof UIFormControl.Label> &
|
|
||||||
VariantProps<typeof formControlLabelStyle>;
|
|
||||||
|
|
||||||
const FormControlLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Label>,
|
|
||||||
IFormControlLabelProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIFormControl.Label
|
|
||||||
ref={ref}
|
|
||||||
className={formControlLabelStyle({ class: className })}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlLabelTextProps = React.ComponentProps<
|
|
||||||
typeof UIFormControl.Label.Text
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlLabelTextStyle>;
|
|
||||||
|
|
||||||
const FormControlLabelText = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Label.Text>,
|
|
||||||
IFormControlLabelTextProps
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<UIFormControl.Label.Text
|
|
||||||
className={formControlLabelTextStyle({
|
|
||||||
parentVariants: { size: parentSize },
|
|
||||||
size,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlHelperProps = React.ComponentProps<
|
|
||||||
typeof UIFormControl.Helper
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlHelperStyle>;
|
|
||||||
|
|
||||||
const FormControlHelper = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Helper>,
|
|
||||||
IFormControlHelperProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIFormControl.Helper
|
|
||||||
ref={ref}
|
|
||||||
className={formControlHelperStyle({
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IFormControlHelperTextProps = React.ComponentProps<
|
|
||||||
typeof UIFormControl.Helper.Text
|
|
||||||
> &
|
|
||||||
VariantProps<typeof formControlHelperTextStyle>;
|
|
||||||
|
|
||||||
const FormControlHelperText = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIFormControl.Helper.Text>,
|
|
||||||
IFormControlHelperTextProps
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<UIFormControl.Helper.Text
|
|
||||||
className={formControlHelperTextStyle({
|
|
||||||
parentVariants: { size: parentSize },
|
|
||||||
size,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
FormControl.displayName = 'FormControl';
|
|
||||||
FormControlError.displayName = 'FormControlError';
|
|
||||||
FormControlErrorText.displayName = 'FormControlErrorText';
|
|
||||||
FormControlErrorIcon.displayName = 'FormControlErrorIcon';
|
|
||||||
FormControlLabel.displayName = 'FormControlLabel';
|
|
||||||
FormControlLabelText.displayName = 'FormControlLabelText';
|
|
||||||
FormControlLabelAstrick.displayName = 'FormControlLabelAstrick';
|
|
||||||
FormControlHelper.displayName = 'FormControlHelper';
|
|
||||||
FormControlHelperText.displayName = 'FormControlHelperText';
|
|
||||||
|
|
||||||
export {
|
|
||||||
FormControl,
|
|
||||||
FormControlError,
|
|
||||||
FormControlErrorText,
|
|
||||||
FormControlErrorIcon,
|
|
||||||
FormControlLabel,
|
|
||||||
FormControlLabelText,
|
|
||||||
FormControlLabelAstrick,
|
|
||||||
FormControlHelper,
|
|
||||||
FormControlHelperText,
|
|
||||||
};
|
|
@ -1,309 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import { vars } from "nativewind";
|
|
||||||
|
|
||||||
export const config = {
|
|
||||||
light: vars({
|
|
||||||
"--color-primary-0": "179 179 179",
|
|
||||||
"--color-primary-50": "153 153 153",
|
|
||||||
"--color-primary-100": "128 128 128",
|
|
||||||
"--color-primary-200": "115 115 115",
|
|
||||||
"--color-primary-300": "102 102 102",
|
|
||||||
"--color-primary-400": "82 82 82",
|
|
||||||
"--color-primary-500": "51 51 51",
|
|
||||||
"--color-primary-600": "41 41 41",
|
|
||||||
"--color-primary-700": "31 31 31",
|
|
||||||
"--color-primary-800": "13 13 13",
|
|
||||||
"--color-primary-900": "10 10 10",
|
|
||||||
"--color-primary-950": "8 8 8",
|
|
||||||
|
|
||||||
/* Secondary */
|
|
||||||
"--color-secondary-0": "253 253 253",
|
|
||||||
"--color-secondary-50": "251 251 251",
|
|
||||||
"--color-secondary-100": "246 246 246",
|
|
||||||
"--color-secondary-200": "242 242 242",
|
|
||||||
"--color-secondary-300": "237 237 237",
|
|
||||||
"--color-secondary-400": "230 230 231",
|
|
||||||
"--color-secondary-500": "217 217 219",
|
|
||||||
"--color-secondary-600": "198 199 199",
|
|
||||||
"--color-secondary-700": "189 189 189",
|
|
||||||
"--color-secondary-800": "177 177 177",
|
|
||||||
"--color-secondary-900": "165 164 164",
|
|
||||||
"--color-secondary-950": "157 157 157",
|
|
||||||
|
|
||||||
/* Tertiary */
|
|
||||||
"--color-tertiary-0": "255 250 245",
|
|
||||||
"--color-tertiary-50": "255 242 229",
|
|
||||||
"--color-tertiary-100": "255 233 213",
|
|
||||||
"--color-tertiary-200": "254 209 170",
|
|
||||||
"--color-tertiary-300": "253 180 116",
|
|
||||||
"--color-tertiary-400": "251 157 75",
|
|
||||||
"--color-tertiary-500": "231 129 40",
|
|
||||||
"--color-tertiary-600": "215 117 31",
|
|
||||||
"--color-tertiary-700": "180 98 26",
|
|
||||||
"--color-tertiary-800": "130 73 23",
|
|
||||||
"--color-tertiary-900": "108 61 19",
|
|
||||||
"--color-tertiary-950": "84 49 18",
|
|
||||||
|
|
||||||
/* Error */
|
|
||||||
"--color-error-0": "254 233 233",
|
|
||||||
"--color-error-50": "254 226 226",
|
|
||||||
"--color-error-100": "254 202 202",
|
|
||||||
"--color-error-200": "252 165 165",
|
|
||||||
"--color-error-300": "248 113 113",
|
|
||||||
"--color-error-400": "239 68 68",
|
|
||||||
"--color-error-500": "230 53 53",
|
|
||||||
"--color-error-600": "220 38 38",
|
|
||||||
"--color-error-700": "185 28 28",
|
|
||||||
"--color-error-800": "153 27 27",
|
|
||||||
"--color-error-900": "127 29 29",
|
|
||||||
"--color-error-950": "83 19 19",
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
"--color-success-0": "228 255 244",
|
|
||||||
"--color-success-50": "202 255 232",
|
|
||||||
"--color-success-100": "162 241 192",
|
|
||||||
"--color-success-200": "132 211 162",
|
|
||||||
"--color-success-300": "102 181 132",
|
|
||||||
"--color-success-400": "72 151 102",
|
|
||||||
"--color-success-500": "52 131 82",
|
|
||||||
"--color-success-600": "42 121 72",
|
|
||||||
"--color-success-700": "32 111 62",
|
|
||||||
"--color-success-800": "22 101 52",
|
|
||||||
"--color-success-900": "20 83 45",
|
|
||||||
"--color-success-950": "27 50 36",
|
|
||||||
|
|
||||||
/* Warning */
|
|
||||||
"--color-warning-0": "255 249 245",
|
|
||||||
"--color-warning-50": "255 244 236",
|
|
||||||
"--color-warning-100": "255 231 213",
|
|
||||||
"--color-warning-200": "254 205 170",
|
|
||||||
"--color-warning-300": "253 173 116",
|
|
||||||
"--color-warning-400": "251 149 75",
|
|
||||||
"--color-warning-500": "231 120 40",
|
|
||||||
"--color-warning-600": "215 108 31",
|
|
||||||
"--color-warning-700": "180 90 26",
|
|
||||||
"--color-warning-800": "130 68 23",
|
|
||||||
"--color-warning-900": "108 56 19",
|
|
||||||
"--color-warning-950": "84 45 18",
|
|
||||||
|
|
||||||
/* Info */
|
|
||||||
"--color-info-0": "236 248 254",
|
|
||||||
"--color-info-50": "199 235 252",
|
|
||||||
"--color-info-100": "162 221 250",
|
|
||||||
"--color-info-200": "124 207 248",
|
|
||||||
"--color-info-300": "87 194 246",
|
|
||||||
"--color-info-400": "50 180 244",
|
|
||||||
"--color-info-500": "13 166 242",
|
|
||||||
"--color-info-600": "11 141 205",
|
|
||||||
"--color-info-700": "9 115 168",
|
|
||||||
"--color-info-800": "7 90 131",
|
|
||||||
"--color-info-900": "5 64 93",
|
|
||||||
"--color-info-950": "3 38 56",
|
|
||||||
|
|
||||||
/* Typography */
|
|
||||||
"--color-typography-0": "254 254 255",
|
|
||||||
"--color-typography-50": "245 245 245",
|
|
||||||
"--color-typography-100": "229 229 229",
|
|
||||||
"--color-typography-200": "219 219 220",
|
|
||||||
"--color-typography-300": "212 212 212",
|
|
||||||
"--color-typography-400": "163 163 163",
|
|
||||||
"--color-typography-500": "140 140 140",
|
|
||||||
"--color-typography-600": "115 115 115",
|
|
||||||
"--color-typography-700": "82 82 82",
|
|
||||||
"--color-typography-800": "64 64 64",
|
|
||||||
"--color-typography-900": "38 38 39",
|
|
||||||
"--color-typography-950": "23 23 23",
|
|
||||||
|
|
||||||
/* Outline */
|
|
||||||
"--color-outline-0": "253 254 254",
|
|
||||||
"--color-outline-50": "243 243 243",
|
|
||||||
"--color-outline-100": "230 230 230",
|
|
||||||
"--color-outline-200": "221 220 219",
|
|
||||||
"--color-outline-300": "211 211 211",
|
|
||||||
"--color-outline-400": "165 163 163",
|
|
||||||
"--color-outline-500": "140 141 141",
|
|
||||||
"--color-outline-600": "115 116 116",
|
|
||||||
"--color-outline-700": "83 82 82",
|
|
||||||
"--color-outline-800": "65 65 65",
|
|
||||||
"--color-outline-900": "39 38 36",
|
|
||||||
"--color-outline-950": "26 23 23",
|
|
||||||
|
|
||||||
/* Background */
|
|
||||||
"--color-background-0": "255 255 255",
|
|
||||||
"--color-background-50": "246 246 246",
|
|
||||||
"--color-background-100": "242 241 241",
|
|
||||||
"--color-background-200": "220 219 219",
|
|
||||||
"--color-background-300": "213 212 212",
|
|
||||||
"--color-background-400": "162 163 163",
|
|
||||||
"--color-background-500": "142 142 142",
|
|
||||||
"--color-background-600": "116 116 116",
|
|
||||||
"--color-background-700": "83 82 82",
|
|
||||||
"--color-background-800": "65 64 64",
|
|
||||||
"--color-background-900": "39 38 37",
|
|
||||||
"--color-background-950": "18 18 18",
|
|
||||||
|
|
||||||
/* Background Special */
|
|
||||||
"--color-background-error": "254 241 241",
|
|
||||||
"--color-background-warning": "255 243 234",
|
|
||||||
"--color-background-success": "237 252 242",
|
|
||||||
"--color-background-muted": "247 248 247",
|
|
||||||
"--color-background-info": "235 248 254",
|
|
||||||
|
|
||||||
/* Focus Ring Indicator */
|
|
||||||
"--color-indicator-primary": "55 55 55",
|
|
||||||
"--color-indicator-info": "83 153 236",
|
|
||||||
"--color-indicator-error": "185 28 28",
|
|
||||||
}),
|
|
||||||
dark: vars({
|
|
||||||
"--color-primary-0": "166 166 166",
|
|
||||||
"--color-primary-50": "175 175 175",
|
|
||||||
"--color-primary-100": "186 186 186",
|
|
||||||
"--color-primary-200": "197 197 197",
|
|
||||||
"--color-primary-300": "212 212 212",
|
|
||||||
"--color-primary-400": "221 221 221",
|
|
||||||
"--color-primary-500": "230 230 230",
|
|
||||||
"--color-primary-600": "240 240 240",
|
|
||||||
"--color-primary-700": "250 250 250",
|
|
||||||
"--color-primary-800": "253 253 253",
|
|
||||||
"--color-primary-900": "254 249 249",
|
|
||||||
"--color-primary-950": "253 252 252",
|
|
||||||
|
|
||||||
/* Secondary */
|
|
||||||
"--color-secondary-0": "20 20 20",
|
|
||||||
"--color-secondary-50": "23 23 23",
|
|
||||||
"--color-secondary-100": "31 31 31",
|
|
||||||
"--color-secondary-200": "39 39 39",
|
|
||||||
"--color-secondary-300": "44 44 44",
|
|
||||||
"--color-secondary-400": "56 57 57",
|
|
||||||
"--color-secondary-500": "63 64 64",
|
|
||||||
"--color-secondary-600": "86 86 86",
|
|
||||||
"--color-secondary-700": "110 110 110",
|
|
||||||
"--color-secondary-800": "135 135 135",
|
|
||||||
"--color-secondary-900": "150 150 150",
|
|
||||||
"--color-secondary-950": "164 164 164",
|
|
||||||
|
|
||||||
/* Tertiary */
|
|
||||||
"--color-tertiary-0": "84 49 18",
|
|
||||||
"--color-tertiary-50": "108 61 19",
|
|
||||||
"--color-tertiary-100": "130 73 23",
|
|
||||||
"--color-tertiary-200": "180 98 26",
|
|
||||||
"--color-tertiary-300": "215 117 31",
|
|
||||||
"--color-tertiary-400": "231 129 40",
|
|
||||||
"--color-tertiary-500": "251 157 75",
|
|
||||||
"--color-tertiary-600": "253 180 116",
|
|
||||||
"--color-tertiary-700": "254 209 170",
|
|
||||||
"--color-tertiary-800": "255 233 213",
|
|
||||||
"--color-tertiary-900": "255 242 229",
|
|
||||||
"--color-tertiary-950": "255 250 245",
|
|
||||||
|
|
||||||
/* Error */
|
|
||||||
"--color-error-0": "83 19 19",
|
|
||||||
"--color-error-50": "127 29 29",
|
|
||||||
"--color-error-100": "153 27 27",
|
|
||||||
"--color-error-200": "185 28 28",
|
|
||||||
"--color-error-300": "220 38 38",
|
|
||||||
"--color-error-400": "230 53 53",
|
|
||||||
"--color-error-500": "239 68 68",
|
|
||||||
"--color-error-600": "249 97 96",
|
|
||||||
"--color-error-700": "229 91 90",
|
|
||||||
"--color-error-800": "254 202 202",
|
|
||||||
"--color-error-900": "254 226 226",
|
|
||||||
"--color-error-950": "254 233 233",
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
"--color-success-0": "27 50 36",
|
|
||||||
"--color-success-50": "20 83 45",
|
|
||||||
"--color-success-100": "22 101 52",
|
|
||||||
"--color-success-200": "32 111 62",
|
|
||||||
"--color-success-300": "42 121 72",
|
|
||||||
"--color-success-400": "52 131 82",
|
|
||||||
"--color-success-500": "72 151 102",
|
|
||||||
"--color-success-600": "102 181 132",
|
|
||||||
"--color-success-700": "132 211 162",
|
|
||||||
"--color-success-800": "162 241 192",
|
|
||||||
"--color-success-900": "202 255 232",
|
|
||||||
"--color-success-950": "228 255 244",
|
|
||||||
|
|
||||||
/* Warning */
|
|
||||||
"--color-warning-0": "84 45 18",
|
|
||||||
"--color-warning-50": "108 56 19",
|
|
||||||
"--color-warning-100": "130 68 23",
|
|
||||||
"--color-warning-200": "180 90 26",
|
|
||||||
"--color-warning-300": "215 108 31",
|
|
||||||
"--color-warning-400": "231 120 40",
|
|
||||||
"--color-warning-500": "251 149 75",
|
|
||||||
"--color-warning-600": "253 173 116",
|
|
||||||
"--color-warning-700": "254 205 170",
|
|
||||||
"--color-warning-800": "255 231 213",
|
|
||||||
"--color-warning-900": "255 244 237",
|
|
||||||
"--color-warning-950": "255 249 245",
|
|
||||||
|
|
||||||
/* Info */
|
|
||||||
"--color-info-0": "3 38 56",
|
|
||||||
"--color-info-50": "5 64 93",
|
|
||||||
"--color-info-100": "7 90 131",
|
|
||||||
"--color-info-200": "9 115 168",
|
|
||||||
"--color-info-300": "11 141 205",
|
|
||||||
"--color-info-400": "13 166 242",
|
|
||||||
"--color-info-500": "50 180 244",
|
|
||||||
"--color-info-600": "87 194 246",
|
|
||||||
"--color-info-700": "124 207 248",
|
|
||||||
"--color-info-800": "162 221 250",
|
|
||||||
"--color-info-900": "199 235 252",
|
|
||||||
"--color-info-950": "236 248 254",
|
|
||||||
|
|
||||||
/* Typography */
|
|
||||||
"--color-typography-0": "23 23 23",
|
|
||||||
"--color-typography-50": "38 38 39",
|
|
||||||
"--color-typography-100": "64 64 64",
|
|
||||||
"--color-typography-200": "82 82 82",
|
|
||||||
"--color-typography-300": "115 115 115",
|
|
||||||
"--color-typography-400": "140 140 140",
|
|
||||||
"--color-typography-500": "163 163 163",
|
|
||||||
"--color-typography-600": "212 212 212",
|
|
||||||
"--color-typography-700": "219 219 220",
|
|
||||||
"--color-typography-800": "229 229 229",
|
|
||||||
"--color-typography-900": "245 245 245",
|
|
||||||
"--color-typography-950": "254 254 255",
|
|
||||||
|
|
||||||
/* Outline */
|
|
||||||
"--color-outline-0": "26 23 23",
|
|
||||||
"--color-outline-50": "39 38 36",
|
|
||||||
"--color-outline-100": "65 65 65",
|
|
||||||
"--color-outline-200": "83 82 82",
|
|
||||||
"--color-outline-300": "115 116 116",
|
|
||||||
"--color-outline-400": "140 141 141",
|
|
||||||
"--color-outline-500": "165 163 163",
|
|
||||||
"--color-outline-600": "211 211 211",
|
|
||||||
"--color-outline-700": "221 220 219",
|
|
||||||
"--color-outline-800": "230 230 230",
|
|
||||||
"--color-outline-900": "243 243 243",
|
|
||||||
"--color-outline-950": "253 254 254",
|
|
||||||
|
|
||||||
/* Background */
|
|
||||||
"--color-background-0": "18 18 18",
|
|
||||||
"--color-background-50": "39 38 37",
|
|
||||||
"--color-background-100": "65 64 64",
|
|
||||||
"--color-background-200": "83 82 82",
|
|
||||||
"--color-background-300": "116 116 116",
|
|
||||||
"--color-background-400": "142 142 142",
|
|
||||||
"--color-background-500": "162 163 163",
|
|
||||||
"--color-background-600": "213 212 212",
|
|
||||||
"--color-background-700": "229 228 228",
|
|
||||||
"--color-background-800": "242 241 241",
|
|
||||||
"--color-background-900": "246 246 246",
|
|
||||||
"--color-background-950": "255 255 255",
|
|
||||||
|
|
||||||
/* Background Special */
|
|
||||||
"--color-background-error": "66 43 43",
|
|
||||||
"--color-background-warning": "65 47 35",
|
|
||||||
"--color-background-success": "28 43 33",
|
|
||||||
"--color-background-muted": "51 51 51",
|
|
||||||
"--color-background-info": "26 40 46",
|
|
||||||
|
|
||||||
/* Focus Ring Indicator */
|
|
||||||
"--color-indicator-primary": "247 247 247",
|
|
||||||
"--color-indicator-info": "161 199 245",
|
|
||||||
"--color-indicator-error": "232 70 69",
|
|
||||||
}),
|
|
||||||
};
|
|
@ -1,48 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import { config } from "./config";
|
|
||||||
import { ColorSchemeName, useColorScheme, View, ViewProps } from "react-native";
|
|
||||||
import { OverlayProvider } from "@gluestack-ui/overlay";
|
|
||||||
import { ToastProvider } from "@gluestack-ui/toast";
|
|
||||||
import { colorScheme as colorSchemeNW } from "nativewind";
|
|
||||||
|
|
||||||
type ModeType = "light" | "dark" | "system";
|
|
||||||
|
|
||||||
const getColorSchemeName = (
|
|
||||||
colorScheme: ColorSchemeName,
|
|
||||||
mode: ModeType
|
|
||||||
): "light" | "dark" => {
|
|
||||||
if (mode === "system") {
|
|
||||||
return colorScheme ?? "light";
|
|
||||||
}
|
|
||||||
return mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function GluestackUIProvider({
|
|
||||||
mode = "light",
|
|
||||||
...props
|
|
||||||
}: {
|
|
||||||
mode?: "light" | "dark" | "system";
|
|
||||||
children?: React.ReactNode;
|
|
||||||
style?: ViewProps["style"];
|
|
||||||
}) {
|
|
||||||
const colorScheme = useColorScheme();
|
|
||||||
|
|
||||||
const colorSchemeName = getColorSchemeName(colorScheme, mode);
|
|
||||||
|
|
||||||
colorSchemeNW.set(mode);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
config[colorSchemeName],
|
|
||||||
// eslint-disable-next-line react-native/no-inline-styles
|
|
||||||
{ flex: 1, height: "100%", width: "100%" },
|
|
||||||
props.style,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<OverlayProvider>
|
|
||||||
<ToastProvider>{props.children}</ToastProvider>
|
|
||||||
</OverlayProvider>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,219 +0,0 @@
|
|||||||
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.ElementRef<typeof H1>, IHeadingProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
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
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case '2xl':
|
|
||||||
return (
|
|
||||||
<H2
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'xl':
|
|
||||||
return (
|
|
||||||
<H3
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'lg':
|
|
||||||
return (
|
|
||||||
<H4
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'md':
|
|
||||||
return (
|
|
||||||
<H5
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'sm':
|
|
||||||
case 'xs':
|
|
||||||
return (
|
|
||||||
<H6
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<H4
|
|
||||||
className={headingStyle({
|
|
||||||
size,
|
|
||||||
isTruncated,
|
|
||||||
bold,
|
|
||||||
underline,
|
|
||||||
strikeThrough,
|
|
||||||
sub,
|
|
||||||
italic,
|
|
||||||
highlight,
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
{...props}
|
|
||||||
// @ts-expect-error
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const Heading = memo(
|
|
||||||
forwardRef<React.ElementRef<typeof H1>, IHeadingProps>(
|
|
||||||
({ 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 };
|
|
@ -1,203 +0,0 @@
|
|||||||
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>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
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>(
|
|
||||||
({ 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 };
|
|
@ -1,43 +0,0 @@
|
|||||||
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,23 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
|
|
||||||
import { View } from 'react-native';
|
|
||||||
import type { ViewProps } from 'react-native';
|
|
||||||
import { hstackStyle } from './styles';
|
|
||||||
|
|
||||||
type IHStackProps = ViewProps & VariantProps<typeof hstackStyle>;
|
|
||||||
|
|
||||||
const HStack = React.forwardRef<React.ElementRef<typeof View>, IHStackProps>(
|
|
||||||
({ className, space, reversed, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
className={hstackStyle({ space, reversed, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
HStack.displayName = 'HStack';
|
|
||||||
|
|
||||||
export { HStack };
|
|
@ -1,22 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
|
|
||||||
import { hstackStyle } from './styles';
|
|
||||||
|
|
||||||
type IHStackProps = React.ComponentPropsWithoutRef<'div'> &
|
|
||||||
VariantProps<typeof hstackStyle>;
|
|
||||||
|
|
||||||
const HStack = React.forwardRef<React.ElementRef<'div'>, IHStackProps>(
|
|
||||||
({ className, space, reversed, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={hstackStyle({ space, reversed, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
HStack.displayName = 'HStack';
|
|
||||||
|
|
||||||
export { HStack };
|
|
@ -1,25 +0,0 @@
|
|||||||
import { isWeb } from "@gluestack-ui/nativewind-utils/IsWeb";
|
|
||||||
import { tva } from "@gluestack-ui/nativewind-utils/tva";
|
|
||||||
|
|
||||||
const baseStyle = isWeb
|
|
||||||
? "flex 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 hstackStyle = tva({
|
|
||||||
base: `flex-row ${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-row-reverse",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,214 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import React from "react";
|
|
||||||
import { createInput } from "@gluestack-ui/input";
|
|
||||||
import { View, Pressable, TextInput } from "react-native";
|
|
||||||
import { tva } from "@gluestack-ui/nativewind-utils/tva";
|
|
||||||
import {
|
|
||||||
withStyleContext,
|
|
||||||
useStyleContext,
|
|
||||||
} from "@gluestack-ui/nativewind-utils/withStyleContext";
|
|
||||||
import { cssInterop } from "nativewind";
|
|
||||||
import type { VariantProps } from "@gluestack-ui/nativewind-utils";
|
|
||||||
import { PrimitiveIcon, UIIcon } from "@gluestack-ui/icon";
|
|
||||||
|
|
||||||
const SCOPE = "INPUT";
|
|
||||||
|
|
||||||
const UIInput = createInput({
|
|
||||||
Root: withStyleContext(View, SCOPE),
|
|
||||||
Icon: UIIcon,
|
|
||||||
Slot: Pressable,
|
|
||||||
Input: TextInput,
|
|
||||||
});
|
|
||||||
|
|
||||||
cssInterop(PrimitiveIcon, {
|
|
||||||
className: {
|
|
||||||
target: "style",
|
|
||||||
nativeStyleToProp: {
|
|
||||||
height: true,
|
|
||||||
width: true,
|
|
||||||
fill: true,
|
|
||||||
color: "classNameColor",
|
|
||||||
stroke: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const inputStyle = tva({
|
|
||||||
base: "border-background-300 flex-row overflow-hidden content-center data-[hover=true]:border-outline-400 data-[focus=true]:border-orange-400 data-[focus=true]:hover:border-primary-700 data-[disabled=true]:opacity-40 data-[disabled=true]:hover:border-background-300 items-center",
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
xl: "px-4 h-16",
|
|
||||||
lg: "px-4 h-11",
|
|
||||||
md: "px-4 h-10",
|
|
||||||
sm: "px-4 h-9",
|
|
||||||
},
|
|
||||||
|
|
||||||
variant: {
|
|
||||||
underlined:
|
|
||||||
"rounded-none border-b data-[invalid=true]:border-b-2 data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700",
|
|
||||||
|
|
||||||
outline:
|
|
||||||
"rounded-3xl border data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700 data-[focus=true]:web:ring-1 data-[focus=true]:web:ring-inset data-[focus=true]:web:ring-indicator-primary data-[invalid=true]:web:ring-1 data-[invalid=true]:web:ring-inset data-[invalid=true]:web:ring-indicator-error data-[invalid=true]:data-[focus=true]:hover:web:ring-1 data-[invalid=true]:data-[focus=true]:hover:web:ring-inset data-[invalid=true]:data-[focus=true]:hover:web:ring-indicator-error data-[invalid=true]:data-[disabled=true]:hover:web:ring-1 data-[invalid=true]:data-[disabled=true]:hover:web:ring-inset data-[invalid=true]:data-[disabled=true]:hover:web:ring-indicator-error",
|
|
||||||
|
|
||||||
rounded:
|
|
||||||
"rounded-full border data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700 data-[focus=true]:web:ring-1 data-[focus=true]:web:ring-inset data-[focus=true]:web:ring-indicator-primary data-[invalid=true]:web:ring-1 data-[invalid=true]:web:ring-inset data-[invalid=true]:web:ring-indicator-error data-[invalid=true]:data-[focus=true]:hover:web:ring-1 data-[invalid=true]:data-[focus=true]:hover:web:ring-inset data-[invalid=true]:data-[focus=true]:hover:web:ring-indicator-error data-[invalid=true]:data-[disabled=true]:hover:web:ring-1 data-[invalid=true]:data-[disabled=true]:hover:web:ring-inset data-[invalid=true]:data-[disabled=true]:hover:web:ring-indicator-error",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const inputIconStyle = tva({
|
|
||||||
base: "justify-center items-center text-typography-400 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 inputSlotStyle = tva({
|
|
||||||
base: "justify-center items-center web:disabled:cursor-not-allowed",
|
|
||||||
});
|
|
||||||
|
|
||||||
const inputFieldStyle = tva({
|
|
||||||
base: "flex-1 text-typography-900 py-0 px-3 placeholder:text-typography-500 h-full ios:leading-[0px] web:cursor-text web:data-[disabled=true]:cursor-not-allowed",
|
|
||||||
|
|
||||||
parentVariants: {
|
|
||||||
variant: {
|
|
||||||
underlined: "web:outline-0 web:outline-none px-0",
|
|
||||||
outline: "web:outline-0 web:outline-none",
|
|
||||||
rounded: "web:outline-0 web:outline-none px-4",
|
|
||||||
},
|
|
||||||
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
type IInputProps = React.ComponentProps<typeof UIInput> &
|
|
||||||
VariantProps<typeof inputStyle> & { className?: string };
|
|
||||||
const Input = React.forwardRef<React.ElementRef<typeof UIInput>, IInputProps>(
|
|
||||||
({ className, variant = "outline", size = "md", ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIInput
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputStyle({ variant, size, class: className })}
|
|
||||||
context={{ variant, size }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
type IInputIconProps = React.ComponentProps<typeof UIInput.Icon> &
|
|
||||||
VariantProps<typeof inputIconStyle> & {
|
|
||||||
className?: string;
|
|
||||||
height?: number;
|
|
||||||
width?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const InputIcon = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIInput.Icon>,
|
|
||||||
IInputIconProps
|
|
||||||
>(({ className, size, ...props }, ref) => {
|
|
||||||
const { size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
if (typeof size === "number") {
|
|
||||||
return (
|
|
||||||
<UIInput.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputIconStyle({ class: className })}
|
|
||||||
size={size}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
(props.height !== undefined || props.width !== undefined) &&
|
|
||||||
size === undefined
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<UIInput.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputIconStyle({ class: className })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<UIInput.Icon
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputIconStyle({
|
|
||||||
parentVariants: {
|
|
||||||
size: parentSize,
|
|
||||||
},
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IInputSlotProps = React.ComponentProps<typeof UIInput.Slot> &
|
|
||||||
VariantProps<typeof inputSlotStyle> & { className?: string };
|
|
||||||
|
|
||||||
const InputSlot = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIInput.Slot>,
|
|
||||||
IInputSlotProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UIInput.Slot
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputSlotStyle({
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type IInputFieldProps = React.ComponentProps<typeof UIInput.Input> &
|
|
||||||
VariantProps<typeof inputFieldStyle> & { className?: string };
|
|
||||||
|
|
||||||
const InputField = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UIInput.Input>,
|
|
||||||
IInputFieldProps
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
const { variant: parentVariant, size: parentSize } = useStyleContext(SCOPE);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<UIInput.Input
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={inputFieldStyle({
|
|
||||||
parentVariants: {
|
|
||||||
variant: parentVariant,
|
|
||||||
size: parentSize,
|
|
||||||
},
|
|
||||||
class: className,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Input.displayName = "Input";
|
|
||||||
InputIcon.displayName = "InputIcon";
|
|
||||||
InputSlot.displayName = "InputSlot";
|
|
||||||
InputField.displayName = "InputField";
|
|
||||||
|
|
||||||
export { Input, InputField, InputIcon, InputSlot };
|
|
@ -1,102 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import { createLink } from "@gluestack-ui/link";
|
|
||||||
import { Pressable } from "react-native";
|
|
||||||
import { Text } from "react-native";
|
|
||||||
|
|
||||||
import { tva } from "@gluestack-ui/nativewind-utils/tva";
|
|
||||||
import { withStyleContext } from "@gluestack-ui/nativewind-utils/withStyleContext";
|
|
||||||
import { cssInterop } from "nativewind";
|
|
||||||
import type { VariantProps } from "@gluestack-ui/nativewind-utils";
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
export const UILink = createLink({
|
|
||||||
Root: withStyleContext(Pressable),
|
|
||||||
Text: Text,
|
|
||||||
});
|
|
||||||
|
|
||||||
cssInterop(UILink, { className: "style" });
|
|
||||||
cssInterop(UILink.Text, { className: "style" });
|
|
||||||
|
|
||||||
const linkStyle = tva({
|
|
||||||
base: "group/link web:outline-0 data-[disabled=true]:web:cursor-not-allowed data-[focus-visible=true]:web:ring-2 data-[focus-visible=true]:web:ring-indicator-primary data-[focus-visible=true]:web:outline-0 data-[disabled=true]:opacity-4 ",
|
|
||||||
});
|
|
||||||
|
|
||||||
const linkTextStyle = tva({
|
|
||||||
base: "underline text-orange-400 data-[hover=true]:text-orange-400 data-[hover=true]:no-underline data-[active=true]:text-orange-400 font-normal font-body web:font-sans web:tracking-sm web:my-0 web:bg-transparent web:border-0 web:box-border web:display-inline web:list-none web:margin-0 web:padding-0 web:position-relative web:text-start web:whitespace-pre-wrap web:word-wrap-break-word",
|
|
||||||
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
type ILinkProps = React.ComponentProps<typeof UILink> &
|
|
||||||
VariantProps<typeof linkStyle> & { className?: string };
|
|
||||||
|
|
||||||
const Link = React.forwardRef<React.ElementRef<typeof UILink>, ILinkProps>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UILink
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={linkStyle({ class: className })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
type ILinkTextProps = React.ComponentProps<typeof UILink.Text> &
|
|
||||||
VariantProps<typeof linkTextStyle> & { className?: string };
|
|
||||||
|
|
||||||
const LinkText = React.forwardRef<
|
|
||||||
React.ElementRef<typeof UILink.Text>,
|
|
||||||
ILinkTextProps
|
|
||||||
>(({ className, size = "md", ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<UILink.Text
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
className={linkTextStyle({
|
|
||||||
class: className,
|
|
||||||
size,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Link.displayName = "Link";
|
|
||||||
LinkText.displayName = "LinkText";
|
|
||||||
|
|
||||||
export { Link, LinkText };
|
|
@ -1,48 +0,0 @@
|
|||||||
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.ElementRef<typeof RNText>, ITextProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
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 };
|
|
@ -1,45 +0,0 @@
|
|||||||
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.ElementRef<'span'>, ITextProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
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 };
|
|
@ -1,47 +0,0 @@
|
|||||||
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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,24 +0,0 @@
|
|||||||
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.ElementRef<typeof View>, IVStackProps>(
|
|
||||||
({ className, space, reversed, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
className={vstackStyle({ space, reversed, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
VStack.displayName = 'VStack';
|
|
||||||
|
|
||||||
export { VStack };
|
|
@ -1,23 +0,0 @@
|
|||||||
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.ElementRef<'div'>, IVStackProps>(
|
|
||||||
({ className, space, reversed, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={vstackStyle({ space, reversed, class: className })}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
VStack.displayName = 'VStack';
|
|
||||||
|
|
||||||
export { VStack };
|
|
@ -1,25 +0,0 @@
|
|||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
Loading…
Reference in new issue