diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 4093190..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/components/ui/* \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 36c6836..9cd31c5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,34 +1,48 @@ module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - ], - overrides: [ - { - env: { - node: true, - }, - files: [".eslintrc.{js,cjs}"], - parserOptions: { - sourceType: "script", - }, + "env": { + "browser": true, + "es2021": true }, - ], - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - }, - plugins: ["@typescript-eslint", "react"], - rules: { - indent: ["error", 2], - "linebreak-style": ["error", "unix"], - quotes: ["error", "double"], - semi: ["error", "always"], - }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended" + ], + "overrides": [ + { + "env": { + "node": true + }, + "files": [ + ".eslintrc.{js,cjs}" + ], + "parserOptions": { + "sourceType": "script" + } + } + ], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "react" + ], + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ] + } }; diff --git a/components.json b/components.json index ae46c56..3a68836 100644 --- a/components.json +++ b/components.json @@ -2,7 +2,7 @@ "$schema": "https://ui.shadcn.com/schema.json", "style": "default", "rsc": false, - "tsx": true, + "tsx": false, "tailwind": { "config": "tailwind.config.js", "css": "src/App.css", @@ -14,4 +14,4 @@ "components": "@/components", "utils": "@/utils/utils" } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 3c2b162..cfe5936 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", "@types/node": "^18.0.6", + "@types/react": "^18.2.48", "@vitejs/plugin-react": "^4.2.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", @@ -40,6 +41,8 @@ "typescript": "^5.3.3", "unplugin-inject-preload": "^2.0.0", "vite": "^5.0.12", + "vite-plugin-build-metadata": "^0.4.0", + "vite-plugin-open-graph": "^2.0.4", "vite-plugin-plain-text": "^1.4.2" }, "devDependencies": { @@ -2610,6 +2613,26 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==" }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + }, + "node_modules/@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -3967,6 +3990,11 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -8345,6 +8373,25 @@ "vite": "^2.7.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, + "node_modules/vite-plugin-build-metadata": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/vite-plugin-build-metadata/-/vite-plugin-build-metadata-0.4.0.tgz", + "integrity": "sha512-TtxSkbSuhMcoV09o9Vlv2+2JB39iQ9rDNho4AUVE9XiihCX9wmRHAlWYigCfYSWXbLkHBdNbKuhK1W3h0FkU3w==", + "funding": { + "url": "https://github.com/sponsors/daniil4udo" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/vite-plugin-open-graph": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vite-plugin-open-graph/-/vite-plugin-open-graph-2.0.4.tgz", + "integrity": "sha512-IrJ4DWkb3iVtiOO2v3xIkmvQvdZHuhh0S1hD+Dr9GcMJ4mdbtRDhp66rou061k32B9uckGJW0jjY8RYzzbB9Lg==", + "engines": { + "node": ">=16" + } + }, "node_modules/vite-plugin-plain-text": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/vite-plugin-plain-text/-/vite-plugin-plain-text-1.4.2.tgz", @@ -10134,6 +10181,26 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.6.tgz", "integrity": "sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==" }, + "@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + }, + "@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, "@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -11015,6 +11082,11 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -13982,6 +14054,17 @@ "dev": true, "requires": {} }, + "vite-plugin-build-metadata": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/vite-plugin-build-metadata/-/vite-plugin-build-metadata-0.4.0.tgz", + "integrity": "sha512-TtxSkbSuhMcoV09o9Vlv2+2JB39iQ9rDNho4AUVE9XiihCX9wmRHAlWYigCfYSWXbLkHBdNbKuhK1W3h0FkU3w==", + "requires": {} + }, + "vite-plugin-open-graph": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vite-plugin-open-graph/-/vite-plugin-open-graph-2.0.4.tgz", + "integrity": "sha512-IrJ4DWkb3iVtiOO2v3xIkmvQvdZHuhh0S1hD+Dr9GcMJ4mdbtRDhp66rou061k32B9uckGJW0jjY8RYzzbB9Lg==" + }, "vite-plugin-plain-text": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/vite-plugin-plain-text/-/vite-plugin-plain-text-1.4.2.tgz", diff --git a/package.json b/package.json index 5b4c530..13b5d4c 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", "@types/node": "^18.0.6", + "@types/react": "^18.2.48", "@vitejs/plugin-react": "^4.2.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", @@ -45,6 +46,8 @@ "typescript": "^5.3.3", "unplugin-inject-preload": "^2.0.0", "vite": "^5.0.12", + "vite-plugin-build-metadata": "^0.4.0", + "vite-plugin-open-graph": "^2.0.4", "vite-plugin-plain-text": "^1.4.2" }, "devDependencies": { diff --git a/src/components/ui/alert.jsx b/src/components/ui/alert.jsx new file mode 100644 index 0000000..2790744 --- /dev/null +++ b/src/components/ui/alert.jsx @@ -0,0 +1,47 @@ +import * as React from "react" +import { cva } from "class-variance-authority"; + +import { cn } from "@/utils/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx deleted file mode 100644 index 54b5153..0000000 --- a/src/components/ui/alert.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/utils/utils"; - -const alertVariants = cva( - "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", - { - variants: { - variant: { - default: "bg-background text-foreground", - destructive: - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", - }, - }, - defaultVariants: { - variant: "default", - }, - } -); - -const Alert = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & VariantProps ->(({ className, variant, ...props }, ref) => ( -
-)); -Alert.displayName = "Alert"; - -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -AlertTitle.displayName = "AlertTitle"; - -const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -AlertDescription.displayName = "AlertDescription"; - -export { Alert, AlertTitle, AlertDescription }; diff --git a/src/components/ui/avatar.jsx b/src/components/ui/avatar.jsx new file mode 100644 index 0000000..4e6d699 --- /dev/null +++ b/src/components/ui/avatar.jsx @@ -0,0 +1,33 @@ +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/utils/utils" + +const Avatar = React.forwardRef(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx deleted file mode 100644 index 0d09e5f..0000000 --- a/src/components/ui/avatar.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import * as React from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; - -import { cn } from "@/utils/utils"; - -const Avatar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -Avatar.displayName = AvatarPrimitive.Root.displayName; - -const AvatarImage = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AvatarImage.displayName = AvatarPrimitive.Image.displayName; - -const AvatarFallback = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; - -export { Avatar, AvatarImage, AvatarFallback }; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.jsx similarity index 60% rename from src/components/ui/button.tsx rename to src/components/ui/button.jsx index b486c54..060a069 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.jsx @@ -1,8 +1,8 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva } from "class-variance-authority"; -import { cn } from "@/utils/utils"; +import { cn } from "@/utils/utils" const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", @@ -31,26 +31,17 @@ const buttonVariants = cva( size: "default", }, } -); +) -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean -} +const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + () + ); +}) +Button.displayName = "Button" -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - return ( - - ); - } -); -Button.displayName = "Button"; - -export { Button, buttonVariants }; +export { Button, buttonVariants } diff --git a/src/components/ui/card.jsx b/src/components/ui/card.jsx new file mode 100644 index 0000000..56bc2ff --- /dev/null +++ b/src/components/ui/card.jsx @@ -0,0 +1,50 @@ +import * as React from "react" + +import { cn } from "@/utils/utils" + +const Card = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx deleted file mode 100644 index 646b2b1..0000000 --- a/src/components/ui/card.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import * as React from "react"; - -import { cn } from "@/utils/utils"; - -const Card = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -Card.displayName = "Card"; - -const CardHeader = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -CardHeader.displayName = "CardHeader"; - -const CardTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardTitle.displayName = "CardTitle"; - -const CardDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardDescription.displayName = "CardDescription"; - -const CardContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardContent.displayName = "CardContent"; - -const CardFooter = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -CardFooter.displayName = "CardFooter"; - -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/src/components/ui/hover-card.tsx b/src/components/ui/hover-card.jsx similarity index 58% rename from src/components/ui/hover-card.tsx rename to src/components/ui/hover-card.jsx index 1916cda..3b7a4b8 100644 --- a/src/components/ui/hover-card.tsx +++ b/src/components/ui/hover-card.jsx @@ -1,16 +1,13 @@ -import * as React from "react"; -import * as HoverCardPrimitive from "@radix-ui/react-hover-card"; +import * as React from "react" +import * as HoverCardPrimitive from "@radix-ui/react-hover-card" -import { cn } from "@/utils/utils"; +import { cn } from "@/utils/utils" -const HoverCard = HoverCardPrimitive.Root; +const HoverCard = HoverCardPrimitive.Root -const HoverCardTrigger = HoverCardPrimitive.Trigger; +const HoverCardTrigger = HoverCardPrimitive.Trigger -const HoverCardContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( +const HoverCardContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( -)); -HoverCardContent.displayName = HoverCardPrimitive.Content.displayName; + {...props} /> +)) +HoverCardContent.displayName = HoverCardPrimitive.Content.displayName -export { HoverCard, HoverCardTrigger, HoverCardContent }; +export { HoverCard, HoverCardTrigger, HoverCardContent } diff --git a/src/components/ui/input.jsx b/src/components/ui/input.jsx new file mode 100644 index 0000000..1adbcc2 --- /dev/null +++ b/src/components/ui/input.jsx @@ -0,0 +1,19 @@ +import * as React from "react" + +import { cn } from "@/utils/utils" + +const Input = React.forwardRef(({ className, type, ...props }, ref) => { + return ( + () + ); +}) +Input.displayName = "Input" + +export { Input } diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx deleted file mode 100644 index 0f884e2..0000000 --- a/src/components/ui/input.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from "react"; - -import { cn } from "@/utils/utils"; - -export interface InputProps - extends React.InputHTMLAttributes {} - -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ); - } -); -Input.displayName = "Input"; - -export { Input }; diff --git a/src/components/ui/label.jsx b/src/components/ui/label.jsx new file mode 100644 index 0000000..f1fc1f3 --- /dev/null +++ b/src/components/ui/label.jsx @@ -0,0 +1,16 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva } from "class-variance-authority"; + +import { cn } from "@/utils/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx deleted file mode 100644 index 7058235..0000000 --- a/src/components/ui/label.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react"; -import * as LabelPrimitive from "@radix-ui/react-label"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/utils/utils"; - -const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -); - -const Label = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, ...props }, ref) => ( - -)); -Label.displayName = LabelPrimitive.Root.displayName; - -export { Label }; diff --git a/src/components/ui/navigation-menu.tsx b/src/components/ui/navigation-menu.jsx similarity index 59% rename from src/components/ui/navigation-menu.tsx rename to src/components/ui/navigation-menu.jsx index 3ae5bc4..c234f5a 100644 --- a/src/components/ui/navigation-menu.tsx +++ b/src/components/ui/navigation-menu.jsx @@ -1,88 +1,68 @@ -import * as React from "react"; -import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"; -import { cva } from "class-variance-authority"; -import { ChevronDown } from "lucide-react"; +import * as React from "react" +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" +import { cva } from "class-variance-authority" +import { ChevronDown } from "lucide-react" -import { cn } from "@/utils/utils"; +import { cn } from "@/utils/utils" -const NavigationMenu = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( +const NavigationMenu = React.forwardRef(({ className, children, ...props }, ref) => ( + {...props}> {children} -)); -NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; +)) +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName -const NavigationMenuList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const NavigationMenuList = React.forwardRef(({ className, ...props }, ref) => ( -)); -NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName; + {...props} /> +)) +NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName -const NavigationMenuItem = NavigationMenuPrimitive.Item; +const NavigationMenuItem = NavigationMenuPrimitive.Item const navigationMenuTriggerStyle = cva( "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" -); +) -const NavigationMenuTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( +const NavigationMenuTrigger = React.forwardRef(({ className, children, ...props }, ref) => ( + {...props}> {children}{" "} -)); -NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; +)) +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName -const NavigationMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const NavigationMenuContent = React.forwardRef(({ className, ...props }, ref) => ( -)); -NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName; + {...props} /> +)) +NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName -const NavigationMenuLink = NavigationMenuPrimitive.Link; +const NavigationMenuLink = NavigationMenuPrimitive.Link -const NavigationMenuViewport = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const NavigationMenuViewport = React.forwardRef(({ className, ...props }, ref) => (
+ {...props} />
-)); +)) NavigationMenuViewport.displayName = - NavigationMenuPrimitive.Viewport.displayName; + NavigationMenuPrimitive.Viewport.displayName -const NavigationMenuIndicator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const NavigationMenuIndicator = React.forwardRef(({ className, ...props }, ref) => ( -
+ {...props}> +
-)); +)) NavigationMenuIndicator.displayName = - NavigationMenuPrimitive.Indicator.displayName; + NavigationMenuPrimitive.Indicator.displayName export { navigationMenuTriggerStyle, @@ -125,4 +101,4 @@ export { NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, -}; +} diff --git a/src/components/ui/select.tsx b/src/components/ui/select.jsx similarity index 52% rename from src/components/ui/select.tsx rename to src/components/ui/select.jsx index a574ee8..40d8333 100644 --- a/src/components/ui/select.tsx +++ b/src/components/ui/select.jsx @@ -1,74 +1,53 @@ -import * as React from "react"; -import * as SelectPrimitive from "@radix-ui/react-select"; -import { Check, ChevronDown, ChevronUp } from "lucide-react"; +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" -import { cn } from "@/utils/utils"; +import { cn } from "@/utils/utils" -const Select = SelectPrimitive.Root; +const Select = SelectPrimitive.Root -const SelectGroup = SelectPrimitive.Group; +const SelectGroup = SelectPrimitive.Group -const SelectValue = SelectPrimitive.Value; +const SelectValue = SelectPrimitive.Value -const SelectTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( +const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => ( span]:line-clamp-1", className )} - {...props} - > + {...props}> {children} -)); -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName -const SelectScrollUpButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => ( + className={cn("flex cursor-default items-center justify-center py-1", className)} + {...props}> -)); -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName -const SelectScrollDownButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) => ( + className={cn("flex cursor-default items-center justify-center py-1", className)} + {...props}> -)); +)) SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName; + SelectPrimitive.ScrollDownButton.displayName -const SelectContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( +const SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => ( + {...props}> + className={cn("p-1", position === "popper" && + "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]")}> {children} -)); -SelectContent.displayName = SelectPrimitive.Content.displayName; +)) +SelectContent.displayName = SelectPrimitive.Content.displayName -const SelectLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const SelectLabel = React.forwardRef(({ className, ...props }, ref) => ( -)); -SelectLabel.displayName = SelectPrimitive.Label.displayName; + {...props} /> +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName -const SelectItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( +const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => ( + {...props}> @@ -129,20 +95,16 @@ const SelectItem = React.forwardRef< {children} -)); -SelectItem.displayName = SelectPrimitive.Item.displayName; +)) +SelectItem.displayName = SelectPrimitive.Item.displayName -const SelectSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => ( -)); -SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + {...props} /> +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName export { Select, @@ -155,4 +117,4 @@ export { SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, -}; +} diff --git a/src/components/ui/sheet.jsx b/src/components/ui/sheet.jsx new file mode 100644 index 0000000..6dd610c --- /dev/null +++ b/src/components/ui/sheet.jsx @@ -0,0 +1,108 @@ +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { cva } from "class-variance-authority"; +import { X } from "lucide-react" + +import { cn } from "@/utils/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const SheetClose = SheetPrimitive.Close + +const SheetPortal = SheetPrimitive.Portal + +const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", + { + variants: { + side: { + top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", + bottom: + "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", + left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", + right: + "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, + } +) + +const SheetContent = React.forwardRef(({ side = "right", className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetPortal, + SheetOverlay, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/src/components/ui/sheet.tsx b/src/components/ui/sheet.tsx deleted file mode 100644 index ff69ef1..0000000 --- a/src/components/ui/sheet.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import * as React from "react"; -import * as SheetPrimitive from "@radix-ui/react-dialog"; -import { cva, type VariantProps } from "class-variance-authority"; -import { X } from "lucide-react"; - -import { cn } from "@/utils/utils"; - -const Sheet = SheetPrimitive.Root; - -const SheetTrigger = SheetPrimitive.Trigger; - -const SheetClose = SheetPrimitive.Close; - -const SheetPortal = SheetPrimitive.Portal; - -const SheetOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; - -const sheetVariants = cva( - "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", - { - variants: { - side: { - top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", - bottom: - "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", - left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", - right: - "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", - }, - }, - defaultVariants: { - side: "right", - }, - } -); - -interface SheetContentProps - extends React.ComponentPropsWithoutRef, - VariantProps {} - -const SheetContent = React.forwardRef< - React.ElementRef, - SheetContentProps ->(({ side = "right", className, children, ...props }, ref) => ( - - - - {children} - - - Close - - - -)); -SheetContent.displayName = SheetPrimitive.Content.displayName; - -const SheetHeader = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-); -SheetHeader.displayName = "SheetHeader"; - -const SheetFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-); -SheetFooter.displayName = "SheetFooter"; - -const SheetTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetTitle.displayName = SheetPrimitive.Title.displayName; - -const SheetDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -SheetDescription.displayName = SheetPrimitive.Description.displayName; - -export { - Sheet, - SheetPortal, - SheetOverlay, - SheetTrigger, - SheetClose, - SheetContent, - SheetHeader, - SheetFooter, - SheetTitle, - SheetDescription, -}; diff --git a/src/components/ui/skeleton.jsx b/src/components/ui/skeleton.jsx new file mode 100644 index 0000000..f1b9a63 --- /dev/null +++ b/src/components/ui/skeleton.jsx @@ -0,0 +1,10 @@ +import { cn } from "@/utils/utils" + +function Skeleton({ + className, + ...props +}) { + return (
); +} + +export { Skeleton } diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx deleted file mode 100644 index e2ad531..0000000 --- a/src/components/ui/skeleton.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { cn } from "@/utils/utils"; - -function Skeleton({ - className, - ...props -}: React.HTMLAttributes) { - return ( -
- ); -} - -export { Skeleton }; diff --git a/src/components/ui/tabs.jsx b/src/components/ui/tabs.jsx new file mode 100644 index 0000000..7d0f55f --- /dev/null +++ b/src/components/ui/tabs.jsx @@ -0,0 +1,41 @@ +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/utils/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx deleted file mode 100644 index 91b60ef..0000000 --- a/src/components/ui/tabs.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from "react"; -import * as TabsPrimitive from "@radix-ui/react-tabs"; - -import { cn } from "@/utils/utils"; - -const Tabs = TabsPrimitive.Root; - -const TabsList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsList.displayName = TabsPrimitive.List.displayName; - -const TabsTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; - -const TabsContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -TabsContent.displayName = TabsPrimitive.Content.displayName; - -export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/src/components/ui/toast.tsx b/src/components/ui/toast.jsx similarity index 51% rename from src/components/ui/toast.tsx rename to src/components/ui/toast.jsx index 52e03af..c81d6a7 100644 --- a/src/components/ui/toast.tsx +++ b/src/components/ui/toast.jsx @@ -1,26 +1,22 @@ -import * as React from "react"; -import * as ToastPrimitives from "@radix-ui/react-toast"; -import { cva, type VariantProps } from "class-variance-authority"; -import { X } from "lucide-react"; +import * as React from "react" +import * as ToastPrimitives from "@radix-ui/react-toast" +import { cva } from "class-variance-authority"; +import { X } from "lucide-react" -import { cn } from "@/utils/utils"; +import { cn } from "@/utils/utils" -const ToastProvider = ToastPrimitives.Provider; +const ToastProvider = ToastPrimitives.Provider -const ToastViewport = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const ToastViewport = React.forwardRef(({ className, ...props }, ref) => ( -)); -ToastViewport.displayName = ToastPrimitives.Viewport.displayName; + {...props} /> +)) +ToastViewport.displayName = ToastPrimitives.Viewport.displayName const toastVariants = cva( "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", @@ -36,42 +32,30 @@ const toastVariants = cva( variant: "default", }, } -); +) -const Toast = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, variant, ...props }, ref) => { +const Toast = React.forwardRef(({ className, variant, ...props }, ref) => { return ( - + {...props} />) ); -}); -Toast.displayName = ToastPrimitives.Root.displayName; +}) +Toast.displayName = ToastPrimitives.Root.displayName -const ToastAction = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const ToastAction = React.forwardRef(({ className, ...props }, ref) => ( -)); -ToastAction.displayName = ToastPrimitives.Action.displayName; + {...props} /> +)) +ToastAction.displayName = ToastPrimitives.Action.displayName -const ToastClose = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( +const ToastClose = React.forwardRef(({ className, ...props }, ref) => ( + {...props}> -)); -ToastClose.displayName = ToastPrimitives.Close.displayName; +)) +ToastClose.displayName = ToastPrimitives.Close.displayName -const ToastTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -ToastTitle.displayName = ToastPrimitives.Title.displayName; - -const ToastDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -ToastDescription.displayName = ToastPrimitives.Description.displayName; - -type ToastProps = React.ComponentPropsWithoutRef +const ToastTitle = React.forwardRef(({ className, ...props }, ref) => ( + +)) +ToastTitle.displayName = ToastPrimitives.Title.displayName -type ToastActionElement = React.ReactElement +const ToastDescription = React.forwardRef(({ className, ...props }, ref) => ( + +)) +ToastDescription.displayName = ToastPrimitives.Description.displayName -export { - type ToastProps, - type ToastActionElement, - ToastProvider, - ToastViewport, - Toast, - ToastTitle, - ToastDescription, - ToastClose, - ToastAction, -}; +export { ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction }; diff --git a/src/components/ui/toaster.tsx b/src/components/ui/toaster.jsx similarity index 72% rename from src/components/ui/toaster.tsx rename to src/components/ui/toaster.jsx index 5ff5709..b7a9a25 100644 --- a/src/components/ui/toaster.tsx +++ b/src/components/ui/toaster.jsx @@ -5,17 +5,17 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@/components/ui/toast"; -import { useToast } from "@/components/ui/use-toast"; +} from "@/components/ui/toast" +import { useToast } from "@/components/ui/use-toast" export function Toaster() { - const { toasts } = useToast(); + const { toasts } = useToast() return ( - + ( {toasts.map(function ({ id, title, description, action, ...props }) { return ( - + (
{title && {title}} {description && ( @@ -24,10 +24,10 @@ export function Toaster() {
{action} -
+
) ); })} -
+
) ); } diff --git a/src/components/ui/use-toast.js b/src/components/ui/use-toast.js new file mode 100644 index 0000000..df6b786 --- /dev/null +++ b/src/components/ui/use-toast.js @@ -0,0 +1,154 @@ +// Inspired by react-hot-toast library +import * as React from "react" + +const TOAST_LIMIT = 1 +const TOAST_REMOVE_DELAY = 1000000 + +const actionTypes = { + ADD_TOAST: "ADD_TOAST", + UPDATE_TOAST: "UPDATE_TOAST", + DISMISS_TOAST: "DISMISS_TOAST", + REMOVE_TOAST: "REMOVE_TOAST" +} + +let count = 0 + +function genId() { + count = (count + 1) % Number.MAX_SAFE_INTEGER + return count.toString(); +} + +const toastTimeouts = new Map() + +const addToRemoveQueue = (toastId) => { + if (toastTimeouts.has(toastId)) { + return + } + + const timeout = setTimeout(() => { + toastTimeouts.delete(toastId) + dispatch({ + type: "REMOVE_TOAST", + toastId: toastId, + }) + }, TOAST_REMOVE_DELAY) + + toastTimeouts.set(toastId, timeout) +} + +export const reducer = (state, action) => { + switch (action.type) { + case "ADD_TOAST": + return { + ...state, + toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), + }; + + case "UPDATE_TOAST": + return { + ...state, + toasts: state.toasts.map((t) => + t.id === action.toast.id ? { ...t, ...action.toast } : t), + }; + + case "DISMISS_TOAST": { + const { toastId } = action + + // ! Side effects ! - This could be extracted into a dismissToast() action, + // but I'll keep it here for simplicity + if (toastId) { + addToRemoveQueue(toastId) + } else { + state.toasts.forEach((toast) => { + addToRemoveQueue(toast.id) + }) + } + + return { + ...state, + toasts: state.toasts.map((t) => + t.id === toastId || toastId === undefined + ? { + ...t, + open: false, + } + : t), + }; + } + case "REMOVE_TOAST": + if (action.toastId === undefined) { + return { + ...state, + toasts: [], + } + } + return { + ...state, + toasts: state.toasts.filter((t) => t.id !== action.toastId), + }; + } +} + +const listeners = [] + +let memoryState = { toasts: [] } + +function dispatch(action) { + memoryState = reducer(memoryState, action) + listeners.forEach((listener) => { + listener(memoryState) + }) +} + +function toast({ + ...props +}) { + const id = genId() + + const update = (props) => + dispatch({ + type: "UPDATE_TOAST", + toast: { ...props, id }, + }) + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) + + dispatch({ + type: "ADD_TOAST", + toast: { + ...props, + id, + open: true, + onOpenChange: (open) => { + if (!open) dismiss() + }, + }, + }) + + return { + id: id, + dismiss, + update, + } +} + +function useToast() { + const [state, setState] = React.useState(memoryState) + + React.useEffect(() => { + listeners.push(setState) + return () => { + const index = listeners.indexOf(setState) + if (index > -1) { + listeners.splice(index, 1) + } + }; + }, [state]) + + return { + ...state, + toast, + dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }), + }; +} + +export { useToast, toast } diff --git a/src/components/ui/use-toast.ts b/src/components/ui/use-toast.ts deleted file mode 100644 index 806fa0a..0000000 --- a/src/components/ui/use-toast.ts +++ /dev/null @@ -1,192 +0,0 @@ -// Inspired by react-hot-toast library -import * as React from "react"; - -import type { - ToastActionElement, - ToastProps, -} from "@/components/ui/toast"; - -const TOAST_LIMIT = 1; -const TOAST_REMOVE_DELAY = 1000000; - -type ToasterToast = ToastProps & { - id: string - title?: React.ReactNode - description?: React.ReactNode - action?: ToastActionElement -} - -const actionTypes = { - ADD_TOAST: "ADD_TOAST", - UPDATE_TOAST: "UPDATE_TOAST", - DISMISS_TOAST: "DISMISS_TOAST", - REMOVE_TOAST: "REMOVE_TOAST", -} as const; - -let count = 0; - -function genId() { - count = (count + 1) % Number.MAX_SAFE_INTEGER; - return count.toString(); -} - -type ActionType = typeof actionTypes - -type Action = - | { - type: ActionType["ADD_TOAST"] - toast: ToasterToast - } - | { - type: ActionType["UPDATE_TOAST"] - toast: Partial - } - | { - type: ActionType["DISMISS_TOAST"] - toastId?: ToasterToast["id"] - } - | { - type: ActionType["REMOVE_TOAST"] - toastId?: ToasterToast["id"] - } - -interface State { - toasts: ToasterToast[] -} - -const toastTimeouts = new Map>(); - -const addToRemoveQueue = (toastId: string) => { - if (toastTimeouts.has(toastId)) { - return; - } - - const timeout = setTimeout(() => { - toastTimeouts.delete(toastId); - dispatch({ - type: "REMOVE_TOAST", - toastId: toastId, - }); - }, TOAST_REMOVE_DELAY); - - toastTimeouts.set(toastId, timeout); -}; - -export const reducer = (state: State, action: Action): State => { - switch (action.type) { - case "ADD_TOAST": - return { - ...state, - toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), - }; - - case "UPDATE_TOAST": - return { - ...state, - toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t - ), - }; - - case "DISMISS_TOAST": { - const { toastId } = action; - - // ! Side effects ! - This could be extracted into a dismissToast() action, - // but I'll keep it here for simplicity - if (toastId) { - addToRemoveQueue(toastId); - } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id); - }); - } - - return { - ...state, - toasts: state.toasts.map((t) => - t.id === toastId || toastId === undefined - ? { - ...t, - open: false, - } - : t - ), - }; - } - case "REMOVE_TOAST": - if (action.toastId === undefined) { - return { - ...state, - toasts: [], - }; - } - return { - ...state, - toasts: state.toasts.filter((t) => t.id !== action.toastId), - }; - } -}; - -const listeners: Array<(state: State) => void> = []; - -let memoryState: State = { toasts: [] }; - -function dispatch(action: Action) { - memoryState = reducer(memoryState, action); - listeners.forEach((listener) => { - listener(memoryState); - }); -} - -type Toast = Omit - -function toast({ ...props }: Toast) { - const id = genId(); - - const update = (props: ToasterToast) => - dispatch({ - type: "UPDATE_TOAST", - toast: { ...props, id }, - }); - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); - - dispatch({ - type: "ADD_TOAST", - toast: { - ...props, - id, - open: true, - onOpenChange: (open) => { - if (!open) dismiss(); - }, - }, - }); - - return { - id: id, - dismiss, - update, - }; -} - -function useToast() { - const [state, setState] = React.useState(memoryState); - - React.useEffect(() => { - listeners.push(setState); - return () => { - const index = listeners.indexOf(setState); - if (index > -1) { - listeners.splice(index, 1); - } - }; - }, [state]); - - return { - ...state, - toast, - dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), - }; -} - -export { useToast, toast }; diff --git a/vite.config.js b/vite.config.js index 6d4311e..60b5b44 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,7 +2,10 @@ import { defineConfig } from 'vite'; import path from "path"; import react from '@vitejs/plugin-react'; import dotenv from 'dotenv'; -import UnpluginInjectPreload from 'unplugin-inject-preload/vite' +import UnpluginInjectPreload from 'unplugin-inject-preload/vite'; +import VitePluginBuildMetadata from 'vite-plugin-build-metadata'; +import ogPlugin from 'vite-plugin-open-graph'; + dotenv.config(); @@ -14,7 +17,30 @@ export default defineConfig({ plugins: ["@babel/plugin-syntax-import-attributes"] } }), - // UnpluginInjectPreload({ /* options */ }) + UnpluginInjectPreload({ + files: [{ + entryMatch: /.*\.ttf/ + }] + }), + VitePluginBuildMetadata(), + ogPlugin({ + basic: { + title: "Sword Manager", + type: "website", + url: process.env.VITE_URL || "http://sword-manager.pages.dev", + image: { + url: "./src/swordlogo.png", + type: "image/png", + width: 300, + height: 300, + alt: "Sword with Gear" + }, + description: "100% client sided Sword Battle account manager written in react" + }, + twitter: { + + } + }) ], base: process.env.VITE_BASE_URL || "/", server: {