From 77b250a52f6826f592b2a75d39fe6e9151d1d325 Mon Sep 17 00:00:00 2001 From: Anthony RICHARD Date: Thu, 16 Jan 2025 17:06:46 +0100 Subject: [PATCH] Fix auth pages and logic (stub) --- app/(auth)/_layout.tsx | 9 +- app/(auth)/code-send.tsx | 58 --- app/(auth)/log-in.tsx | 66 ++++ app/(auth)/login.tsx | 89 ----- app/(auth)/reset-password-with-email.tsx | 68 ++++ app/(auth)/reset-password.tsx | 110 +++--- app/(auth)/sign-in.tsx | 65 ++-- app/(tabs)/(profil)/ProfileScreen.tsx | 31 +- app/(tabs)/_layout.tsx | 96 ++--- app/loading.tsx | 12 + components/BackButton.tsx | 46 ++- components/Constants.tsx | 58 +++ components/Errors.tsx | 3 + components/Icons.tsx | 3 + components/form/FormError.tsx | 44 ++- components/form/FormInput.tsx | 49 +++ components/form/LoginForm.tsx | 139 ++++--- components/form/PasswordField.tsx | 31 -- components/form/SecretTextInput.tsx | 29 ++ components/form/SigninForm.tsx | 185 ++++----- components/modals/CodeSent.tsx | 50 +++ components/ui/Button.tsx | 113 +++++- components/ui/Screen.tsx | 23 +- components/ui/Text.tsx | 81 ++-- package-lock.json | 29 +- package.json | 4 +- ui/box/index.tsx | 19 - ui/box/index.web.tsx | 18 - ui/box/styles.tsx | 10 - ui/button/index.tsx | 432 --------------------- ui/card/index.tsx | 23 -- ui/card/index.web.tsx | 22 -- ui/card/styles.tsx | 20 - ui/form-control/index.tsx | 468 ----------------------- ui/gluestack-ui-provider/config.ts | 309 --------------- ui/gluestack-ui-provider/index.tsx | 48 --- ui/heading/index.tsx | 219 ----------- ui/heading/index.web.tsx | 203 ---------- ui/heading/styles.tsx | 43 --- ui/hstack/index.tsx | 23 -- ui/hstack/index.web.tsx | 22 -- ui/hstack/styles.tsx | 25 -- ui/input/index.tsx | 214 ----------- ui/link/index.tsx | 102 ----- ui/text/index.tsx | 48 --- ui/text/index.web.tsx | 45 --- ui/text/styles.tsx | 47 --- ui/vstack/index.tsx | 24 -- ui/vstack/index.web.tsx | 23 -- ui/vstack/styles.tsx | 25 -- 50 files changed, 888 insertions(+), 3035 deletions(-) delete mode 100644 app/(auth)/code-send.tsx create mode 100644 app/(auth)/log-in.tsx delete mode 100644 app/(auth)/login.tsx create mode 100644 app/(auth)/reset-password-with-email.tsx create mode 100644 app/loading.tsx create mode 100644 components/Constants.tsx create mode 100644 components/Errors.tsx create mode 100644 components/Icons.tsx create mode 100644 components/form/FormInput.tsx delete mode 100644 components/form/PasswordField.tsx create mode 100644 components/form/SecretTextInput.tsx create mode 100644 components/modals/CodeSent.tsx delete mode 100644 ui/box/index.tsx delete mode 100644 ui/box/index.web.tsx delete mode 100644 ui/box/styles.tsx delete mode 100644 ui/button/index.tsx delete mode 100644 ui/card/index.tsx delete mode 100644 ui/card/index.web.tsx delete mode 100644 ui/card/styles.tsx delete mode 100644 ui/form-control/index.tsx delete mode 100644 ui/gluestack-ui-provider/config.ts delete mode 100644 ui/gluestack-ui-provider/index.tsx delete mode 100644 ui/heading/index.tsx delete mode 100644 ui/heading/index.web.tsx delete mode 100644 ui/heading/styles.tsx delete mode 100644 ui/hstack/index.tsx delete mode 100644 ui/hstack/index.web.tsx delete mode 100644 ui/hstack/styles.tsx delete mode 100644 ui/input/index.tsx delete mode 100644 ui/link/index.tsx delete mode 100644 ui/text/index.tsx delete mode 100644 ui/text/index.web.tsx delete mode 100644 ui/text/styles.tsx delete mode 100644 ui/vstack/index.tsx delete mode 100644 ui/vstack/index.web.tsx delete mode 100644 ui/vstack/styles.tsx diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx index 0a21bab..f759851 100644 --- a/app/(auth)/_layout.tsx +++ b/app/(auth)/_layout.tsx @@ -2,11 +2,14 @@ import { Stack } from "expo-router"; export default function AuthLayout() { return ( - - - + + + ); } diff --git a/app/(auth)/code-send.tsx b/app/(auth)/code-send.tsx deleted file mode 100644 index 9d57b59..0000000 --- a/app/(auth)/code-send.tsx +++ /dev/null @@ -1,58 +0,0 @@ -// import BackButton from "@/components/BackButton"; -// import React from "react"; -// import { Card } from "@/components/ui/card"; -// import Screen from "@/components/Screen"; -// import { Heading } from "@/components/ui/heading"; -// import { AntDesign } from "@expo/vector-icons"; -// import { VStack } from "@/components/ui/vstack"; -// import { Text } from "@/components/ui/text"; -// import { Button, ButtonIcon, ButtonText } from "@/components/ui/button"; -// import { LockIcon } from "@/components/ui/icon"; - -// function truncateEmail(email: string) { -// const splitedEmail = email.split("@"); -// let hiddenPart = splitedEmail[0][0]; -// for (let i = 1; i < splitedEmail[0].length - 1; i++) { -// hiddenPart += "⋆"; -// } -// return hiddenPart + splitedEmail[0].slice(-1) + "@" + splitedEmail[1]; -// } - -// type props = { email?: string }; - -// export default function CodeSentPage({ email }: props) { -// return ( -// -// -// -// -// -// -// Code envoyé ! -// -// -// -// Nous t'avons envoyé le code de vérification à -// -// -// {truncateEmail(email ?? "test@Optifit.com")} -// -// -// Clique sur renvoyer si tu n'as pas reçu d’ici quelques secondes ! -// 🔥 -// -// -// -// -// -// -// ); -// } diff --git a/app/(auth)/log-in.tsx b/app/(auth)/log-in.tsx new file mode 100644 index 0000000..b8bce77 --- /dev/null +++ b/app/(auth)/log-in.tsx @@ -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 ( + + + + + Connexion à Optifit + + + Personnalise ton expérience du sport avec Optifit, ton nouveau coach + IA. + + + + + {socialNetworkButtons.map((socialNetworkButton) => ( + + ))} + + + + Tu n'as pas encore de compte ?{" "} + + + Inscris-toi ! + + + + + + Mot de passe oublié ? + + + + + + ); +} diff --git a/app/(auth)/login.tsx b/app/(auth)/login.tsx deleted file mode 100644 index 33c338a..0000000 --- a/app/(auth)/login.tsx +++ /dev/null @@ -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 ( - - - - - Connexion à Optifit - - - Personnalise ton expérience du sport avec Optifit, ton nouveau coach - IA. - - - {/* */} - - - Tu n'as pas encore de compte ? - - - {" "} - Inscris-toi ! - - - - - - Mot de passe oublié ? - - - - - - - // - // - // - // - // - // Connexion à Optifit - // - // - // Personnalise ton expérience du sport avec Optifit, ton nouveau - // coach IA. - // - // - // - // - // {socialNetworkButtons.map((socialNetworkButton) => ( - // - // ))} - // - // - // - // Tu n'as pas encore de compte ? - // - // Inscris-toi ! - // - // - // - // Mot de passe oublié ? - // - // - // - // - // - ); -} diff --git a/app/(auth)/reset-password-with-email.tsx b/app/(auth)/reset-password-with-email.tsx new file mode 100644 index 0000000..1041196 --- /dev/null +++ b/app/(auth)/reset-password-with-email.tsx @@ -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 ( + + setIsModalVisible(false)} + visible={isModalVisible} + /> + + + + Recevoir un code par email + + + {error} + + + + ); +} diff --git a/app/(auth)/reset-password.tsx b/app/(auth)/reset-password.tsx index ca31952..9861419 100644 --- a/app/(auth)/reset-password.tsx +++ b/app/(auth)/reset-password.tsx @@ -1,67 +1,49 @@ -// import {Text} from "@/components/ui/text"; -// import { -// Button, -// ButtonGroup, -// ButtonIcon, -// ButtonText, -// } from "@/components/ui/button"; -// 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"; +import BackButton from "@/components/BackButton"; +import { AntDesignIconNames } from "@/components/Icons"; +import Button from "@/components/ui/Button"; +import Screen from "@/components/ui/Screen"; +import Text from "@/components/ui/Text"; +import { Link } from "expo-router"; +import { View } from "react-native"; -// const resetButtons: IResetButton[] = [ -// {icon: MailIcon, text: "Envoyer par email"}, -// {icon: LockIcon, text: "Envoyer par 2FA"}, -// {icon: MessageCircleIcon, text: "Envoyer par SMS"}, -// ]; +export default function ResetPasswordPage() { + interface IResetButton { + icon: AntDesignIconNames; + text: string; + } -// interface IResetButton { -// icon: React.ElementType; -// text: string; -// } + const resetButtons: IResetButton[] = [ + { icon: "mail", text: "Envoyer par email" }, + { icon: "lock", text: "Envoyer par 2FA" }, + { icon: "message1", text: "Envoyer par SMS" }, + ]; -// export default function ResetPasswordPage() { -// return ( -// -// -// -// -// -// -// Réinitialisation de ton mot de passe -// -// -// Selectionne une méthode pour recevoir ton code temporaire -// -// -// -// {resetButtons.map((resetButton) => ( -// -// -// -// ))} -// -// -// -// -// ); -// } + return ( + + + + + + Réinitialisation de ton mot de passe + + + Selectionne une méthode pour recevoir ton code temporaire ! + + + + {resetButtons.map((resetButton) => ( + + ))} + + + + ); +} diff --git a/app/(auth)/sign-in.tsx b/app/(auth)/sign-in.tsx index c013bb3..29cf372 100644 --- a/app/(auth)/sign-in.tsx +++ b/app/(auth)/sign-in.tsx @@ -1,36 +1,31 @@ -// import { Text } from "@/components/ui/text"; -// import { VStack } from "@/components/ui/vstack"; -// import { Box } from "@/components/ui/box"; -// import { HStack } from "@/components/ui/hstack"; -// import React from "react"; -// 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"; +import SigninForm from "@/components/form/SigninForm"; +import Screen from "@/components/ui/Screen"; +import Text from "@/components/ui/Text"; +import { Link } from "expo-router"; +import { View } from "react-native"; -// export default function SigninPage() { -// return ( -// -// -// -// -// -// Inscris-toi gratuitement -// -// -// Génère un programme personnalisé en quelques clics et 1 minute ! -// -// -// -// -// Tu as déjà un compte ? -// -// Connectes-toi ! -// -// -// -// -// -// ); -// } +export default function SigninPage() { + return ( + + + + + Inscris-toi gratuitement + + + Génère un programme personnalisé en quelques clics et 1 minute ! + + + + + Tu as déjà un compte ?{" "} + + + Connectes-toi ! + + + + + + ); +} diff --git a/app/(tabs)/(profil)/ProfileScreen.tsx b/app/(tabs)/(profil)/ProfileScreen.tsx index 393f69f..67d5bab 100644 --- a/app/(tabs)/(profil)/ProfileScreen.tsx +++ b/app/(tabs)/(profil)/ProfileScreen.tsx @@ -1,13 +1,24 @@ -import {SafeAreaView, Text, View} from "react-native"; +import { SafeAreaView, Text, View } from "react-native"; import React from "react"; +import Button from "@/components/ui/Button"; +import { useSession } from "@/ctx"; +import { router } from "expo-router"; export default function ProfileScreen() { - return ( - - - Welcome Screen - We will do it soon - - - ); -} \ No newline at end of file + const { signOut } = useSession(); + + const disconnect = () => { + signOut(); + router.replace("/log-in"); + }; + + return ( + + + Welcome Screen + We will do it soon + + + + ); +} diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index eca8daf..e6ee3da 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,26 +1,25 @@ import { Redirect, Tabs } from "expo-router"; import { useSession } from "@/ctx"; -import { Text } from "react-native"; import React from "react"; -import {AntDesign, Ionicons, MaterialIcons} from "@expo/vector-icons"; +import { AntDesign, Ionicons, MaterialIcons } from "@expo/vector-icons"; +import Loading from "../loading"; export default function TabBarLayout() { const { session, isLoading } = useSession(); - const sizeIcon = 24; // You can keep the splash screen open, or render a loading screen like we do here. if (isLoading) { - return Loading...; + return ; } // Only require authentication within the (app) group's layout as users // need to be able to access the (auth) group and sign in again. - /*if (!session) { + if (!session) { // On web, static rendering will stop here as the user is not authenticated // in the headless Node process that the pages are rendered in. - return ; - }*/ + return ; + } return ( , + tabBarShowLabel: false, + tabBarIcon: () => ( + + ), }} /> - , - - }} + ( + + ), + }} + /> - , - - }} - /> - - , - - }} - /> - - , - - }} - /> - + ( + + ), + }} + /> + ( + + ), + }} + /> + ( + + ), + }} + /> ); } diff --git a/app/loading.tsx b/app/loading.tsx new file mode 100644 index 0000000..93f673d --- /dev/null +++ b/app/loading.tsx @@ -0,0 +1,12 @@ +import Text from "@/components/ui/Text"; +import { View } from "react-native"; + +export default function Loading() { + return ( + + + Chargement en cours + + + ); +} diff --git a/components/BackButton.tsx b/components/BackButton.tsx index df396be..05c40f8 100644 --- a/components/BackButton.tsx +++ b/components/BackButton.tsx @@ -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 { Button, ButtonActions } from "./ui/Button"; -import { Href, Link } from "expo-router"; +import React from "react"; +import { AntDesignIconNames } from "./Icons"; -type props = { - icon?: any; - link: Href; - action?: ButtonActions; -}; - -export default function BackButton({ icon, link, action }: props) { - return ( - - ); +interface Props extends TouchableOpacityProps { + icon?: AntDesignIconNames; } + +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { icon, onPress } = props; + const defaultOnPress = () => { + router.back(); + }; + + return ( + + ); + } +); diff --git a/components/Constants.tsx b/components/Constants.tsx new file mode 100644 index 0000000..22d2301 --- /dev/null +++ b/components/Constants.tsx @@ -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"; + } +} diff --git a/components/Errors.tsx b/components/Errors.tsx new file mode 100644 index 0000000..f0e9a38 --- /dev/null +++ b/components/Errors.tsx @@ -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"; diff --git a/components/Icons.tsx b/components/Icons.tsx new file mode 100644 index 0000000..c00ea36 --- /dev/null +++ b/components/Icons.tsx @@ -0,0 +1,3 @@ +import { AntDesign } from "@expo/vector-icons"; + +export type AntDesignIconNames = keyof typeof AntDesign.glyphMap; diff --git a/components/form/FormError.tsx b/components/form/FormError.tsx index f1b3058..c0c16af 100644 --- a/components/form/FormError.tsx +++ b/components/form/FormError.tsx @@ -1,19 +1,29 @@ -import { - FormControlError, - FormControlErrorIcon, - FormControlErrorText, -} from "../ui/form-control"; -import { AlertCircleIcon } from "../ui/icon"; +import React from "react"; +import { View } from "react-native"; +import Text, { ExtendedTextProps } from "../ui/Text"; +import { MaterialIcons } from "@expo/vector-icons"; -type props = { text: string }; - -export default function FormError({ text }: props) { - return ( - - - - {text} - - - ); +interface Props extends ExtendedTextProps { + isVisible: boolean; } + +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { isVisible, ...rest } = props; + + const buildClassName = (): string => { + return ( + "flex-row items-center gap-2 bg-red-300 p-4 border-2 border-red-500 rounded-3xl" + + " " + + (isVisible ? "block" : "hidden") + ); + }; + + return ( + + + + + ); + } +); diff --git a/components/form/FormInput.tsx b/components/form/FormInput.tsx new file mode 100644 index 0000000..340d082 --- /dev/null +++ b/components/form/FormInput.tsx @@ -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( + (props, ref): React.ReactElement => { + const { + onBlur, + onChangeText, + value, + beforeIcon, + afterIcon, + label, + placeholder, + onPress, + ...rest + } = props; + + return ( + + {label} + + + + {afterIcon != null ? ( + + ) : null} + + + ); + } +); diff --git a/components/form/LoginForm.tsx b/components/form/LoginForm.tsx index 0406cfb..b43e57d 100644 --- a/components/form/LoginForm.tsx +++ b/components/form/LoginForm.tsx @@ -1,75 +1,72 @@ -import React from "react"; -import { Text } from "react-native"; +import { View, ViewProps } from "react-native"; +import TextInput from "./FormInput"; import Button from "../ui/Button"; -export default function LoginForm() { - const REQUIRED_ERROR = "Au moins un des champs requis est vide !"; - const [emailValue, setEmailValue] = React.useState(""); - const [isEmailInvalid, setIsEmailInvalid] = React.useState(false); - const [passwordValue, setPasswordValue] = React.useState(""); - const [isPasswordInvalid, setIsPasswordInvalid] = React.useState(false); - const [isFormInvalid, setIsFormInvalid] = React.useState(false); - const handleSubmit = () => { - //check for empty fields - setIsEmailInvalid(emailValue == ""); - setIsPasswordInvalid(passwordValue == ""); - setIsFormInvalid(isEmailInvalid || isPasswordInvalid); - }; +import PasswordTextInput from "./SecretTextInput"; +import React from "react"; +import { EMPTY_FIELD, INVALID_EMAIL } from "../Errors"; +import FormError from "./FormError"; +import { isEmail } from "validator"; +import { useSession } from "@/ctx"; +import { router } from "expo-router"; + +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { ...rest } = props; + 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); + }; - return ( - - - - Adresse mail - - - - { + 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 ( + + + - - - - - Mot de passe - - - - - - - - - - - - Adresse mail - - - - - - - - - Mot de passe - - - - - - - - - - - - - ); -} + + ); + } +); diff --git a/components/modals/CodeSent.tsx b/components/modals/CodeSent.tsx new file mode 100644 index 0000000..2b1b768 --- /dev/null +++ b/components/modals/CodeSent.tsx @@ -0,0 +1,50 @@ +import BackButton from "@/components/BackButton"; +import Button from "@/components/ui/Button"; +import { AntDesign } from "@expo/vector-icons"; +import { GestureResponderEvent, Modal, ModalProps, View } from "react-native"; +import Text from "@/components/ui/Text"; +import React from "react"; +import Screen from "../ui/Screen"; + +interface Props extends ModalProps { + email: string; + onPress: (event: GestureResponderEvent) => void; +} + +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { email, onPress, ...rest } = props; + + return ( + + + + + + + Code envoyé ! + + + + Nous t'avons envoyé le code de vérification à + + + {email ?? "test@Optifit.com"} + + + Clique sur renvoyer si tu n'as pas reçu d’ici quelques secondes + ! 🔥 + + + + + + + ); + } +); diff --git a/components/ui/Button.tsx b/components/ui/Button.tsx index b753b7c..a489ef1 100644 --- a/components/ui/Button.tsx +++ b/components/ui/Button.tsx @@ -1,17 +1,106 @@ import React from "react"; -import { TouchableOpacity, View } from "react-native"; +import { TouchableOpacity, TouchableOpacityProps, View } from "react-native"; import CustomText from "./Text"; +import { AntDesign } from "@expo/vector-icons"; +import { AntDesignIconNames } from "../Icons"; +import { Size } from "../Constants"; -type props = { title: string; size: string }; +export type ButtonStyle = "default" | "outline" | "secondary"; -const Button = ({ title, size }: props) => ( - - - - {title} - - - -); +//@ts-ignore +interface Props extends TouchableOpacityProps { + size?: Size; + style?: ButtonStyle; + insideClassName?: string; + beforeIcon?: AntDesignIconNames; + afterIcon?: AntDesignIconNames; +} + +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { + size, + style, + beforeIcon, + afterIcon, + onPress, + className, + insideClassName, + children, + ...rest + } = props; + + const getButtonStyle = (): string => { + switch (style ?? "default") { + case "default": + return ( + "justify-center items-center bg-black text-white rounded-3xl" + + " " + + className + ); + case "outline": + return ( + "justify-center items-center border-black text-black border-2 rounded-3xl" + + " " + + className + ); + case "secondary": + return ( + "justify-center items-center bg-gray-200 text-black rounded-3xl" + + " " + + className + ); + } + }; -export default Button; + const getIconSize = (): number => { + switch (size ?? "lg") { + case "xs": + return 24; + case "md": + return 24; + case "lg": + return 24; + case "xl": + return 24; + case "2xl": + return 30; + case "3xl": + return 36; + } + }; + + return ( + + + {beforeIcon != null ? ( + + ) : null} + + {children} + + {afterIcon != null ? ( + + ) : null} + + + ); + } +); diff --git a/components/ui/Screen.tsx b/components/ui/Screen.tsx index 1e52d82..92bd833 100644 --- a/components/ui/Screen.tsx +++ b/components/ui/Screen.tsx @@ -1,13 +1,14 @@ -import { PropsWithChildren } from "react"; -import { View } from "react-native"; +import { View, ViewProps } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; +import React from "react"; -type props = PropsWithChildren; - -export default function Screen({ children }: props) { - return ( - - {children} - - ); -} +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { children, ...rest } = props; + return ( + + {children} + + ); + } +); diff --git a/components/ui/Text.tsx b/components/ui/Text.tsx index 98516a2..f37b73b 100644 --- a/components/ui/Text.tsx +++ b/components/ui/Text.tsx @@ -1,27 +1,62 @@ -import { PropsWithChildren } from "react"; -import { Text } from "react-native"; +import React from "react"; +import { Text, TextProps } from "react-native"; +import { + Color, + Position, + Size, + toTextColor, + toTextPosition, + toTextSize, + toTextWeight, + Weight, +} from "../Constants"; -type props = PropsWithChildren & { - center?: boolean; - color?: string; - size?: string; - bold?: boolean; +export interface ExtendedTextProps extends TextProps { + position?: Position; + color?: Color; + size?: Size; + weight?: Weight; isLink?: boolean; -}; +} -const CustomText = ({ children, center, color, size, bold, isLink }: props) => { - const className = - "text-" + - (size ?? "md") + - " " + - (center ? "text-center" : "") + - " " + - ("text-" + (color ?? "black ")) + - " " + - (bold ? "font-bold" : "") + - " " + - (isLink ? "text-orange-500 underline" : ""); - return {children}; -}; +export default React.forwardRef( + (props, ref): React.ReactElement => { + const { + position, + color, + size, + weight, + isLink, + className, + children, + ...rest + } = props; -export default CustomText; + 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 + + " " + + textColor + + " " + + textWeight + + " " + + (isLink ? "text-orange-500 underline" : "") + + " " + + className + ); + }; + + return ( + + {children} + + ); + } +); diff --git a/package-lock.json b/package-lock.json index b73a6fe..7df089d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "nativewind": "^4.1.23", "react": "18.3.1", "react-dom": "18.3.1", + "react-hook-form": "^7.54.2", "react-native": "0.76.6", "react-native-gesture-handler": "^2.20.2", "react-native-gifted-charts": "^1.4.54", @@ -43,7 +44,8 @@ "react-native-vector-icons": "^10.2.0", "react-native-web": "^0.19.13", "react-native-webview": "13.12.5", - "tailwindcss": "^3.4.17" + "tailwindcss": "^3.4.17", + "validator": "^13.12.0" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -12095,6 +12097,22 @@ "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-hook-form": { + "version": "7.54.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", + "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -14732,6 +14750,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 5ca6bb1..c090dc4 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "nativewind": "^4.1.23", "react": "18.3.1", "react-dom": "18.3.1", + "react-hook-form": "^7.54.2", "react-native": "0.76.6", "react-native-gesture-handler": "^2.20.2", "react-native-gifted-charts": "^1.4.54", @@ -50,7 +51,8 @@ "react-native-vector-icons": "^10.2.0", "react-native-web": "^0.19.13", "react-native-webview": "13.12.5", - "tailwindcss": "^3.4.17" + "tailwindcss": "^3.4.17", + "validator": "^13.12.0" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/ui/box/index.tsx b/ui/box/index.tsx deleted file mode 100644 index 5b8e8d1..0000000 --- a/ui/box/index.tsx +++ /dev/null @@ -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 & { className?: string }; - -const Box = React.forwardRef, IBoxProps>( - ({ className, ...props }, ref) => { - return ( - - ); - } -); - -Box.displayName = "Box"; -export { Box }; diff --git a/ui/box/index.web.tsx b/ui/box/index.web.tsx deleted file mode 100644 index 51b375b..0000000 --- a/ui/box/index.web.tsx +++ /dev/null @@ -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 & { className?: string }; - -const Box = React.forwardRef( - ({ className, ...props }, ref) => { - return ( -
- ); - } -); - -Box.displayName = 'Box'; -export { Box }; diff --git a/ui/box/styles.tsx b/ui/box/styles.tsx deleted file mode 100644 index 760e8ff..0000000 --- a/ui/box/styles.tsx +++ /dev/null @@ -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, -}); diff --git a/ui/button/index.tsx b/ui/button/index.tsx deleted file mode 100644 index b95345e..0000000 --- a/ui/button/index.tsx +++ /dev/null @@ -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, - "context" -> & - VariantProps & { className?: string }; - -const Button = React.forwardRef< - React.ElementRef, - IButtonProps ->( - ( - { className, variant = "solid", size = "md", action = "primary", ...props }, - ref - ) => { - return ( - - ); - } -); - -type IButtonTextProps = React.ComponentPropsWithoutRef & - VariantProps & { className?: string }; - -const ButtonText = React.forwardRef< - React.ElementRef, - IButtonTextProps ->(({ className, variant, size, action, ...props }, ref) => { - const { - variant: parentVariant, - size: parentSize, - action: parentAction, - } = useStyleContext(SCOPE); - - return ( - - ); -}); - -const ButtonSpinner = UIButton.Spinner; - -type IButtonIcon = React.ComponentPropsWithoutRef & - VariantProps & { - className?: string | undefined; - as?: React.ElementType; - height?: number; - width?: number; - }; - -const ButtonIcon = React.forwardRef< - React.ElementRef, - IButtonIcon ->(({ className, size, ...props }, ref) => { - const { - variant: parentVariant, - size: parentSize, - action: parentAction, - } = useStyleContext(SCOPE); - - if (typeof size === "number") { - return ( - - ); - } else if ( - (props.height !== undefined || props.width !== undefined) && - size === undefined - ) { - return ( - - ); - } - return ( - - ); -}); - -type IButtonGroupProps = React.ComponentPropsWithoutRef & - VariantProps; - -const ButtonGroup = React.forwardRef< - React.ElementRef, - IButtonGroupProps ->( - ( - { - className, - space = "md", - isAttached = false, - flexDirection = "column", - ...props - }, - ref - ) => { - return ( - - ); - } -); - -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; diff --git a/ui/card/index.tsx b/ui/card/index.tsx deleted file mode 100644 index f8c068d..0000000 --- a/ui/card/index.tsx +++ /dev/null @@ -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 & { className?: string }; - -const Card = React.forwardRef, ICardProps>( - ({ className, size = 'md', variant = 'elevated', ...props }, ref) => { - return ( - - ); - } -); - -Card.displayName = 'Card'; - -export { Card }; diff --git a/ui/card/index.web.tsx b/ui/card/index.web.tsx deleted file mode 100644 index f521d08..0000000 --- a/ui/card/index.web.tsx +++ /dev/null @@ -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; - -const Card = React.forwardRef( - ({ className, size = 'md', variant = 'elevated', ...props }, ref) => { - return ( -
- ); - } -); - -Card.displayName = 'Card'; - -export { Card }; diff --git a/ui/card/styles.tsx b/ui/card/styles.tsx deleted file mode 100644 index 59de8b7..0000000 --- a/ui/card/styles.tsx +++ /dev/null @@ -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', - }, - }, -}); diff --git a/ui/form-control/index.tsx b/ui/form-control/index.tsx deleted file mode 100644 index b982f4c..0000000 --- a/ui/form-control/index.tsx +++ /dev/null @@ -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; - -const FormControlLabelAstrick = React.forwardRef< - React.ElementRef, - IFormControlLabelAstrickProps ->(({ className, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - - return ( - - ); -}); - -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 & - VariantProps; - -const FormControl = React.forwardRef< - React.ElementRef, - IFormControlProps ->(({ className, size = 'md', ...props }, ref) => { - return ( - - ); -}); - -type IFormControlErrorProps = React.ComponentProps & - VariantProps; - -const FormControlError = React.forwardRef< - React.ElementRef, - IFormControlErrorProps ->(({ className, ...props }, ref) => { - return ( - - ); -}); - -type IFormControlErrorTextProps = React.ComponentProps< - typeof UIFormControl.Error.Text -> & - VariantProps; - -const FormControlErrorText = React.forwardRef< - React.ElementRef, - IFormControlErrorTextProps ->(({ className, size, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - return ( - - ); -}); - -type IFormControlErrorIconProps = React.ComponentProps< - typeof UIFormControl.Error.Icon -> & - VariantProps & { - height?: number; - width?: number; - }; - -const FormControlErrorIcon = React.forwardRef< - React.ElementRef, - IFormControlErrorIconProps ->(({ className, size, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - - if (typeof size === 'number') { - return ( - - ); - } else if ( - (props.height !== undefined || props.width !== undefined) && - size === undefined - ) { - return ( - - ); - } - return ( - - ); -}); - -type IFormControlLabelProps = React.ComponentProps & - VariantProps; - -const FormControlLabel = React.forwardRef< - React.ElementRef, - IFormControlLabelProps ->(({ className, ...props }, ref) => { - return ( - - ); -}); - -type IFormControlLabelTextProps = React.ComponentProps< - typeof UIFormControl.Label.Text -> & - VariantProps; - -const FormControlLabelText = React.forwardRef< - React.ElementRef, - IFormControlLabelTextProps ->(({ className, size, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - - return ( - - ); -}); - -type IFormControlHelperProps = React.ComponentProps< - typeof UIFormControl.Helper -> & - VariantProps; - -const FormControlHelper = React.forwardRef< - React.ElementRef, - IFormControlHelperProps ->(({ className, ...props }, ref) => { - return ( - - ); -}); - -type IFormControlHelperTextProps = React.ComponentProps< - typeof UIFormControl.Helper.Text -> & - VariantProps; - -const FormControlHelperText = React.forwardRef< - React.ElementRef, - IFormControlHelperTextProps ->(({ className, size, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - - return ( - - ); -}); - -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, -}; diff --git a/ui/gluestack-ui-provider/config.ts b/ui/gluestack-ui-provider/config.ts deleted file mode 100644 index 32842d9..0000000 --- a/ui/gluestack-ui-provider/config.ts +++ /dev/null @@ -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", - }), -}; diff --git a/ui/gluestack-ui-provider/index.tsx b/ui/gluestack-ui-provider/index.tsx deleted file mode 100644 index 737991a..0000000 --- a/ui/gluestack-ui-provider/index.tsx +++ /dev/null @@ -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 ( - - - {props.children} - - - ); -} diff --git a/ui/heading/index.tsx b/ui/heading/index.tsx deleted file mode 100644 index be876d4..0000000 --- a/ui/heading/index.tsx +++ /dev/null @@ -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 & - React.ComponentPropsWithoutRef & { - 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, IHeadingProps>( - ( - { - size, - className, - isTruncated, - bold, - underline, - strikeThrough, - sub, - italic, - highlight, - ...props - }, - ref - ) => { - switch (size) { - case '5xl': - case '4xl': - case '3xl': - return ( -

