{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "comp-297",
  "type": "registry:component",
  "title": "Comp 297",
  "description": "Comp 297",
  "files": [
    {
      "path": "registry/ui-basic/comp-297.tsx",
      "content": "\"use client\";\r\n\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { ToastAction } from \"@/components/ui/toast\";\r\n\r\nimport { useToast } from \"../utilities/useToast\";\r\n\r\nexport default function Component() {\r\n\tconst { toast } = useToast();\r\n\r\n\treturn (\r\n\t\t<Button\r\n\t\t\tvariant=\"outline\"\r\n\t\t\tonClick={() => {\r\n\t\t\t\ttoast({\r\n\t\t\t\t\ttitle: \"We couldn't complete your request!\",\r\n\t\t\t\t\tdescription: \"There was a problem with your request.\",\r\n\t\t\t\t\taction: <ToastAction altText=\"Try again\">Try again</ToastAction>,\r\n\t\t\t\t});\r\n\t\t\t}}\r\n\t\t>\r\n\t\t\tShow toast\r\n\t\t</Button>\r\n\t);\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/button.tsx",
      "content": "import * as React from \"react\";\r\n\r\nimport { cn } from \"@/registry/utilities/cn\";\r\nimport { Slot } from \"@radix-ui/react-slot\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nconst buttonVariants = cva(\r\n\t\"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm text-white hover:text-gray-400 font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\r\n\t{\r\n\t\tvariants: {\r\n\t\t\tvariant: {\r\n\t\t\t\tsimple:\r\n\t\t\t\t\t\"bg-secondary relative z-10 bg-transparent hover:border-secondary hover:bg-secondary/50  border border-transparent dark:text-white text-sm md:text-sm transition font-medium duration-200  rounded-md px-4 py-2  flex items-center justify-center\",\r\n\t\t\t\tdefault: \"bg-primary text-primary-foreground hover:bg-primary/90\",\r\n\t\t\t\tdestructive:\r\n\t\t\t\t\t\"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\r\n\t\t\t\toutline:\r\n\t\t\t\t\t\"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\r\n\t\t\t\tsecondary:\r\n\t\t\t\t\t\"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n\t\t\t\tghost: \"hover:bg-accent hover:text-black hover:stroke-black dark:text-white text-black\",\r\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\tdefault: \"h-10 px-4 py-2\",\r\n\t\t\t\tsm: \"h-9 rounded-md px-3\",\r\n\t\t\t\tlg: \"h-11 rounded-md px-8\",\r\n\t\t\t\ticon: \"h-10 w-10\",\r\n\t\t\t},\r\n\t\t},\r\n\t\tdefaultVariants: {\r\n\t\t\tvariant: \"default\",\r\n\t\t\tsize: \"default\",\r\n\t\t},\r\n\t}\r\n);\r\n\r\nexport interface ButtonProps\r\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\r\n\t\tVariantProps<typeof buttonVariants> {\r\n\tasChild?: boolean;\r\n}\r\n\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n\t({ className, variant, size, asChild = false, ...props }, ref) => {\r\n\t\tconst Comp = asChild ? Slot : \"button\";\r\n\t\treturn (\r\n\t\t\t<Comp\r\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\r\n\t\t\t\tref={ref}\r\n\t\t\t\t{...props}\r\n\t\t\t/>\r\n\t\t);\r\n\t}\r\n);\r\nButton.displayName = \"Button\";\r\n\r\nexport { Button, buttonVariants };\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "components/ui/toast.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\n\nimport { cn } from \"@/registry/utilities/cn\";\nimport * as ToastPrimitives from \"@radix-ui/react-toast\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\n\nconst ToastProvider = ToastPrimitives.Provider;\n\nconst ToastViewport = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Viewport>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>\n>(({ className, ...props }, ref) => (\n\t<ToastPrimitives.Viewport\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"fixed top-0 z-100 flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]\",\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t/>\n));\nToastViewport.displayName = ToastPrimitives.Viewport.displayName;\n\nconst toastVariants = cva(\n\t\"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-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--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 sm:data-[state=open]:slide-in-from-bottom-full\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"border bg-background text-foreground\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"destructive group border-destructive bg-destructive text-destructive-foreground\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t},\n\t}\n);\n\nconst Toast = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Root>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &\n\t\tVariantProps<typeof toastVariants>\n>(({ className, variant, ...props }, ref) => {\n\treturn (\n\t\t<ToastPrimitives.Root\n\t\t\tref={ref}\n\t\t\tclassName={cn(toastVariants({ variant }), className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nToast.displayName = ToastPrimitives.Root.displayName;\n\nconst ToastAction = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Action>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>\n>(({ className, ...props }, ref) => (\n\t<ToastPrimitives.Action\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 hover:group-[.destructive]:border-destructive/30 hover:group-[.destructive]:bg-destructive hover:group-[.destructive]:text-destructive-foreground focus:group-[.destructive]:ring-destructive\",\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t/>\n));\nToastAction.displayName = ToastPrimitives.Action.displayName;\n\nconst ToastClose = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Close>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>\n>(({ className, ...props }, ref) => (\n\t<ToastPrimitives.Close\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-hidden focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 hover:group-[.destructive]:text-red-50 focus:group-[.destructive]:ring-red-400 focus:group-[.destructive]:ring-offset-red-600\",\n\t\t\tclassName\n\t\t)}\n\t\ttoast-close=\"\"\n\t\t{...props}\n\t>\n\t\t<X className=\"h-4 w-4\" />\n\t</ToastPrimitives.Close>\n));\nToastClose.displayName = ToastPrimitives.Close.displayName;\n\nconst ToastTitle = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Title>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>\n>(({ className, ...props }, ref) => (\n\t<ToastPrimitives.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-sm font-semibold\", className)}\n\t\t{...props}\n\t/>\n));\nToastTitle.displayName = ToastPrimitives.Title.displayName;\n\nconst ToastDescription = React.forwardRef<\n\tReact.ElementRef<typeof ToastPrimitives.Description>,\n\tReact.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>\n>(({ className, ...props }, ref) => (\n\t<ToastPrimitives.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-sm opacity-90\", className)}\n\t\t{...props}\n\t/>\n));\nToastDescription.displayName = ToastPrimitives.Description.displayName;\n\ntype ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;\n\ntype ToastActionElement = React.ReactElement<typeof ToastAction>;\n\nexport {\n\ttype ToastProps,\n\ttype ToastActionElement,\n\tToastProvider,\n\tToastViewport,\n\tToast,\n\tToastTitle,\n\tToastDescription,\n\tToastClose,\n\tToastAction,\n};\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/useToast.ts",
      "content": "\"use client\"\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\"\n\nimport type {\n    ToastActionElement,\n    ToastProps,\n} from \"@/components/ui/toast\"\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\ntype ToasterToast = ToastProps & {\n    id: string\n    title?: React.ReactNode\n    description?: React.ReactNode\n    action?: ToastActionElement\n}\n\nconst actionTypes = {\n    ADD_TOAST: \"ADD_TOAST\",\n    UPDATE_TOAST: \"UPDATE_TOAST\",\n    DISMISS_TOAST: \"DISMISS_TOAST\",\n    REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const\n\nlet count = 0\n\nfunction genId() {\n    count = (count + 1) % Number.MAX_SAFE_INTEGER\n    return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n    | {\n        type: ActionType[\"ADD_TOAST\"]\n        toast: ToasterToast\n    }\n    | {\n        type: ActionType[\"UPDATE_TOAST\"]\n        toast: Partial<ToasterToast>\n    }\n    | {\n        type: ActionType[\"DISMISS_TOAST\"]\n        toastId?: ToasterToast[\"id\"]\n    }\n    | {\n        type: ActionType[\"REMOVE_TOAST\"]\n        toastId?: ToasterToast[\"id\"]\n    }\n\ninterface State {\n    toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()\n\nconst addToRemoveQueue = (toastId: string) => {\n    if (toastTimeouts.has(toastId)) {\n        return\n    }\n\n    const timeout = setTimeout(() => {\n        toastTimeouts.delete(toastId)\n        dispatch({\n            type: \"REMOVE_TOAST\",\n            toastId: toastId,\n        })\n    }, TOAST_REMOVE_DELAY)\n\n    toastTimeouts.set(toastId, timeout)\n}\n\nexport const reducer = (state: State, action: Action): State => {\n    switch (action.type) {\n        case \"ADD_TOAST\":\n            return {\n                ...state,\n                toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n            }\n\n        case \"UPDATE_TOAST\":\n            return {\n                ...state,\n                toasts: state.toasts.map((t) =>\n                    t.id === action.toast.id ? { ...t, ...action.toast } : t\n                ),\n            }\n\n        case \"DISMISS_TOAST\": {\n            const { toastId } = action\n\n            // ! Side effects ! - This could be extracted into a dismissToast() action,\n            // but I'll keep it here for simplicity\n            if (toastId) {\n                addToRemoveQueue(toastId)\n            } else {\n                state.toasts.forEach((toast) => {\n                    addToRemoveQueue(toast.id)\n                })\n            }\n\n            return {\n                ...state,\n                toasts: state.toasts.map((t) =>\n                    t.id === toastId || toastId === undefined\n                        ? {\n                            ...t,\n                            open: false,\n                        }\n                        : t\n                ),\n            }\n        }\n        case \"REMOVE_TOAST\":\n            if (action.toastId === undefined) {\n                return {\n                    ...state,\n                    toasts: [],\n                }\n            }\n            return {\n                ...state,\n                toasts: state.toasts.filter((t) => t.id !== action.toastId),\n            }\n    }\n}\n\nconst listeners: Array<(state: State) => void> = []\n\nlet memoryState: State = { toasts: [] }\n\nfunction dispatch(action: Action) {\n    memoryState = reducer(memoryState, action)\n    listeners.forEach((listener) => {\n        listener(memoryState)\n    })\n}\n\ntype Toast = Omit<ToasterToast, \"id\">\n\nfunction toast({ ...props }: Toast) {\n    const id = genId()\n\n    const update = (props: ToasterToast) =>\n        dispatch({\n            type: \"UPDATE_TOAST\",\n            toast: { ...props, id },\n        })\n    const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id })\n\n    dispatch({\n        type: \"ADD_TOAST\",\n        toast: {\n            ...props,\n            id,\n            open: true,\n            onOpenChange: (open) => {\n                if (!open) dismiss()\n            },\n        },\n    })\n\n    return {\n        id: id,\n        dismiss,\n        update,\n    }\n}\n\nfunction useToast() {\n    const [state, setState] = React.useState<State>(memoryState)\n\n    React.useEffect(() => {\n        listeners.push(setState)\n        return () => {\n            const index = listeners.indexOf(setState)\n            if (index > -1) {\n                listeners.splice(index, 1)\n            }\n        }\n    }, [state])\n\n    return {\n        ...state,\n        toast,\n        dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n    }\n}\n\nexport { toast, useToast }",
      "type": "registry:ui"
    }
  ]
}