diff --git a/apps/web/package.json b/apps/web/package.json index b886bb5..deb31b6 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,14 +14,15 @@ "with-env": "dotenv -e ../../.env --" }, "dependencies": { - "@tanya.in/ui": "*", "@t3-oss/env-nextjs": "^0.10.0", "@tanstack/react-query": "^5.32.0", + "@tanya.in/ui": "*", "geist": "^1.3.0", "next": "^14.2.0", "next-auth": "beta", "react": "18.3.1", "react-dom": "18.3.1", + "react-icons": "^5.2.0", "superjson": "2.2.1", "zod": "^3.23.0" }, diff --git a/apps/web/src/components/signin-form.tsx b/apps/web/src/components/signin-form.tsx index 529d1e7..33843d1 100644 --- a/apps/web/src/components/signin-form.tsx +++ b/apps/web/src/components/signin-form.tsx @@ -1,6 +1,9 @@ "use client"; +import * as React from "react"; import Link from "next/link"; +import { signInFormSchema } from "@/lib/validation/sign-in"; +import { FaEye, FaEyeSlash } from "react-icons/fa"; import { Button } from "@tanya.in/ui/button"; import { @@ -10,10 +13,17 @@ import { CardHeader, CardTitle, } from "@tanya.in/ui/card"; -import { Input } from "@tanya.in/ui/input"; -import { Label } from "@tanya.in/ui/label"; +import { Form, FormInput, useForm } from "@tanya.in/ui/form"; export function SigninForm() { + const [isVisible, setIsVisible] = React.useState(false); + + const methods = useForm({ + schema: signInFormSchema, + mode: "onTouched", + }); + const { handleSubmit, control } = methods; + return ( @@ -23,32 +33,41 @@ export function SigninForm() { -
-
- - +
{ + console.log(data); + })} + > + + setIsVisible(!isVisible)} + > + {isVisible ? ( + + ) : ( + + )} + + } + type={isVisible ? "text" : "password"} /> -
-
-
- - - Forgot your password? - -
- -
- - -
+ + + + +
Don't have an account?{" "} diff --git a/apps/web/src/lib/validation/sign-in.ts b/apps/web/src/lib/validation/sign-in.ts new file mode 100644 index 0000000..1066bd7 --- /dev/null +++ b/apps/web/src/lib/validation/sign-in.ts @@ -0,0 +1,6 @@ +import { z } from "zod"; + +export const signInFormSchema = z.object({ + email: z.string().email(), + password: z.string().min(8), +}); diff --git a/bun.lockb b/bun.lockb index 1622bd8..de0d848 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/ui/package.json b/packages/ui/package.json index bdaa6fb..387d438 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -22,12 +22,11 @@ "@hookform/resolvers": "^3.3.4", "@nextui-org/button": "^2.0.31", "@nextui-org/dropdown": "^2.1.23", + "@nextui-org/input": "^2.1.21", "@nextui-org/system": "^2.1.2", "@nextui-org/theme": "^2.2.3", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-slot": "^1.0.2", "class-variance-authority": "^0.7.0", "framer-motion": "^11.1.7", "next-themes": "^0.3.0", diff --git a/packages/ui/src/form.tsx b/packages/ui/src/form.tsx index a3f3362..21f0ab3 100644 --- a/packages/ui/src/form.tsx +++ b/packages/ui/src/form.tsx @@ -1,27 +1,21 @@ "use client"; -import type * as LabelPrimitive from "@radix-ui/react-label"; import type { - ControllerProps, FieldPath, FieldValues, + UseControllerProps, UseFormProps, } from "react-hook-form"; import type { ZodType, ZodTypeDef } from "zod"; import * as React from "react"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Slot } from "@radix-ui/react-slot"; +import { Input, InputProps } from "@nextui-org/input"; import { useForm as __useForm, - Controller, FormProvider, - useFormContext, + useController, } from "react-hook-form"; -import { cn } from "@tanya.in/ui"; - -import { Label } from "./label"; - const useForm = ( props: Omit, "resolver"> & { schema: ZodType; @@ -37,165 +31,31 @@ const useForm = ( const Form = FormProvider; -interface FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, -> { - name: TName; -} - -const FormFieldContext = React.createContext( - null, -); - -const FormField = < +const FormInput = < TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, >({ ...props -}: ControllerProps) => { - return ( - - - - ); -}; - -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext); - const itemContext = React.useContext(FormItemContext); - const { getFieldState, formState } = useFormContext(); - - if (!fieldContext) { - throw new Error("useFormField should be used within "); - } - const fieldState = getFieldState(fieldContext.name, formState); - - const { id } = itemContext; - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - }; -}; - -interface FormItemContextValue { - id: string; -} - -const FormItemContext = React.createContext( - {} as FormItemContextValue, -); - -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId(); - - return ( - -
- - ); -}); -FormItem.displayName = "FormItem"; - -const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField(); - - return ( -