- ); - case '2xl': - return ( -

- ); - case 'xl': - return ( -

- ); - case 'lg': - return ( -

- ); - case 'md': - return ( -

- ); - case 'sm': - case 'xs': - return ( -
- ); - default: - return ( -

- ); - } - } - ) -); - -const Heading = memo( - forwardRef, IHeadingProps>( - ({ className, size = 'lg', as: AsComp, ...props }, ref) => { - const { - isTruncated, - bold, - underline, - strikeThrough, - sub, - italic, - highlight, - } = props; - - if (AsComp) { - return ( - - ); - } - - return ( - - ); - } - ) -); - -Heading.displayName = 'Heading'; - -export { Heading }; diff --git a/ui/heading/index.web.tsx b/ui/heading/index.web.tsx deleted file mode 100644 index 2806c70..0000000 --- a/ui/heading/index.web.tsx +++ /dev/null @@ -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 & - React.ComponentPropsWithoutRef<'h1'> & { - as?: React.ElementType; - }; - -const MappedHeading = memo( - forwardRef( - ( - { - size, - className, - isTruncated, - bold, - underline, - strikeThrough, - sub, - italic, - highlight, - ...props - }, - ref - ) => { - switch (size) { - case '5xl': - case '4xl': - case '3xl': - return ( -

- ); - case '2xl': - return ( -

- ); - case 'xl': - return ( -

- ); - case 'lg': - return ( -

- ); - case 'md': - return ( -

- ); - case 'sm': - case 'xs': - return ( -
- ); - default: - return ( -

- ); - } - } - ) -); - -const Heading = memo( - forwardRef( - ({ className, size = 'lg', as: AsComp, ...props }, ref) => { - const { - isTruncated, - bold, - underline, - strikeThrough, - sub, - italic, - highlight, - } = props; - - if (AsComp) { - return ( - - ); - } - - return ( - - ); - } - ) -); - -Heading.displayName = 'Heading'; - -export { Heading }; diff --git a/ui/heading/styles.tsx b/ui/heading/styles.tsx deleted file mode 100644 index e695159..0000000 --- a/ui/heading/styles.tsx +++ /dev/null @@ -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", - }, - }, -}); diff --git a/ui/hstack/index.tsx b/ui/hstack/index.tsx deleted file mode 100644 index 5c4a81e..0000000 --- a/ui/hstack/index.tsx +++ /dev/null @@ -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; - -const HStack = React.forwardRef, IHStackProps>( - ({ className, space, reversed, ...props }, ref) => { - return ( - - ); - } -); - -HStack.displayName = 'HStack'; - -export { HStack }; diff --git a/ui/hstack/index.web.tsx b/ui/hstack/index.web.tsx deleted file mode 100644 index 7d1c50f..0000000 --- a/ui/hstack/index.web.tsx +++ /dev/null @@ -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; - -const HStack = React.forwardRef, IHStackProps>( - ({ className, space, reversed, ...props }, ref) => { - return ( -
- ); - } -); - -HStack.displayName = 'HStack'; - -export { HStack }; diff --git a/ui/hstack/styles.tsx b/ui/hstack/styles.tsx deleted file mode 100644 index 646241f..0000000 --- a/ui/hstack/styles.tsx +++ /dev/null @@ -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", - }, - }, -}); diff --git a/ui/input/index.tsx b/ui/input/index.tsx deleted file mode 100644 index ed6ee27..0000000 --- a/ui/input/index.tsx +++ /dev/null @@ -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 & - VariantProps & { className?: string }; -const Input = React.forwardRef, IInputProps>( - ({ className, variant = "outline", size = "md", ...props }, ref) => { - return ( - - ); - } -); - -type IInputIconProps = React.ComponentProps & - VariantProps & { - className?: string; - height?: number; - width?: number; - }; - -const InputIcon = React.forwardRef< - React.ElementRef, - IInputIconProps ->(({ className, size, ...props }, ref) => { - const { size: parentSize } = useStyleContext(SCOPE); - - if (typeof size === "number") { - return ( - - ); - } else if ( - (props.height !== undefined || props.width !== undefined) && - size === undefined - ) { - return ( - - ); - } - return ( - - ); -}); - -type IInputSlotProps = React.ComponentProps & - VariantProps & { className?: string }; - -const InputSlot = React.forwardRef< - React.ElementRef, - IInputSlotProps ->(({ className, ...props }, ref) => { - return ( - - ); -}); - -type IInputFieldProps = React.ComponentProps & - VariantProps & { className?: string }; - -const InputField = React.forwardRef< - React.ElementRef, - IInputFieldProps ->(({ className, ...props }, ref) => { - const { variant: parentVariant, size: parentSize } = useStyleContext(SCOPE); - - return ( - - ); -}); - -Input.displayName = "Input"; -InputIcon.displayName = "InputIcon"; -InputSlot.displayName = "InputSlot"; -InputField.displayName = "InputField"; - -export { Input, InputField, InputIcon, InputSlot }; diff --git a/ui/link/index.tsx b/ui/link/index.tsx deleted file mode 100644 index 635b23c..0000000 --- a/ui/link/index.tsx +++ /dev/null @@ -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 & - VariantProps & { className?: string }; - -const Link = React.forwardRef, ILinkProps>( - ({ className, ...props }, ref) => { - return ( - - ); - } -); - -type ILinkTextProps = React.ComponentProps & - VariantProps & { className?: string }; - -const LinkText = React.forwardRef< - React.ElementRef, - ILinkTextProps ->(({ className, size = "md", ...props }, ref) => { - return ( - - ); -}); - -Link.displayName = "Link"; -LinkText.displayName = "LinkText"; - -export { Link, LinkText }; diff --git a/ui/text/index.tsx b/ui/text/index.tsx deleted file mode 100644 index c662b72..0000000 --- a/ui/text/index.tsx +++ /dev/null @@ -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 & - VariantProps; - -const Text = React.forwardRef, ITextProps>( - ( - { - className, - isTruncated, - bold, - underline, - strikeThrough, - size = 'md', - sub, - italic, - highlight, - ...props - }, - ref - ) => { - return ( - - ); - } -); - -Text.displayName = 'Text'; - -export { Text }; diff --git a/ui/text/index.web.tsx b/ui/text/index.web.tsx deleted file mode 100644 index 4abb61c..0000000 --- a/ui/text/index.web.tsx +++ /dev/null @@ -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; - -const Text = React.forwardRef, ITextProps>( - ( - { - className, - isTruncated, - bold, - underline, - strikeThrough, - size = 'md', - sub, - italic, - highlight, - ...props - }: { className?: string } & ITextProps, - ref - ) => { - return ( - - ); - } -); - -Text.displayName = 'Text'; - -export { Text }; diff --git a/ui/text/styles.tsx b/ui/text/styles.tsx deleted file mode 100644 index a8f12f7..0000000 --- a/ui/text/styles.tsx +++ /dev/null @@ -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", - }, - }, -}); diff --git a/ui/vstack/index.tsx b/ui/vstack/index.tsx deleted file mode 100644 index 343b97a..0000000 --- a/ui/vstack/index.tsx +++ /dev/null @@ -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 & - VariantProps; - -const VStack = React.forwardRef, IVStackProps>( - ({ className, space, reversed, ...props }, ref) => { - return ( - - ); - } -); - -VStack.displayName = 'VStack'; - -export { VStack }; diff --git a/ui/vstack/index.web.tsx b/ui/vstack/index.web.tsx deleted file mode 100644 index 2f76b46..0000000 --- a/ui/vstack/index.web.tsx +++ /dev/null @@ -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; - -const VStack = React.forwardRef, IVStackProps>( - ({ className, space, reversed, ...props }, ref) => { - return ( -
- ); - } -); - -VStack.displayName = 'VStack'; - -export { VStack }; diff --git a/ui/vstack/styles.tsx b/ui/vstack/styles.tsx deleted file mode 100644 index abc5dbe..0000000 --- a/ui/vstack/styles.tsx +++ /dev/null @@ -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', - }, - }, -});