chore: add eslint plugins for import and className sorting
This commit is contained in:
parent
0fa620719b
commit
d96be6654d
36 changed files with 522 additions and 174 deletions
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import { type Message } from 'ai-connector'
|
||||
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { ChatMessage } from '@/components/chat-message'
|
||||
import { EmptyScreen } from '@/components/empty-screen'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
|
||||
export interface ChatList {
|
||||
messages: Message[]
|
||||
|
|
@ -12,7 +12,7 @@ export interface ChatList {
|
|||
|
||||
export function ChatList({ messages }: ChatList) {
|
||||
return (
|
||||
<div className="relative max-w-2xl px-4 mx-auto">
|
||||
<div className="relative mx-auto max-w-2xl px-4">
|
||||
{messages.length > 0 ? (
|
||||
messages.map((message, index) => (
|
||||
<div key={index}>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { User } from 'lucide-react'
|
|||
import remarkGfm from 'remark-gfm'
|
||||
import remarkMath from 'remark-math'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { fontMessage } from '@/lib/fonts'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { CodeBlock } from '@/components/ui/codeblock'
|
||||
import { MemoizedReactMarkdown } from '@/components/markdown'
|
||||
import { OpenAI } from '@/components/icons'
|
||||
import { MemoizedReactMarkdown } from '@/components/markdown'
|
||||
|
||||
export interface ChatMessageProps {
|
||||
message: Message
|
||||
|
|
@ -17,32 +17,32 @@ export function ChatMessage({ message, ...props }: ChatMessageProps) {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-start mb-4 relative md:-ml-12',
|
||||
'relative mb-4 flex items-start md:-ml-12',
|
||||
fontMessage.className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'md:flex h-8 w-8 shrink-0 hidden items-center justify-center rounded-full select-none border',
|
||||
'hidden h-8 w-8 shrink-0 select-none items-center justify-center rounded-full border md:flex',
|
||||
message.role === 'user'
|
||||
? 'bg-background'
|
||||
: 'bg-primary text-primary-foreground'
|
||||
)}
|
||||
>
|
||||
{message.role === 'user' ? (
|
||||
<User className="w-4 h-4" />
|
||||
<User className="h-4 w-4" />
|
||||
) : (
|
||||
<OpenAI className="w-4 h-4" />
|
||||
<OpenAI className="h-4 w-4" />
|
||||
)}
|
||||
</div>
|
||||
<div className="md:ml-4">
|
||||
<MemoizedReactMarkdown
|
||||
className="prose dark:prose-invert prose-pre:rounded-md leading-6 prose-p:leading-[1.8rem] prose-pre:bg-[#282c34]"
|
||||
className="prose leading-6 dark:prose-invert prose-p:leading-[1.8rem] prose-pre:rounded-md prose-pre:bg-[#282c34]"
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
components={{
|
||||
p({ children }) {
|
||||
return <p className={cn('mb-2 last:mb-0')}>{children}</p>
|
||||
return <p className="mb-2 last:mb-0">{children}</p>
|
||||
},
|
||||
code({ node, inline, className, children, ...props }) {
|
||||
if (children.length) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
import { UseChatHelpers } from 'ai-connector'
|
||||
import { RefreshCcw, StopCircle } from 'lucide-react'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { ExternalLink } from '@/components/external-link'
|
||||
import { PromptForm } from '@/components/prompt-form'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export interface ChatPanelProps
|
||||
extends Pick<
|
||||
|
|
@ -23,8 +23,8 @@ export function ChatPanel({
|
|||
messages
|
||||
}: ChatPanelProps) {
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-gradient-to-b from-muted/10 from-10% to-muted/30 to-50%">
|
||||
<div className="sm:max-w-2xl sm:px-4 mx-auto">
|
||||
<div className="fixed inset-x-0 bottom-0 bg-gradient-to-b from-muted/10 from-10% to-muted/30 to-50%">
|
||||
<div className="mx-auto sm:max-w-2xl sm:px-4">
|
||||
<div className="flex items-center justify-center py-2">
|
||||
{isLoading ? (
|
||||
<Button
|
||||
|
|
@ -32,7 +32,7 @@ export function ChatPanel({
|
|||
onClick={() => stop()}
|
||||
className="bg-background"
|
||||
>
|
||||
<StopCircle className="h-4 w-4 mr-2" />
|
||||
<StopCircle className="mr-2 h-4 w-4" />
|
||||
Stop generating
|
||||
</Button>
|
||||
) : (
|
||||
|
|
@ -42,13 +42,13 @@ export function ChatPanel({
|
|||
onClick={() => reload()}
|
||||
className="bg-background"
|
||||
>
|
||||
<RefreshCcw className="h-4 w-4 mr-2" />
|
||||
<RefreshCcw className="mr-2 h-4 w-4" />
|
||||
Regenerate response
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className="sm:p-4 border-t sm:border bg-background space-y-4 shadow-lg sm:rounded-t-xl">
|
||||
<div className="space-y-4 border-t bg-background shadow-lg sm:rounded-t-xl sm:border sm:p-4">
|
||||
<PromptForm
|
||||
onSubmit={value => {
|
||||
append({
|
||||
|
|
@ -58,7 +58,7 @@ export function ChatPanel({
|
|||
}}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<p className="hidden sm:block text-muted-foreground text-xs leading-normal text-center px-2">
|
||||
<p className="hidden px-2 text-center text-xs leading-normal text-muted-foreground sm:block">
|
||||
Open source AI chatbot app built with{' '}
|
||||
<ExternalLink href="https://nextjs.org">Next.js</ExternalLink> and{' '}
|
||||
<ExternalLink href="https://vercel.com/storage/kv">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
'use client'
|
||||
|
||||
import { useChat, type Message } from 'ai-connector'
|
||||
|
||||
import { ChatList } from '@/components/chat-list'
|
||||
import { ChatPanel } from '@/components/chat-panel'
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ export function Chat({ id, initialMessages }: ChatProps) {
|
|||
})
|
||||
|
||||
return (
|
||||
<div className="h-full w-full overflow-auto pt-4 md:pt-10 bg-muted/50 pb-[200px]">
|
||||
<div className="h-full w-full overflow-auto bg-muted/50 pb-[200px] pt-4 md:pt-10">
|
||||
<ChatList messages={messages} />
|
||||
<ChatPanel
|
||||
id={id}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ArrowRight } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { fontMessage } from '@/lib/fonts'
|
||||
import { useChatStore } from '@/lib/hooks/use-chat-store'
|
||||
import { ExternalLink } from '@/components/external-link'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { ExternalLink } from '@/components/external-link'
|
||||
|
||||
const exampleMessages = [
|
||||
{
|
||||
|
|
@ -27,15 +27,15 @@ export function EmptyScreen({ className }: React.ComponentProps<'div'>) {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'border bg-background p-8 rounded-lg',
|
||||
'rounded-lg border bg-background p-8',
|
||||
fontMessage.className,
|
||||
className
|
||||
)}
|
||||
>
|
||||
<h1 className="font-semibold text-lg mb-2">
|
||||
<h1 className="mb-2 text-lg font-semibold">
|
||||
Welcome to Next.js Chatbot!
|
||||
</h1>
|
||||
<p className="text-muted-foreground leading-normal mb-2">
|
||||
<p className="mb-2 leading-normal text-muted-foreground">
|
||||
This is an open source AI chatbot app built with{' '}
|
||||
<ExternalLink href="https://nextjs.org">Next.js</ExternalLink> and{' '}
|
||||
<ExternalLink href="https://vercel.com/storage/kv">
|
||||
|
|
@ -43,7 +43,7 @@ export function EmptyScreen({ className }: React.ComponentProps<'div'>) {
|
|||
</ExternalLink>
|
||||
.
|
||||
</p>
|
||||
<p className="text-muted-foreground leading-normal">
|
||||
<p className="leading-normal text-muted-foreground">
|
||||
You can start a conversation here or try the following examples:
|
||||
</p>
|
||||
<div className="mt-4 flex flex-col items-start space-y-2">
|
||||
|
|
@ -51,10 +51,10 @@ export function EmptyScreen({ className }: React.ComponentProps<'div'>) {
|
|||
<Button
|
||||
key={index}
|
||||
variant="link"
|
||||
className="p-0 h-auto text-base"
|
||||
className="h-auto p-0 text-base"
|
||||
onClick={() => setDefaultMessage(message.message)}
|
||||
>
|
||||
<ArrowRight className="w-4 h-4 mr-2 text-muted-foreground" />
|
||||
<ArrowRight className="mr-2 h-4 w-4 text-muted-foreground" />
|
||||
{message.heading}
|
||||
</Button>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export function ExternalLink({
|
|||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
className="inline-flex gap-1 hover:underline flex-1 justify-center leading-4"
|
||||
className="inline-flex flex-1 justify-center gap-1 leading-4 hover:underline"
|
||||
>
|
||||
<span>{children}</span>
|
||||
<svg
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
import { cn } from '@/lib/utils'
|
||||
import { auth } from '@/auth'
|
||||
import { getChats } from '@/app/actions'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
import { UserMenu } from '@/components/user-menu'
|
||||
import { GitHub, Separator, Vercel } from '@/components/icons'
|
||||
import { Sidebar } from '@/components/sidebar'
|
||||
import { UserMenu } from '@/components/user-menu'
|
||||
import { getChats } from '@/app/actions'
|
||||
|
||||
export async function Header() {
|
||||
const session = await auth()
|
||||
const chats = session?.user?.email ? await getChats(session.user.email) : []
|
||||
|
||||
return (
|
||||
<header className="h-16 shrink-0 z-50 border-b bg-gradient-to-b from-background/10 via-background/50 backdrop-blur-xl to-background/80 px-4 flex sticky top-0 w-full items-center justify-between">
|
||||
<header className="sticky top-0 z-50 flex h-16 w-full shrink-0 items-center justify-between border-b bg-gradient-to-b from-background/10 via-background/50 to-background/80 px-4 backdrop-blur-xl">
|
||||
<div className="flex items-center">
|
||||
{/* @ts-ignore */}
|
||||
<Sidebar chats={chats} session={session} />
|
||||
<div className="hidden md:flex items-center">
|
||||
<div className="hidden items-center md:flex">
|
||||
<Separator className="h-6 w-6 text-muted-foreground/50" />
|
||||
<UserMenu session={session} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex space-x-2 items-center justify-end">
|
||||
<div className="flex items-center justify-end space-x-2">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/vercel/nextjs-ai-chatbot/"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(buttonVariants({ variant: 'outline' }))}
|
||||
>
|
||||
<GitHub className="w-4 h-4 mr-2" />
|
||||
<GitHub className="mr-2 h-4 w-4" />
|
||||
<span>GitHub</span>
|
||||
</a>
|
||||
<a
|
||||
|
|
@ -35,7 +36,7 @@ export async function Header() {
|
|||
target="_blank"
|
||||
className={cn(buttonVariants())}
|
||||
>
|
||||
<Vercel className="w-4 h-4 mr-2" />
|
||||
<Vercel className="mr-2 h-4 w-4" />
|
||||
<span className="hidden sm:block">Deploy to Vercel</span>
|
||||
<span className="sm:hidden">Vercel</span>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function NextChat({
|
|||
viewBox="0 0 17 17"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn('w-4 h-4', className)}
|
||||
className={cn('h-4 w-4', className)}
|
||||
{...props}
|
||||
>
|
||||
<defs>
|
||||
|
|
@ -95,7 +95,7 @@ export function OpenAI({ className, ...props }: React.ComponentProps<'svg'>) {
|
|||
viewBox="0 0 24 24"
|
||||
role="img"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={cn('w-4 h-4', className)}
|
||||
className={cn('h-4 w-4', className)}
|
||||
{...props}
|
||||
>
|
||||
<title>OpenAI icon</title>
|
||||
|
|
@ -110,7 +110,7 @@ export function Vercel({ className, ...props }: React.ComponentProps<'svg'>) {
|
|||
aria-label="Vercel logomark"
|
||||
role="img"
|
||||
viewBox="0 0 74 64"
|
||||
className={cn('w-4 h-4', className)}
|
||||
className={cn('h-4 w-4', className)}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
|
|
@ -128,7 +128,7 @@ export function GitHub({ className, ...props }: React.ComponentProps<'svg'>) {
|
|||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
className={cn('w-4 h-4', className)}
|
||||
className={cn('h-4 w-4', className)}
|
||||
{...props}
|
||||
>
|
||||
<title>GitHub</title>
|
||||
|
|
@ -151,7 +151,7 @@ export function Separator({
|
|||
strokeWidth="1"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
className={cn('w-4 h-4', className)}
|
||||
className={cn('h-4 w-4', className)}
|
||||
{...props}
|
||||
>
|
||||
<path d="M16.88 3.549L7.12 20.451"></path>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { CornerDownLeft, Plus } from 'lucide-react'
|
||||
import Textarea from 'react-textarea-autosize'
|
||||
|
||||
import { Button, buttonVariants } from '@/components/ui/button'
|
||||
import { useChatStore } from '@/lib/hooks/use-chat-store'
|
||||
import { useEnterSubmit } from '@/lib/hooks/use-enter-submit'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useChatStore } from '@/lib/hooks/use-chat-store'
|
||||
import { Button, buttonVariants } from '@/components/ui/button'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger
|
||||
} from '@/components/ui/tooltip'
|
||||
import Link from 'next/link'
|
||||
|
||||
export interface PromptProps {
|
||||
onSubmit: (value: string) => void
|
||||
|
|
@ -50,14 +50,14 @@ export function PromptForm({ onSubmit, isLoading }: PromptProps) {
|
|||
ref={formRef}
|
||||
>
|
||||
<TooltipProvider>
|
||||
<div className="relative flex w-full grow flex-col sm:rounded-md sm:border bg-background overflow-hidden px-12">
|
||||
<div className="relative flex w-full grow flex-col overflow-hidden bg-background px-12 sm:rounded-md sm:border">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Link
|
||||
href="/"
|
||||
className={cn(
|
||||
buttonVariants({ size: 'sm', variant: 'outline' }),
|
||||
'w-8 h-8 p-0 rounded-full absolute top-4 left-4 bg-background'
|
||||
'absolute left-4 top-4 h-8 w-8 rounded-full bg-background p-0'
|
||||
)}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
|
|
@ -75,9 +75,9 @@ export function PromptForm({ onSubmit, isLoading }: PromptProps) {
|
|||
onChange={e => setInput(e.target.value)}
|
||||
placeholder="Send a message."
|
||||
spellCheck={false}
|
||||
className="min-h-[60px] sm:text-sm bg-transparent px-4 py-[1.4rem] focus-within:outline-none w-full resize-none"
|
||||
className="min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.4rem] focus-within:outline-none sm:text-sm"
|
||||
/>
|
||||
<div className="absolute top-4 right-4">
|
||||
<div className="absolute right-4 top-4">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
import * as React from 'react'
|
||||
import { useTransition } from 'react'
|
||||
import { Loader2Icon, MessageSquare, Trash2Icon } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import { Loader2Icon, MessageSquare, Trash2Icon } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { removeChat } from '@/app/actions'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
|
|
@ -19,6 +18,7 @@ import {
|
|||
AlertDialogTitle
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Button, buttonVariants } from '@/components/ui/button'
|
||||
import { removeChat } from '@/app/actions'
|
||||
|
||||
export function SidebarItem({
|
||||
title,
|
||||
|
|
@ -49,9 +49,9 @@ export function SidebarItem({
|
|||
isActive && 'bg-accent'
|
||||
)}
|
||||
>
|
||||
<MessageSquare className="h-4 w-4 mr-2" />
|
||||
<MessageSquare className="mr-2 h-4 w-4" />
|
||||
<div
|
||||
className="relative max-h-5 flex-1 overflow-hidden text-ellipsis break-all select-none"
|
||||
className="relative max-h-5 flex-1 select-none overflow-hidden text-ellipsis break-all"
|
||||
title={title}
|
||||
>
|
||||
<span className="whitespace-nowrap">{title}</span>
|
||||
|
|
@ -60,7 +60,7 @@ export function SidebarItem({
|
|||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="w-7 h-7"
|
||||
className="h-7 w-7"
|
||||
disabled={isPending}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
|
|
@ -92,7 +92,7 @@ export function SidebarItem({
|
|||
}}
|
||||
>
|
||||
{isPending && (
|
||||
<Loader2Icon className="animate-spin h-4 w-4 mr-2" />
|
||||
<Loader2Icon className="mr-2 h-4 w-4 animate-spin" />
|
||||
)}
|
||||
Delete
|
||||
</AlertDialogAction>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import { Sidebar as SidebarIcon } from 'lucide-react'
|
||||
import { type Session } from '@auth/nextjs/types'
|
||||
import { signOut } from '@auth/nextjs/client'
|
||||
import { type Session } from '@auth/nextjs/types'
|
||||
import { Sidebar as SidebarIcon } from 'lucide-react'
|
||||
|
||||
import { type Chat } from '@/lib/types'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
|
@ -26,16 +26,16 @@ export async function Sidebar({ session, chats }: SidebarProps) {
|
|||
return (
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="ghost" className="w-9 h-9 p-0 -ml-2">
|
||||
<SidebarIcon className="w-6 h-6" />
|
||||
<Button variant="ghost" className="-ml-2 h-9 w-9 p-0">
|
||||
<SidebarIcon className="h-6 w-6" />
|
||||
<span className="sr-only">Toggle Sidebar</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent
|
||||
position="left"
|
||||
className="w-[300px] gap-0 top-0 bottom-0 lg:top-2 p-0 rounded-r-lg lg:bottom-2 h-auto flex flex-col"
|
||||
className="inset-y-0 flex h-auto w-[300px] flex-col gap-0 rounded-r-lg p-0 lg:inset-y-2"
|
||||
>
|
||||
<SheetHeader className="px-4 py-4">
|
||||
<SheetHeader className="p-4">
|
||||
<SheetTitle className="text-sm">Chat History</SheetTitle>
|
||||
</SheetHeader>
|
||||
<div className="flex-1 overflow-auto">
|
||||
|
|
@ -52,7 +52,7 @@ export async function Sidebar({ session, chats }: SidebarProps) {
|
|||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center p-8">
|
||||
<div className="p-8 text-center">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{session?.user ? <>No chat history</> : <>Login for history</>}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { Moon, Sun } from 'lucide-react'
|
||||
import { useTheme } from 'next-themes'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
"use client"
|
||||
'use client'
|
||||
|
||||
import * as React from "react"
|
||||
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
||||
import * as React from 'react'
|
||||
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { buttonVariants } from "@/components/ui/button"
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
|
||||
const AlertDialog = AlertDialogPrimitive.Root
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ const AlertDialogOverlay = React.forwardRef<
|
|||
>(({ className, children, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-opacity animate-in fade-in",
|
||||
'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm transition-opacity animate-in fade-in',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -47,7 +47,7 @@ const AlertDialogContent = React.forwardRef<
|
|||
<AlertDialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed z-50 grid w-full max-w-lg scale-100 gap-4 border bg-background p-6 opacity-100 shadow-lg animate-in fade-in-90 slide-in-from-bottom-10 sm:rounded-lg sm:zoom-in-90 sm:slide-in-from-bottom-0 md:w-full",
|
||||
'fixed z-50 grid w-full max-w-lg scale-100 gap-4 border bg-background p-6 opacity-100 shadow-lg animate-in fade-in-90 slide-in-from-bottom-10 sm:rounded-lg sm:zoom-in-90 sm:slide-in-from-bottom-0 md:w-full',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -62,13 +62,13 @@ const AlertDialogHeader = ({
|
|||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
'flex flex-col space-y-2 text-center sm:text-left',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
AlertDialogHeader.displayName = "AlertDialogHeader"
|
||||
AlertDialogHeader.displayName = 'AlertDialogHeader'
|
||||
|
||||
const AlertDialogFooter = ({
|
||||
className,
|
||||
|
|
@ -76,13 +76,13 @@ const AlertDialogFooter = ({
|
|||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
AlertDialogFooter.displayName = "AlertDialogFooter"
|
||||
AlertDialogFooter.displayName = 'AlertDialogFooter'
|
||||
|
||||
const AlertDialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
||||
|
|
@ -90,7 +90,7 @@ const AlertDialogTitle = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-lg font-semibold", className)}
|
||||
className={cn('text-lg font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
|
@ -102,7 +102,7 @@ const AlertDialogDescription = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<AlertDialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
className={cn('text-sm text-muted-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
|
@ -128,8 +128,8 @@ const AlertDialogCancel = React.forwardRef<
|
|||
<AlertDialogPrimitive.Cancel
|
||||
ref={ref}
|
||||
className={cn(
|
||||
buttonVariants({ variant: "outline" }),
|
||||
"mt-2 sm:mt-0",
|
||||
buttonVariants({ variant: 'outline' }),
|
||||
'mt-2 sm:mt-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -146,5 +146,5 @@ export {
|
|||
AlertDialogTitle,
|
||||
AlertDialogDescription,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogCancel
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
const buttonVariants = cva(
|
||||
'inline-flex items-center justify-center shadow rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
|
||||
'inline-flex items-center justify-center rounded-md text-sm font-medium shadow 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',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'bg-primary shadow-md text-primary-foreground hover:bg-primary/90',
|
||||
'bg-primary text-primary-foreground shadow-md hover:bg-primary/90',
|
||||
destructive:
|
||||
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||
outline:
|
||||
'border border-input hover:bg-accent hover:text-accent-foreground',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent shadow-none hover:text-accent-foreground',
|
||||
link: 'underline-offset-4 shadow-none hover:underline text-primary'
|
||||
ghost: 'shadow-none hover:bg-accent hover:text-accent-foreground',
|
||||
link: 'text-primary underline-offset-4 shadow-none hover:underline'
|
||||
},
|
||||
size: {
|
||||
default: 'h-8 py-2 px-4',
|
||||
sm: 'h-8 px-3 rounded-md',
|
||||
lg: 'h-11 px-8 rounded-md',
|
||||
default: 'h-8 px-4 py-2',
|
||||
sm: 'h-8 rounded-md px-3',
|
||||
lg: 'h-11 rounded-md px-8',
|
||||
icon: 'h-8 w-8 p-0'
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
'use client'
|
||||
import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-cliipboard'
|
||||
import { Check, Clipboard, Download } from 'lucide-react'
|
||||
|
||||
import { FC, memo } from 'react'
|
||||
import { Check, Clipboard, Download } from 'lucide-react'
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
||||
import { coldarkDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'
|
||||
|
||||
import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-cliipboard'
|
||||
|
||||
interface Props {
|
||||
language: string
|
||||
value: string
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-9 w-full shadow-sm rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
"use client"
|
||||
'use client'
|
||||
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
import * as React from 'react'
|
||||
import * as SeparatorPrimitive from '@radix-ui/react-separator'
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
||||
>(
|
||||
(
|
||||
{ className, orientation = "horizontal", decorative = true, ...props },
|
||||
{ className, orientation = 'horizontal', decorative = true, ...props },
|
||||
ref
|
||||
) => (
|
||||
<SeparatorPrimitive.Root
|
||||
|
|
@ -18,8 +18,8 @@ const Separator = React.forwardRef<
|
|||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"shrink-0 bg-border",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
'shrink-0 bg-border',
|
||||
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@ const SheetOverlay = React.forwardRef<
|
|||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
||||
|
||||
const sheetVariants = cva(
|
||||
'fixed z-50 scale-100 gap-4 bg-background p-6 opacity-100 shadow-lg border h-full',
|
||||
'fixed z-50 h-full scale-100 gap-4 border bg-background p-6 opacity-100 shadow-lg',
|
||||
{
|
||||
variants: {
|
||||
position: {
|
||||
left: 'data-[state=open]:animate-slide-from-left data-[state=closed]:animate-slide-to-left',
|
||||
right: 'animate-in slide-in-from-right h-full duration-300'
|
||||
left: 'data-[state=closed]:animate-slide-to-left data-[state=open]:animate-slide-from-left',
|
||||
right: 'h-full animate-in slide-in-from-right duration-300'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from "react"
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
export interface TextareaProps
|
||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
|
|
@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
'flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
@ -19,6 +19,6 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|||
)
|
||||
}
|
||||
)
|
||||
Textarea.displayName = "Textarea"
|
||||
Textarea.displayName = 'Textarea'
|
||||
|
||||
export { Textarea }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
|
|||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 overflow-hidden rounded-md border bg-popover font-medium px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1',
|
||||
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm font-medium text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
import { signIn } from '@auth/nextjs/client'
|
||||
import { type Session } from '@auth/nextjs/types'
|
||||
import { Loader2Icon } from 'lucide-react'
|
||||
|
|
@ -26,13 +25,13 @@ export function UserMenu({ session }: UserMenuProps) {
|
|||
}}
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading && <Loader2Icon className="animate-spin w-4 h-4 mr-2" />}
|
||||
{isLoading && <Loader2Icon className="mr-2 h-4 w-4 animate-spin" />}
|
||||
Login
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<p className="text-sm font-medium px-2">Logged in as {session.user.name}</p>
|
||||
<p className="px-2 text-sm font-medium">Logged in as {session.user.name}</p>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue