diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..10d6a5c
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,16 @@
+# Then get your Google Gemini API Key here: https://cloud.google.com/vertex-ai
+GOOGLE_GENERATIVE_AI_API_KEY=XXXXXXXX
+
+# Generate a random secret: https://generate-secret.vercel.app/32 or `openssl rand -base64 32`
+AUTH_SECRET=XXXXXXXX
+
+# Instructions to create kv database here: https://vercel.com/docs/storage/vercel-kv/quickstart and
+KV_URL=XXXXXXXX
+KV_REST_API_URL=XXXXXXXX
+KV_REST_API_TOKEN=XXXXXXXX
+KV_REST_API_READ_ONLY_TOKEN=XXXXXXXX
+
+# Get your kasada configurations here: https://kasada.io
+KASADA_API_ENDPOINT=XXXXXXXX
+KASADA_API_VERSION=XXXXXXXX
+KASADA_HEADER_HOST=XXXXXXXX
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..c17b532
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,26 @@
+{
+ "$schema": "https://json.schemastore.org/eslintrc",
+ "root": true,
+ "extends": [
+ "next/core-web-vitals",
+ "prettier",
+ "plugin:tailwindcss/recommended"
+ ],
+ "plugins": ["tailwindcss"],
+ "rules": {
+ "tailwindcss/no-custom-classname": "off",
+ "tailwindcss/classnames-order": "off"
+ },
+ "settings": {
+ "tailwindcss": {
+ "callees": ["cn", "cva"],
+ "config": "tailwind.config.js"
+ }
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "parser": "@typescript-eslint/parser"
+ }
+ ]
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dd019e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+node_modules
+.pnp
+.pnp.js
+
+# testing
+coverage
+
+# next.js
+.next/
+out/
+build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# turbo
+.turbo
+
+.env
+.vercel
+.vscode
+.env*.local
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6c16c29
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2023 Vercel, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..30d7161
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+
+
+ Next.js AI Chatbot
+
+
+
+ An open-source AI chatbot app template built with Next.js, the Vercel AI SDK, Google Gemini, and Vercel KV.
+
+
+
+ Features ·
+ Model Providers ·
+ Deploy Your Own ·
+ Running locally ·
+ Authors
+
+
+
+## Features
+
+- [Next.js](https://nextjs.org) App Router
+- React Server Components (RSCs), Suspense, and Server Actions
+- [Vercel AI SDK](https://sdk.vercel.ai/docs) for streaming chat UI
+- Support for Google Gemini (default), OpenAI, Anthropic, Cohere, Hugging Face, or custom AI chat models and/or LangChain
+- [shadcn/ui](https://ui.shadcn.com)
+ - Styling with [Tailwind CSS](https://tailwindcss.com)
+ - [Radix UI](https://radix-ui.com) for headless component primitives
+ - Icons from [Phosphor Icons](https://phosphoricons.com)
+- Chat History, rate limiting, and session storage with [Vercel KV](https://vercel.com/storage/kv)
+- [NextAuth.js](https://github.com/nextauthjs/next-auth) for authentication
+
+## Model Providers
+
+This template ships with Google Gemini `models/gemini-1.0-pro-001` as the default. However, thanks to the [Vercel AI SDK](https://sdk.vercel.ai/docs), you can switch LLM providers to [OpenAI](https://openai.com), [Anthropic](https://anthropic.com), [Cohere](https://cohere.com/), [Hugging Face](https://huggingface.co), or using [LangChain](https://js.langchain.com) with just a few lines of code.
+
+## Deploy Your Own
+
+You can deploy your own version of the Next.js AI Chatbot to Vercel with one click:
+
+[](https://vercel.com/new/clone?demo-title=Next.js+Chat&demo-description=A+full-featured%2C+hackable+Next.js+AI+chatbot+built+by+Vercel+Labs&demo-url=https%3A%2F%2Fchat.vercel.ai%2F&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F4aVPvWuTmBvzM5cEdRdqeW%2F4234f9baf160f68ffb385a43c3527645%2FCleanShot_2023-06-16_at_17.09.21.png&project-name=Next.js+Chat&repository-name=nextjs-chat&repository-url=https%3A%2F%2Fgithub.com%2Fvercel-labs%2Fgemini-chatbot&from=templates&skippable-integrations=1&env=GOOGLE_GENERATIVE_AI_API_KEY%2CAUTH_SECRET&envDescription=How+to+get+these+env+vars&envLink=https%3A%2F%2Fgithub.com%2Fvercel-labs%2Fgemini-chatbot%2Fblob%2Fmain%2F.env.example&teamCreateStatus=hidden&stores=[{%22type%22:%22kv%22}])
+
+## Running locally
+
+You will need to use the environment variables [defined in `.env.example`](.env.example) to run Next.js AI Chatbot. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables) for this, but a `.env` file is all that is necessary.
+
+> Note: You should not commit your `.env` file or it will expose secrets that will allow others to control access to your various Google Cloud and authentication provider accounts.
+
+1. Install Vercel CLI: `npm i -g vercel`
+2. Link local instance with Vercel and GitHub accounts (creates `.vercel` directory): `vercel link`
+3. Download your environment variables: `vercel env pull`
+
+```bash
+pnpm install
+pnpm dev
+```
+
+Your app template should now be running on [localhost:3000](http://localhost:3000/).
+
+## Authors
+
+This library is created by [Vercel](https://vercel.com) and [Next.js](https://nextjs.org) team members, with contributions from:
+
+- Jared Palmer ([@jaredpalmer](https://twitter.com/jaredpalmer)) - [Vercel](https://vercel.com)
+- Shu Ding ([@shuding\_](https://twitter.com/shuding_)) - [Vercel](https://vercel.com)
+- shadcn ([@shadcn](https://twitter.com/shadcn)) - [Vercel](https://vercel.com)
+- Jeremy Philemon ([@jrmyphlmn](https://twitter.com/jrmyphlmn)) - [Vercel](https://vercel.com)
\ No newline at end of file
diff --git a/app/(chat)/chat/[id]/page.tsx b/app/(chat)/chat/[id]/page.tsx
new file mode 100644
index 0000000..a25dfef
--- /dev/null
+++ b/app/(chat)/chat/[id]/page.tsx
@@ -0,0 +1,66 @@
+import { type Metadata } from 'next'
+import { notFound, redirect } from 'next/navigation'
+
+import { auth } from '@/auth'
+import { getChat, getMissingKeys } from '@/app/actions'
+import { Chat } from '@/components/chat'
+import { AI } from '@/lib/chat/actions'
+import { Session } from '@/lib/types'
+
+export interface ChatPageProps {
+ params: {
+ id: string
+ }
+}
+
+export async function generateMetadata({
+ params
+}: ChatPageProps): Promise {
+ const session = await auth()
+
+ if (!session?.user) {
+ return {}
+ }
+
+ const chat = await getChat(params.id, session.user.id)
+ return {
+ title: chat?.title.toString().slice(0, 50) ?? 'Chat'
+ }
+}
+
+export default async function ChatPage({ params }: ChatPageProps) {
+ const session = (await auth()) as Session
+ const missingKeys = await getMissingKeys()
+
+ if (!session?.user) {
+ redirect(`/login?next=/chat/${params.id}`)
+ }
+
+ const userId = session.user.id as string
+ const chat = await getChat(params.id, userId)
+
+ if (!chat) {
+ redirect('/')
+ }
+
+ if (chat?.userId !== session?.user?.id) {
+ notFound()
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/app/(chat)/error.tsx b/app/(chat)/error.tsx
new file mode 100644
index 0000000..2163a74
--- /dev/null
+++ b/app/(chat)/error.tsx
@@ -0,0 +1,19 @@
+'use client'
+
+export default function Error({
+ error
+}: {
+ error: Error & { digest?: string }
+}) {
+ return (
+
+
+ Oops, something went wrong!
+
+
+ {error.message || 'The AI got rate limited, please try again later.'}
+
+
Digest: {error.digest}
+
+ )
+}
diff --git a/app/(chat)/layout.tsx b/app/(chat)/layout.tsx
new file mode 100644
index 0000000..2825d59
--- /dev/null
+++ b/app/(chat)/layout.tsx
@@ -0,0 +1,14 @@
+import { SidebarDesktop } from '@/components/sidebar-desktop'
+
+interface ChatLayoutProps {
+ children: React.ReactNode
+}
+
+export default async function ChatLayout({ children }: ChatLayoutProps) {
+ return (
+
+
+ {children}
+
+ )
+}
diff --git a/app/(chat)/page.tsx b/app/(chat)/page.tsx
new file mode 100644
index 0000000..f43ce9f
--- /dev/null
+++ b/app/(chat)/page.tsx
@@ -0,0 +1,22 @@
+import { nanoid } from '@/lib/utils'
+import { Chat } from '@/components/chat'
+import { AI } from '@/lib/chat/actions'
+import { auth } from '@/auth'
+import { Session } from '@/lib/types'
+import { getMissingKeys } from '../actions'
+
+export const metadata = {
+ title: 'Next.js AI Chatbot'
+}
+
+export default async function IndexPage() {
+ const id = nanoid()
+ const session = (await auth()) as Session
+ const missingKeys = await getMissingKeys()
+
+ return (
+
+
+
+ )
+}
diff --git a/app/(chat)/waiting-room/page.tsx b/app/(chat)/waiting-room/page.tsx
new file mode 100644
index 0000000..862523f
--- /dev/null
+++ b/app/(chat)/waiting-room/page.tsx
@@ -0,0 +1,10 @@
+'use client'
+
+export default function Page() {
+ return (
+
+
You are in the queue
+
Please try again in a few minutes.
+
+ )
+}
diff --git a/app/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/[[...restpath]]/route.ts b/app/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/[[...restpath]]/route.ts
new file mode 100644
index 0000000..b70e01b
--- /dev/null
+++ b/app/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/[[...restpath]]/route.ts
@@ -0,0 +1,37 @@
+export const runtime = 'edge'
+export const dynamic = 'force-dynamic'
+export const maxDuration = 3
+
+async function handler(request: Request) {
+ const url = new URL(request.url)
+
+ url.protocol = 'https:'
+ url.host = process.env.KASADA_API_ENDPOINT || ''
+ url.port = ''
+ url.searchParams.delete('restpath')
+
+ const headers = new Headers(request.headers)
+ headers.set('X-Forwarded-Host', process.env.KASADA_HEADER_HOST || '')
+ headers.delete('host')
+ const r = await fetch(url.toString(), {
+ method: request.method,
+ body: request.body,
+ headers,
+ mode: request.mode,
+ redirect: 'manual',
+ // @ts-expect-error
+ duplex: 'half'
+ })
+ const responseHeaders = new Headers(r.headers)
+ responseHeaders.set('cdn-cache-control', 'no-cache')
+ return new Response(r.body, {
+ status: r.status,
+ statusText: r.statusText,
+ headers: responseHeaders
+ })
+}
+
+export const GET = handler
+export const POST = handler
+export const OPTIONS = handler
+export const PUT = handler
diff --git a/app/actions.ts b/app/actions.ts
new file mode 100644
index 0000000..105f9fa
--- /dev/null
+++ b/app/actions.ts
@@ -0,0 +1,156 @@
+'use server'
+
+import { revalidatePath } from 'next/cache'
+import { redirect } from 'next/navigation'
+import { kv } from '@vercel/kv'
+
+import { auth } from '@/auth'
+import { type Chat } from '@/lib/types'
+
+export async function getChats(userId?: string | null) {
+ if (!userId) {
+ return []
+ }
+
+ try {
+ const pipeline = kv.pipeline()
+ const chats: string[] = await kv.zrange(`user:chat:${userId}`, 0, -1, {
+ rev: true
+ })
+
+ for (const chat of chats) {
+ pipeline.hgetall(chat)
+ }
+
+ const results = await pipeline.exec()
+
+ return results as Chat[]
+ } catch (error) {
+ return []
+ }
+}
+
+export async function getChat(id: string, userId: string) {
+ const chat = await kv.hgetall(`chat:${id}`)
+
+ if (!chat || (userId && chat.userId !== userId)) {
+ return null
+ }
+
+ return chat
+}
+
+export async function removeChat({ id, path }: { id: string; path: string }) {
+ const session = await auth()
+
+ if (!session) {
+ return {
+ error: 'Unauthorized'
+ }
+ }
+
+ //Convert uid to string for consistent comparison with session.user.id
+ const uid = String(await kv.hget(`chat:${id}`, 'userId'))
+
+ if (uid !== session?.user?.id) {
+ return {
+ error: 'Unauthorized'
+ }
+ }
+
+ await kv.del(`chat:${id}`)
+ await kv.zrem(`user:chat:${session.user.id}`, `chat:${id}`)
+
+ revalidatePath('/')
+ return revalidatePath(path)
+}
+
+export async function clearChats() {
+ const session = await auth()
+
+ if (!session?.user?.id) {
+ return {
+ error: 'Unauthorized'
+ }
+ }
+
+ const chats: string[] = await kv.zrange(`user:chat:${session.user.id}`, 0, -1)
+ if (!chats.length) {
+ return redirect('/')
+ }
+ const pipeline = kv.pipeline()
+
+ for (const chat of chats) {
+ pipeline.del(chat)
+ pipeline.zrem(`user:chat:${session.user.id}`, chat)
+ }
+
+ await pipeline.exec()
+
+ revalidatePath('/')
+ return redirect('/')
+}
+
+export async function getSharedChat(id: string) {
+ const chat = await kv.hgetall(`chat:${id}`)
+
+ if (!chat || !chat.sharePath) {
+ return null
+ }
+
+ return chat
+}
+
+export async function shareChat(id: string) {
+ const session = await auth()
+
+ if (!session?.user?.id) {
+ return {
+ error: 'Unauthorized'
+ }
+ }
+
+ const chat = await kv.hgetall(`chat:${id}`)
+
+ if (!chat || chat.userId !== session.user.id) {
+ return {
+ error: 'Something went wrong'
+ }
+ }
+
+ const payload = {
+ ...chat,
+ sharePath: `/share/${chat.id}`
+ }
+
+ await kv.hmset(`chat:${chat.id}`, payload)
+
+ return payload
+}
+
+export async function saveChat(chat: Chat) {
+ const session = await auth()
+
+ if (session && session.user) {
+ const pipeline = kv.pipeline()
+ pipeline.hmset(`chat:${chat.id}`, chat)
+ pipeline.zadd(`user:chat:${chat.userId}`, {
+ score: Date.now(),
+ member: `chat:${chat.id}`
+ })
+ await pipeline.exec()
+ } else {
+ return
+ }
+}
+
+export async function refreshHistory(path: string) {
+ redirect(path)
+}
+
+export async function getMissingKeys() {
+ const keysRequired = ['GOOGLE_GENERATIVE_AI_API_KEY']
+ return keysRequired
+ .map(key => (process.env[key] ? '' : key))
+ .filter(key => key !== '')
+}
diff --git a/app/globals.css b/app/globals.css
new file mode 100644
index 0000000..0b46ea1
--- /dev/null
+++ b/app/globals.css
@@ -0,0 +1,76 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 240 10% 3.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 240 10% 3.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 240 10% 3.9%;
+
+ --primary: 240 5.9% 10%;
+ --primary-foreground: 0 0% 98%;
+
+ --secondary: 240 4.8% 95.9%;
+ --secondary-foreground: 240 5.9% 10%;
+
+ --muted: 240 4.8% 95.9%;
+ --muted-foreground: 240 3.8% 46.1%;
+
+ --accent: 240 4.8% 95.9%;
+ --accent-foreground: 240 5.9% 10%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 0 0% 98%;
+
+ --border: 240 5.9% 90%;
+ --input: 240 5.9% 90%;
+ --ring: 240 10% 3.9%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 240 10% 3.9%;
+ --foreground: 0 0% 98%;
+
+ --card: 240 10% 3.9%;
+ --card-foreground: 0 0% 98%;
+
+ --popover: 240 10% 3.9%;
+ --popover-foreground: 0 0% 98%;
+
+ --primary: 0 0% 98%;
+ --primary-foreground: 240 5.9% 10%;
+
+ --secondary: 240 3.7% 15.9%;
+ --secondary-foreground: 0 0% 98%;
+
+ --muted: 240 3.7% 15.9%;
+ --muted-foreground: 240 5% 64.9%;
+
+ --accent: 240 3.7% 15.9%;
+ --accent-foreground: 0 0% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 0 0% 98%;
+
+ --border: 240 3.7% 15.9%;
+ --input: 240 3.7% 15.9%;
+ --ring: 240 4.9% 83.9%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
\ No newline at end of file
diff --git a/app/layout.tsx b/app/layout.tsx
new file mode 100644
index 0000000..f22cf96
--- /dev/null
+++ b/app/layout.tsx
@@ -0,0 +1,66 @@
+import { GeistSans } from 'geist/font/sans'
+import { GeistMono } from 'geist/font/mono'
+import { Analytics } from '@vercel/analytics/react'
+import '@/app/globals.css'
+import { cn } from '@/lib/utils'
+import { TailwindIndicator } from '@/components/tailwind-indicator'
+import { Providers } from '@/components/providers'
+import { Header } from '@/components/header'
+import { Toaster } from '@/components/ui/sonner'
+import { KasadaClient } from '@/lib/kasada/kasada-client'
+
+export const metadata = {
+ metadataBase: new URL('https://gemini.vercel.ai'),
+ title: {
+ default: 'Next.js Gemini Chatbot',
+ template: `%s - Next.js Gemini Chatbot`
+ },
+ description:
+ 'Build your own generative UI chatbot using the Vercel AI SDK and Google Gemini',
+ icons: {
+ icon: '/favicon.ico',
+ shortcut: '/favicon-16x16.png',
+ apple: '/apple-touch-icon.png'
+ }
+}
+
+export const viewport = {
+ themeColor: [
+ { media: '(prefers-color-scheme: light)', color: 'white' },
+ { media: '(prefers-color-scheme: dark)', color: 'black' }
+ ]
+}
+
+interface RootLayoutProps {
+ children: React.ReactNode
+}
+
+export default function RootLayout({ children }: RootLayoutProps) {
+ return (
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ )
+}
diff --git a/app/login/actions.ts b/app/login/actions.ts
new file mode 100644
index 0000000..f23e220
--- /dev/null
+++ b/app/login/actions.ts
@@ -0,0 +1,71 @@
+'use server'
+
+import { signIn } from '@/auth'
+import { User } from '@/lib/types'
+import { AuthError } from 'next-auth'
+import { z } from 'zod'
+import { kv } from '@vercel/kv'
+import { ResultCode } from '@/lib/utils'
+
+export async function getUser(email: string) {
+ const user = await kv.hgetall(`user:${email}`)
+ return user
+}
+
+interface Result {
+ type: string
+ resultCode: ResultCode
+}
+
+export async function authenticate(
+ _prevState: Result | undefined,
+ formData: FormData
+): Promise {
+ try {
+ const email = formData.get('email')
+ const password = formData.get('password')
+
+ const parsedCredentials = z
+ .object({
+ email: z.string().email(),
+ password: z.string().min(6)
+ })
+ .safeParse({
+ email,
+ password
+ })
+
+ if (parsedCredentials.success) {
+ await signIn('credentials', {
+ email,
+ password,
+ redirect: false
+ })
+
+ return {
+ type: 'success',
+ resultCode: ResultCode.UserLoggedIn
+ }
+ } else {
+ return {
+ type: 'error',
+ resultCode: ResultCode.InvalidCredentials
+ }
+ }
+ } catch (error) {
+ if (error instanceof AuthError) {
+ switch (error.type) {
+ case 'CredentialsSignin':
+ return {
+ type: 'error',
+ resultCode: ResultCode.InvalidCredentials
+ }
+ default:
+ return {
+ type: 'error',
+ resultCode: ResultCode.UnknownError
+ }
+ }
+ }
+ }
+}
diff --git a/app/login/page.tsx b/app/login/page.tsx
new file mode 100644
index 0000000..1fba27b
--- /dev/null
+++ b/app/login/page.tsx
@@ -0,0 +1,18 @@
+import { auth } from '@/auth'
+import LoginForm from '@/components/login-form'
+import { Session } from '@/lib/types'
+import { redirect } from 'next/navigation'
+
+export default async function LoginPage() {
+ const session = (await auth()) as Session
+
+ if (session) {
+ redirect('/')
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/app/new/page.tsx b/app/new/page.tsx
new file mode 100644
index 0000000..d235894
--- /dev/null
+++ b/app/new/page.tsx
@@ -0,0 +1,5 @@
+import { redirect } from 'next/navigation'
+
+export default async function NewPage() {
+ redirect('/')
+}
diff --git a/app/opengraph-image.png b/app/opengraph-image.png
new file mode 100644
index 0000000..73d6023
Binary files /dev/null and b/app/opengraph-image.png differ
diff --git a/app/share/[id]/page.tsx b/app/share/[id]/page.tsx
new file mode 100644
index 0000000..d80f0c8
--- /dev/null
+++ b/app/share/[id]/page.tsx
@@ -0,0 +1,58 @@
+import { type Metadata } from 'next'
+import { notFound, redirect } from 'next/navigation'
+
+import { formatDate } from '@/lib/utils'
+import { getSharedChat } from '@/app/actions'
+import { ChatList } from '@/components/chat-list'
+import { FooterText } from '@/components/footer'
+import { AI, UIState, getUIStateFromAIState } from '@/lib/chat/actions'
+
+export const runtime = 'edge'
+export const preferredRegion = 'home'
+
+interface SharePageProps {
+ params: {
+ id: string
+ }
+}
+
+export async function generateMetadata({
+ params
+}: SharePageProps): Promise {
+ const chat = await getSharedChat(params.id)
+
+ return {
+ title: chat?.title.slice(0, 50) ?? 'Chat'
+ }
+}
+
+export default async function SharePage({ params }: SharePageProps) {
+ const chat = await getSharedChat(params.id)
+
+ if (!chat || !chat?.sharePath) {
+ notFound()
+ }
+
+ const uiState: UIState = getUIStateFromAIState(chat)
+
+ return (
+ <>
+
+
+
+
+
{chat.title}
+
+ {formatDate(chat.createdAt)} · {chat.messages.length} messages
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/app/signup/actions.ts b/app/signup/actions.ts
new file mode 100644
index 0000000..492586a
--- /dev/null
+++ b/app/signup/actions.ts
@@ -0,0 +1,111 @@
+'use server'
+
+import { signIn } from '@/auth'
+import { ResultCode, getStringFromBuffer } from '@/lib/utils'
+import { z } from 'zod'
+import { kv } from '@vercel/kv'
+import { getUser } from '../login/actions'
+import { AuthError } from 'next-auth'
+
+export async function createUser(
+ email: string,
+ hashedPassword: string,
+ salt: string
+) {
+ const existingUser = await getUser(email)
+
+ if (existingUser) {
+ return {
+ type: 'error',
+ resultCode: ResultCode.UserAlreadyExists
+ }
+ } else {
+ const user = {
+ id: crypto.randomUUID(),
+ email,
+ password: hashedPassword,
+ salt
+ }
+
+ await kv.hmset(`user:${email}`, user)
+
+ return {
+ type: 'success',
+ resultCode: ResultCode.UserCreated
+ }
+ }
+}
+
+interface Result {
+ type: string
+ resultCode: ResultCode
+}
+
+export async function signup(
+ _prevState: Result | undefined,
+ formData: FormData
+): Promise {
+ const email = formData.get('email') as string
+ const password = formData.get('password') as string
+
+ const parsedCredentials = z
+ .object({
+ email: z.string().email(),
+ password: z.string().min(6)
+ })
+ .safeParse({
+ email,
+ password
+ })
+
+ if (parsedCredentials.success) {
+ const salt = crypto.randomUUID()
+
+ const encoder = new TextEncoder()
+ const saltedPassword = encoder.encode(password + salt)
+ const hashedPasswordBuffer = await crypto.subtle.digest(
+ 'SHA-256',
+ saltedPassword
+ )
+ const hashedPassword = getStringFromBuffer(hashedPasswordBuffer)
+
+ try {
+ const result = await createUser(email, hashedPassword, salt)
+
+ if (result.resultCode === ResultCode.UserCreated) {
+ await signIn('credentials', {
+ email,
+ password,
+ redirect: false
+ })
+ }
+
+ return result
+ } catch (error) {
+ if (error instanceof AuthError) {
+ switch (error.type) {
+ case 'CredentialsSignin':
+ return {
+ type: 'error',
+ resultCode: ResultCode.InvalidCredentials
+ }
+ default:
+ return {
+ type: 'error',
+ resultCode: ResultCode.UnknownError
+ }
+ }
+ } else {
+ return {
+ type: 'error',
+ resultCode: ResultCode.UnknownError
+ }
+ }
+ }
+ } else {
+ return {
+ type: 'error',
+ resultCode: ResultCode.InvalidCredentials
+ }
+ }
+}
diff --git a/app/signup/page.tsx b/app/signup/page.tsx
new file mode 100644
index 0000000..dbac964
--- /dev/null
+++ b/app/signup/page.tsx
@@ -0,0 +1,18 @@
+import { auth } from '@/auth'
+import SignupForm from '@/components/signup-form'
+import { Session } from '@/lib/types'
+import { redirect } from 'next/navigation'
+
+export default async function SignupPage() {
+ const session = (await auth()) as Session
+
+ if (session) {
+ redirect('/')
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/app/twitter-image.png b/app/twitter-image.png
new file mode 100644
index 0000000..73d6023
Binary files /dev/null and b/app/twitter-image.png differ
diff --git a/auth.config.ts b/auth.config.ts
new file mode 100644
index 0000000..6e74c18
--- /dev/null
+++ b/auth.config.ts
@@ -0,0 +1,42 @@
+import type { NextAuthConfig } from 'next-auth'
+
+export const authConfig = {
+ secret: process.env.AUTH_SECRET,
+ pages: {
+ signIn: '/login',
+ newUser: '/signup'
+ },
+ callbacks: {
+ async authorized({ auth, request: { nextUrl } }) {
+ const isLoggedIn = !!auth?.user
+ const isOnLoginPage = nextUrl.pathname.startsWith('/login')
+ const isOnSignupPage = nextUrl.pathname.startsWith('/signup')
+
+ if (isLoggedIn) {
+ if (isOnLoginPage || isOnSignupPage) {
+ return Response.redirect(new URL('/', nextUrl))
+ }
+ }
+
+ return true
+ },
+ async jwt({ token, user }) {
+ if (user) {
+ token = { ...token, id: user.id }
+ }
+
+ return token
+ },
+ async session({ session, token }) {
+ if (token) {
+ const { id } = token as { id: string }
+ const { user } = session
+
+ session = { ...session, user: { ...user, id } }
+ }
+
+ return session
+ }
+ },
+ providers: []
+} satisfies NextAuthConfig
diff --git a/auth.ts b/auth.ts
new file mode 100644
index 0000000..7542992
--- /dev/null
+++ b/auth.ts
@@ -0,0 +1,45 @@
+import NextAuth from 'next-auth'
+import Credentials from 'next-auth/providers/credentials'
+import { authConfig } from './auth.config'
+import { z } from 'zod'
+import { getStringFromBuffer } from './lib/utils'
+import { getUser } from './app/login/actions'
+
+export const { auth, signIn, signOut } = NextAuth({
+ ...authConfig,
+ providers: [
+ Credentials({
+ async authorize(credentials) {
+ const parsedCredentials = z
+ .object({
+ email: z.string().email(),
+ password: z.string().min(6)
+ })
+ .safeParse(credentials)
+
+ if (parsedCredentials.success) {
+ const { email, password } = parsedCredentials.data
+ const user = await getUser(email)
+
+ if (!user) return null
+
+ const encoder = new TextEncoder()
+ const saltedPassword = encoder.encode(password + user.salt)
+ const hashedPasswordBuffer = await crypto.subtle.digest(
+ 'SHA-256',
+ saltedPassword
+ )
+ const hashedPassword = getStringFromBuffer(hashedPasswordBuffer)
+
+ if (hashedPassword === user.password) {
+ return user
+ } else {
+ return null
+ }
+ }
+
+ return null
+ }
+ })
+ ]
+})
diff --git a/components.json b/components.json
new file mode 100644
index 0000000..58b812d
--- /dev/null
+++ b/components.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "app/globals.css",
+ "baseColor": "zinc",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
\ No newline at end of file
diff --git a/components/button-scroll-to-bottom.tsx b/components/button-scroll-to-bottom.tsx
new file mode 100644
index 0000000..e1403f2
--- /dev/null
+++ b/components/button-scroll-to-bottom.tsx
@@ -0,0 +1,36 @@
+'use client'
+
+import * as React from 'react'
+
+import { cn } from '@/lib/utils'
+import { Button, type ButtonProps } from '@/components/ui/button'
+import { IconArrowDown } from '@/components/ui/icons'
+
+interface ButtonScrollToBottomProps extends ButtonProps {
+ isAtBottom: boolean
+ scrollToBottom: () => void
+}
+
+export function ButtonScrollToBottom({
+ className,
+ isAtBottom,
+ scrollToBottom,
+ ...props
+}: ButtonScrollToBottomProps) {
+ return (
+ scrollToBottom()}
+ {...props}
+ >
+
+ Scroll to bottom
+
+ )
+}
diff --git a/components/chat-history.tsx b/components/chat-history.tsx
new file mode 100644
index 0000000..d91dfe5
--- /dev/null
+++ b/components/chat-history.tsx
@@ -0,0 +1,49 @@
+import * as React from 'react'
+
+import Link from 'next/link'
+
+import { cn } from '@/lib/utils'
+import { SidebarList } from '@/components/sidebar-list'
+import { buttonVariants } from '@/components/ui/button'
+import { IconPlus } from '@/components/ui/icons'
+
+interface ChatHistoryProps {
+ userId?: string
+}
+
+export async function ChatHistory({ userId }: ChatHistoryProps) {
+ return (
+
+
+
Chat History
+
+
+
+
+ New Chat
+
+
+
+ {Array.from({ length: 10 }).map((_, i) => (
+
+ ))}
+
+ }
+ >
+ {/* @ts-ignore */}
+
+
+
+ )
+}
diff --git a/components/chat-list.tsx b/components/chat-list.tsx
new file mode 100644
index 0000000..6831e3e
--- /dev/null
+++ b/components/chat-list.tsx
@@ -0,0 +1,47 @@
+import { UIState } from '@/lib/chat/actions'
+import { Session } from '@/lib/types'
+import { ExclamationTriangleIcon } from '@radix-ui/react-icons'
+import Link from 'next/link'
+
+export interface ChatList {
+ messages: UIState
+ session?: Session
+ isShared: boolean
+}
+
+export function ChatList({ messages, session, isShared }: ChatList) {
+ return messages.length ? (
+
+ {!isShared && !session ? (
+ <>
+
+
+
+
+
+
+ Please{' '}
+
+ log in
+ {' '}
+ or{' '}
+
+ sign up
+ {' '}
+ to save and revisit your chat history!
+
+
+
+ >
+ ) : null}
+
+ {messages.map(message => (
+
+ {message.spinner}
+ {message.display}
+ {message.attachments}
+
+ ))}
+
+ ) : null
+}
diff --git a/components/chat-message-actions.tsx b/components/chat-message-actions.tsx
new file mode 100644
index 0000000..d4e4b40
--- /dev/null
+++ b/components/chat-message-actions.tsx
@@ -0,0 +1,40 @@
+'use client'
+
+import { type Message } from 'ai'
+
+import { Button } from '@/components/ui/button'
+import { IconCheck, IconCopy } from '@/components/ui/icons'
+import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard'
+import { cn } from '@/lib/utils'
+
+interface ChatMessageActionsProps extends React.ComponentProps<'div'> {
+ message: Message
+}
+
+export function ChatMessageActions({
+ message,
+ className,
+ ...props
+}: ChatMessageActionsProps) {
+ const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })
+
+ const onCopy = () => {
+ if (isCopied) return
+ copyToClipboard(message.content)
+ }
+
+ return (
+
+
+ {isCopied ? : }
+ Copy message
+
+
+ )
+}
diff --git a/components/chat-message.tsx b/components/chat-message.tsx
new file mode 100644
index 0000000..e17d857
--- /dev/null
+++ b/components/chat-message.tsx
@@ -0,0 +1,80 @@
+// Inspired by Chatbot-UI and modified to fit the needs of this project
+// @see https://github.com/mckaywrigley/chatbot-ui/blob/main/components/Chat/ChatMessage.tsx
+
+import { Message } from 'ai'
+import remarkGfm from 'remark-gfm'
+import remarkMath from 'remark-math'
+
+import { cn } from '@/lib/utils'
+import { CodeBlock } from '@/components/ui/codeblock'
+import { MemoizedReactMarkdown } from '@/components/markdown'
+import { IconGemini, IconUser } from '@/components/ui/icons'
+import { ChatMessageActions } from '@/components/chat-message-actions'
+
+export interface ChatMessageProps {
+ message: Message
+}
+
+export function ChatMessage({ message, ...props }: ChatMessageProps) {
+ return (
+
+
+ {message.role === 'user' ? : }
+
+
+ {children}
+ },
+ code({ node, inline, className, children, ...props }) {
+ if (children.length) {
+ if (children[0] == '▍') {
+ return (
+ ▍
+ )
+ }
+
+ children[0] = (children[0] as string).replace('`▍`', '▍')
+ }
+
+ const match = /language-(\w+)/.exec(className || '')
+
+ if (inline) {
+ return (
+
+ {children}
+
+ )
+ }
+
+ return (
+
+ )
+ }
+ }}
+ >
+ {message.content}
+
+
+
+
+ )
+}
diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx
new file mode 100644
index 0000000..afa0e1c
--- /dev/null
+++ b/components/chat-panel.tsx
@@ -0,0 +1,150 @@
+import * as React from 'react'
+
+import { shareChat } from '@/app/actions'
+import { Button } from '@/components/ui/button'
+import { PromptForm } from '@/components/prompt-form'
+import { ButtonScrollToBottom } from '@/components/button-scroll-to-bottom'
+import { IconShare } from '@/components/ui/icons'
+import { FooterText } from '@/components/footer'
+import { ChatShareDialog } from '@/components/chat-share-dialog'
+import { useAIState, useActions, useUIState } from 'ai/rsc'
+import type { AI } from '@/lib/chat/actions'
+import { nanoid } from 'nanoid'
+import { UserMessage } from './stocks/message'
+import { cn } from '@/lib/utils'
+import { toast } from 'sonner'
+
+export interface ChatPanelProps {
+ id?: string
+ title?: string
+ input: string
+ setInput: (value: string) => void
+ isAtBottom: boolean
+ scrollToBottom: () => void
+}
+
+export function ChatPanel({
+ id,
+ title,
+ input,
+ setInput,
+ isAtBottom,
+ scrollToBottom
+}: ChatPanelProps) {
+ const [aiState] = useAIState()
+ const [messages, setMessages] = useUIState()
+ const { submitUserMessage } = useActions()
+ const [shareDialogOpen, setShareDialogOpen] = React.useState(false)
+
+ const exampleMessages = [
+ {
+ heading: 'List flights flying from',
+ subheading: 'San Francisco to Rome today',
+ message: `List flights flying from San Francisco to Rome today`
+ },
+ {
+ heading: 'What is the status',
+ subheading: 'of flight BA142?',
+ message: 'What is the status of flight BA142?'
+ }
+ ]
+
+ return (
+
+
+
+
+
+ {messages.length === 0 &&
+ exampleMessages.map((example, index) => (
+
1 && 'hidden md:block'
+ )}
+ onClick={async () => {
+ setMessages(currentMessages => [
+ ...currentMessages,
+ {
+ id: nanoid(),
+ display:
{example.message}
+ }
+ ])
+
+ try {
+ const responseMessage = await submitUserMessage(
+ example.message
+ )
+
+ setMessages(currentMessages => [
+ ...currentMessages,
+ responseMessage
+ ])
+ } catch {
+ toast(
+
+ )
+ }
+ }}
+ >
+
{example.heading}
+
+ {example.subheading}
+
+
+ ))}
+
+
+ {messages?.length >= 2 ? (
+
+
+ {id && title ? (
+ <>
+ setShareDialogOpen(true)}
+ >
+
+ Share
+
+ setShareDialogOpen(false)}
+ shareChat={shareChat}
+ chat={{
+ id,
+ title,
+ messages: aiState.messages
+ }}
+ />
+ >
+ ) : null}
+
+
+ ) : null}
+
+
+
+
+ )
+}
diff --git a/components/chat-share-dialog.tsx b/components/chat-share-dialog.tsx
new file mode 100644
index 0000000..d96447c
--- /dev/null
+++ b/components/chat-share-dialog.tsx
@@ -0,0 +1,95 @@
+'use client'
+
+import * as React from 'react'
+import { type DialogProps } from '@radix-ui/react-dialog'
+import { toast } from 'sonner'
+
+import { ServerActionResult, type Chat } from '@/lib/types'
+import { Button } from '@/components/ui/button'
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle
+} from '@/components/ui/dialog'
+import { IconSpinner } from '@/components/ui/icons'
+import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard'
+
+interface ChatShareDialogProps extends DialogProps {
+ chat: Pick
+ shareChat: (id: string) => ServerActionResult
+ onCopy: () => void
+}
+
+export function ChatShareDialog({
+ chat,
+ shareChat,
+ onCopy,
+ ...props
+}: ChatShareDialogProps) {
+ const { copyToClipboard } = useCopyToClipboard({ timeout: 1000 })
+ const [isSharePending, startShareTransition] = React.useTransition()
+
+ const copyShareLink = React.useCallback(
+ async (chat: Chat) => {
+ if (!chat.sharePath) {
+ return toast.error('Could not copy share link to clipboard')
+ }
+
+ const url = new URL(window.location.href)
+ url.pathname = chat.sharePath
+ copyToClipboard(url.toString())
+ onCopy()
+ toast.success('Share link copied to clipboard')
+ },
+ [copyToClipboard, onCopy]
+ )
+
+ return (
+
+
+
+ Share link to chat
+
+ Anyone with the URL will be able to view the shared chat.
+
+
+
+
{chat.title}
+
+ {chat.messages.length} messages
+
+
+
+ {
+ // @ts-ignore
+ startShareTransition(async () => {
+ const result = await shareChat(chat.id)
+
+ if (result && 'error' in result) {
+ toast.error(result.error)
+ return
+ }
+
+ copyShareLink(result)
+ })
+ }}
+ >
+ {isSharePending ? (
+ <>
+
+ Copying...
+ >
+ ) : (
+ <>Copy link>
+ )}
+
+
+
+
+ )
+}
diff --git a/components/chat.tsx b/components/chat.tsx
new file mode 100644
index 0000000..608f8c6
--- /dev/null
+++ b/components/chat.tsx
@@ -0,0 +1,84 @@
+'use client'
+
+import { ChatList } from '@/components/chat-list'
+import { ChatPanel } from '@/components/chat-panel'
+import { EmptyScreen } from '@/components/empty-screen'
+import { ListFlights } from '@/components/flights/list-flights'
+import { ListHotels } from '@/components/hotels/list-hotels'
+import { Message } from '@/lib/chat/actions'
+import { useLocalStorage } from '@/lib/hooks/use-local-storage'
+import { useScrollAnchor } from '@/lib/hooks/use-scroll-anchor'
+import { Session } from '@/lib/types'
+import { cn } from '@/lib/utils'
+import { useAIState, useUIState } from 'ai/rsc'
+import { usePathname, useRouter } from 'next/navigation'
+import { useEffect, useState } from 'react'
+import { toast } from 'sonner'
+
+export interface ChatProps extends React.ComponentProps<'div'> {
+ initialMessages?: Message[]
+ id?: string
+ session?: Session
+ missingKeys: string[]
+}
+
+export function Chat({ id, className, session, missingKeys }: ChatProps) {
+ const router = useRouter()
+ const path = usePathname()
+ const [input, setInput] = useState('')
+ const [messages] = useUIState()
+ const [aiState] = useAIState()
+
+ const [_, setNewChatId] = useLocalStorage('newChatId', id)
+
+ useEffect(() => {
+ if (session?.user) {
+ if (!path.includes('chat') && messages.length === 1) {
+ window.history.replaceState({}, '', `/chat/${id}`)
+ }
+ }
+ }, [id, path, session?.user, messages])
+
+ useEffect(() => {
+ const messagesLength = aiState.messages?.length
+ if (messagesLength === 2) {
+ router.refresh()
+ }
+ }, [aiState.messages, router])
+
+ useEffect(() => {
+ setNewChatId(id)
+ })
+
+ useEffect(() => {
+ missingKeys.map(key => {
+ toast.error(`Missing ${key} environment variable!`)
+ })
+ }, [missingKeys])
+
+ const { messagesRef, scrollRef, visibilityRef, isAtBottom, scrollToBottom } =
+ useScrollAnchor()
+
+ return (
+
+
+ {messages.length ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ )
+}
diff --git a/components/clear-history.tsx b/components/clear-history.tsx
new file mode 100644
index 0000000..69cf70e
--- /dev/null
+++ b/components/clear-history.tsx
@@ -0,0 +1,75 @@
+'use client'
+
+import * as React from 'react'
+import { useRouter } from 'next/navigation'
+import { toast } from 'sonner'
+
+import { ServerActionResult } from '@/lib/types'
+import { Button } from '@/components/ui/button'
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger
+} from '@/components/ui/alert-dialog'
+import { IconSpinner } from '@/components/ui/icons'
+
+interface ClearHistoryProps {
+ isEnabled: boolean
+ clearChats: () => ServerActionResult
+}
+
+export function ClearHistory({
+ isEnabled = false,
+ clearChats
+}: ClearHistoryProps) {
+ const [open, setOpen] = React.useState(false)
+ const [isPending, startTransition] = React.useTransition()
+ const router = useRouter()
+
+ return (
+
+
+
+ {isPending && }
+ Clear history
+
+
+
+
+ Are you absolutely sure?
+
+ This will permanently delete your chat history and remove your data
+ from our servers.
+
+
+
+ Cancel
+ {
+ event.preventDefault()
+ startTransition(async () => {
+ const result = await clearChats()
+ if (result && 'error' in result) {
+ toast.error(result.error)
+ return
+ }
+
+ setOpen(false)
+ })
+ }}
+ >
+ {isPending && }
+ Delete
+
+
+
+
+ )
+}
diff --git a/components/empty-screen.tsx b/components/empty-screen.tsx
new file mode 100644
index 0000000..719f693
--- /dev/null
+++ b/components/empty-screen.tsx
@@ -0,0 +1,35 @@
+import { ExternalLink } from '@/components/external-link'
+
+export function EmptyScreen() {
+ return (
+
+
+
+ Next.js Gemini Chatbot
+
+
+ This is an open source AI chatbot app template built with{' '}
+ Next.js , the{' '}
+
+ Vercel AI SDK
+
+ , and{' '}
+
+ Google Gemini
+
+ .
+
+
+ It uses{' '}
+
+ React Server Components
+ {' '}
+ with function calling to mix both text with generative UI responses
+ from Gemini. The UI state is synced through the AI SDK so the model is
+ always aware of your stateful interactions as they happen in the
+ browser.
+
+
+
+ )
+}
diff --git a/components/external-link.tsx b/components/external-link.tsx
new file mode 100644
index 0000000..ba6cc01
--- /dev/null
+++ b/components/external-link.tsx
@@ -0,0 +1,29 @@
+export function ExternalLink({
+ href,
+ children
+}: {
+ href: string
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+
+
+
+ )
+}
diff --git a/components/flights/boarding-pass.tsx b/components/flights/boarding-pass.tsx
new file mode 100644
index 0000000..018be51
--- /dev/null
+++ b/components/flights/boarding-pass.tsx
@@ -0,0 +1,88 @@
+'use client'
+
+/* eslint-disable @next/next/no-img-element */
+import Barcode from 'react-jsbarcode'
+
+interface BoardingPassProps {
+ summary: {
+ airline: string
+ arrival: string
+ departure: string
+ departureTime: string
+ arrivalTime: string
+ price: number
+ seat: string
+ date: string
+ gate: string
+ }
+}
+
+export const BoardingPass = ({
+ summary = {
+ airline: 'American Airlines',
+ arrival: 'SFO',
+ departure: 'NYC',
+ departureTime: '10:00 AM',
+ arrivalTime: '12:00 PM',
+ price: 100,
+ seat: '1A',
+ date: '2021-12-25',
+ gate: '31'
+ }
+}: BoardingPassProps) => {
+ return (
+
+
+
+
+
+
+
{summary.airline}
+
+ {summary.departure} - {summary.arrival}
+
+
+
+
Gate
+
{summary.gate}
+
+
+
+
Rauch / Guillermo
+
+
{summary.departure}
+
{summary.date}
+
{summary.arrival}
+
+
+
+
+
Seat
+
{summary.seat}
+
+
+
+
Departs
+
{summary.departureTime}
+
+
+
Arrival
+
{summary.arrivalTime}
+
+
+
+
+
+
+ )
+}
diff --git a/components/flights/destinations.tsx b/components/flights/destinations.tsx
new file mode 100644
index 0000000..74b28ef
--- /dev/null
+++ b/components/flights/destinations.tsx
@@ -0,0 +1,36 @@
+'use client'
+
+import { useActions, useUIState } from 'ai/rsc'
+
+export const Destinations = ({ destinations }: { destinations: string[] }) => {
+ const { submitUserMessage } = useActions()
+ const [_, setMessages] = useUIState()
+
+ return (
+
+
+ Here is a list of holiday destinations based on the books you have read.
+ Choose one to proceed to booking a flight.
+
+
+ {destinations.map(destination => (
+ {
+ const response = await submitUserMessage(
+ `I would like to fly to ${destination}, proceed to choose flights.`
+ )
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+ {destination}
+
+ ))}
+
+
+ )
+}
diff --git a/components/flights/flight-status.tsx b/components/flights/flight-status.tsx
new file mode 100644
index 0000000..110cdfa
--- /dev/null
+++ b/components/flights/flight-status.tsx
@@ -0,0 +1,151 @@
+'use client'
+
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable @next/next/no-img-element */
+import { useActions, useUIState } from 'ai/rsc'
+import {
+ ArrowDownRight,
+ ArrowUpRight,
+ CheckIcon,
+ IconCheck,
+ IconStop,
+ SparklesIcon
+} from '@/components/ui/icons'
+
+export interface StatusProps {
+ summary: {
+ departingCity: string
+ departingAirport: string
+ departingAirportCode: string
+ departingTime: string
+ arrivalCity: string
+ arrivalAirport: string
+ arrivalAirportCode: string
+ arrivalTime: string
+ flightCode: string
+ date: string
+ }
+}
+
+export const suggestions = [
+ 'Change my seat',
+ 'Change my flight',
+ 'Show boarding pass'
+]
+
+export const FlightStatus = ({
+ summary = {
+ departingCity: 'Miami',
+ departingAirport: 'Miami Intl',
+ departingAirportCode: 'MIA',
+ departingTime: '11:45 PM',
+ arrivalCity: 'San Francisco',
+ arrivalAirport: 'San Francisco Intl',
+ arrivalAirportCode: 'SFO',
+ arrivalTime: '4:20 PM',
+ flightCode: 'XY 2421',
+ date: 'Mon, 16 Sep'
+ }
+}: StatusProps) => {
+ const {
+ departingCity,
+ departingAirport,
+ departingAirportCode,
+ departingTime,
+ arrivalCity,
+ arrivalAirport,
+ arrivalAirportCode,
+ arrivalTime,
+ flightCode,
+ date
+ } = summary
+
+ const { submitUserMessage } = useActions()
+ const [_, setMessages] = useUIState()
+
+ return (
+
+
+
+
+
+
+
+
+ {date} · {flightCode}
+
+
+ {departingCity} to {arrivalCity}
+
+
+
+
+
+
+
+
+
{departingAirportCode}
+
{departingAirport}
+
Terminal N · GATE D43
+
+
+
{departingTime}
+
in 6h 50m
+
+ 2h 15m late
+
+
+
+
+
+
+
+
+ Total 11h 30m · 5, 563mi · Overnight
+
+
+
+
+
+
{arrivalAirportCode}
+
{arrivalAirport}
+
Terminal 2 · GATE 59A
+
+
+
{arrivalTime}
+
+ 2h 15m late
+
+
+
+
+
+
+ {suggestions.map(suggestion => (
+
{
+ const response = await submitUserMessage(suggestion)
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+
+ {suggestion}
+
+ ))}
+
+
+ )
+}
diff --git a/components/flights/list-flights.tsx b/components/flights/list-flights.tsx
new file mode 100644
index 0000000..25944c9
--- /dev/null
+++ b/components/flights/list-flights.tsx
@@ -0,0 +1,132 @@
+'use client'
+
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable @next/next/no-img-element */
+
+import { useActions, useUIState } from 'ai/rsc'
+
+interface Flight {
+ id: number
+ airlines: string
+ departureTime: string
+ arrivalTime: string
+ price: number
+}
+
+interface ListFlightsProps {
+ summary: {
+ arrivalCity: string
+ departingCity: string
+ arrivalAirport: string
+ departingAirport: string
+ date: string
+ }
+}
+
+export const ListFlights = ({
+ summary = {
+ arrivalCity: 'San Francisco',
+ departingCity: 'New York City',
+ arrivalAirport: 'SFO',
+ departingAirport: 'JFK',
+ date: '2021-12-25'
+ }
+}: ListFlightsProps) => {
+ const { arrivalCity, departingCity, arrivalAirport, departingAirport, date } =
+ summary
+ const { submitUserMessage } = useActions()
+ const [_, setMessages] = useUIState()
+
+ const flights = [
+ {
+ id: 1,
+ airlines: 'United Airlines',
+ departureTime: '8:30 PM',
+ arrivalTime: '4:20 PM+1',
+ price: 531
+ },
+ {
+ id: 2,
+ airlines: 'United Airlines',
+ departureTime: '2:40 PM',
+ arrivalTime: '10:25 AM+1',
+ price: 564
+ },
+ {
+ id: 3,
+ airlines: 'United Airlines',
+ departureTime: '3:00 PM',
+ arrivalTime: '10:50 AM+1',
+ price: 611
+ }
+ ]
+
+ return (
+
+
+
+
Departure
+
{departingCity}
+
+
+
Arrival
+
{arrivalCity}
+
+
+
+
+ {flights &&
+ flights.map(flight => (
+
{
+ const response = await submitUserMessage(
+ `The user has selected flight ${flight.airlines}, departing at ${flight.departureTime} and arriving at ${flight.arrivalTime} for $${flight.price}. Now proceeding to select seats.`
+ )
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+
+
+
+
+
+
+ {flight.departureTime} - {flight.arrivalTime}
+
+
{flight.airlines}
+
+
+
+ {flight.id === 2 ? '10hr 50min' : '10hr 45min'}
+
+
+ {departingAirport} - {arrivalAirport}
+
+
+
+
+ ${flight.price}
+
+
+ One Way
+
+
+
+
+ ))}
+
+
+ )
+}
diff --git a/components/flights/purchase-ticket.tsx b/components/flights/purchase-ticket.tsx
new file mode 100644
index 0000000..73f7148
--- /dev/null
+++ b/components/flights/purchase-ticket.tsx
@@ -0,0 +1,149 @@
+'use client'
+
+import {
+ CardIcon,
+ GoogleIcon,
+ LockIcon,
+ SparklesIcon
+} from '@/components/ui/icons'
+import { cn } from '@/lib/utils'
+import { readStreamableValue, useActions, useUIState } from 'ai/rsc'
+import { useState } from 'react'
+
+type Status =
+ | 'requires_confirmation'
+ | 'requires_code'
+ | 'completed'
+ | 'failed'
+ | 'expired'
+ | 'in_progress'
+
+interface PurchaseProps {
+ status: Status
+ summary: {
+ airline: string
+ departureTime: string
+ arrivalTime: string
+ price: number
+ seat: string
+ }
+}
+
+export const suggestions = [
+ 'Show flight status',
+ 'Show boarding pass for flight'
+]
+
+export const PurchaseTickets = ({
+ status = 'requires_confirmation',
+ summary = {
+ airline: 'American Airlines',
+ departureTime: '10:00 AM',
+ arrivalTime: '12:00 PM',
+ price: 100,
+ seat: '1A'
+ }
+}: PurchaseProps) => {
+ const [currentStatus, setCurrentStatus] = useState(status)
+ const { requestCode, validateCode, submitUserMessage } = useActions()
+ const [display, setDisplay] = useState(null)
+ const [_, setMessages] = useUIState()
+
+ return (
+
+
+
+
+
+
+
+
Visa · · · · 0512
+
+
+
+ Pay
+
+
+ {currentStatus === 'requires_confirmation' ? (
+
+
+ Thanks for choosing your flight and hotel reservations! Confirm
+ your purchase to complete your booking.
+
+
{
+ const { status, display } = await requestCode()
+ setCurrentStatus(status)
+ setDisplay(display)
+ }}
+ >
+ Pay $981
+
+
+ ) : currentStatus === 'requires_code' ? (
+ <>
+
+ Enter the code sent to your phone (***) *** 6137 to complete your
+ purchase.
+
+
+
+
+
{
+ const { status, display } = await validateCode()
+
+ for await (const statusFromStream of readStreamableValue(
+ status
+ )) {
+ setCurrentStatus(statusFromStream as Status)
+ setDisplay(display)
+ }
+ }}
+ >
+ Submit
+
+ >
+ ) : currentStatus === 'completed' || currentStatus === 'in_progress' ? (
+ display
+ ) : currentStatus === 'expired' ? (
+
+ Your Session has expired!
+
+ ) : null}
+
+
+
+ {suggestions.map(suggestion => (
+ {
+ const response = await submitUserMessage(suggestion)
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+
+ {suggestion}
+
+ ))}
+
+
+ )
+}
diff --git a/components/flights/select-seats.tsx b/components/flights/select-seats.tsx
new file mode 100644
index 0000000..23ebf11
--- /dev/null
+++ b/components/flights/select-seats.tsx
@@ -0,0 +1,143 @@
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable @next/next/no-img-element */
+'use client'
+
+import { useAIState, useActions, useUIState } from 'ai/rsc'
+import { useState } from 'react'
+import { SparklesIcon } from '../ui/icons'
+
+interface SelectSeatsProps {
+ summary: {
+ departingCity: string
+ arrivalCity: string
+ flightCode: string
+ date: string
+ }
+}
+
+export const suggestions = [
+ 'Proceed to checkout',
+ 'List hotels and make a reservation'
+]
+
+export const SelectSeats = ({
+ summary = {
+ departingCity: 'New York City',
+ arrivalCity: 'San Francisco',
+ flightCode: 'CA123',
+ date: '23 March 2024'
+ }
+}: SelectSeatsProps) => {
+ const availableSeats = ['3B', '2D']
+ const [aiState, setAIState] = useAIState()
+ const [selectedSeat, setSelectedSeat] = useState('')
+ const { departingCity, arrivalCity, flightCode, date } = summary
+ const [_, setMessages] = useUIState()
+ const { submitUserMessage } = useActions()
+
+ return (
+
+
+ Great! Here are the available seats for your flight. Please select a
+ seat to continue.
+
+
+
+
+
+
+
+
+ {date} · {flightCode}
+
+
+ {departingCity} to {arrivalCity}
+
+
+
+
+
+ {[4, 3, 2, 1].map((row, rowIndex) => (
+
+ {['A', 'B', 0, 'C', 'D'].map((seat, seatIndex) => (
+
{
+ setSelectedSeat(`${row}${seat}`)
+
+ setAIState({
+ ...aiState,
+ interactions: [
+ `great, I have selected seat ${row}${seat}`
+ ]
+ })
+ }}
+ >
+ {seatIndex === 2 ? (
+
+ {row}
+
+ ) : (
+
+ )}
+
+ ))}
+
+ ))}
+
+ {['A', 'B', '', 'C', 'D'].map((seat, index) => (
+
+ {seat}
+
+ ))}
+
+
+
+
+ {selectedSeat !== '' && (
+
+ {suggestions.map(suggestion => (
+ {
+ const response = await submitUserMessage(suggestion, [])
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+
+ {suggestion}
+
+ ))}
+
+ )}
+
+ )
+}
diff --git a/components/footer.tsx b/components/footer.tsx
new file mode 100644
index 0000000..3e700eb
--- /dev/null
+++ b/components/footer.tsx
@@ -0,0 +1,26 @@
+import React from 'react'
+
+import { cn } from '@/lib/utils'
+import { ExternalLink } from '@/components/external-link'
+
+export function FooterText({ className, ...props }: React.ComponentProps<'p'>) {
+ return (
+
+ Open source AI chatbot built with{' '}
+
+ Google Gemini
+
+ , Next.js and{' '}
+
+ Vercel AI SDK
+
+ .
+
+ )
+}
diff --git a/components/header.tsx b/components/header.tsx
new file mode 100644
index 0000000..3db547d
--- /dev/null
+++ b/components/header.tsx
@@ -0,0 +1,82 @@
+/* eslint-disable @next/next/no-img-element */
+import * as React from 'react'
+import Link from 'next/link'
+
+import { cn } from '@/lib/utils'
+import { auth } from '@/auth'
+import { Button, buttonVariants } from '@/components/ui/button'
+import {
+ IconGitHub,
+ IconNextChat,
+ IconSeparator,
+ IconVercel
+} from '@/components/ui/icons'
+import { UserMenu } from '@/components/user-menu'
+import { SidebarMobile } from './sidebar-mobile'
+import { SidebarToggle } from './sidebar-toggle'
+import { ChatHistory } from './chat-history'
+import { Session } from '@/lib/types'
+
+async function UserOrLogin() {
+ const session = (await auth()) as Session
+ return (
+ <>
+ {session?.user ? (
+ <>
+
+
+
+
+ >
+ ) : (
+
+
+
+ )}
+
+
+ {session?.user ? (
+
+ ) : (
+
+ Login
+
+ )}
+
+ >
+ )
+}
+
+export function Header() {
+ return (
+
+ )
+}
diff --git a/components/hotels/list-hotels.tsx b/components/hotels/list-hotels.tsx
new file mode 100644
index 0000000..7e9664c
--- /dev/null
+++ b/components/hotels/list-hotels.tsx
@@ -0,0 +1,87 @@
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable @next/next/no-img-element */
+'use client'
+
+import { useActions, useUIState } from 'ai/rsc'
+
+interface Hotel {
+ id: number
+ name: string
+ description: string
+ price: number
+}
+
+interface ListHotelsProps {
+ hotels: Hotel[]
+}
+
+export const ListHotels = ({
+ hotels = [
+ {
+ id: 1,
+ name: 'The St. Regis Rome',
+ description: 'Renowned luxury hotel with a lavish spa',
+ price: 450
+ },
+ {
+ id: 2,
+ name: 'The Inn at the Roman Forum',
+ description: 'Upscale hotel with Roman ruins and a bar',
+ price: 145
+ },
+ {
+ id: 3,
+ name: 'Hotel Roma',
+ description: 'Vibrant property with free breakfast',
+ price: 112
+ }
+ ]
+}: ListHotelsProps) => {
+ const { submitUserMessage } = useActions()
+ const [_, setMessages] = useUIState()
+
+ return (
+
+
+ We recommend a 3 night stay in Rome. Here are some hotels you can choose
+ from.
+
+
+ {hotels.map(hotel => (
+
{
+ const response = await submitUserMessage(
+ `I want to book the ${hotel.name}, proceed to checkout by calling checkoutBooking function.`
+ )
+ setMessages((currentMessages: any[]) => [
+ ...currentMessages,
+ response
+ ])
+ }}
+ >
+
+
+
+
+
+
{hotel.name}
+
{hotel.description}
+
+
+
+
+ ${hotel.price}
+
+
per night
+
+
+ ))}
+
+
+ )
+}
diff --git a/components/login-button.tsx b/components/login-button.tsx
new file mode 100644
index 0000000..ae8f842
--- /dev/null
+++ b/components/login-button.tsx
@@ -0,0 +1,42 @@
+'use client'
+
+import * as React from 'react'
+import { signIn } from 'next-auth/react'
+
+import { cn } from '@/lib/utils'
+import { Button, type ButtonProps } from '@/components/ui/button'
+import { IconGitHub, IconSpinner } from '@/components/ui/icons'
+
+interface LoginButtonProps extends ButtonProps {
+ showGithubIcon?: boolean
+ text?: string
+}
+
+export function LoginButton({
+ text = 'Login with GitHub',
+ showGithubIcon = true,
+ className,
+ ...props
+}: LoginButtonProps) {
+ const [isLoading, setIsLoading] = React.useState(false)
+ return (
+ {
+ setIsLoading(true)
+ // next-auth signIn() function doesn't work yet at Edge Runtime due to usage of BroadcastChannel
+ signIn('github', { callbackUrl: `/` })
+ }}
+ disabled={isLoading}
+ className={cn(className)}
+ {...props}
+ >
+ {isLoading ? (
+
+ ) : showGithubIcon ? (
+
+ ) : null}
+ {text}
+
+ )
+}
diff --git a/components/login-form.tsx b/components/login-form.tsx
new file mode 100644
index 0000000..dc64b06
--- /dev/null
+++ b/components/login-form.tsx
@@ -0,0 +1,97 @@
+'use client'
+
+import { useFormState, useFormStatus } from 'react-dom'
+import { authenticate } from '@/app/login/actions'
+import Link from 'next/link'
+import { useEffect } from 'react'
+import { toast } from 'sonner'
+import { IconSpinner } from './ui/icons'
+import { getMessageFromCode } from '@/lib/utils'
+import { useRouter } from 'next/navigation'
+
+export default function LoginForm() {
+ const router = useRouter()
+ const [result, dispatch] = useFormState(authenticate, undefined)
+
+ useEffect(() => {
+ if (result) {
+ if (result.type === 'error') {
+ toast.error(getMessageFromCode(result.resultCode))
+ } else {
+ toast.success(getMessageFromCode(result.resultCode))
+ router.refresh()
+ }
+ }
+ }, [result, router])
+
+ return (
+
+ )
+}
+
+function LoginButton() {
+ const { pending } = useFormStatus()
+
+ return (
+
+ {pending ? : 'Log in'}
+
+ )
+}
diff --git a/components/markdown.tsx b/components/markdown.tsx
new file mode 100644
index 0000000..d449146
--- /dev/null
+++ b/components/markdown.tsx
@@ -0,0 +1,9 @@
+import { FC, memo } from 'react'
+import ReactMarkdown, { Options } from 'react-markdown'
+
+export const MemoizedReactMarkdown: FC = memo(
+ ReactMarkdown,
+ (prevProps, nextProps) =>
+ prevProps.children === nextProps.children &&
+ prevProps.className === nextProps.className
+)
diff --git a/components/media/video.tsx b/components/media/video.tsx
new file mode 100644
index 0000000..a8f3846
--- /dev/null
+++ b/components/media/video.tsx
@@ -0,0 +1,19 @@
+import { SpinnerIcon } from '../ui/icons'
+
+export const Video = ({ isLoading }: { isLoading: boolean }) => {
+ return (
+
+ )
+}
diff --git a/components/prompt-form.tsx b/components/prompt-form.tsx
new file mode 100644
index 0000000..2e9bdfc
--- /dev/null
+++ b/components/prompt-form.tsx
@@ -0,0 +1,172 @@
+'use client'
+
+import * as React from 'react'
+import Textarea from 'react-textarea-autosize'
+
+import { useActions, useUIState } from 'ai/rsc'
+
+import { UserMessage } from './stocks/message'
+import { type AI } from '@/lib/chat/actions'
+import { Button } from '@/components/ui/button'
+import { IconArrowElbow, IconPlus } from '@/components/ui/icons'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger
+} from '@/components/ui/tooltip'
+import { useEnterSubmit } from '@/lib/hooks/use-enter-submit'
+import { nanoid } from 'nanoid'
+import { toast } from 'sonner'
+
+export function PromptForm({
+ input,
+ setInput
+}: {
+ input: string
+ setInput: (value: string) => void
+}) {
+ const { formRef, onKeyDown } = useEnterSubmit()
+ const inputRef = React.useRef(null)
+ const { submitUserMessage, describeImage } = useActions()
+ const [_, setMessages] = useUIState()
+
+ React.useEffect(() => {
+ if (inputRef.current) {
+ inputRef.current.focus()
+ }
+ }, [])
+
+ const fileRef = React.useRef(null)
+
+ return (
+
+ )
+}
diff --git a/components/providers.tsx b/components/providers.tsx
new file mode 100644
index 0000000..fb5dec3
--- /dev/null
+++ b/components/providers.tsx
@@ -0,0 +1,15 @@
+'use client'
+
+import * as React from 'react'
+// import { ThemeProvider as NextThemesProvider } from 'next-themes'
+import { ThemeProviderProps } from 'next-themes/dist/types'
+import { SidebarProvider } from '@/lib/hooks/use-sidebar'
+import { TooltipProvider } from '@/components/ui/tooltip'
+
+export function Providers({ children, ...props }: ThemeProviderProps) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/components/sidebar-actions.tsx b/components/sidebar-actions.tsx
new file mode 100644
index 0000000..4f90f2d
--- /dev/null
+++ b/components/sidebar-actions.tsx
@@ -0,0 +1,125 @@
+'use client'
+
+import { useRouter } from 'next/navigation'
+import * as React from 'react'
+import { toast } from 'sonner'
+
+import { ServerActionResult, type Chat } from '@/lib/types'
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle
+} from '@/components/ui/alert-dialog'
+import { Button } from '@/components/ui/button'
+import { IconShare, IconSpinner, IconTrash } from '@/components/ui/icons'
+import { ChatShareDialog } from '@/components/chat-share-dialog'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger
+} from '@/components/ui/tooltip'
+
+interface SidebarActionsProps {
+ chat: Chat
+ removeChat: (args: { id: string; path: string }) => ServerActionResult
+ shareChat: (id: string) => ServerActionResult
+}
+
+export function SidebarActions({
+ chat,
+ removeChat,
+ shareChat
+}: SidebarActionsProps) {
+ const router = useRouter()
+ const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false)
+ const [shareDialogOpen, setShareDialogOpen] = React.useState(false)
+ const [isRemovePending, startRemoveTransition] = React.useTransition()
+
+ return (
+ <>
+
+
+
+ setShareDialogOpen(true)}
+ >
+
+ Share
+
+
+ Share chat
+
+
+
+ setDeleteDialogOpen(true)}
+ >
+
+ Delete
+
+
+ Delete chat
+
+
+ setShareDialogOpen(false)}
+ />
+
+
+
+ Are you absolutely sure?
+
+ This will permanently delete your chat message and remove your
+ data from our servers.
+
+
+
+
+ Cancel
+
+ {
+ event.preventDefault()
+ // @ts-ignore
+ startRemoveTransition(async () => {
+ const result = await removeChat({
+ id: chat.id,
+ path: chat.path
+ })
+
+ if (result && 'error' in result) {
+ toast.error(result.error)
+ return
+ }
+
+ setDeleteDialogOpen(false)
+ router.refresh()
+ router.push('/')
+ toast.success('Chat deleted')
+ })
+ }}
+ >
+ {isRemovePending && }
+ Delete
+
+
+
+
+ >
+ )
+}
diff --git a/components/sidebar-desktop.tsx b/components/sidebar-desktop.tsx
new file mode 100644
index 0000000..7bc0e19
--- /dev/null
+++ b/components/sidebar-desktop.tsx
@@ -0,0 +1,19 @@
+import { Sidebar } from '@/components/sidebar'
+
+import { auth } from '@/auth'
+import { ChatHistory } from '@/components/chat-history'
+
+export async function SidebarDesktop() {
+ const session = await auth()
+
+ if (!session?.user?.id) {
+ return null
+ }
+
+ return (
+
+ {/* @ts-ignore */}
+
+
+ )
+}
diff --git a/components/sidebar-footer.tsx b/components/sidebar-footer.tsx
new file mode 100644
index 0000000..a2e18ea
--- /dev/null
+++ b/components/sidebar-footer.tsx
@@ -0,0 +1,16 @@
+import { cn } from '@/lib/utils'
+
+export function SidebarFooter({
+ children,
+ className,
+ ...props
+}: React.ComponentProps<'div'>) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/components/sidebar-item.tsx b/components/sidebar-item.tsx
new file mode 100644
index 0000000..fc7020b
--- /dev/null
+++ b/components/sidebar-item.tsx
@@ -0,0 +1,124 @@
+'use client'
+
+import * as React from 'react'
+
+import Link from 'next/link'
+import { usePathname } from 'next/navigation'
+
+import { motion } from 'framer-motion'
+
+import { buttonVariants } from '@/components/ui/button'
+import { IconMessage, IconUsers } from '@/components/ui/icons'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger
+} from '@/components/ui/tooltip'
+import { useLocalStorage } from '@/lib/hooks/use-local-storage'
+import { type Chat } from '@/lib/types'
+import { cn } from '@/lib/utils'
+
+interface SidebarItemProps {
+ index: number
+ chat: Chat
+ children: React.ReactNode
+}
+
+export function SidebarItem({ index, chat, children }: SidebarItemProps) {
+ const pathname = usePathname()
+
+ const isActive = pathname === chat.path
+ const [newChatId, setNewChatId] = useLocalStorage('newChatId', null)
+ const shouldAnimate = index === 0 && isActive && newChatId
+
+ if (!chat?.id) return null
+
+ return (
+
+
+ {chat.sharePath ? (
+
+
+
+
+ This is a shared chat.
+
+ ) : (
+
+ )}
+
+
+
+
+ {shouldAnimate ? (
+ chat.title.split('').map((character, index) => (
+ {
+ if (index === chat.title.length - 1) {
+ setNewChatId(null)
+ }
+ }}
+ >
+ {character}
+
+ ))
+ ) : (
+ {chat.title}
+ )}
+
+
+
+ {isActive && {children}
}
+
+ )
+}
diff --git a/components/sidebar-items.tsx b/components/sidebar-items.tsx
new file mode 100644
index 0000000..11cc7fc
--- /dev/null
+++ b/components/sidebar-items.tsx
@@ -0,0 +1,42 @@
+'use client'
+
+import { Chat } from '@/lib/types'
+import { AnimatePresence, motion } from 'framer-motion'
+
+import { removeChat, shareChat } from '@/app/actions'
+
+import { SidebarActions } from '@/components/sidebar-actions'
+import { SidebarItem } from '@/components/sidebar-item'
+
+interface SidebarItemsProps {
+ chats?: Chat[]
+}
+
+export function SidebarItems({ chats }: SidebarItemsProps) {
+ if (!chats?.length) return null
+
+ return (
+
+ {chats.map(
+ (chat, index) =>
+ chat && (
+
+
+
+
+
+ )
+ )}
+
+ )
+}
diff --git a/components/sidebar-list.tsx b/components/sidebar-list.tsx
new file mode 100644
index 0000000..9f04a97
--- /dev/null
+++ b/components/sidebar-list.tsx
@@ -0,0 +1,38 @@
+import { clearChats, getChats } from '@/app/actions'
+import { ClearHistory } from '@/components/clear-history'
+import { SidebarItems } from '@/components/sidebar-items'
+import { ThemeToggle } from '@/components/theme-toggle'
+import { cache } from 'react'
+
+interface SidebarListProps {
+ userId?: string
+ children?: React.ReactNode
+}
+
+const loadChats = cache(async (userId?: string) => {
+ return await getChats(userId)
+})
+
+export async function SidebarList({ userId }: SidebarListProps) {
+ const chats = await loadChats(userId)
+
+ return (
+
+
+ {chats?.length ? (
+
+
+
+ ) : (
+
+ )}
+
+
+ {/* */}
+ 0} />
+
+
+ )
+}
diff --git a/components/sidebar-mobile.tsx b/components/sidebar-mobile.tsx
new file mode 100644
index 0000000..82f0aa5
--- /dev/null
+++ b/components/sidebar-mobile.tsx
@@ -0,0 +1,31 @@
+'use client'
+
+import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'
+
+import { Sidebar } from '@/components/sidebar'
+import { Button } from '@/components/ui/button'
+
+import { IconSidebar } from '@/components/ui/icons'
+
+interface SidebarMobileProps {
+ children: React.ReactNode
+}
+
+export function SidebarMobile({ children }: SidebarMobileProps) {
+ return (
+
+
+
+
+ Toggle Sidebar
+
+
+
+ {children}
+
+
+ )
+}
diff --git a/components/sidebar-toggle.tsx b/components/sidebar-toggle.tsx
new file mode 100644
index 0000000..6c75009
--- /dev/null
+++ b/components/sidebar-toggle.tsx
@@ -0,0 +1,24 @@
+'use client'
+
+import * as React from 'react'
+
+import { useSidebar } from '@/lib/hooks/use-sidebar'
+import { Button } from '@/components/ui/button'
+import { IconSidebar } from '@/components/ui/icons'
+
+export function SidebarToggle() {
+ const { toggleSidebar } = useSidebar()
+
+ return (
+ {
+ toggleSidebar()
+ }}
+ >
+
+ Toggle Sidebar
+
+ )
+}
diff --git a/components/sidebar.tsx b/components/sidebar.tsx
new file mode 100644
index 0000000..52dc5bd
--- /dev/null
+++ b/components/sidebar.tsx
@@ -0,0 +1,21 @@
+'use client'
+
+import * as React from 'react'
+
+import { useSidebar } from '@/lib/hooks/use-sidebar'
+import { cn } from '@/lib/utils'
+
+export interface SidebarProps extends React.ComponentProps<'div'> {}
+
+export function Sidebar({ className, children }: SidebarProps) {
+ const { isSidebarOpen, isLoading } = useSidebar()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/components/signup-form.tsx b/components/signup-form.tsx
new file mode 100644
index 0000000..cda179c
--- /dev/null
+++ b/components/signup-form.tsx
@@ -0,0 +1,95 @@
+'use client'
+
+import { useFormState, useFormStatus } from 'react-dom'
+import { signup } from '@/app/signup/actions'
+import Link from 'next/link'
+import { useEffect } from 'react'
+import { toast } from 'sonner'
+import { IconSpinner } from './ui/icons'
+import { getMessageFromCode } from '@/lib/utils'
+import { useRouter } from 'next/navigation'
+
+export default function SignupForm() {
+ const router = useRouter()
+ const [result, dispatch] = useFormState(signup, undefined)
+
+ useEffect(() => {
+ if (result) {
+ if (result.type === 'error') {
+ toast.error(getMessageFromCode(result.resultCode))
+ } else {
+ toast.success(getMessageFromCode(result.resultCode))
+ router.refresh()
+ }
+ }
+ }, [result, router])
+
+ return (
+
+
+
Sign up for an account!
+
+
+
+
+
+ Already have an account?
+ Log in
+
+
+ )
+}
+
+function LoginButton() {
+ const { pending } = useFormStatus()
+
+ return (
+
+ {pending ? : 'Create account'}
+
+ )
+}
diff --git a/components/stocks/events-skeleton.tsx b/components/stocks/events-skeleton.tsx
new file mode 100644
index 0000000..0202362
--- /dev/null
+++ b/components/stocks/events-skeleton.tsx
@@ -0,0 +1,31 @@
+const placeholderEvents = [
+ {
+ date: '2022-10-01',
+ headline: 'NVIDIA releases new AI-powered graphics card',
+ description:
+ 'NVIDIA unveils the latest graphics card infused with AI capabilities, revolutionizing gaming and rendering experiences.'
+ }
+]
+
+export const EventsSkeleton = () => {
+ return (
+
+ {placeholderEvents.map(event => (
+
+
+ {event.date}
+
+
+ {event.headline}
+
+
+ {event.description.slice(0, 70)}...
+
+
+ ))}
+
+ )
+}
diff --git a/components/stocks/events.tsx b/components/stocks/events.tsx
new file mode 100644
index 0000000..a714994
--- /dev/null
+++ b/components/stocks/events.tsx
@@ -0,0 +1,30 @@
+import { format, parseISO } from 'date-fns'
+
+interface Event {
+ date: string
+ headline: string
+ description: string
+}
+
+export function Events({ props: events }: { props: Event[] }) {
+ return (
+
+ {events.map(event => (
+
+
+ {format(parseISO(event.date), 'dd LLL, yyyy')}
+
+
+ {event.headline}
+
+
+ {event.description.slice(0, 70)}...
+
+
+ ))}
+
+ )
+}
diff --git a/components/stocks/index.tsx b/components/stocks/index.tsx
new file mode 100644
index 0000000..13dedbe
--- /dev/null
+++ b/components/stocks/index.tsx
@@ -0,0 +1,36 @@
+'use client'
+
+import dynamic from 'next/dynamic'
+import { StockSkeleton } from './stock-skeleton'
+import { StocksSkeleton } from './stocks-skeleton'
+import { EventsSkeleton } from './events-skeleton'
+
+export { spinner } from './spinner'
+export { BotCard, BotMessage, SystemMessage } from './message'
+
+const Stock = dynamic(() => import('./stock').then(mod => mod.Stock), {
+ ssr: false,
+ loading: () =>
+})
+
+const Purchase = dynamic(
+ () => import('./stock-purchase').then(mod => mod.Purchase),
+ {
+ ssr: false,
+ loading: () => (
+
+ )
+ }
+)
+
+const Stocks = dynamic(() => import('./stocks').then(mod => mod.Stocks), {
+ ssr: false,
+ loading: () =>
+})
+
+const Events = dynamic(() => import('./events').then(mod => mod.Events), {
+ ssr: false,
+ loading: () =>
+})
+
+export { Stock, Purchase, Stocks, Events }
diff --git a/components/stocks/message.tsx b/components/stocks/message.tsx
new file mode 100644
index 0000000..6576878
--- /dev/null
+++ b/components/stocks/message.tsx
@@ -0,0 +1,136 @@
+'use client'
+
+/* eslint-disable @next/next/no-img-element */
+
+import { GoogleIcon, IconGemini, IconUser } from '@/components/ui/icons'
+import { cn } from '@/lib/utils'
+import { spinner } from './spinner'
+import { CodeBlock } from '../ui/codeblock'
+import { MemoizedReactMarkdown } from '../markdown'
+import remarkGfm from 'remark-gfm'
+import remarkMath from 'remark-math'
+import { StreamableValue } from 'ai/rsc'
+import { useStreamableText } from '@/lib/hooks/use-streamable-text'
+
+// Different types of message bubbles.
+
+export function UserMessage({ children }: { children: React.ReactNode }) {
+ return (
+
+ )
+}
+
+export function BotMessage({
+ content,
+ className
+}: {
+ content: string | StreamableValue
+ className?: string
+}) {
+ const text = useStreamableText(content)
+
+ return (
+
+
+
+
+
+ {children}
+ },
+ code({ node, inline, className, children, ...props }) {
+ if (children.length) {
+ if (children[0] == '▍') {
+ return (
+ ▍
+ )
+ }
+
+ children[0] = (children[0] as string).replace('`▍`', '▍')
+ }
+
+ const match = /language-(\w+)/.exec(className || '')
+
+ if (inline) {
+ return (
+
+ {children}
+
+ )
+ }
+
+ return (
+
+ )
+ }
+ }}
+ >
+ {text}
+
+
+
+ )
+}
+
+export function BotCard({
+ children,
+ showAvatar = true
+}: {
+ children: React.ReactNode
+ showAvatar?: boolean
+}) {
+ return (
+
+
+
+
+
{children}
+
+ )
+}
+
+export function SystemMessage({ children }: { children: React.ReactNode }) {
+ return (
+
+ )
+}
+
+export function SpinnerMessage() {
+ return (
+
+
+
+
+
+ {spinner}
+
+
+ )
+}
diff --git a/components/stocks/spinner.tsx b/components/stocks/spinner.tsx
new file mode 100644
index 0000000..8eab1d3
--- /dev/null
+++ b/components/stocks/spinner.tsx
@@ -0,0 +1,16 @@
+'use client'
+
+export const spinner = (
+
+
+
+)
diff --git a/components/stocks/stock-purchase.tsx b/components/stocks/stock-purchase.tsx
new file mode 100644
index 0000000..9f05d2e
--- /dev/null
+++ b/components/stocks/stock-purchase.tsx
@@ -0,0 +1,146 @@
+'use client'
+
+import { useId, useState } from 'react'
+import { useActions, useAIState, useUIState } from 'ai/rsc'
+import { formatNumber } from '@/lib/utils'
+
+import type { AI } from '@/lib/chat/actions'
+
+interface Purchase {
+ numberOfShares?: number
+ symbol: string
+ price: number
+ status: 'requires_action' | 'completed' | 'expired'
+}
+
+export function Purchase({
+ props: { numberOfShares, symbol, price, status = 'requires_action' }
+}: {
+ props: Purchase
+}) {
+ const [value, setValue] = useState(numberOfShares || 100)
+ const [purchasingUI, setPurchasingUI] = useState(null)
+ const [aiState, setAIState] = useAIState()
+ const [, setMessages] = useUIState()
+ const { confirmPurchase } = useActions()
+
+ // Unique identifier for this UI component.
+ const id = useId()
+
+ // Whenever the slider changes, we need to update the local value state and the history
+ // so LLM also knows what's going on.
+ function onSliderChange(e: React.ChangeEvent) {
+ const newValue = Number(e.target.value)
+ setValue(newValue)
+
+ // Insert a hidden history info to the list.
+ const message = {
+ role: 'system' as const,
+ content: `[User has changed to purchase ${newValue} shares of ${name}. Total cost: $${(
+ newValue * price
+ ).toFixed(2)}]`,
+
+ // Identifier of this UI component, so we don't insert it many times.
+ id
+ }
+
+ // If last history state is already this info, update it. This is to avoid
+ // adding every slider change to the history.
+ if (aiState.messages[aiState.messages.length - 1]?.id === id) {
+ setAIState({
+ ...aiState,
+ messages: [...aiState.messages.slice(0, -1), message]
+ })
+
+ return
+ }
+
+ // If it doesn't exist, append it to history.
+ setAIState({ ...aiState, messages: [...aiState.messages, message] })
+ }
+
+ return (
+
+
+ +1.23% ↑
+
+
{symbol}
+
${price}
+ {purchasingUI ? (
+
{purchasingUI}
+ ) : status === 'requires_action' ? (
+ <>
+
+
Shares to purchase
+
+
+ 10
+
+
+ 100
+
+
+ 500
+
+
+ 1000
+
+
+
+
+
Total cost
+
+
+ {value}
+
+ shares
+
+
+
×
+
+ ${price}
+
+ per share
+
+
+
+ = {formatNumber(value * price)}
+
+
+
+
+
{
+ const response = await confirmPurchase(symbol, price, value)
+ setPurchasingUI(response.purchasingUI)
+
+ // Insert a new system message to the UI.
+ setMessages((currentMessages: any) => [
+ ...currentMessages,
+ response.newMessage
+ ])
+ }}
+ >
+ Purchase
+
+ >
+ ) : status === 'completed' ? (
+
+ You have successfully purchased {value} ${symbol}. Total cost:{' '}
+ {formatNumber(value * price)}
+
+ ) : status === 'expired' ? (
+
Your checkout session has expired!
+ ) : null}
+
+ )
+}
diff --git a/components/stocks/stock-skeleton.tsx b/components/stocks/stock-skeleton.tsx
new file mode 100644
index 0000000..27b8709
--- /dev/null
+++ b/components/stocks/stock-skeleton.tsx
@@ -0,0 +1,22 @@
+export const StockSkeleton = () => {
+ return (
+
+
+ xxxxxxx
+
+
+ xxxx
+
+
+ xxxx
+
+
+ xxxxxx xxx xx xxxx xx xxx
+
+
+
+
+ )
+}
diff --git a/components/stocks/stock.tsx b/components/stocks/stock.tsx
new file mode 100644
index 0000000..a9da590
--- /dev/null
+++ b/components/stocks/stock.tsx
@@ -0,0 +1,210 @@
+'use client'
+
+import { useState, useRef, useEffect, useId } from 'react'
+import { scaleLinear } from 'd3-scale'
+import { subMonths, format } from 'date-fns'
+import { useResizeObserver } from 'usehooks-ts'
+import { useAIState } from 'ai/rsc'
+
+interface Stock {
+ symbol: string
+ price: number
+ delta: number
+}
+
+export function Stock({ props: { symbol, price, delta } }: { props: Stock }) {
+ const [aiState, setAIState] = useAIState()
+ const id = useId()
+
+ const [priceAtTime, setPriceAtTime] = useState({
+ time: '00:00',
+ value: price.toFixed(2),
+ x: 0
+ })
+
+ const [startHighlight, setStartHighlight] = useState(0)
+ const [endHighlight, setEndHighlight] = useState(0)
+
+ const chartRef = useRef(null)
+ const { width = 0 } = useResizeObserver({
+ ref: chartRef,
+ box: 'border-box'
+ })
+
+ const xToDate = scaleLinear(
+ [0, width],
+ [subMonths(new Date(), 6), new Date()]
+ )
+ const xToValue = scaleLinear(
+ [0, width],
+ [price - price / 2, price + price / 2]
+ )
+
+ useEffect(() => {
+ if (startHighlight && endHighlight) {
+ const message = {
+ id,
+ role: 'system' as const,
+ content: `[User has highlighted dates between between ${format(
+ xToDate(startHighlight),
+ 'd LLL'
+ )} and ${format(xToDate(endHighlight), 'd LLL, yyyy')}`
+ }
+
+ if (aiState.messages[aiState.messages.length - 1]?.id === id) {
+ setAIState({
+ ...aiState,
+ messages: [...aiState.messages.slice(0, -1), message]
+ })
+ } else {
+ setAIState({
+ ...aiState,
+ messages: [...aiState.messages, message]
+ })
+ }
+ }
+ }, [startHighlight, endHighlight])
+
+ return (
+
+
+ {`${delta > 0 ? '+' : ''}${((delta / price) * 100).toFixed(2)}% ${
+ delta > 0 ? '↑' : '↓'
+ }`}
+
+
{symbol}
+
${price}
+
+ Closed: Feb 27, 4:59 PM EST
+
+
+
{
+ if (chartRef.current) {
+ const { clientX } = event
+ const { left } = chartRef.current.getBoundingClientRect()
+
+ setStartHighlight(clientX - left)
+ setEndHighlight(0)
+
+ setPriceAtTime({
+ time: format(xToDate(clientX), 'dd LLL yy'),
+ value: xToValue(clientX).toFixed(2),
+ x: clientX - left
+ })
+ }
+ }}
+ onPointerUp={event => {
+ if (chartRef.current) {
+ const { clientX } = event
+ const { left } = chartRef.current.getBoundingClientRect()
+
+ setEndHighlight(clientX - left)
+ }
+ }}
+ onPointerMove={event => {
+ if (chartRef.current) {
+ const { clientX } = event
+ const { left } = chartRef.current.getBoundingClientRect()
+
+ setPriceAtTime({
+ time: format(xToDate(clientX), 'dd LLL yy'),
+ value: xToValue(clientX).toFixed(2),
+ x: clientX - left
+ })
+ }
+ }}
+ onPointerLeave={() => {
+ setPriceAtTime({
+ time: '00:00',
+ value: price.toFixed(2),
+ x: 0
+ })
+ }}
+ ref={chartRef}
+ >
+ {priceAtTime.x > 0 ? (
+
+
${priceAtTime.value}
+
+ {priceAtTime.time}
+
+
+ ) : null}
+
+ {startHighlight ? (
+
+ ) : null}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/components/stocks/stocks-skeleton.tsx b/components/stocks/stocks-skeleton.tsx
new file mode 100644
index 0000000..8355d99
--- /dev/null
+++ b/components/stocks/stocks-skeleton.tsx
@@ -0,0 +1,9 @@
+export const StocksSkeleton = () => {
+ return (
+
+ )
+}
diff --git a/components/stocks/stocks.tsx b/components/stocks/stocks.tsx
new file mode 100644
index 0000000..cf9c549
--- /dev/null
+++ b/components/stocks/stocks.tsx
@@ -0,0 +1,67 @@
+'use client'
+
+import { useActions, useUIState } from 'ai/rsc'
+
+import type { AI } from '@/lib/chat/actions'
+
+interface Stock {
+ symbol: string
+ price: number
+ delta: number
+}
+
+export function Stocks({ props: stocks }: { props: Stock[] }) {
+ const [, setMessages] = useUIState()
+ const { submitUserMessage } = useActions()
+
+ return (
+
+
+ {stocks.map(stock => (
+
{
+ const response = await submitUserMessage(`View ${stock.symbol}`)
+ setMessages(currentMessages => [...currentMessages, response])
+ }}
+ >
+ 0 ? 'text-green-600' : 'text-red-600'
+ } flex w-11 flex-row justify-center rounded-lg bg-white/10 p-2`}
+ >
+ {stock.delta > 0 ? '↑' : '↓'}
+
+
+
{stock.symbol}
+
+ ${stock.price.toExponential(1)}
+
+
+
+
0 ? 'text-green-600' : 'text-red-600'
+ } bold text-right uppercase`}
+ >
+ {` ${((stock.delta / stock.price) * 100).toExponential(1)}%`}
+
+
0 ? 'text-green-700' : 'text-red-700'
+ } text-right text-base`}
+ >
+ {stock.delta.toExponential(1)}
+
+
+
+ ))}
+
+
+ Note: Data and latency are simulated for illustrative purposes and
+ should not be considered as financial advice.
+
+
+ )
+}
diff --git a/components/tailwind-indicator.tsx b/components/tailwind-indicator.tsx
new file mode 100644
index 0000000..846faa9
--- /dev/null
+++ b/components/tailwind-indicator.tsx
@@ -0,0 +1,14 @@
+export function TailwindIndicator() {
+ if (process.env.NODE_ENV === 'production') return null
+
+ return (
+
+
xs
+
sm
+
md
+
lg
+
xl
+
2xl
+
+ )
+}
diff --git a/components/theme-toggle.tsx b/components/theme-toggle.tsx
new file mode 100644
index 0000000..67d3f1a
--- /dev/null
+++ b/components/theme-toggle.tsx
@@ -0,0 +1,31 @@
+'use client'
+
+import * as React from 'react'
+import { useTheme } from 'next-themes'
+
+import { Button } from '@/components/ui/button'
+import { IconMoon, IconSun } from '@/components/ui/icons'
+
+export function ThemeToggle() {
+ const { setTheme, theme } = useTheme()
+ const [_, startTransition] = React.useTransition()
+
+ return (
+ {
+ startTransition(() => {
+ setTheme(theme === 'light' ? 'dark' : 'light')
+ })
+ }}
+ >
+ {!theme ? null : theme === 'dark' ? (
+
+ ) : (
+
+ )}
+ Toggle theme
+
+ )
+}
diff --git a/components/ui/alert-dialog.tsx b/components/ui/alert-dialog.tsx
new file mode 100644
index 0000000..f38ab68
--- /dev/null
+++ b/components/ui/alert-dialog.tsx
@@ -0,0 +1,141 @@
+'use client'
+
+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'
+
+const AlertDialog = AlertDialogPrimitive.Root
+
+const AlertDialogTrigger = AlertDialogPrimitive.Trigger
+
+const AlertDialogPortal = AlertDialogPrimitive.Portal
+
+const AlertDialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
+
+const AlertDialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+
+))
+AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
+
+const AlertDialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+AlertDialogHeader.displayName = 'AlertDialogHeader'
+
+const AlertDialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+AlertDialogFooter.displayName = 'AlertDialogFooter'
+
+const AlertDialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
+
+const AlertDialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogDescription.displayName =
+ AlertDialogPrimitive.Description.displayName
+
+const AlertDialogAction = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
+
+const AlertDialogCancel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
+
+export {
+ AlertDialog,
+ AlertDialogPortal,
+ AlertDialogOverlay,
+ AlertDialogTrigger,
+ AlertDialogContent,
+ AlertDialogHeader,
+ AlertDialogFooter,
+ AlertDialogTitle,
+ AlertDialogDescription,
+ AlertDialogAction,
+ AlertDialogCancel
+}
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
new file mode 100644
index 0000000..9ac846a
--- /dev/null
+++ b/components/ui/badge.tsx
@@ -0,0 +1,36 @@
+import * as React from 'react'
+import { cva, type VariantProps } from 'class-variance-authority'
+
+import { cn } from '@/lib/utils'
+
+const badgeVariants = cva(
+ 'inline-flex items-center rounded-lg border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
+ {
+ variants: {
+ variant: {
+ default:
+ 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
+ secondary:
+ 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
+ destructive:
+ 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
+ outline: 'text-foreground'
+ }
+ },
+ defaultVariants: {
+ variant: 'default'
+ }
+ }
+)
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ )
+}
+
+export { Badge, badgeVariants }
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
new file mode 100644
index 0000000..6db16bb
--- /dev/null
+++ b/components/ui/button.tsx
@@ -0,0 +1,57 @@
+import * as React from 'react'
+import { Slot } from '@radix-ui/react-slot'
+import { cva, type VariantProps } from 'class-variance-authority'
+
+import { cn } from '@/lib/utils'
+
+const buttonVariants = cva(
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
+ {
+ variants: {
+ variant: {
+ default:
+ 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
+ destructive:
+ 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
+ outline:
+ 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
+ secondary:
+ 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
+ link: 'text-primary underline-offset-4 hover:underline'
+ },
+ size: {
+ default: 'h-9 px-4 py-2',
+ sm: 'h-8 rounded-lg px-3 text-xs',
+ lg: 'h-10 rounded-lg px-8',
+ icon: 'size-9'
+ }
+ },
+ defaultVariants: {
+ variant: 'default',
+ 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'
+
+export { Button, buttonVariants }
diff --git a/components/ui/codeblock.tsx b/components/ui/codeblock.tsx
new file mode 100644
index 0000000..1bde5ac
--- /dev/null
+++ b/components/ui/codeblock.tsx
@@ -0,0 +1,148 @@
+// Inspired by Chatbot-UI and modified to fit the needs of this project
+// @see https://github.com/mckaywrigley/chatbot-ui/blob/main/components/Markdown/CodeBlock.tsx
+
+'use client'
+
+import { FC, memo } from '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-clipboard'
+import { IconCheck, IconCopy, IconDownload } from '@/components/ui/icons'
+import { Button } from '@/components/ui/button'
+
+interface Props {
+ language: string
+ value: string
+}
+
+interface languageMap {
+ [key: string]: string | undefined
+}
+
+export const programmingLanguages: languageMap = {
+ javascript: '.js',
+ python: '.py',
+ java: '.java',
+ c: '.c',
+ cpp: '.cpp',
+ 'c++': '.cpp',
+ 'c#': '.cs',
+ ruby: '.rb',
+ php: '.php',
+ swift: '.swift',
+ 'objective-c': '.m',
+ kotlin: '.kt',
+ typescript: '.ts',
+ go: '.go',
+ perl: '.pl',
+ rust: '.rs',
+ scala: '.scala',
+ haskell: '.hs',
+ lua: '.lua',
+ shell: '.sh',
+ sql: '.sql',
+ html: '.html',
+ css: '.css'
+ // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
+}
+
+export const generateRandomString = (length: number, lowercase = false) => {
+ const chars = 'ABCDEFGHJKLMNPQRSTUVWXY3456789' // excluding similar looking characters like Z, 2, I, 1, O, 0
+ let result = ''
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length))
+ }
+ return lowercase ? result.toLowerCase() : result
+}
+
+const CodeBlock: FC = memo(({ language, value }) => {
+ const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })
+
+ const downloadAsFile = () => {
+ if (typeof window === 'undefined') {
+ return
+ }
+ const fileExtension = programmingLanguages[language] || '.file'
+ const suggestedFileName = `file-${generateRandomString(
+ 3,
+ true
+ )}${fileExtension}`
+ const fileName = window.prompt('Enter file name' || '', suggestedFileName)
+
+ if (!fileName) {
+ // User pressed cancel on prompt.
+ return
+ }
+
+ const blob = new Blob([value], { type: 'text/plain' })
+ const url = URL.createObjectURL(blob)
+ const link = document.createElement('a')
+ link.download = fileName
+ link.href = url
+ link.style.display = 'none'
+ document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(link)
+ URL.revokeObjectURL(url)
+ }
+
+ const onCopy = () => {
+ if (isCopied) return
+ copyToClipboard(value)
+ }
+
+ return (
+
+
+
{language}
+
+
+
+ Download
+
+
+ {isCopied ? : }
+ Copy code
+
+
+
+
+ {value}
+
+
+ )
+})
+CodeBlock.displayName = 'CodeBlock'
+
+export { CodeBlock }
diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx
new file mode 100644
index 0000000..f078780
--- /dev/null
+++ b/components/ui/dialog.tsx
@@ -0,0 +1,122 @@
+'use client'
+
+import * as React from 'react'
+import * as DialogPrimitive from '@radix-ui/react-dialog'
+import { Cross2Icon } from '@radix-ui/react-icons'
+
+import { cn } from '@/lib/utils'
+
+const Dialog = DialogPrimitive.Root
+
+const DialogTrigger = DialogPrimitive.Trigger
+
+const DialogPortal = DialogPrimitive.Portal
+
+const DialogClose = DialogPrimitive.Close
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+))
+DialogContent.displayName = DialogPrimitive.Content.displayName
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogHeader.displayName = 'DialogHeader'
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogFooter.displayName = 'DialogFooter'
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogTitle.displayName = DialogPrimitive.Title.displayName
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogDescription.displayName = DialogPrimitive.Description.displayName
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogTrigger,
+ DialogClose,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription
+}
diff --git a/components/ui/dropdown-menu.tsx b/components/ui/dropdown-menu.tsx
new file mode 100644
index 0000000..e7af75e
--- /dev/null
+++ b/components/ui/dropdown-menu.tsx
@@ -0,0 +1,205 @@
+'use client'
+
+import * as React from 'react'
+import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
+import {
+ CheckIcon,
+ ChevronRightIcon,
+ DotFilledIcon
+} from '@radix-ui/react-icons'
+
+import { cn } from '@/lib/utils'
+
+const DropdownMenu = DropdownMenuPrimitive.Root
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup
+}
diff --git a/components/ui/icons.tsx b/components/ui/icons.tsx
new file mode 100644
index 0000000..c5adc23
--- /dev/null
+++ b/components/ui/icons.tsx
@@ -0,0 +1,765 @@
+'use client'
+
+import * as React from 'react'
+
+import { cn } from '@/lib/utils'
+
+function IconNextChat({
+ className,
+ inverted,
+ ...props
+}: React.ComponentProps<'svg'> & { inverted?: boolean }) {
+ const id = React.useId()
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+function IconGemini({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+ Gemini icon
+
+
+ )
+}
+
+function IconVercel({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconGitHub({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+ GitHub
+
+
+ )
+}
+
+function IconSeparator({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconArrowDown({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconArrowRight({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconUser({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconPlus({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconArrowElbow({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconSpinner({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconMessage({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconTrash({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconRefresh({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconStop({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconSidebar({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconMoon({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconSun({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconCopy({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconCheck({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconDownload({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconClose({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconEdit({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconShare({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconUsers({ className, ...props }: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconExternalLink({
+ className,
+ ...props
+}: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+function IconChevronUpDown({
+ className,
+ ...props
+}: React.ComponentProps<'svg'>) {
+ return (
+
+
+
+ )
+}
+
+export const GoogleIcon = () => {
+ return (
+
+
+
+
+
+
+ )
+}
+
+export const ArrowUpRight = () => {
+ return (
+
+
+
+ )
+}
+
+export const ArrowDownRight = () => {
+ return (
+
+
+
+ )
+}
+
+export const SparklesIcon = () => {
+ return (
+
+
+
+
+
+ )
+}
+
+export const LockIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const CheckIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const CardIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const SpinnerIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const DeviceIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const GooglePayIcon = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export {
+ IconEdit,
+ IconNextChat,
+ IconGemini,
+ IconVercel,
+ IconGitHub,
+ IconSeparator,
+ IconArrowDown,
+ IconArrowRight,
+ IconUser,
+ IconPlus,
+ IconArrowElbow,
+ IconSpinner,
+ IconMessage,
+ IconTrash,
+ IconRefresh,
+ IconStop,
+ IconSidebar,
+ IconMoon,
+ IconSun,
+ IconCopy,
+ IconCheck,
+ IconDownload,
+ IconClose,
+ IconShare,
+ IconUsers,
+ IconExternalLink,
+ IconChevronUpDown
+}
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
new file mode 100644
index 0000000..452b06c
--- /dev/null
+++ b/components/ui/input.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react'
+
+import { cn } from '@/lib/utils'
+
+export interface InputProps
+ extends React.InputHTMLAttributes {}
+
+const Input = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Input.displayName = 'Input'
+
+export { Input }
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
new file mode 100644
index 0000000..5341821
--- /dev/null
+++ b/components/ui/label.tsx
@@ -0,0 +1,26 @@
+"use client"
+
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/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/components/ui/select.tsx b/components/ui/select.tsx
new file mode 100644
index 0000000..364a56c
--- /dev/null
+++ b/components/ui/select.tsx
@@ -0,0 +1,164 @@
+'use client'
+
+import * as React from 'react'
+import {
+ CaretSortIcon,
+ CheckIcon,
+ ChevronDownIcon,
+ ChevronUpIcon
+} from '@radix-ui/react-icons'
+import * as SelectPrimitive from '@radix-ui/react-select'
+
+import { cn } from '@/lib/utils'
+
+const Select = SelectPrimitive.Root
+
+const SelectGroup = SelectPrimitive.Group
+
+const SelectValue = SelectPrimitive.Value
+
+const SelectTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+ span]:line-clamp-1',
+ className
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+
+))
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
+
+const SelectScrollUpButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
+
+const SelectScrollDownButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+SelectScrollDownButton.displayName =
+ SelectPrimitive.ScrollDownButton.displayName
+
+const SelectContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, position = 'popper', ...props }, ref) => (
+
+
+
+
+ {children}
+
+
+
+
+))
+SelectContent.displayName = SelectPrimitive.Content.displayName
+
+const SelectLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+SelectLabel.displayName = SelectPrimitive.Label.displayName
+
+const SelectItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+SelectItem.displayName = SelectPrimitive.Item.displayName
+
+const SelectSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName
+
+export {
+ Select,
+ SelectGroup,
+ SelectValue,
+ SelectTrigger,
+ SelectContent,
+ SelectLabel,
+ SelectItem,
+ SelectSeparator,
+ SelectScrollUpButton,
+ SelectScrollDownButton
+}
diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx
new file mode 100644
index 0000000..12d81c4
--- /dev/null
+++ b/components/ui/separator.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import * as SeparatorPrimitive from "@radix-ui/react-separator"
+
+import { cn } from "@/lib/utils"
+
+const Separator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(
+ (
+ { className, orientation = "horizontal", decorative = true, ...props },
+ ref
+ ) => (
+
+ )
+)
+Separator.displayName = SeparatorPrimitive.Root.displayName
+
+export { Separator }
diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx
new file mode 100644
index 0000000..a16275c
--- /dev/null
+++ b/components/ui/sheet.tsx
@@ -0,0 +1,140 @@
+"use client"
+
+import * as React from "react"
+import * as SheetPrimitive from "@radix-ui/react-dialog"
+import { Cross2Icon } from "@radix-ui/react-icons"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/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/components/ui/sonner.tsx b/components/ui/sonner.tsx
new file mode 100644
index 0000000..452f4d9
--- /dev/null
+++ b/components/ui/sonner.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import { useTheme } from "next-themes"
+import { Toaster as Sonner } from "sonner"
+
+type ToasterProps = React.ComponentProps
+
+const Toaster = ({ ...props }: ToasterProps) => {
+ const { theme = "system" } = useTheme()
+
+ return (
+
+ )
+}
+
+export { Toaster }
diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx
new file mode 100644
index 0000000..37d61e4
--- /dev/null
+++ b/components/ui/switch.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as SwitchPrimitives from "@radix-ui/react-switch"
+
+import { cn } from "@/lib/utils"
+
+const Switch = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+Switch.displayName = SwitchPrimitives.Root.displayName
+
+export { Switch }
diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx
new file mode 100644
index 0000000..de1c556
--- /dev/null
+++ b/components/ui/textarea.tsx
@@ -0,0 +1,24 @@
+import * as React from 'react'
+
+import { cn } from '@/lib/utils'
+
+export interface TextareaProps
+ extends React.TextareaHTMLAttributes {}
+
+const Textarea = React.forwardRef(
+ ({ className, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Textarea.displayName = 'Textarea'
+
+export { Textarea }
diff --git a/components/ui/tooltip.tsx b/components/ui/tooltip.tsx
new file mode 100644
index 0000000..a733751
--- /dev/null
+++ b/components/ui/tooltip.tsx
@@ -0,0 +1,30 @@
+'use client'
+
+import * as React from 'react'
+import * as TooltipPrimitive from '@radix-ui/react-tooltip'
+
+import { cn } from '@/lib/utils'
+
+const TooltipProvider = TooltipPrimitive.Provider
+
+const Tooltip = TooltipPrimitive.Root
+
+const TooltipTrigger = TooltipPrimitive.Trigger
+
+const TooltipContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+))
+TooltipContent.displayName = TooltipPrimitive.Content.displayName
+
+export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
diff --git a/components/user-menu.tsx b/components/user-menu.tsx
new file mode 100644
index 0000000..3ad28f0
--- /dev/null
+++ b/components/user-menu.tsx
@@ -0,0 +1,53 @@
+import { type Session } from '@/lib/types'
+
+import { Button } from '@/components/ui/button'
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSeparator,
+ DropdownMenuTrigger
+} from '@/components/ui/dropdown-menu'
+import { signOut } from '@/auth'
+
+export interface UserMenuProps {
+ user: Session['user']
+}
+
+function getUserInitials(name: string) {
+ const [firstName, lastName] = name.split(' ')
+ return lastName ? `${firstName[0]}${lastName[0]}` : firstName.slice(0, 2)
+}
+
+export function UserMenu({ user }: UserMenuProps) {
+ return (
+
+
+
+
+
+ {getUserInitials(user.email)}
+
+ {user.email}
+
+
+
+
+ {user.email}
+
+
+ {
+ 'use server'
+ await signOut()
+ }}
+ >
+
+ Sign Out
+
+
+
+
+
+ )
+}
diff --git a/lib/chat/actions.tsx b/lib/chat/actions.tsx
new file mode 100644
index 0000000..a97e067
--- /dev/null
+++ b/lib/chat/actions.tsx
@@ -0,0 +1,691 @@
+// @ts-nocheck
+
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable @next/next/no-img-element */
+import 'server-only'
+
+import {
+ createAI,
+ createStreamableUI,
+ getMutableAIState,
+ getAIState,
+ createStreamableValue
+} from 'ai/rsc'
+
+import { BotCard, BotMessage } from '@/components/stocks'
+
+import { nanoid, sleep } from '@/lib/utils'
+import { saveChat } from '@/app/actions'
+import { SpinnerMessage, UserMessage } from '@/components/stocks/message'
+import { Chat } from '../types'
+import { auth } from '@/auth'
+import { FlightStatus } from '@/components/flights/flight-status'
+import { SelectSeats } from '@/components/flights/select-seats'
+import { ListFlights } from '@/components/flights/list-flights'
+import { BoardingPass } from '@/components/flights/boarding-pass'
+import { PurchaseTickets } from '@/components/flights/purchase-ticket'
+import { CheckIcon, SpinnerIcon } from '@/components/ui/icons'
+import { format } from 'date-fns'
+import { streamText } from 'ai'
+import { google } from '@ai-sdk/google'
+import { GoogleGenerativeAI } from '@google/generative-ai'
+import { z } from 'zod'
+import { ListHotels } from '@/components/hotels/list-hotels'
+import { Destinations } from '@/components/flights/destinations'
+import { Video } from '@/components/media/video'
+import { rateLimit } from './ratelimit'
+
+const genAI = new GoogleGenerativeAI(
+ process.env.GOOGLE_GENERATIVE_AI_API_KEY || ''
+)
+
+async function describeImage(imageBase64: string) {
+ 'use server'
+
+ await rateLimit()
+
+ const aiState = getMutableAIState()
+ const spinnerStream = createStreamableUI(null)
+ const messageStream = createStreamableUI(null)
+ const uiStream = createStreamableUI()
+
+ uiStream.update(
+
+
+
+ )
+ ;(async () => {
+ try {
+ let text = ''
+
+ // attachment as video for demo purposes,
+ // add your implementation here to support
+ // video as input for prompts.
+ if (imageBase64 === '') {
+ await new Promise(resolve => setTimeout(resolve, 5000))
+
+ text = `
+ The books in this image are:
+
+ 1. The Little Prince by Antoine de Saint-Exupéry
+ 2. The Prophet by Kahlil Gibran
+ 3. Man's Search for Meaning by Viktor Frankl
+ 4. The Alchemist by Paulo Coelho
+ 5. The Kite Runner by Khaled Hosseini
+ 6. To Kill a Mockingbird by Harper Lee
+ 7. The Catcher in the Rye by J.D. Salinger
+ 8. The Great Gatsby by F. Scott Fitzgerald
+ 9. 1984 by George Orwell
+ 10. Animal Farm by George Orwell
+ `
+ } else {
+ const imageData = imageBase64.split(',')[1]
+
+ const model = genAI.getGenerativeModel({ model: 'gemini-pro-vision' })
+ const prompt = 'List the books in this image.'
+ const image = {
+ inlineData: {
+ data: imageData,
+ mimeType: 'image/png'
+ }
+ }
+
+ const result = await model.generateContent([prompt, image])
+ text = result.response.text()
+ console.log(text)
+ }
+
+ spinnerStream.done(null)
+ messageStream.done(null)
+
+ uiStream.done(
+
+
+
+ )
+
+ aiState.done({
+ ...aiState.get(),
+ interactions: [text]
+ })
+ } catch (e) {
+ console.error(e)
+
+ const error = new Error(
+ 'The AI got rate limited, please try again later.'
+ )
+ uiStream.error(error)
+ spinnerStream.error(error)
+ messageStream.error(error)
+ aiState.done()
+ }
+ })()
+
+ return {
+ id: nanoid(),
+ attachments: uiStream.value,
+ spinner: spinnerStream.value,
+ display: messageStream.value
+ }
+}
+
+async function submitUserMessage(content: string) {
+ 'use server'
+
+ await rateLimit()
+
+ const aiState = getMutableAIState()
+
+ aiState.update({
+ ...aiState.get(),
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'user',
+ content: `${aiState.get().interactions.join('\n\n')}\n\n${content}`
+ }
+ ]
+ })
+
+ const history = aiState.get().messages.map(message => ({
+ role: message.role,
+ content: message.content
+ }))
+ // console.log(history)
+
+ const textStream = createStreamableValue('')
+ const spinnerStream = createStreamableUI( )
+ const messageStream = createStreamableUI(null)
+ const uiStream = createStreamableUI()
+
+ ;(async () => {
+ try {
+ const result = await streamText({
+ model: google('models/gemini-1.5-flash'),
+ temperature: 0,
+ tools: {
+ showFlights: {
+ description:
+ "List available flights in the UI. List 3 that match user's query.",
+ parameters: z.object({
+ departingCity: z.string(),
+ arrivalCity: z.string(),
+ departingAirport: z.string().describe('Departing airport code'),
+ arrivalAirport: z.string().describe('Arrival airport code'),
+ date: z
+ .string()
+ .describe(
+ "Date of the user's flight, example format: 6 April, 1998"
+ )
+ })
+ },
+ listDestinations: {
+ description: 'List destinations to travel cities, max 5.',
+ parameters: z.object({
+ destinations: z.array(
+ z
+ .string()
+ .describe(
+ 'List of destination cities. Include rome as one of the cities.'
+ )
+ )
+ })
+ },
+ showSeatPicker: {
+ description:
+ 'Show the UI to choose or change seat for the selected flight.',
+ parameters: z.object({
+ departingCity: z.string(),
+ arrivalCity: z.string(),
+ flightCode: z.string(),
+ date: z.string()
+ })
+ },
+ showHotels: {
+ description: 'Show the UI to choose a hotel for the trip.',
+ parameters: z.object({ city: z.string() })
+ },
+ checkoutBooking: {
+ description:
+ 'Show the UI to purchase/checkout a flight and hotel booking.',
+ parameters: z.object({ shouldConfirm: z.boolean() })
+ },
+ showBoardingPass: {
+ description: "Show user's imaginary boarding pass.",
+ parameters: z.object({
+ airline: z.string(),
+ arrival: z.string(),
+ departure: z.string(),
+ departureTime: z.string(),
+ arrivalTime: z.string(),
+ price: z.number(),
+ seat: z.string(),
+ date: z
+ .string()
+ .describe('Date of the flight, example format: 6 April, 1998'),
+ gate: z.string()
+ })
+ },
+ showFlightStatus: {
+ description:
+ 'Get the current status of imaginary flight by flight number and date.',
+ parameters: z.object({
+ flightCode: z.string(),
+ date: z.string(),
+ departingCity: z.string(),
+ departingAirport: z.string(),
+ departingAirportCode: z.string(),
+ departingTime: z.string(),
+ arrivalCity: z.string(),
+ arrivalAirport: z.string(),
+ arrivalAirportCode: z.string(),
+ arrivalTime: z.string()
+ })
+ }
+ },
+ system: `\
+ You are a friendly assistant that helps the user with booking flights to destinations that are based on a list of books. You can you give travel recommendations based on the books, and will continue to help the user book a flight to their destination.
+
+ The date today is ${format(new Date(), 'd LLLL, yyyy')}.
+ The user's current location is San Francisco, CA, so the departure city will be San Francisco and airport will be San Francisco International Airport (SFO). The user would like to book the flight out on May 12, 2024.
+
+ List United Airlines flights only.
+
+ Here's the flow:
+ 1. List holiday destinations based on a collection of books.
+ 2. List flights to destination.
+ 3. Choose a flight.
+ 4. Choose a seat.
+ 5. Choose hotel
+ 6. Purchase booking.
+ 7. Show boarding pass.
+ `,
+ messages: [...history]
+ })
+
+ let textContent = ''
+ spinnerStream.done(null)
+
+ for await (const delta of result.fullStream) {
+ const { type } = delta
+
+ if (type === 'text-delta') {
+ const { textDelta } = delta
+
+ textContent += textDelta
+ messageStream.update( )
+
+ aiState.update({
+ ...aiState.get(),
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content: textContent
+ }
+ ]
+ })
+ } else if (type === 'tool-call') {
+ const { toolName, args } = delta
+
+ if (toolName === 'listDestinations') {
+ const { destinations } = args
+
+ uiStream.update(
+
+
+
+ )
+
+ aiState.done({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content: `Here's a list of holiday destinations based on the books you've read. Choose one to proceed to booking a flight. \n\n ${args.destinations.join(', ')}.`,
+ display: {
+ name: 'listDestinations',
+ props: {
+ destinations
+ }
+ }
+ }
+ ]
+ })
+ } else if (toolName === 'showFlights') {
+ aiState.done({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content:
+ "Here's a list of flights for you. Choose one and we can proceed to pick a seat.",
+ display: {
+ name: 'showFlights',
+ props: {
+ summary: args
+ }
+ }
+ }
+ ]
+ })
+
+ uiStream.update(
+
+
+
+ )
+ } else if (toolName === 'showSeatPicker') {
+ aiState.done({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content:
+ "Here's a list of available seats for you to choose from. Select one to proceed to payment.",
+ display: {
+ name: 'showSeatPicker',
+ props: {
+ summary: args
+ }
+ }
+ }
+ ]
+ })
+
+ uiStream.update(
+
+
+
+ )
+ } else if (toolName === 'showHotels') {
+ aiState.done({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content:
+ "Here's a list of hotels for you to choose from. Select one to proceed to payment.",
+ display: {
+ name: 'showHotels',
+ props: {}
+ }
+ }
+ ]
+ })
+
+ uiStream.update(
+
+
+
+ )
+ } else if (toolName === 'checkoutBooking') {
+ aiState.done({
+ ...aiState.get(),
+ interactions: []
+ })
+
+ uiStream.update(
+
+
+
+ )
+ } else if (toolName === 'showBoardingPass') {
+ aiState.done({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content:
+ "Here's your boarding pass. Please have it ready for your flight.",
+ display: {
+ name: 'showBoardingPass',
+ props: {
+ summary: args
+ }
+ }
+ }
+ ]
+ })
+
+ uiStream.update(
+
+
+
+ )
+ } else if (toolName === 'showFlightStatus') {
+ aiState.update({
+ ...aiState.get(),
+ interactions: [],
+ messages: [
+ ...aiState.get().messages,
+ {
+ id: nanoid(),
+ role: 'assistant',
+ content: `The flight status of ${args.flightCode} is as follows:
+ Departing: ${args.departingCity} at ${args.departingTime} from ${args.departingAirport} (${args.departingAirportCode})
+ `
+ }
+ ],
+ display: {
+ name: 'showFlights',
+ props: {
+ summary: args
+ }
+ }
+ })
+
+ uiStream.update(
+
+
+
+ )
+ }
+ }
+ }
+
+ uiStream.done()
+ textStream.done()
+ messageStream.done()
+ } catch (e) {
+ console.error(e)
+
+ const error = new Error(
+ 'The AI got rate limited, please try again later.'
+ )
+ uiStream.error(error)
+ textStream.error(error)
+ messageStream.error(error)
+ aiState.done()
+ }
+ })()
+
+ return {
+ id: nanoid(),
+ attachments: uiStream.value,
+ spinner: spinnerStream.value,
+ display: messageStream.value
+ }
+}
+
+export async function requestCode() {
+ 'use server'
+
+ const aiState = getMutableAIState()
+
+ aiState.done({
+ ...aiState.get(),
+ messages: [
+ ...aiState.get().messages,
+ {
+ role: 'assistant',
+ content:
+ "A code has been sent to user's phone. They should enter it in the user interface to continue."
+ }
+ ]
+ })
+
+ const ui = createStreamableUI(
+
+
+
+ )
+
+ ;(async () => {
+ await sleep(2000)
+ ui.done()
+ })()
+
+ return {
+ status: 'requires_code',
+ display: ui.value
+ }
+}
+
+export async function validateCode() {
+ 'use server'
+
+ const aiState = getMutableAIState()
+
+ const status = createStreamableValue('in_progress')
+ const ui = createStreamableUI(
+
+
+
+
+
+ Please wait while we fulfill your order.
+
+
+ )
+
+ ;(async () => {
+ await sleep(2000)
+
+ ui.done(
+
+
+
Payment Succeeded
+
+ Thanks for your purchase! You will receive an email confirmation
+ shortly.
+
+
+ )
+
+ aiState.done({
+ ...aiState.get(),
+ messages: [
+ ...aiState.get().messages.slice(0, -1),
+ {
+ role: 'assistant',
+ content: 'The purchase has completed successfully.'
+ }
+ ]
+ })
+
+ status.done('completed')
+ })()
+
+ return {
+ status: status.value,
+ display: ui.value
+ }
+}
+
+export type Message = {
+ role: 'user' | 'assistant' | 'system' | 'function' | 'data' | 'tool'
+ content: string
+ id?: string
+ name?: string
+ display?: {
+ name: string
+ props: Record
+ }
+}
+
+export type AIState = {
+ chatId: string
+ interactions?: string[]
+ messages: Message[]
+}
+
+export type UIState = {
+ id: string
+ display: React.ReactNode
+ spinner?: React.ReactNode
+ attachments?: React.ReactNode
+}[]
+
+export const AI = createAI({
+ actions: {
+ submitUserMessage,
+ requestCode,
+ validateCode,
+ describeImage
+ },
+ initialUIState: [],
+ initialAIState: { chatId: nanoid(), interactions: [], messages: [] },
+ unstable_onGetUIState: async () => {
+ 'use server'
+
+ const session = await auth()
+
+ if (session && session.user) {
+ const aiState = getAIState()
+
+ if (aiState) {
+ const uiState = getUIStateFromAIState(aiState)
+ return uiState
+ }
+ } else {
+ return
+ }
+ },
+ unstable_onSetAIState: async ({ state }) => {
+ 'use server'
+
+ const session = await auth()
+
+ if (session && session.user) {
+ const { chatId, messages } = state
+
+ const createdAt = new Date()
+ const userId = session.user.id as string
+ const path = `/chat/${chatId}`
+ const title = messages[0].content.substring(0, 100)
+
+ const chat: Chat = {
+ id: chatId,
+ title,
+ userId,
+ createdAt,
+ messages,
+ path
+ }
+
+ await saveChat(chat)
+ } else {
+ return
+ }
+ }
+})
+
+export const getUIStateFromAIState = (aiState: Chat) => {
+ return aiState.messages
+ .filter(message => message.role !== 'system')
+ .map((message, index) => ({
+ id: `${aiState.chatId}-${index}`,
+ display:
+ message.role === 'assistant' ? (
+ message.display?.name === 'showFlights' ? (
+
+
+
+ ) : message.display?.name === 'showSeatPicker' ? (
+
+
+
+ ) : message.display?.name === 'showHotels' ? (
+
+
+
+ ) : message.content === 'The purchase has completed successfully.' ? (
+
+
+
+ ) : message.display?.name === 'showBoardingPass' ? (
+
+
+
+ ) : message.display?.name === 'listDestinations' ? (
+
+
+
+ ) : (
+
+ )
+ ) : message.role === 'user' ? (
+ {message.content}
+ ) : (
+
+ )
+ }))
+}
diff --git a/lib/chat/ratelimit.ts b/lib/chat/ratelimit.ts
new file mode 100644
index 0000000..6ad48dc
--- /dev/null
+++ b/lib/chat/ratelimit.ts
@@ -0,0 +1,22 @@
+import { Ratelimit } from '@upstash/ratelimit'
+import { kv } from '@vercel/kv'
+import { redirect } from 'next/navigation'
+import { headers } from 'next/headers'
+
+const geminiRatelimit = new Ratelimit({
+ redis: kv,
+ limiter: Ratelimit.slidingWindow(60, '1 m'),
+ analytics: true,
+ prefix: 'gemini_ratelimit'
+})
+
+function getIP() {
+ return headers().get('x-real-ip') ?? 'unknown'
+}
+
+export async function rateLimit() {
+ const limit = await geminiRatelimit.limit(getIP())
+ if (!limit.success) {
+ redirect('/waiting-room')
+ }
+}
diff --git a/lib/chat/responses.tsx b/lib/chat/responses.tsx
new file mode 100644
index 0000000..21254d9
--- /dev/null
+++ b/lib/chat/responses.tsx
@@ -0,0 +1,68 @@
+export const responses = {
+ listFlights: {
+ arrival: 'SFO',
+ departure: 'JFK',
+ flights: [
+ {
+ id: 1,
+ airlines: 'Cathay Pacific',
+ departureTime: '11:00',
+ arrivalTime: '14:00',
+ price: 200
+ },
+ {
+ id: 2,
+ airlines: 'Lufthansa',
+ departureTime: '15:00',
+ arrivalTime: '18:00',
+ price: 250
+ },
+ {
+ id: 3,
+ airlines: 'Cathay Pacific',
+ departureTime: '19:00',
+ arrivalTime: '22:00',
+ price: 300
+ }
+ ]
+ },
+ showSeatPicker: {
+ summary: {
+ departingCity: 'San Francisco',
+ arrivalCity: 'New York City',
+ flightCode: 'BA123',
+ date: '23 March 2024'
+ }
+ },
+ showPurchaseFlight: {
+ status: 'requires_confirmation',
+ summary: {
+ airline: 'American Airlines',
+ departureTime: '10:00 AM',
+ arrivalTime: '12:00 PM',
+ price: 100,
+ seat: '1A'
+ }
+ },
+ showBoardingPass: {
+ airline: 'American Airlines',
+ arrival: 'SFO',
+ departure: 'NYC',
+ departureTime: '10:00 AM',
+ arrivalTime: '12:00 PM',
+ price: 100,
+ seat: '1A'
+ },
+ getFlightStatus: {
+ departingCity: 'Miami',
+ departingAirport: 'Miami Intl',
+ departingAirportCode: 'MIA',
+ departingTime: '11:45 PM',
+ arrivalCity: 'San Francisco',
+ arrivalAirport: 'San Francisco Intl',
+ arrivalAirportCode: 'SFO',
+ arrivalTime: '4:20 PM',
+ flightCode: 'XY 2421',
+ date: 'Mon, 16 Sep'
+ }
+}
diff --git a/lib/hooks/use-copy-to-clipboard.tsx b/lib/hooks/use-copy-to-clipboard.tsx
new file mode 100644
index 0000000..62f7156
--- /dev/null
+++ b/lib/hooks/use-copy-to-clipboard.tsx
@@ -0,0 +1,33 @@
+'use client'
+
+import * as React from 'react'
+
+export interface useCopyToClipboardProps {
+ timeout?: number
+}
+
+export function useCopyToClipboard({
+ timeout = 2000
+}: useCopyToClipboardProps) {
+ const [isCopied, setIsCopied] = React.useState(false)
+
+ const copyToClipboard = (value: string) => {
+ if (typeof window === 'undefined' || !navigator.clipboard?.writeText) {
+ return
+ }
+
+ if (!value) {
+ return
+ }
+
+ navigator.clipboard.writeText(value).then(() => {
+ setIsCopied(true)
+
+ setTimeout(() => {
+ setIsCopied(false)
+ }, timeout)
+ })
+ }
+
+ return { isCopied, copyToClipboard }
+}
diff --git a/lib/hooks/use-enter-submit.tsx b/lib/hooks/use-enter-submit.tsx
new file mode 100644
index 0000000..d66b2d3
--- /dev/null
+++ b/lib/hooks/use-enter-submit.tsx
@@ -0,0 +1,23 @@
+import { useRef, type RefObject } from 'react'
+
+export function useEnterSubmit(): {
+ formRef: RefObject
+ onKeyDown: (event: React.KeyboardEvent) => void
+} {
+ const formRef = useRef(null)
+
+ const handleKeyDown = (
+ event: React.KeyboardEvent
+ ): void => {
+ if (
+ event.key === 'Enter' &&
+ !event.shiftKey &&
+ !event.nativeEvent.isComposing
+ ) {
+ formRef.current?.requestSubmit()
+ event.preventDefault()
+ }
+ }
+
+ return { formRef, onKeyDown: handleKeyDown }
+}
diff --git a/lib/hooks/use-local-storage.ts b/lib/hooks/use-local-storage.ts
new file mode 100644
index 0000000..19f6b7e
--- /dev/null
+++ b/lib/hooks/use-local-storage.ts
@@ -0,0 +1,24 @@
+import { useEffect, useState } from 'react'
+
+export const useLocalStorage = (
+ key: string,
+ initialValue: T
+): [T, (value: T) => void] => {
+ const [storedValue, setStoredValue] = useState(initialValue)
+
+ useEffect(() => {
+ // Retrieve from localStorage
+ const item = window.localStorage.getItem(key)
+ if (item) {
+ setStoredValue(JSON.parse(item))
+ }
+ }, [key])
+
+ const setValue = (value: T) => {
+ // Save state
+ setStoredValue(value)
+ // Save to localStorage
+ window.localStorage.setItem(key, JSON.stringify(value))
+ }
+ return [storedValue, setValue]
+}
diff --git a/lib/hooks/use-scroll-anchor.tsx b/lib/hooks/use-scroll-anchor.tsx
new file mode 100644
index 0000000..ff39d66
--- /dev/null
+++ b/lib/hooks/use-scroll-anchor.tsx
@@ -0,0 +1,87 @@
+import { useCallback, useEffect, useRef, useState } from 'react'
+
+export const useScrollAnchor = () => {
+ const messagesRef = useRef(null)
+ const scrollRef = useRef(null)
+ const visibilityRef = useRef(null)
+
+ const [isAtBottom, setIsAtBottom] = useState(true)
+ const [isVisible, setIsVisible] = useState(false)
+
+ const scrollToBottom = useCallback(() => {
+ if (messagesRef.current) {
+ messagesRef.current.scrollIntoView({
+ block: 'end',
+ behavior: 'smooth'
+ })
+ }
+ }, [])
+
+ useEffect(() => {
+ if (messagesRef.current) {
+ if (isAtBottom && !isVisible) {
+ messagesRef.current.scrollIntoView({
+ block: 'end',
+ behavior: 'smooth'
+ })
+ }
+ }
+ }, [isAtBottom, isVisible])
+
+ useEffect(() => {
+ const { current } = scrollRef
+
+ if (current) {
+ const handleScroll = (event: Event) => {
+ const target = event.target as HTMLDivElement
+ const offset = 25
+ const isAtBottom =
+ target.scrollTop + target.clientHeight >= target.scrollHeight - offset
+
+ setIsAtBottom(isAtBottom)
+ }
+
+ current.addEventListener('scroll', handleScroll, {
+ passive: true
+ })
+
+ return () => {
+ current.removeEventListener('scroll', handleScroll)
+ }
+ }
+ }, [])
+
+ useEffect(() => {
+ if (visibilityRef.current) {
+ let observer = new IntersectionObserver(
+ entries => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ setIsVisible(true)
+ } else {
+ setIsVisible(false)
+ }
+ })
+ },
+ {
+ rootMargin: '0px 0px -150px 0px'
+ }
+ )
+
+ observer.observe(visibilityRef.current)
+
+ return () => {
+ observer.disconnect()
+ }
+ }
+ })
+
+ return {
+ messagesRef,
+ scrollRef,
+ visibilityRef,
+ scrollToBottom,
+ isAtBottom,
+ isVisible
+ }
+}
diff --git a/lib/hooks/use-sidebar.tsx b/lib/hooks/use-sidebar.tsx
new file mode 100644
index 0000000..4a52baf
--- /dev/null
+++ b/lib/hooks/use-sidebar.tsx
@@ -0,0 +1,60 @@
+'use client'
+
+import * as React from 'react'
+
+const LOCAL_STORAGE_KEY = 'sidebar'
+
+interface SidebarContext {
+ isSidebarOpen: boolean
+ toggleSidebar: () => void
+ isLoading: boolean
+}
+
+const SidebarContext = React.createContext(
+ undefined
+)
+
+export function useSidebar() {
+ const context = React.useContext(SidebarContext)
+ if (!context) {
+ throw new Error('useSidebarContext must be used within a SidebarProvider')
+ }
+ return context
+}
+
+interface SidebarProviderProps {
+ children: React.ReactNode
+}
+
+export function SidebarProvider({ children }: SidebarProviderProps) {
+ const [isSidebarOpen, setSidebarOpen] = React.useState(true)
+ const [isLoading, setLoading] = React.useState(true)
+
+ React.useEffect(() => {
+ const value = localStorage.getItem(LOCAL_STORAGE_KEY)
+ if (value) {
+ setSidebarOpen(JSON.parse(value))
+ }
+ setLoading(false)
+ }, [])
+
+ const toggleSidebar = () => {
+ setSidebarOpen(value => {
+ const newState = !value
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(newState))
+ return newState
+ })
+ }
+
+ if (isLoading) {
+ return null
+ }
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/lib/hooks/use-streamable-text.ts b/lib/hooks/use-streamable-text.ts
new file mode 100644
index 0000000..f951823
--- /dev/null
+++ b/lib/hooks/use-streamable-text.ts
@@ -0,0 +1,26 @@
+import { StreamableValue, readStreamableValue } from 'ai/rsc'
+import { useEffect, useState } from 'react'
+
+export const useStreamableText = (
+ content: string | StreamableValue
+) => {
+ const [rawContent, setRawContent] = useState(
+ typeof content === 'string' ? content : ''
+ )
+
+ useEffect(() => {
+ ;(async () => {
+ if (typeof content === 'object') {
+ let value = ''
+ for await (const delta of readStreamableValue(content)) {
+ console.log(delta)
+ if (typeof delta === 'string') {
+ setRawContent((value = value + delta))
+ }
+ }
+ }
+ })()
+ }, [content])
+
+ return rawContent
+}
diff --git a/lib/kasada/kasada-client.tsx b/lib/kasada/kasada-client.tsx
new file mode 100644
index 0000000..4af06a8
--- /dev/null
+++ b/lib/kasada/kasada-client.tsx
@@ -0,0 +1,30 @@
+import Script from 'next/script'
+
+export function KasadaClient() {
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/lib/kasada/kasada-server.ts b/lib/kasada/kasada-server.ts
new file mode 100644
index 0000000..474e00c
--- /dev/null
+++ b/lib/kasada/kasada-server.ts
@@ -0,0 +1,212 @@
+import { NextFetchEvent, NextRequest, NextResponse } from 'next/server'
+import { track } from '@vercel/analytics/server'
+
+// You can get this endpoint name from the application details on the Kasada Portal.
+const kasadaAPIEndpoint = process.env.KASADA_API_ENDPOINT
+const kasadaAPIVersion = process.env.KASADA_API_VERSION
+const kasadaAPIURL = `https://${kasadaAPIEndpoint}/149e9513-01fa-4fb0-aad4-566afd725d1b/2d206a39-8ed7-437e-a3be-862e0f06eea3/api/${kasadaAPIVersion}/classification`
+
+export interface APIRequest {
+ // valid IPv4 orIPv6 address of the original client making the request
+ clientIp: string
+ // always provide as many of the available header from the client request
+ headers: Array<{
+ key: string
+ value: string
+ }>
+ method: 'HEAD' | 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'
+ protocol: 'HTTP' | 'HTTPS'
+ // /some/path
+ path: string
+ // request querystring including leading '?', e.g. '?foo=bar&bar=foo'
+ querystring: string
+ // always provide the (redacted) body if available in the client request
+ body?: string
+}
+
+export interface APIResponse {
+ // unique request id as generated by the API
+ requestId: string
+ // unique client id; only present when a client ID is available
+ clientId?: string
+ // API classification
+ classification: 'ALLOWED' | 'BAD-BOT' | 'GOOD-BOT' | 'HUMAN'
+ // array of Set-Cookie strings, like '=; SameSite=None; Secure'
+ responseHeadersToSet: Array<{ key: string; value: string }>
+ application: {
+ mode: 'MONITOR' | 'PROTECT' | 'PASS_THROUGH'
+ domain: string
+ }
+ error: string
+}
+
+/**
+ * Function that fetches the Kasada classification and metadata about the request
+ * and returns either this metadata or an error if something went wrong.
+ */
+async function getKasadaMetadata(request: NextRequest): Promise<{
+ metadata?: APIResponse
+ error?: Error
+}> {
+ const url = new URL(request.url)
+
+ const headers = new Headers(request.headers)
+ headers.delete('x-forwarded-host')
+ headers.set('Host', process.env.KASADA_HEADER_HOST || '')
+
+ const headersArray = [...headers.entries()].map(([key, value]) => ({
+ key,
+ value
+ }))
+
+ const kasadaPayload: APIRequest = {
+ clientIp: String(request.headers.get('x-real-ip') || request.ip),
+ headers: headersArray,
+ method: request.method as APIRequest['method'],
+ protocol: url.protocol.slice(0, -1).toUpperCase() as APIRequest['protocol'],
+ path: url.pathname,
+ querystring: url.search
+ }
+
+ // Set a maximum Kasada response time of 3 seconds
+ const timeout = 3000
+ const timeoutController = new AbortController()
+ const timeoutId = setTimeout(() => timeoutController.abort(), timeout)
+
+ try {
+ // Send request information off to Kasada for classification
+ const response = await fetch(kasadaAPIURL, {
+ method: 'POST',
+ headers: {
+ 'X-Forwarded-Host': url.hostname,
+ 'Content-Type': 'application/json',
+ Authorization: `KasadaApiTokenV1 ${process.env.KASADA_TOKEN ?? ''}`
+ },
+ signal: timeoutController.signal,
+ body: JSON.stringify(kasadaPayload),
+ keepalive: true
+ })
+ const metadata = (await response.json()) as APIResponse
+
+ return {
+ metadata
+ }
+ } catch (error) {
+ if (timeoutController.signal.aborted) {
+ return {
+ error: new Error('Fetch request timed out')
+ }
+ }
+
+ // Some other error occurred
+ return {
+ error: error instanceof Error ? error : new Error(String(error))
+ }
+ } finally {
+ clearTimeout(timeoutId)
+ }
+}
+
+/**
+ * Function that continues the request to the origin
+ */
+async function callOrigin(): Promise {
+ return NextResponse.next()
+}
+
+/**
+ * Function that adds the `responseHeadersToSet` headers returned as part of the request metadata
+ * to the response. These headers are necessary for the correct working of the client side SDK.
+ */
+function addKasadaHeaders(metadata: APIResponse, response: Response): void {
+ metadata.responseHeadersToSet.forEach(({ key, value }) => {
+ response.headers.set(key, value)
+ })
+}
+
+/**
+ * Function that adds the required CORS headers to the response on an OPTIONS request
+ */
+function addKasadaCORSHeaders(response: Response): void {
+ const kasadaHeaders = [
+ 'x-kpsdk-ct',
+ 'x-kpsdk-cd',
+ 'x-kpsdk-h',
+ 'x-kpsdk-fc',
+ 'x-kpsdk-v',
+ 'x-kpsdk-r'
+ ].join(', ')
+
+ response.headers.append('access-control-allow-headers', kasadaHeaders)
+}
+
+export async function kasadaHandler(
+ request: NextRequest,
+ ev: NextFetchEvent
+): Promise {
+ // If the request is an OPTIONS request we don't send it to Kasada
+ // but we do add the necessary CORS headers.
+ if (request.method === 'OPTIONS') {
+ const response = await callOrigin()
+ addKasadaCORSHeaders(response)
+ return response
+ }
+
+ // Get the classification and associated Kasada metadata about this request
+ const { error, metadata } = await getKasadaMetadata(request)
+ if (error || metadata === undefined || metadata.error) {
+ console.error('Kasada error', error || metadata?.error)
+
+ return callOrigin()
+ }
+
+ if (metadata.classification !== 'ALLOWED') {
+ console.info('Kasada metadata bot', metadata.classification, metadata)
+ } else {
+ console.log('Kasada metadata', metadata.classification, metadata)
+ }
+
+ // If the request is a Bad Bot and we're in Protect mode, we'll block this request
+ // and add the Kasada headers to the response for the Client-side SDKs
+ if (
+ metadata.classification === 'BAD-BOT' &&
+ metadata.application.mode === 'PROTECT'
+ ) {
+ ev.waitUntil(
+ track('kasada-blocked', {
+ classification: metadata.classification,
+ mode: metadata.application.mode,
+ ip: request.ip || 'unknown'
+ })
+ )
+ const blockResponse = new Response(undefined, {
+ status: 429
+ })
+
+ addKasadaHeaders(metadata, blockResponse)
+ return blockResponse
+ }
+
+ if (metadata.classification === 'GOOD-BOT') {
+ try {
+ const body = await request.json()
+ ev.waitUntil(
+ track('kasada-good-bot', {
+ classification: metadata.classification,
+ userAgent: request.headers.get('user-agent') || 'unknown',
+ ip: request.ip || 'unknown',
+ model: body.model || 'unknown',
+ prompt: body.messages?.[0]?.content || 'unknown'
+ })
+ )
+ } catch (e) {
+ console.error('Error tracking good bot', e)
+ }
+ }
+
+ // No Bad Bot detected (or application is not in Protect mode)
+ // let's send the request to the Origin and add Kasada headers to response
+ const response = await callOrigin()
+ addKasadaHeaders(metadata, response)
+ return response
+}
diff --git a/lib/types.ts b/lib/types.ts
new file mode 100644
index 0000000..b65c941
--- /dev/null
+++ b/lib/types.ts
@@ -0,0 +1,37 @@
+import { Message } from 'ai'
+
+export interface Chat extends Record {
+ id: string
+ title: string
+ createdAt: Date
+ userId: string
+ path: string
+ messages: Message[]
+ sharePath?: string
+}
+
+export type ServerActionResult = Promise<
+ | Result
+ | {
+ error: string
+ }
+>
+
+export interface Session {
+ user: {
+ id: string
+ email: string
+ }
+}
+
+export interface AuthResult {
+ type: string
+ message: string
+}
+
+export interface User extends Record {
+ id: string
+ email: string
+ password: string
+ salt: string
+}
diff --git a/lib/utils.ts b/lib/utils.ts
new file mode 100644
index 0000000..a0a213f
--- /dev/null
+++ b/lib/utils.ts
@@ -0,0 +1,89 @@
+import { clsx, type ClassValue } from 'clsx'
+import { customAlphabet } from 'nanoid'
+import { twMerge } from 'tailwind-merge'
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
+
+export const nanoid = customAlphabet(
+ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
+ 7
+) // 7-character random string
+
+export async function fetcher(
+ input: RequestInfo,
+ init?: RequestInit
+): Promise {
+ const res = await fetch(input, init)
+
+ if (!res.ok) {
+ const json = await res.json()
+ if (json.error) {
+ const error = new Error(json.error) as Error & {
+ status: number
+ }
+ error.status = res.status
+ throw error
+ } else {
+ throw new Error('An unexpected error occurred')
+ }
+ }
+
+ return res.json()
+}
+
+export function formatDate(input: string | number | Date): string {
+ const date = new Date(input)
+ return date.toLocaleDateString('en-US', {
+ month: 'long',
+ day: 'numeric',
+ year: 'numeric'
+ })
+}
+
+export const formatNumber = (value: number) =>
+ new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD'
+ }).format(value)
+
+export const runAsyncFnWithoutBlocking = (
+ fn: (...args: any) => Promise
+) => {
+ fn()
+}
+
+export const sleep = (ms: number) =>
+ new Promise(resolve => setTimeout(resolve, ms))
+
+export const getStringFromBuffer = (buffer: ArrayBuffer) =>
+ Array.from(new Uint8Array(buffer))
+ .map(b => b.toString(16).padStart(2, '0'))
+ .join('')
+
+export enum ResultCode {
+ InvalidCredentials = 'INVALID_CREDENTIALS',
+ InvalidSubmission = 'INVALID_SUBMISSION',
+ UserAlreadyExists = 'USER_ALREADY_EXISTS',
+ UnknownError = 'UNKNOWN_ERROR',
+ UserCreated = 'USER_CREATED',
+ UserLoggedIn = 'USER_LOGGED_IN'
+}
+
+export const getMessageFromCode = (resultCode: string) => {
+ switch (resultCode) {
+ case ResultCode.InvalidCredentials:
+ return 'Invalid credentials!'
+ case ResultCode.InvalidSubmission:
+ return 'Invalid submission, please try again!'
+ case ResultCode.UserAlreadyExists:
+ return 'User already exists, please log in!'
+ case ResultCode.UserCreated:
+ return 'User created, welcome!'
+ case ResultCode.UnknownError:
+ return 'Something went wrong, please try again!'
+ case ResultCode.UserLoggedIn:
+ return 'Logged in!'
+ }
+}
diff --git a/middleware.ts b/middleware.ts
new file mode 100644
index 0000000..915ec61
--- /dev/null
+++ b/middleware.ts
@@ -0,0 +1,29 @@
+import { kv } from '@vercel/kv'
+import type { NextFetchEvent, NextRequest } from 'next/server'
+import { kasadaHandler } from './lib/kasada/kasada-server'
+
+const MAX_REQUESTS = 50
+
+export async function middleware(req: NextRequest, ev: NextFetchEvent) {
+ if (req.method === 'POST') {
+ const realIp = req.headers.get('x-real-ip') || 'no-ip'
+ const pipeline = kv.pipeline()
+ pipeline.incr(`rate-limit:${realIp}`)
+ pipeline.expire(`rate-limit:${realIp}`, 60 * 60 * 24)
+ const [requests] = (await pipeline.exec()) as [number]
+
+ if (process.env.NODE_ENV === 'development') {
+ return undefined
+ }
+
+ if (requests > MAX_REQUESTS) {
+ return new Response('Too many requests', { status: 429 })
+ }
+
+ return kasadaHandler(req, ev)
+ }
+}
+
+export const config = {
+ matcher: ['/', '/chat/:id*', '/share/:id*']
+}
diff --git a/next-env.d.ts b/next-env.d.ts
new file mode 100644
index 0000000..4f11a03
--- /dev/null
+++ b/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..9b7d60b
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,13 @@
+/** @type {import('next').NextConfig} */
+module.exports = {
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'avatars.githubusercontent.com',
+ port: '',
+ pathname: '**'
+ }
+ ]
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5948a9e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,80 @@
+{
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "lint:fix": "next lint --fix",
+ "preview": "next build && next start",
+ "seed": "node -r dotenv/config ./scripts/seed.mjs",
+ "type-check": "tsc --noEmit",
+ "format:write": "prettier --write \"{app,lib,components}/**/*.{ts,tsx,mdx}\" --cache",
+ "format:check": "prettier --check \"{app,lib,components}**/*.{ts,tsx,mdx}\" --cache"
+ },
+ "dependencies": {
+ "@ai-sdk/google": "0.0.23",
+ "@google/generative-ai": "^0.3.1",
+ "@radix-ui/react-alert-dialog": "^1.0.5",
+ "@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-dropdown-menu": "^2.0.6",
+ "@radix-ui/react-icons": "^1.3.0",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-select": "^2.0.0",
+ "@radix-ui/react-separator": "^1.0.3",
+ "@radix-ui/react-slot": "^1.0.2",
+ "@radix-ui/react-switch": "^1.0.3",
+ "@radix-ui/react-tooltip": "^1.0.7",
+ "@upstash/ratelimit": "^1.0.3",
+ "@vercel/analytics": "^1.1.2",
+ "@vercel/kv": "^1.0.1",
+ "@vercel/og": "^0.6.2",
+ "ai": "^3.2.10",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.0",
+ "d3-scale": "^4.0.2",
+ "date-fns": "^3.3.1",
+ "focus-trap-react": "^10.2.3",
+ "framer-motion": "^10.18.0",
+ "geist": "^1.2.1",
+ "nanoid": "^5.0.4",
+ "next": "14.1.3",
+ "next-auth": "5.0.0-beta.4",
+ "next-themes": "^0.2.1",
+ "openai": "^4.24.7",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-intersection-observer": "^9.5.3",
+ "react-jsbarcode": "^0.4.2",
+ "react-markdown": "^8.0.7",
+ "react-syntax-highlighter": "^15.5.0",
+ "react-textarea-autosize": "^8.5.3",
+ "remark-gfm": "^3.0.1",
+ "remark-math": "^5.1.1",
+ "sonner": "^1.4.3",
+ "usehooks-ts": "^2.16.0",
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.10",
+ "@types/d3-scale": "^4.0.8",
+ "@types/node": "^20.11.5",
+ "@types/react": "^18.2.48",
+ "@types/react-dom": "^18.2.18",
+ "@types/react-syntax-highlighter": "^15.5.11",
+ "@typescript-eslint/parser": "^6.19.0",
+ "autoprefixer": "^10.4.17",
+ "dotenv": "^16.4.5",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "14.1.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-tailwindcss": "^3.14.0",
+ "postcss": "^8.4.33",
+ "prettier": "^3.2.4",
+ "tailwind-merge": "^2.2.0",
+ "tailwindcss": "^3.4.1",
+ "tailwindcss-animate": "^1.0.7",
+ "typescript": "^5.3.3"
+ },
+ "packageManager": "pnpm@8.6.3"
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..67b63ee
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,5849 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+dependencies:
+ '@ai-sdk/google':
+ specifier: 0.0.23
+ version: 0.0.23(zod@3.22.4)
+ '@google/generative-ai':
+ specifier: ^0.3.1
+ version: 0.3.1
+ '@radix-ui/react-alert-dialog':
+ specifier: ^1.0.5
+ version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-dialog':
+ specifier: ^1.0.5
+ version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.0.6
+ version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-icons':
+ specifier: ^1.3.0
+ version: 1.3.0(react@18.2.0)
+ '@radix-ui/react-label':
+ specifier: ^2.0.2
+ version: 2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-select':
+ specifier: ^2.0.0
+ version: 2.0.0(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-separator':
+ specifier: ^1.0.3
+ version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot':
+ specifier: ^1.0.2
+ version: 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-switch':
+ specifier: ^1.0.3
+ version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-tooltip':
+ specifier: ^1.0.7
+ version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@upstash/ratelimit':
+ specifier: ^1.0.3
+ version: 1.0.3
+ '@vercel/analytics':
+ specifier: ^1.1.2
+ version: 1.1.2
+ '@vercel/kv':
+ specifier: ^1.0.1
+ version: 1.0.1
+ '@vercel/og':
+ specifier: ^0.6.2
+ version: 0.6.2
+ ai:
+ specifier: ^3.2.10
+ version: 3.2.10(openai@4.24.7)(react@18.2.0)(solid-js@1.8.16)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4)
+ class-variance-authority:
+ specifier: ^0.7.0
+ version: 0.7.0
+ clsx:
+ specifier: ^2.1.0
+ version: 2.1.0
+ d3-scale:
+ specifier: ^4.0.2
+ version: 4.0.2
+ date-fns:
+ specifier: ^3.3.1
+ version: 3.3.1
+ focus-trap-react:
+ specifier: ^10.2.3
+ version: 10.2.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)
+ framer-motion:
+ specifier: ^10.18.0
+ version: 10.18.0(react-dom@18.2.0)(react@18.2.0)
+ geist:
+ specifier: ^1.2.1
+ version: 1.2.1(next@14.1.3)
+ nanoid:
+ specifier: ^5.0.4
+ version: 5.0.4
+ next:
+ specifier: 14.1.3
+ version: 14.1.3(react-dom@18.2.0)(react@18.2.0)
+ next-auth:
+ specifier: 5.0.0-beta.4
+ version: 5.0.0-beta.4(next@14.1.3)(react@18.2.0)
+ next-themes:
+ specifier: ^0.2.1
+ version: 0.2.1(next@14.1.3)(react-dom@18.2.0)(react@18.2.0)
+ openai:
+ specifier: ^4.24.7
+ version: 4.24.7
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ react-intersection-observer:
+ specifier: ^9.5.3
+ version: 9.5.3(react@18.2.0)
+ react-jsbarcode:
+ specifier: ^0.4.2
+ version: 0.4.2(react@18.2.0)
+ react-markdown:
+ specifier: ^8.0.7
+ version: 8.0.7(@types/react@18.2.48)(react@18.2.0)
+ react-syntax-highlighter:
+ specifier: ^15.5.0
+ version: 15.5.0(react@18.2.0)
+ react-textarea-autosize:
+ specifier: ^8.5.3
+ version: 8.5.3(@types/react@18.2.48)(react@18.2.0)
+ remark-gfm:
+ specifier: ^3.0.1
+ version: 3.0.1
+ remark-math:
+ specifier: ^5.1.1
+ version: 5.1.1
+ sonner:
+ specifier: ^1.4.3
+ version: 1.4.3(react-dom@18.2.0)(react@18.2.0)
+ usehooks-ts:
+ specifier: ^2.16.0
+ version: 2.16.0(react@18.2.0)
+ zod:
+ specifier: ^3.22.4
+ version: 3.22.4
+
+devDependencies:
+ '@tailwindcss/typography':
+ specifier: ^0.5.10
+ version: 0.5.10(tailwindcss@3.4.1)
+ '@types/d3-scale':
+ specifier: ^4.0.8
+ version: 4.0.8
+ '@types/node':
+ specifier: ^20.11.5
+ version: 20.11.5
+ '@types/react':
+ specifier: ^18.2.48
+ version: 18.2.48
+ '@types/react-dom':
+ specifier: ^18.2.18
+ version: 18.2.18
+ '@types/react-syntax-highlighter':
+ specifier: ^15.5.11
+ version: 15.5.11
+ '@typescript-eslint/parser':
+ specifier: ^6.19.0
+ version: 6.19.0(eslint@8.56.0)(typescript@5.3.3)
+ autoprefixer:
+ specifier: ^10.4.17
+ version: 10.4.17(postcss@8.4.33)
+ dotenv:
+ specifier: ^16.4.5
+ version: 16.4.5
+ eslint:
+ specifier: ^8.56.0
+ version: 8.56.0
+ eslint-config-next:
+ specifier: 14.1.0
+ version: 14.1.0(eslint@8.56.0)(typescript@5.3.3)
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.0(eslint@8.56.0)
+ eslint-plugin-tailwindcss:
+ specifier: ^3.14.0
+ version: 3.14.0(tailwindcss@3.4.1)
+ postcss:
+ specifier: ^8.4.33
+ version: 8.4.33
+ prettier:
+ specifier: ^3.2.4
+ version: 3.2.4
+ tailwind-merge:
+ specifier: ^2.2.0
+ version: 2.2.0
+ tailwindcss:
+ specifier: ^3.4.1
+ version: 3.4.1
+ tailwindcss-animate:
+ specifier: ^1.0.7
+ version: 1.0.7(tailwindcss@3.4.1)
+ typescript:
+ specifier: ^5.3.3
+ version: 5.3.3
+
+packages:
+
+ /@aashutoshrathi/word-wrap@1.2.6:
+ resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /@ai-sdk/google@0.0.23(zod@3.22.4):
+ resolution: {integrity: sha512-Ariq7Oy6ge02JPqWa900spQewNIdWkSSeZ2Rfe0RLoGa/PDEEU5bQBvUNvRpiTUgGOsmkiUMHY6OJB5L0LDOxQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+ dependencies:
+ '@ai-sdk/provider': 0.0.10
+ '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4)
+ zod: 3.22.4
+ dev: false
+
+ /@ai-sdk/provider-utils@0.0.16(zod@3.22.4):
+ resolution: {integrity: sha512-W2zUZ+C5uDr2P9/KZwtV4r4F0l2RlD0AvtJyug7ER5g3hGHAfKrPM0y2hSlRxNfph5BTCC6YQX0nFLyBph+6bQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+ dependencies:
+ '@ai-sdk/provider': 0.0.10
+ eventsource-parser: 1.1.2
+ nanoid: 3.3.6
+ secure-json-parse: 2.7.0
+ zod: 3.22.4
+ dev: false
+
+ /@ai-sdk/provider@0.0.10:
+ resolution: {integrity: sha512-NzkrtREQpHID1cTqY/C4CI30PVOaXWKYytDR2EcytmFgnP7Z6+CrGIA/YCnNhYAuUm6Nx+nGpRL/Hmyrv7NYzg==}
+ engines: {node: '>=18'}
+ dependencies:
+ json-schema: 0.4.0
+ dev: false
+
+ /@ai-sdk/react@0.0.10(react@18.2.0)(zod@3.22.4):
+ resolution: {integrity: sha512-T3z5PdidmAe3FJLODwdhD19ohKelqhfgV2l8jbpMQ1m7AYGGMbMPLOBVXpi5SqDTtJ6znx5Hj7cEQ61+peACyw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ react: ^18 || ^19
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ zod:
+ optional: true
+ dependencies:
+ '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4)
+ '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4)
+ react: 18.2.0
+ swr: 2.2.0(react@18.2.0)
+ zod: 3.22.4
+ dev: false
+
+ /@ai-sdk/solid@0.0.7(solid-js@1.8.16)(zod@3.22.4):
+ resolution: {integrity: sha512-3aN5JWbgRMeyZiXgSVwTL6TjNrTIvESl05Hm2+eAFEDMcnSzgYKnCUbKgBNm4eZgKvrY7XDRMdJ37uXzRxdF7Q==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ solid-js: ^1.7.7
+ peerDependenciesMeta:
+ solid-js:
+ optional: true
+ dependencies:
+ '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4)
+ solid-js: 1.8.16
+ solid-swr-store: 0.10.7(solid-js@1.8.16)(swr-store@0.10.6)
+ swr-store: 0.10.6
+ transitivePeerDependencies:
+ - zod
+ dev: false
+
+ /@ai-sdk/svelte@0.0.8(svelte@4.2.12)(zod@3.22.4):
+ resolution: {integrity: sha512-JcyjDZ2M7Mb/8ZTvy9hCn2Rob++LmJE+icqBL90TcjKFdvINvc1GlNlVntXIJFkRO5XyIfqEOGOmqwkTp4mRmg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ svelte: ^3.0.0 || ^4.0.0
+ peerDependenciesMeta:
+ svelte:
+ optional: true
+ dependencies:
+ '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4)
+ '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4)
+ sswr: 2.1.0(svelte@4.2.12)
+ svelte: 4.2.12
+ transitivePeerDependencies:
+ - zod
+ dev: false
+
+ /@ai-sdk/ui-utils@0.0.6(zod@3.22.4):
+ resolution: {integrity: sha512-CpenkIWaA3nkY/cUJ0/paC/mT9hD7znCc91ZbDK1jH/MwLobLl1IPAACbjxYhnTo72od7S9/dGrpiI+RqWIwXg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+ dependencies:
+ '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4)
+ secure-json-parse: 2.7.0
+ zod: 3.22.4
+ dev: false
+
+ /@ai-sdk/vue@0.0.8(vue@3.4.21)(zod@3.22.4):
+ resolution: {integrity: sha512-p/JDZbW7cJlxODmdtv82hTCkzP+K96xLJwQFPyoXglfMztDx9/VKoHj+riBqRUyp2S4yYyT7m9TMbt33ZaPzxw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ vue: ^3.3.4
+ peerDependenciesMeta:
+ vue:
+ optional: true
+ dependencies:
+ '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4)
+ swrv: 1.0.4(vue@3.4.21)
+ vue: 3.4.21(typescript@5.3.3)
+ transitivePeerDependencies:
+ - zod
+ dev: false
+
+ /@alloc/quick-lru@5.2.0:
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /@ampproject/remapping@2.3.0:
+ resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+ dev: false
+
+ /@auth/core@0.18.4:
+ resolution: {integrity: sha512-GsNhsP1xE/3FoNS3dVkPjqRljLNJ4iyL2OLv3klQGNvw3bMpROFcK4lqhx7+pPHiamnVaYt2vg1xbB+lsNaevg==}
+ peerDependencies:
+ nodemailer: ^6.8.0
+ peerDependenciesMeta:
+ nodemailer:
+ optional: true
+ dependencies:
+ '@panva/hkdf': 1.1.1
+ cookie: 0.6.0
+ jose: 5.2.0
+ oauth4webapi: 2.7.0
+ preact: 10.11.3
+ preact-render-to-string: 5.2.3(preact@10.11.3)
+ dev: false
+
+ /@babel/helper-string-parser@7.24.1:
+ resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
+ engines: {node: '>=6.9.0'}
+ dev: false
+
+ /@babel/helper-validator-identifier@7.22.20:
+ resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
+ engines: {node: '>=6.9.0'}
+ dev: false
+
+ /@babel/parser@7.24.1:
+ resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.24.0
+ dev: false
+
+ /@babel/runtime@7.23.8:
+ resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.1
+
+ /@babel/types@7.24.0:
+ resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.24.1
+ '@babel/helper-validator-identifier': 7.22.20
+ to-fast-properties: 2.0.0
+ dev: false
+
+ /@emotion/is-prop-valid@0.8.8:
+ resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
+ requiresBuild: true
+ dependencies:
+ '@emotion/memoize': 0.7.4
+ dev: false
+ optional: true
+
+ /@emotion/memoize@0.7.4:
+ resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0):
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@eslint-community/regexpp@4.10.0:
+ resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.4:
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.0
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.56.0:
+ resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@floating-ui/core@1.5.3:
+ resolution: {integrity: sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==}
+ dependencies:
+ '@floating-ui/utils': 0.2.1
+ dev: false
+
+ /@floating-ui/dom@1.5.4:
+ resolution: {integrity: sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==}
+ dependencies:
+ '@floating-ui/core': 1.5.3
+ '@floating-ui/utils': 0.2.1
+ dev: false
+
+ /@floating-ui/react-dom@2.0.6(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+ dependencies:
+ '@floating-ui/dom': 1.5.4
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@floating-ui/utils@0.2.1:
+ resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==}
+ dev: false
+
+ /@google/generative-ai@0.3.1:
+ resolution: {integrity: sha512-Zh1EK5nCWqIhxPm3K1KOM2mOwwgBvp6lkze74yTj6+Zqibtf55Db1q87cbbzWZeET3ZbNgHMYjVf2JyMM6pI7A==}
+ engines: {node: '>=18.0.0'}
+ dev: false
+
+ /@humanwhocodes/config-array@0.11.14:
+ resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.2
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@2.0.2:
+ resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
+ dev: true
+
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+ dev: true
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.22
+ dev: true
+
+ /@jridgewell/gen-mapping@0.3.5:
+ resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.25
+ dev: false
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/set-array@1.2.1:
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+ dev: false
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+ /@jridgewell/trace-mapping@0.3.22:
+ resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.25:
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: false
+
+ /@next/env@14.1.3:
+ resolution: {integrity: sha512-VhgXTvrgeBRxNPjyfBsDIMvgsKDxjlpw4IAUsHCX8Gjl1vtHUYRT3+xfQ/wwvLPDd/6kqfLqk9Pt4+7gysuCKQ==}
+ dev: false
+
+ /@next/eslint-plugin-next@14.1.0:
+ resolution: {integrity: sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==}
+ dependencies:
+ glob: 10.3.10
+ dev: true
+
+ /@next/swc-darwin-arm64@14.1.3:
+ resolution: {integrity: sha512-LALu0yIBPRiG9ANrD5ncB3pjpO0Gli9ZLhxdOu6ZUNf3x1r3ea1rd9Q+4xxUkGrUXLqKVK9/lDkpYIJaCJ6AHQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-darwin-x64@14.1.3:
+ resolution: {integrity: sha512-E/9WQeXxkqw2dfcn5UcjApFgUq73jqNKaE5bysDm58hEUdUGedVrnRhblhJM7HbCZNhtVl0j+6TXsK0PuzXTCg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-arm64-gnu@14.1.3:
+ resolution: {integrity: sha512-USArX9B+3rZSXYLFvgy0NVWQgqh6LHWDmMt38O4lmiJNQcwazeI6xRvSsliDLKt+78KChVacNiwvOMbl6g6BBw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-arm64-musl@14.1.3:
+ resolution: {integrity: sha512-esk1RkRBLSIEp1qaQXv1+s6ZdYzuVCnDAZySpa62iFTMGTisCyNQmqyCTL9P+cLJ4N9FKCI3ojtSfsyPHJDQNw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-x64-gnu@14.1.3:
+ resolution: {integrity: sha512-8uOgRlYEYiKo0L8YGeS+3TudHVDWDjPVDUcST+z+dUzgBbTEwSSIaSgF/vkcC1T/iwl4QX9iuUyUdQEl0Kxalg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-x64-musl@14.1.3:
+ resolution: {integrity: sha512-DX2zqz05ziElLoxskgHasaJBREC5Y9TJcbR2LYqu4r7naff25B4iXkfXWfcp69uD75/0URmmoSgT8JclJtrBoQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-arm64-msvc@14.1.3:
+ resolution: {integrity: sha512-HjssFsCdsD4GHstXSQxsi2l70F/5FsRTRQp8xNgmQs15SxUfUJRvSI9qKny/jLkY3gLgiCR3+6A7wzzK0DBlfA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-ia32-msvc@14.1.3:
+ resolution: {integrity: sha512-DRuxD5axfDM1/Ue4VahwSxl1O5rn61hX8/sF0HY8y0iCbpqdxw3rB3QasdHn/LJ6Wb2y5DoWzXcz3L1Cr+Thrw==}
+ engines: {node: '>= 10'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-x64-msvc@14.1.3:
+ resolution: {integrity: sha512-uC2DaDoWH7h1P/aJ4Fok3Xiw6P0Lo4ez7NbowW2VGNXw/Xv6tOuLUcxhBYZxsSUJtpeknCi8/fvnSpyCFp4Rcg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.16.0
+ dev: true
+
+ /@panva/hkdf@1.1.1:
+ resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==}
+ dev: false
+
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@radix-ui/number@1.0.1:
+ resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /@radix-ui/primitive@1.0.1:
+ resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-context@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ aria-hidden: 1.2.3
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-icons@1.3.0(react@18.2.0):
+ resolution: {integrity: sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==}
+ peerDependencies:
+ react: ^16.x || ^17.x || ^18.x
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-id@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ aria-hidden: 1.2.3
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@floating-ui/react-dom': 2.0.6(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/rect': 1.0.1
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-select@2.0.0(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/number': 1.0.1
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ aria-hidden: 1.2.3
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-separator@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-slot@1.0.2(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-previous@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-rect@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/rect': 1.0.1
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-size@1.0.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.48
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/rect@1.0.1:
+ resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /@resvg/resvg-wasm@2.4.0:
+ resolution: {integrity: sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg==}
+ engines: {node: '>= 10'}
+ dev: false
+
+ /@rushstack/eslint-patch@1.7.0:
+ resolution: {integrity: sha512-Jh4t/593gxs0lJZ/z3NnasKlplXT2f+4y/LZYuaKZW5KAaiVFL/fThhs+17EbUd53jUVJ0QudYCBGbN/psvaqg==}
+ dev: true
+
+ /@shuding/opentype.js@1.4.0-beta.0:
+ resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==}
+ engines: {node: '>= 8.0.0'}
+ hasBin: true
+ dependencies:
+ fflate: 0.7.4
+ string.prototype.codepointat: 0.2.1
+ dev: false
+
+ /@swc/helpers@0.5.2:
+ resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==}
+ dependencies:
+ tslib: 2.6.2
+ dev: false
+
+ /@tailwindcss/typography@0.5.10(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+ dependencies:
+ lodash.castarray: 4.4.0
+ lodash.isplainobject: 4.0.6
+ lodash.merge: 4.6.2
+ postcss-selector-parser: 6.0.10
+ tailwindcss: 3.4.1
+ dev: true
+
+ /@types/d3-scale@4.0.8:
+ resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==}
+ dependencies:
+ '@types/d3-time': 3.0.3
+ dev: true
+
+ /@types/d3-time@3.0.3:
+ resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==}
+ dev: true
+
+ /@types/debug@4.1.12:
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ dependencies:
+ '@types/ms': 0.7.34
+ dev: false
+
+ /@types/diff-match-patch@1.0.36:
+ resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
+ dev: false
+
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ dev: false
+
+ /@types/hast@2.3.9:
+ resolution: {integrity: sha512-pTHyNlaMD/oKJmS+ZZUyFUcsZeBZpC0lmGquw98CqRVNgAdJZJeD7GoeLiT6Xbx5rU9VCjSt0RwEvDgzh4obFw==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: false
+
+ /@types/json5@0.0.29:
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ dev: true
+
+ /@types/katex@0.16.7:
+ resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
+ dev: false
+
+ /@types/mdast@3.0.15:
+ resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: false
+
+ /@types/ms@0.7.34:
+ resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
+ dev: false
+
+ /@types/node-fetch@2.6.11:
+ resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
+ dependencies:
+ '@types/node': 20.11.5
+ form-data: 4.0.0
+ dev: false
+
+ /@types/node@18.19.8:
+ resolution: {integrity: sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: false
+
+ /@types/node@20.11.5:
+ resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==}
+ dependencies:
+ undici-types: 5.26.5
+
+ /@types/prop-types@15.7.11:
+ resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==}
+
+ /@types/react-dom@18.2.18:
+ resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==}
+ dependencies:
+ '@types/react': 18.2.48
+
+ /@types/react-syntax-highlighter@15.5.11:
+ resolution: {integrity: sha512-ZqIJl+Pg8kD+47kxUjvrlElrraSUrYa4h0dauY/U/FTUuprSCqvUj+9PNQNQzVc6AJgIWUUxn87/gqsMHNbRjw==}
+ dependencies:
+ '@types/react': 18.2.48
+ dev: true
+
+ /@types/react@18.2.48:
+ resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==}
+ dependencies:
+ '@types/prop-types': 15.7.11
+ '@types/scheduler': 0.16.8
+ csstype: 3.1.3
+
+ /@types/scheduler@0.16.8:
+ resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
+
+ /@types/unist@2.0.10:
+ resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
+ dev: false
+
+ /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ eslint: ^7.0.0 || ^8.0.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/scope-manager': 6.19.0
+ '@typescript-eslint/types': 6.19.0
+ '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3)
+ '@typescript-eslint/visitor-keys': 6.19.0
+ debug: 4.3.4
+ eslint: 8.56.0
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/scope-manager@6.19.0:
+ resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dependencies:
+ '@typescript-eslint/types': 6.19.0
+ '@typescript-eslint/visitor-keys': 6.19.0
+ dev: true
+
+ /@typescript-eslint/types@6.19.0:
+ resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dev: true
+
+ /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3):
+ resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@typescript-eslint/types': 6.19.0
+ '@typescript-eslint/visitor-keys': 6.19.0
+ debug: 4.3.4
+ globby: 11.1.0
+ is-glob: 4.0.3
+ minimatch: 9.0.3
+ semver: 7.5.4
+ ts-api-utils: 1.0.3(typescript@5.3.3)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/visitor-keys@6.19.0:
+ resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==}
+ engines: {node: ^16.0.0 || >=18.0.0}
+ dependencies:
+ '@typescript-eslint/types': 6.19.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@ungap/structured-clone@1.2.0:
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ dev: true
+
+ /@upstash/core-analytics@0.0.7:
+ resolution: {integrity: sha512-lC2j5efqb1haX/fpTGaPUx1rue1WUkOZBVHDzCB7eMIVsRdFFp4xiHtyH/G9omiR1zj39fU5SCTWFiKJH3KOpw==}
+ engines: {node: '>=16.0.0'}
+ dependencies:
+ '@upstash/redis': 1.29.0
+ dev: false
+
+ /@upstash/ratelimit@1.0.3:
+ resolution: {integrity: sha512-uaws/6Ar28TICm61wfIbL4Ba91WYtIfl6HMj0PNJ0H/nm0SSXwVbCxPEiX9aXa41gMlVWujaJcOreqIuO8/mqg==}
+ dependencies:
+ '@upstash/core-analytics': 0.0.7
+ dev: false
+
+ /@upstash/redis@1.25.1:
+ resolution: {integrity: sha512-ACj0GhJ4qrQyBshwFgPod6XufVEfKX2wcaihsEvSdLYnY+m+pa13kGt1RXm/yTHKf4TQi/Dy2A8z/y6WUEOmlg==}
+ dependencies:
+ crypto-js: 4.2.0
+ dev: false
+
+ /@upstash/redis@1.29.0:
+ resolution: {integrity: sha512-kbO5fgMAeUzErnA/SOtaSbAa0dguYhhBT4MZHJ1O8gVl4iK754aC9+rIYY5hsp4nlxeCGfnIDkWpof991c9jjA==}
+ dependencies:
+ crypto-js: 4.2.0
+ dev: false
+
+ /@vercel/analytics@1.1.2:
+ resolution: {integrity: sha512-CodhkLCQ/EHzjX8k+Qg+OzTBY0UadykrcfolfSOJVZZY/ZJM5nbhztm9KdbYvMfqKlasAr1+OYy0ThZnDA/MYA==}
+ dependencies:
+ server-only: 0.0.1
+ dev: false
+
+ /@vercel/kv@1.0.1:
+ resolution: {integrity: sha512-uTKddsqVYS2GRAM/QMNNXCTuw9N742mLoGRXoNDcyECaxEXvIHG0dEY+ZnYISV4Vz534VwJO+64fd9XeSggSKw==}
+ engines: {node: '>=14.6'}
+ dependencies:
+ '@upstash/redis': 1.25.1
+ dev: false
+
+ /@vercel/og@0.6.2:
+ resolution: {integrity: sha512-OTe0KE37F5Y2eTys6eMnfopC+P4qr2ooXUTFyFPTplYSPwowmFk/HLD1FXtbKLjqsIH0SgekcJWad+C5uX4nkg==}
+ engines: {node: '>=16'}
+ dependencies:
+ '@resvg/resvg-wasm': 2.4.0
+ satori: 0.10.9
+ yoga-wasm-web: 0.3.3
+ dev: false
+
+ /@vue/compiler-core@3.4.21:
+ resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==}
+ dependencies:
+ '@babel/parser': 7.24.1
+ '@vue/shared': 3.4.21
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.2.0
+ dev: false
+
+ /@vue/compiler-dom@3.4.21:
+ resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==}
+ dependencies:
+ '@vue/compiler-core': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: false
+
+ /@vue/compiler-sfc@3.4.21:
+ resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==}
+ dependencies:
+ '@babel/parser': 7.24.1
+ '@vue/compiler-core': 3.4.21
+ '@vue/compiler-dom': 3.4.21
+ '@vue/compiler-ssr': 3.4.21
+ '@vue/shared': 3.4.21
+ estree-walker: 2.0.2
+ magic-string: 0.30.8
+ postcss: 8.4.38
+ source-map-js: 1.2.0
+ dev: false
+
+ /@vue/compiler-ssr@3.4.21:
+ resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==}
+ dependencies:
+ '@vue/compiler-dom': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: false
+
+ /@vue/reactivity@3.4.21:
+ resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==}
+ dependencies:
+ '@vue/shared': 3.4.21
+ dev: false
+
+ /@vue/runtime-core@3.4.21:
+ resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==}
+ dependencies:
+ '@vue/reactivity': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: false
+
+ /@vue/runtime-dom@3.4.21:
+ resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==}
+ dependencies:
+ '@vue/runtime-core': 3.4.21
+ '@vue/shared': 3.4.21
+ csstype: 3.1.3
+ dev: false
+
+ /@vue/server-renderer@3.4.21(vue@3.4.21):
+ resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==}
+ peerDependencies:
+ vue: 3.4.21
+ dependencies:
+ '@vue/compiler-ssr': 3.4.21
+ '@vue/shared': 3.4.21
+ vue: 3.4.21(typescript@5.3.3)
+ dev: false
+
+ /@vue/shared@3.4.21:
+ resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
+ dev: false
+
+ /abort-controller@3.0.0:
+ resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
+ engines: {node: '>=6.5'}
+ dependencies:
+ event-target-shim: 5.0.1
+ dev: false
+
+ /acorn-jsx@5.3.2(acorn@8.11.3):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.11.3
+ dev: true
+
+ /acorn@8.11.3:
+ resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ /agentkeepalive@4.5.0:
+ resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==}
+ engines: {node: '>= 8.0.0'}
+ dependencies:
+ humanize-ms: 1.2.1
+ dev: false
+
+ /ai@3.2.10(openai@4.24.7)(react@18.2.0)(solid-js@1.8.16)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4):
+ resolution: {integrity: sha512-RsNt4h7ygV150qWzIAdJimzKEPP2VtboVk1aZvR4vsIhQqbgglIRfHHuGTBRQgX6JMEXY5u1+VqQRdwcvzvr5w==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ openai: ^4.42.0
+ react: ^18 || ^19
+ svelte: ^3.0.0 || ^4.0.0
+ zod: ^3.0.0
+ peerDependenciesMeta:
+ openai:
+ optional: true
+ react:
+ optional: true
+ svelte:
+ optional: true
+ zod:
+ optional: true
+ dependencies:
+ '@ai-sdk/provider': 0.0.10
+ '@ai-sdk/provider-utils': 0.0.16(zod@3.22.4)
+ '@ai-sdk/react': 0.0.10(react@18.2.0)(zod@3.22.4)
+ '@ai-sdk/solid': 0.0.7(solid-js@1.8.16)(zod@3.22.4)
+ '@ai-sdk/svelte': 0.0.8(svelte@4.2.12)(zod@3.22.4)
+ '@ai-sdk/ui-utils': 0.0.6(zod@3.22.4)
+ '@ai-sdk/vue': 0.0.8(vue@3.4.21)(zod@3.22.4)
+ eventsource-parser: 1.1.2
+ json-schema: 0.4.0
+ jsondiffpatch: 0.6.0
+ nanoid: 3.3.6
+ openai: 4.24.7
+ react: 18.2.0
+ secure-json-parse: 2.7.0
+ sswr: 2.1.0(svelte@4.2.12)
+ svelte: 4.2.12
+ zod: 3.22.4
+ zod-to-json-schema: 3.22.5(zod@3.22.4)
+ transitivePeerDependencies:
+ - solid-js
+ - vue
+ dev: false
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /aria-hidden@1.2.3:
+ resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ tslib: 2.6.2
+ dev: false
+
+ /aria-query@5.3.0:
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+ dependencies:
+ dequal: 2.0.3
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.5
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /array-includes@3.1.7:
+ resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-string: 1.0.7
+ dev: true
+
+ /array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /array.prototype.findlastindex@1.2.3:
+ resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /array.prototype.flat@1.3.2:
+ resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.flatmap@1.3.2:
+ resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.tosorted@1.1.2:
+ resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.2:
+ resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-array-buffer: 3.0.2
+ is-shared-array-buffer: 1.0.2
+ dev: true
+
+ /ast-types-flow@0.0.8:
+ resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+ dev: true
+
+ /asynciterator.prototype@1.0.0:
+ resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ dev: false
+
+ /autoprefixer@10.4.17(postcss@8.4.33):
+ resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.22.2
+ caniuse-lite: 1.0.30001579
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /axe-core@4.7.0:
+ resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /axobject-query@3.2.1:
+ resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
+ dependencies:
+ dequal: 2.0.3
+ dev: true
+
+ /axobject-query@4.0.0:
+ resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==}
+ dependencies:
+ dequal: 2.0.3
+ dev: false
+
+ /bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+ dev: false
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /base-64@0.1.0:
+ resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==}
+ dev: false
+
+ /base64-js@0.0.8:
+ resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==}
+ engines: {node: '>= 0.4'}
+ dev: false
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /browserslist@4.22.2:
+ resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001579
+ electron-to-chromium: 1.4.640
+ node-releases: 2.0.14
+ update-browserslist-db: 1.0.13(browserslist@4.22.2)
+ dev: true
+
+ /busboy@1.6.0:
+ resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
+ engines: {node: '>=10.16.0'}
+ dependencies:
+ streamsearch: 1.1.0
+ dev: false
+
+ /call-bind@1.0.5:
+ resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
+ dependencies:
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ set-function-length: 1.2.0
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /camelize@1.0.1:
+ resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
+ dev: false
+
+ /caniuse-lite@1.0.30001579:
+ resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==}
+
+ /ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+ dev: false
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chalk@5.3.0:
+ resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ dev: false
+
+ /character-entities-legacy@1.1.4:
+ resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==}
+ dev: false
+
+ /character-entities@1.2.4:
+ resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==}
+ dev: false
+
+ /character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+ dev: false
+
+ /character-reference-invalid@1.1.4:
+ resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
+ dev: false
+
+ /charenc@0.0.2:
+ resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
+ dev: false
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /class-variance-authority@0.7.0:
+ resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==}
+ dependencies:
+ clsx: 2.0.0
+ dev: false
+
+ /client-only@0.0.1:
+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ dev: false
+
+ /clsx@2.0.0:
+ resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /clsx@2.1.0:
+ resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /code-red@1.0.4:
+ resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@types/estree': 1.0.5
+ acorn: 8.11.3
+ estree-walker: 3.0.3
+ periscopic: 3.1.0
+ dev: false
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ /combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ delayed-stream: 1.0.0
+ dev: false
+
+ /comma-separated-tokens@1.0.8:
+ resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
+ dev: false
+
+ /comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+ dev: false
+
+ /commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /commander@8.3.0:
+ resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
+ engines: {node: '>= 12'}
+ dev: false
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
+ dev: true
+
+ /cookie@0.6.0:
+ resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /crypt@0.0.2:
+ resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
+ dev: false
+
+ /crypto-js@4.2.0:
+ resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
+ dev: false
+
+ /css-background-parser@0.1.0:
+ resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==}
+ dev: false
+
+ /css-box-shadow@1.0.0-3:
+ resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==}
+ dev: false
+
+ /css-color-keywords@1.0.0:
+ resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /css-to-react-native@3.2.0:
+ resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==}
+ dependencies:
+ camelize: 1.0.1
+ css-color-keywords: 1.0.0
+ postcss-value-parser: 4.2.0
+ dev: false
+
+ /css-tree@2.3.1:
+ resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+ dependencies:
+ mdn-data: 2.0.30
+ source-map-js: 1.2.0
+ dev: false
+
+ /cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ /d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+ dependencies:
+ internmap: 2.0.3
+ dev: false
+
+ /d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /d3-format@3.1.0:
+ resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-color: 3.1.0
+ dev: false
+
+ /d3-scale@4.0.2:
+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ d3-format: 3.1.0
+ d3-interpolate: 3.0.1
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ dev: false
+
+ /d3-time-format@4.1.0:
+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-time: 3.1.0
+ dev: false
+
+ /d3-time@3.1.0:
+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ dev: false
+
+ /damerau-levenshtein@1.0.8:
+ resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+ dev: true
+
+ /date-fns@3.3.1:
+ resolution: {integrity: sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==}
+ dev: false
+
+ /debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+
+ /decode-named-character-reference@1.0.2:
+ resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
+ dependencies:
+ character-entities: 2.0.2
+ dev: false
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-data-property@1.1.1:
+ resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ has-property-descriptors: 1.0.1
+ object-keys: 1.1.1
+ dev: true
+
+ /delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+ dev: false
+
+ /dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ /detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+ dev: false
+
+ /didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+ dev: true
+
+ /diff-match-patch@1.0.5:
+ resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
+ dev: false
+
+ /diff@5.1.0:
+ resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
+ engines: {node: '>=0.3.1'}
+ dev: false
+
+ /digest-fetch@1.3.0:
+ resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==}
+ dependencies:
+ base-64: 0.1.0
+ md5: 2.3.0
+ dev: false
+
+ /dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-type: 4.0.0
+ dev: true
+
+ /dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+ dev: true
+
+ /doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /dotenv@16.4.5:
+ resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ dev: true
+
+ /electron-to-chromium@1.4.640:
+ resolution: {integrity: sha512-z/6oZ/Muqk4BaE7P69bXhUhpJbUM9ZJeka43ZwxsDshKtePns4mhBlh8bU5+yrnOnz3fhG82XLzGUXazOmsWnA==}
+ dev: true
+
+ /emoji-regex@10.3.0:
+ resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
+ dev: false
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ dev: true
+
+ /enhanced-resolve@5.15.0:
+ resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.1
+ dev: true
+
+ /entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+ dev: false
+
+ /es-abstract@1.22.3:
+ resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ arraybuffer.prototype.slice: 1.0.2
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ es-set-tostringtag: 2.0.2
+ es-to-primitive: 1.2.1
+ function.prototype.name: 1.1.6
+ get-intrinsic: 1.2.2
+ get-symbol-description: 1.0.0
+ globalthis: 1.0.3
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ internal-slot: 1.0.6
+ is-array-buffer: 3.0.2
+ is-callable: 1.2.7
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-typed-array: 1.1.12
+ is-weakref: 1.0.2
+ object-inspect: 1.13.1
+ object-keys: 1.1.1
+ object.assign: 4.1.5
+ regexp.prototype.flags: 1.5.1
+ safe-array-concat: 1.1.0
+ safe-regex-test: 1.0.2
+ string.prototype.trim: 1.2.8
+ string.prototype.trimend: 1.0.7
+ string.prototype.trimstart: 1.0.7
+ typed-array-buffer: 1.0.0
+ typed-array-byte-length: 1.0.0
+ typed-array-byte-offset: 1.0.0
+ typed-array-length: 1.0.4
+ unbox-primitive: 1.0.2
+ which-typed-array: 1.1.13
+ dev: true
+
+ /es-iterator-helpers@1.0.15:
+ resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==}
+ dependencies:
+ asynciterator.prototype: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-set-tostringtag: 2.0.2
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ iterator.prototype: 1.1.2
+ safe-array-concat: 1.1.0
+ dev: true
+
+ /es-set-tostringtag@2.0.2:
+ resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ has-tostringtag: 1.0.0
+ hasown: 2.0.0
+ dev: true
+
+ /es-shim-unscopables@1.0.2:
+ resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
+ dependencies:
+ hasown: 2.0.0
+ dev: true
+
+ /es-to-primitive@1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+ dev: false
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /eslint-config-next@14.1.0(eslint@8.56.0)(typescript@5.3.3):
+ resolution: {integrity: sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==}
+ peerDependencies:
+ eslint: ^7.23.0 || ^8.0.0
+ typescript: '>=3.3.1'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@next/eslint-plugin-next': 14.1.0
+ '@rushstack/eslint-patch': 1.7.0
+ '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3)
+ eslint: 8.56.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0)
+ eslint-plugin-react: 7.33.2(eslint@8.56.0)
+ eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0)
+ typescript: 5.3.3
+ transitivePeerDependencies:
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-config-prettier@9.1.0(eslint@8.56.0):
+ resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-import-resolver-node@0.3.9:
+ resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+ dependencies:
+ debug: 3.2.7
+ is-core-module: 2.13.1
+ resolve: 1.22.8
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ eslint-plugin-import: '*'
+ dependencies:
+ debug: 4.3.4
+ enhanced-resolve: 5.15.0
+ eslint: 8.56.0
+ eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ fast-glob: 3.3.2
+ get-tsconfig: 4.7.2
+ is-core-module: 2.13.1
+ is-glob: 4.0.3
+ transitivePeerDependencies:
+ - '@typescript-eslint/parser'
+ - eslint-import-resolver-node
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3)
+ debug: 3.2.7
+ eslint: 8.56.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
+ resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3)
+ array-includes: 3.1.7
+ array.prototype.findlastindex: 1.2.3
+ array.prototype.flat: 1.3.2
+ array.prototype.flatmap: 1.3.2
+ debug: 3.2.7
+ doctrine: 2.1.0
+ eslint: 8.56.0
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
+ hasown: 2.0.0
+ is-core-module: 2.13.1
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.fromentries: 2.0.7
+ object.groupby: 1.0.1
+ object.values: 1.1.7
+ semver: 6.3.1
+ tsconfig-paths: 3.15.0
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-plugin-jsx-a11y@6.8.0(eslint@8.56.0):
+ resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
+ dependencies:
+ '@babel/runtime': 7.23.8
+ aria-query: 5.3.0
+ array-includes: 3.1.7
+ array.prototype.flatmap: 1.3.2
+ ast-types-flow: 0.0.8
+ axe-core: 4.7.0
+ axobject-query: 3.2.1
+ damerau-levenshtein: 1.0.8
+ emoji-regex: 9.2.2
+ es-iterator-helpers: 1.0.15
+ eslint: 8.56.0
+ hasown: 2.0.0
+ jsx-ast-utils: 3.3.5
+ language-tags: 1.0.9
+ minimatch: 3.1.2
+ object.entries: 1.1.7
+ object.fromentries: 2.0.7
+ dev: true
+
+ /eslint-plugin-react-hooks@4.6.0(eslint@8.56.0):
+ resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react@7.33.2(eslint@8.56.0):
+ resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flatmap: 1.3.2
+ array.prototype.tosorted: 1.1.2
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.0.15
+ eslint: 8.56.0
+ estraverse: 5.3.0
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.7
+ object.fromentries: 2.0.7
+ object.hasown: 1.1.3
+ object.values: 1.1.7
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.10
+ dev: true
+
+ /eslint-plugin-tailwindcss@3.14.0(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-SGy4JmZoP5m1bXCbcsPfQg1/axOdriJf9L22HghNMyDTM5mybg2XEkaMwgax4aR13zZJRRB1nWmkuYUn+SV6/Q==}
+ engines: {node: '>=12.13.0'}
+ peerDependencies:
+ tailwindcss: ^3.4.0
+ dependencies:
+ fast-glob: 3.3.2
+ postcss: 8.4.33
+ tailwindcss: 3.4.1
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint@8.56.0:
+ resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
+ '@eslint-community/regexpp': 4.10.0
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.56.0
+ '@humanwhocodes/config-array': 0.11.14
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.0
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.3
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.11.3
+ acorn-jsx: 5.3.2(acorn@8.11.3)
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: false
+
+ /estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+ dependencies:
+ '@types/estree': 1.0.5
+ dev: false
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /event-target-shim@5.0.1:
+ resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /eventsource-parser@1.1.2:
+ resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==}
+ engines: {node: '>=14.18'}
+ dev: false
+
+ /extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+ dev: false
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.16.0:
+ resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /fault@1.0.4:
+ resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==}
+ dependencies:
+ format: 0.2.2
+ dev: false
+
+ /fflate@0.7.4:
+ resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==}
+ dev: false
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.2.0
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.2.9
+ keyv: 4.5.4
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted@3.2.9:
+ resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
+ dev: true
+
+ /focus-trap-react@10.2.3(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-YXBpFu/hIeSu6NnmV2xlXzOYxuWkoOtar9jzgp3lOmjWLWY59C/b8DtDHEAV4SPU07Nd/t+nS/SBNGkhUBFmEw==}
+ peerDependencies:
+ prop-types: ^15.8.1
+ react: '>=16.3.0'
+ react-dom: '>=16.3.0'
+ dependencies:
+ focus-trap: 7.5.4
+ prop-types: 15.8.1
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ tabbable: 6.2.0
+ dev: false
+
+ /focus-trap@7.5.4:
+ resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
+ dependencies:
+ tabbable: 6.2.0
+ dev: false
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+ dev: true
+
+ /form-data-encoder@1.7.2:
+ resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
+ dev: false
+
+ /form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+ dev: false
+
+ /format@0.2.2:
+ resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
+ engines: {node: '>=0.4.x'}
+ dev: false
+
+ /formdata-node@4.4.1:
+ resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
+ engines: {node: '>= 12.20'}
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 4.0.0-beta.3
+ dev: false
+
+ /fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+ dev: true
+
+ /framer-motion@10.18.0(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==}
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ tslib: 2.6.2
+ optionalDependencies:
+ '@emotion/is-prop-valid': 0.8.8
+ dev: false
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ dev: true
+
+ /function.prototype.name@1.1.6:
+ resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /geist@1.2.1(next@14.1.3):
+ resolution: {integrity: sha512-xCl7zWfnWqc+TbCG5qqyeT5tnVlOO4pSJsT3Ei59DN1SR4N2VlauF8Fv0D1pPFXGUJgu6RMoeZX+wsR4T9bMhg==}
+ peerDependencies:
+ next: ^13.2 || ^14
+ dependencies:
+ next: 14.1.3(react-dom@18.2.0)(react@18.2.0)
+ dev: false
+
+ /get-intrinsic@1.2.2:
+ resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
+ dependencies:
+ function-bind: 1.1.2
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ dev: true
+
+ /get-nonce@1.0.1:
+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /get-symbol-description@1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /get-tsconfig@4.7.2:
+ resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==}
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob@10.3.10:
+ resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ foreground-child: 3.1.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.3
+ minipass: 7.0.4
+ path-scurry: 1.10.1
+ dev: true
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.1
+ dev: true
+
+ /globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ ignore: 5.3.0
+ merge2: 1.4.1
+ slash: 3.0.0
+ dev: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ /graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.1:
+ resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /hasown@2.0.0:
+ resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function-bind: 1.1.2
+ dev: true
+
+ /hast-util-parse-selector@2.2.5:
+ resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==}
+ dev: false
+
+ /hast-util-whitespace@2.0.1:
+ resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==}
+ dev: false
+
+ /hastscript@6.0.0:
+ resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==}
+ dependencies:
+ '@types/hast': 2.3.9
+ comma-separated-tokens: 1.0.8
+ hast-util-parse-selector: 2.2.5
+ property-information: 5.6.0
+ space-separated-tokens: 1.1.5
+ dev: false
+
+ /hex-rgb@4.3.0:
+ resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /highlight.js@10.7.3:
+ resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
+ dev: false
+
+ /humanize-ms@1.2.1:
+ resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
+ dependencies:
+ ms: 2.1.3
+ dev: false
+
+ /ignore@5.3.0:
+ resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /inline-style-parser@0.1.1:
+ resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==}
+ dev: false
+
+ /internal-slot@1.0.6:
+ resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ hasown: 2.0.0
+ side-channel: 1.0.4
+ dev: true
+
+ /internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /invariant@2.2.4:
+ resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /is-alphabetical@1.0.4:
+ resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
+ dev: false
+
+ /is-alphanumerical@1.0.4:
+ resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==}
+ dependencies:
+ is-alphabetical: 1.0.4
+ is-decimal: 1.0.4
+ dev: false
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /is-async-function@2.0.0:
+ resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-buffer@1.1.6:
+ resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
+ dev: false
+
+ /is-buffer@2.0.5:
+ resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.13.1:
+ resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ dependencies:
+ hasown: 2.0.0
+ dev: true
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-decimal@1.0.4:
+ resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
+ dev: false
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-finalizationregistry@1.0.2:
+ resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-generator-function@1.0.10:
+ resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-hexadecimal@1.0.4:
+ resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
+ dev: false
+
+ /is-map@2.0.2:
+ resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
+ dev: true
+
+ /is-negative-zero@2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+ dev: false
+
+ /is-reference@3.0.2:
+ resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
+ dependencies:
+ '@types/estree': 1.0.5
+ dev: false
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-set@2.0.2:
+ resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.12:
+ resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.13
+ dev: true
+
+ /is-weakmap@2.0.1:
+ resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
+ dev: true
+
+ /is-weakref@1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-weakset@2.0.2:
+ resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /iterator.prototype@1.1.2:
+ resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
+ dependencies:
+ define-properties: 1.2.1
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ reflect.getprototypeof: 1.0.4
+ set-function-name: 2.0.1
+ dev: true
+
+ /jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+ dev: true
+
+ /jiti@1.21.0:
+ resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
+ hasBin: true
+ dev: true
+
+ /jose@5.2.0:
+ resolution: {integrity: sha512-oW3PCnvyrcm1HMvGTzqjxxfnEs9EoFOFWi2HsEGhlFVOXxTE3K9GKWVMFoFw06yPUqwpvEWic1BmtUZBI/tIjw==}
+ dev: false
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jsbarcode@3.11.6:
+ resolution: {integrity: sha512-G5TKGyKY1zJo0ZQKFM1IIMfy0nF2rs92BLlCz+cU4/TazIc4ZH+X1GYeDRt7TKjrYqmPfTjwTBkU/QnQlsYiuA==}
+ dev: false
+
+ /json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-schema@0.4.0:
+ resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
+ dev: false
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5@1.0.2:
+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.8
+ dev: true
+
+ /jsondiffpatch@0.6.0:
+ resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ dependencies:
+ '@types/diff-match-patch': 1.0.36
+ chalk: 5.3.0
+ diff-match-patch: 1.0.5
+ dev: false
+
+ /jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flat: 1.3.2
+ object.assign: 4.1.5
+ object.values: 1.1.7
+ dev: true
+
+ /katex@0.16.9:
+ resolution: {integrity: sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==}
+ hasBin: true
+ dependencies:
+ commander: 8.3.0
+ dev: false
+
+ /keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ dependencies:
+ json-buffer: 3.0.1
+ dev: true
+
+ /kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /language-subtag-registry@0.3.22:
+ resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
+ dev: true
+
+ /language-tags@1.0.9:
+ resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ language-subtag-registry: 0.3.22
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /lilconfig@3.0.0:
+ resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /linebreak@1.1.0:
+ resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==}
+ dependencies:
+ base64-js: 0.0.8
+ unicode-trie: 2.0.0
+ dev: false
+
+ /lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ dev: true
+
+ /locate-character@3.0.0:
+ resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+ dev: false
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.castarray@4.4.0:
+ resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
+ dev: true
+
+ /lodash.debounce@4.0.8:
+ resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+ dev: false
+
+ /lodash.isplainobject@4.0.6:
+ resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+ dev: false
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+
+ /lowlight@1.20.0:
+ resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==}
+ dependencies:
+ fault: 1.0.4
+ highlight.js: 10.7.3
+ dev: false
+
+ /lru-cache@10.1.0:
+ resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==}
+ engines: {node: 14 || >=16.14}
+ dev: true
+
+ /lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /magic-string@0.30.8:
+ resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: false
+
+ /markdown-table@3.0.3:
+ resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
+ dev: false
+
+ /md5@2.3.0:
+ resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
+ dependencies:
+ charenc: 0.0.2
+ crypt: 0.0.2
+ is-buffer: 1.1.6
+ dev: false
+
+ /mdast-util-definitions@5.1.2:
+ resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ '@types/unist': 2.0.10
+ unist-util-visit: 4.1.2
+ dev: false
+
+ /mdast-util-find-and-replace@2.2.2:
+ resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ escape-string-regexp: 5.0.0
+ unist-util-is: 5.2.1
+ unist-util-visit-parents: 5.1.3
+ dev: false
+
+ /mdast-util-from-markdown@1.3.1:
+ resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ '@types/unist': 2.0.10
+ decode-named-character-reference: 1.0.2
+ mdast-util-to-string: 3.2.0
+ micromark: 3.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-decode-string: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ unist-util-stringify-position: 3.0.3
+ uvu: 0.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /mdast-util-gfm-autolink-literal@1.0.3:
+ resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ ccount: 2.0.1
+ mdast-util-find-and-replace: 2.2.2
+ micromark-util-character: 1.2.0
+ dev: false
+
+ /mdast-util-gfm-footnote@1.0.2:
+ resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-to-markdown: 1.5.0
+ micromark-util-normalize-identifier: 1.1.0
+ dev: false
+
+ /mdast-util-gfm-strikethrough@1.0.3:
+ resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-to-markdown: 1.5.0
+ dev: false
+
+ /mdast-util-gfm-table@1.0.7:
+ resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ markdown-table: 3.0.3
+ mdast-util-from-markdown: 1.3.1
+ mdast-util-to-markdown: 1.5.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /mdast-util-gfm-task-list-item@1.0.2:
+ resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-to-markdown: 1.5.0
+ dev: false
+
+ /mdast-util-gfm@2.0.2:
+ resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==}
+ dependencies:
+ mdast-util-from-markdown: 1.3.1
+ mdast-util-gfm-autolink-literal: 1.0.3
+ mdast-util-gfm-footnote: 1.0.2
+ mdast-util-gfm-strikethrough: 1.0.3
+ mdast-util-gfm-table: 1.0.7
+ mdast-util-gfm-task-list-item: 1.0.2
+ mdast-util-to-markdown: 1.5.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /mdast-util-math@2.0.2:
+ resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ longest-streak: 3.1.0
+ mdast-util-to-markdown: 1.5.0
+ dev: false
+
+ /mdast-util-phrasing@3.0.1:
+ resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ unist-util-is: 5.2.1
+ dev: false
+
+ /mdast-util-to-hast@12.3.0:
+ resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==}
+ dependencies:
+ '@types/hast': 2.3.9
+ '@types/mdast': 3.0.15
+ mdast-util-definitions: 5.1.2
+ micromark-util-sanitize-uri: 1.2.0
+ trim-lines: 3.0.1
+ unist-util-generated: 2.0.1
+ unist-util-position: 4.0.4
+ unist-util-visit: 4.1.2
+ dev: false
+
+ /mdast-util-to-markdown@1.5.0:
+ resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ '@types/unist': 2.0.10
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 3.0.1
+ mdast-util-to-string: 3.2.0
+ micromark-util-decode-string: 1.1.0
+ unist-util-visit: 4.1.2
+ zwitch: 2.0.4
+ dev: false
+
+ /mdast-util-to-string@3.2.0:
+ resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ dev: false
+
+ /mdn-data@2.0.30:
+ resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
+ dev: false
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromark-core-commonmark@1.1.0:
+ resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
+ dependencies:
+ decode-named-character-reference: 1.0.2
+ micromark-factory-destination: 1.1.0
+ micromark-factory-label: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-factory-title: 1.1.0
+ micromark-factory-whitespace: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-classify-character: 1.1.0
+ micromark-util-html-tag-name: 1.2.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-extension-gfm-autolink-literal@1.0.5:
+ resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-extension-gfm-footnote@1.1.2:
+ resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==}
+ dependencies:
+ micromark-core-commonmark: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-extension-gfm-strikethrough@1.0.7:
+ resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==}
+ dependencies:
+ micromark-util-chunked: 1.1.0
+ micromark-util-classify-character: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-extension-gfm-table@1.0.7:
+ resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-extension-gfm-tagfilter@1.0.2:
+ resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==}
+ dependencies:
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-extension-gfm-task-list-item@1.0.5:
+ resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-extension-gfm@2.0.3:
+ resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==}
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 1.0.5
+ micromark-extension-gfm-footnote: 1.1.2
+ micromark-extension-gfm-strikethrough: 1.0.7
+ micromark-extension-gfm-table: 1.0.7
+ micromark-extension-gfm-tagfilter: 1.0.2
+ micromark-extension-gfm-task-list-item: 1.0.5
+ micromark-util-combine-extensions: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-extension-math@2.1.2:
+ resolution: {integrity: sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==}
+ dependencies:
+ '@types/katex': 0.16.7
+ katex: 0.16.9
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-factory-destination@1.1.0:
+ resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-factory-label@1.1.0:
+ resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-factory-space@1.1.0:
+ resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-factory-title@1.1.0:
+ resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-factory-whitespace@1.1.0:
+ resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-util-character@1.2.0:
+ resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-util-chunked@1.1.0:
+ resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: false
+
+ /micromark-util-classify-character@1.1.0:
+ resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-util-combine-extensions@1.1.0:
+ resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
+ dependencies:
+ micromark-util-chunked: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-util-decode-numeric-character-reference@1.1.0:
+ resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: false
+
+ /micromark-util-decode-string@1.1.0:
+ resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
+ dependencies:
+ decode-named-character-reference: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-symbol: 1.1.0
+ dev: false
+
+ /micromark-util-encode@1.1.0:
+ resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
+ dev: false
+
+ /micromark-util-html-tag-name@1.2.0:
+ resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
+ dev: false
+
+ /micromark-util-normalize-identifier@1.1.0:
+ resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: false
+
+ /micromark-util-resolve-all@1.1.0:
+ resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
+ dependencies:
+ micromark-util-types: 1.1.0
+ dev: false
+
+ /micromark-util-sanitize-uri@1.2.0:
+ resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-encode: 1.1.0
+ micromark-util-symbol: 1.1.0
+ dev: false
+
+ /micromark-util-subtokenize@1.1.0:
+ resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
+ dependencies:
+ micromark-util-chunked: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: false
+
+ /micromark-util-symbol@1.1.0:
+ resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
+ dev: false
+
+ /micromark-util-types@1.1.0:
+ resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
+ dev: false
+
+ /micromark@3.2.0:
+ resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
+ dependencies:
+ '@types/debug': 4.1.12
+ debug: 4.3.4
+ decode-named-character-reference: 1.0.2
+ micromark-core-commonmark: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-combine-extensions: 1.1.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-encode: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: false
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ dev: true
+
+ /minipass@7.0.4:
+ resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dev: true
+
+ /mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ /ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ /mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+ dev: true
+
+ /nanoid@3.3.6:
+ resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: false
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /nanoid@5.0.4:
+ resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ dev: false
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /next-auth@5.0.0-beta.4(next@14.1.3)(react@18.2.0):
+ resolution: {integrity: sha512-vgocjvwPA8gxd/zrIP/vr9lJ/HeNe+C56lPP1D3sdyenHt8KncQV6ro7q0xCsDp1fcOKx7WAWVZH5o8aMxDzgw==}
+ peerDependencies:
+ next: ^14
+ nodemailer: ^6.6.5
+ react: ^18.2.0
+ peerDependenciesMeta:
+ nodemailer:
+ optional: true
+ dependencies:
+ '@auth/core': 0.18.4
+ next: 14.1.3(react-dom@18.2.0)(react@18.2.0)
+ react: 18.2.0
+ dev: false
+
+ /next-themes@0.2.1(next@14.1.3)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
+ peerDependencies:
+ next: '*'
+ react: '*'
+ react-dom: '*'
+ dependencies:
+ next: 14.1.3(react-dom@18.2.0)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /next@14.1.3(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-oexgMV2MapI0UIWiXKkixF8J8ORxpy64OuJ/J9oVUmIthXOUCcuVEZX+dtpgq7wIfIqtBwQsKEDXejcjTsan9g==}
+ engines: {node: '>=18.17.0'}
+ hasBin: true
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ sass: ^1.3.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ sass:
+ optional: true
+ dependencies:
+ '@next/env': 14.1.3
+ '@swc/helpers': 0.5.2
+ busboy: 1.6.0
+ caniuse-lite: 1.0.30001579
+ graceful-fs: 4.2.11
+ postcss: 8.4.31
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ styled-jsx: 5.1.1(react@18.2.0)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 14.1.3
+ '@next/swc-darwin-x64': 14.1.3
+ '@next/swc-linux-arm64-gnu': 14.1.3
+ '@next/swc-linux-arm64-musl': 14.1.3
+ '@next/swc-linux-x64-gnu': 14.1.3
+ '@next/swc-linux-x64-musl': 14.1.3
+ '@next/swc-win32-arm64-msvc': 14.1.3
+ '@next/swc-win32-ia32-msvc': 14.1.3
+ '@next/swc-win32-x64-msvc': 14.1.3
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+ dev: false
+
+ /node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ dev: false
+
+ /node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+ dependencies:
+ whatwg-url: 5.0.0
+ dev: false
+
+ /node-releases@2.0.14:
+ resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /oauth4webapi@2.7.0:
+ resolution: {integrity: sha512-XxmYWOSL9jO4K/ufyZL0YeqE1M+3ZNJ4gdo8C3bpuBemibFBLAlAXiVia2HCiErTzX+q+CFDlhf4o7P0HVsZ0w==}
+ dev: false
+
+ /object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ /object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /object-inspect@1.13.1:
+ resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.5:
+ resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /object.entries@1.1.7:
+ resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.fromentries@2.0.7:
+ resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.groupby@1.0.1:
+ resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /object.hasown@1.1.3:
+ resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==}
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.values@1.1.7:
+ resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /openai@4.24.7:
+ resolution: {integrity: sha512-JUesECWPtsDHO0TlZGb6q73hnAmXUdzj9NrwgZeL4lqlRt/kR1sWrXoy8LocxN/6uOtitywvcJqe0O1PLkG45g==}
+ hasBin: true
+ dependencies:
+ '@types/node': 18.19.8
+ '@types/node-fetch': 2.6.11
+ abort-controller: 3.0.0
+ agentkeepalive: 4.5.0
+ digest-fetch: 1.3.0
+ form-data-encoder: 1.7.2
+ formdata-node: 4.4.1
+ node-fetch: 2.7.0
+ web-streams-polyfill: 3.3.2
+ transitivePeerDependencies:
+ - encoding
+ dev: false
+
+ /optionator@0.9.3:
+ resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ '@aashutoshrathi/word-wrap': 1.2.6
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /pako@0.2.9:
+ resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
+ dev: false
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /parse-css-color@0.2.1:
+ resolution: {integrity: sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==}
+ dependencies:
+ color-name: 1.1.4
+ hex-rgb: 4.3.0
+ dev: false
+
+ /parse-entities@2.0.0:
+ resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==}
+ dependencies:
+ character-entities: 1.2.4
+ character-entities-legacy: 1.1.4
+ character-reference-invalid: 1.1.4
+ is-alphanumerical: 1.0.4
+ is-decimal: 1.0.4
+ is-hexadecimal: 1.0.4
+ dev: false
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /path-scurry@1.10.1:
+ resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ lru-cache: 10.1.0
+ minipass: 7.0.4
+ dev: true
+
+ /path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /periscopic@3.1.0:
+ resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
+ dependencies:
+ '@types/estree': 1.0.5
+ estree-walker: 3.0.3
+ is-reference: 3.0.2
+ dev: false
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /postcss-import@15.1.0(postcss@8.4.33):
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.8
+ dev: true
+
+ /postcss-js@4.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.4.33
+ dev: true
+
+ /postcss-load-config@4.0.2(postcss@8.4.33):
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 3.0.0
+ postcss: 8.4.33
+ yaml: 2.3.4
+ dev: true
+
+ /postcss-nested@6.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+ dependencies:
+ postcss: 8.4.33
+ postcss-selector-parser: 6.0.15
+ dev: true
+
+ /postcss-selector-parser@6.0.10:
+ resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /postcss-selector-parser@6.0.15:
+ resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ /postcss@8.4.31:
+ resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: false
+
+ /postcss@8.4.33:
+ resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /postcss@8.4.38:
+ resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.2.0
+ dev: false
+
+ /preact-render-to-string@5.2.3(preact@10.11.3):
+ resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
+ peerDependencies:
+ preact: '>=10'
+ dependencies:
+ preact: 10.11.3
+ pretty-format: 3.8.0
+ dev: false
+
+ /preact@10.11.3:
+ resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==}
+ dev: false
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prettier@3.2.4:
+ resolution: {integrity: sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==}
+ engines: {node: '>=14'}
+ hasBin: true
+ dev: true
+
+ /pretty-format@3.8.0:
+ resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
+ dev: false
+
+ /prismjs@1.27.0:
+ resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /prismjs@1.29.0:
+ resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ /property-information@5.6.0:
+ resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==}
+ dependencies:
+ xtend: 4.0.2
+ dev: false
+
+ /property-information@6.4.0:
+ resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==}
+ dev: false
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /react-dom@18.2.0(react@18.2.0):
+ resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
+ peerDependencies:
+ react: ^18.2.0
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.2.0
+ scheduler: 0.23.0
+ dev: false
+
+ /react-intersection-observer@9.5.3(react@18.2.0):
+ resolution: {integrity: sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ==}
+ peerDependencies:
+ react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+ /react-is@18.2.0:
+ resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
+ dev: false
+
+ /react-jsbarcode@0.4.2(react@18.2.0):
+ resolution: {integrity: sha512-0MLrre1bLKsiwB26h7/5Hh1fNli/2QpLtxhRn3FBgm1RgC8G65Chm3O9VitVYyHzcJkegp8U6xeog7DlDLrhNA==}
+ peerDependencies:
+ react: '>=17 <=18'
+ dependencies:
+ jsbarcode: 3.11.6
+ react: 18.2.0
+ dev: false
+
+ /react-markdown@8.0.7(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==}
+ peerDependencies:
+ '@types/react': '>=16'
+ react: '>=16'
+ dependencies:
+ '@types/hast': 2.3.9
+ '@types/prop-types': 15.7.11
+ '@types/react': 18.2.48
+ '@types/unist': 2.0.10
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 2.0.1
+ prop-types: 15.8.1
+ property-information: 6.4.0
+ react: 18.2.0
+ react-is: 18.2.0
+ remark-parse: 10.0.2
+ remark-rehype: 10.1.0
+ space-separated-tokens: 2.0.2
+ style-to-object: 0.4.4
+ unified: 10.1.2
+ unist-util-visit: 4.1.2
+ vfile: 5.3.7
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /react-remove-scroll-bar@2.3.4(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ react: 18.2.0
+ react-style-singleton: 2.2.1(@types/react@18.2.48)(react@18.2.0)
+ tslib: 2.6.2
+ dev: false
+
+ /react-remove-scroll@2.5.5(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ react: 18.2.0
+ react-remove-scroll-bar: 2.3.4(@types/react@18.2.48)(react@18.2.0)
+ react-style-singleton: 2.2.1(@types/react@18.2.48)(react@18.2.0)
+ tslib: 2.6.2
+ use-callback-ref: 1.3.1(@types/react@18.2.48)(react@18.2.0)
+ use-sidecar: 1.1.2(@types/react@18.2.48)(react@18.2.0)
+ dev: false
+
+ /react-style-singleton@2.2.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ get-nonce: 1.0.1
+ invariant: 2.2.4
+ react: 18.2.0
+ tslib: 2.6.2
+ dev: false
+
+ /react-syntax-highlighter@15.5.0(react@18.2.0):
+ resolution: {integrity: sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==}
+ peerDependencies:
+ react: '>= 0.14.0'
+ dependencies:
+ '@babel/runtime': 7.23.8
+ highlight.js: 10.7.3
+ lowlight: 1.20.0
+ prismjs: 1.29.0
+ react: 18.2.0
+ refractor: 3.6.0
+ dev: false
+
+ /react-textarea-autosize@8.5.3(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ '@babel/runtime': 7.23.8
+ react: 18.2.0
+ use-composed-ref: 1.3.0(react@18.2.0)
+ use-latest: 1.2.1(@types/react@18.2.48)(react@18.2.0)
+ transitivePeerDependencies:
+ - '@types/react'
+ dev: false
+
+ /react@18.2.0:
+ resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ dependencies:
+ pify: 2.3.0
+ dev: true
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /reflect.getprototypeof@1.0.4:
+ resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ which-builtin-type: 1.1.3
+ dev: true
+
+ /refractor@3.6.0:
+ resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==}
+ dependencies:
+ hastscript: 6.0.0
+ parse-entities: 2.0.0
+ prismjs: 1.27.0
+ dev: false
+
+ /regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+
+ /regexp.prototype.flags@1.5.1:
+ resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ set-function-name: 2.0.1
+ dev: true
+
+ /remark-gfm@3.0.1:
+ resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-gfm: 2.0.2
+ micromark-extension-gfm: 2.0.3
+ unified: 10.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /remark-math@5.1.1:
+ resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-math: 2.0.2
+ micromark-extension-math: 2.1.2
+ unified: 10.1.2
+ dev: false
+
+ /remark-parse@10.0.2:
+ resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ mdast-util-from-markdown: 1.3.1
+ unified: 10.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /remark-rehype@10.1.0:
+ resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
+ dependencies:
+ '@types/hast': 2.3.9
+ '@types/mdast': 3.0.15
+ mdast-util-to-hast: 12.3.0
+ unified: 10.1.2
+ dev: false
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ dev: true
+
+ /resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /sade@1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+ dependencies:
+ mri: 1.2.0
+ dev: false
+
+ /safe-array-concat@1.1.0:
+ resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ isarray: 2.0.5
+ dev: true
+
+ /safe-regex-test@1.0.2:
+ resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-regex: 1.1.4
+ dev: true
+
+ /satori@0.10.9:
+ resolution: {integrity: sha512-XU9EELUEZuioT4acLIpCXxHcFzrsC8muvg0MY28d+TlqwxbkTzBmWbw+3+hnCzXT7YZ0Qm8k3eXktDaEu+qmEw==}
+ engines: {node: '>=16'}
+ dependencies:
+ '@shuding/opentype.js': 1.4.0-beta.0
+ css-background-parser: 0.1.0
+ css-box-shadow: 1.0.0-3
+ css-to-react-native: 3.2.0
+ emoji-regex: 10.3.0
+ escape-html: 1.0.3
+ linebreak: 1.1.0
+ parse-css-color: 0.2.1
+ postcss-value-parser: 4.2.0
+ yoga-wasm-web: 0.3.3
+ dev: false
+
+ /scheduler@0.23.0:
+ resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /secure-json-parse@2.7.0:
+ resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
+ dev: false
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /seroval-plugins@1.0.5(seroval@1.0.5):
+ resolution: {integrity: sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ seroval: ^1.0
+ dependencies:
+ seroval: 1.0.5
+ dev: false
+
+ /seroval@1.0.5:
+ resolution: {integrity: sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==}
+ engines: {node: '>=10'}
+ dev: false
+
+ /server-only@0.0.1:
+ resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
+ dev: false
+
+ /set-function-length@1.2.0:
+ resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /set-function-name@2.0.1:
+ resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ object-inspect: 1.13.1
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /solid-js@1.8.16:
+ resolution: {integrity: sha512-rja94MNU9flF3qQRLNsu60QHKBDKBkVE1DldJZPIfn2ypIn3NV2WpSbGTQIvsyGPBo+9E2IMjwqnqpbgfWuzeg==}
+ dependencies:
+ csstype: 3.1.3
+ seroval: 1.0.5
+ seroval-plugins: 1.0.5(seroval@1.0.5)
+ dev: false
+
+ /solid-swr-store@0.10.7(solid-js@1.8.16)(swr-store@0.10.6):
+ resolution: {integrity: sha512-A6d68aJmRP471aWqKKPE2tpgOiR5fH4qXQNfKIec+Vap+MGQm3tvXlT8n0I8UgJSlNAsSAUuw2VTviH2h3Vv5g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ solid-js: ^1.2
+ swr-store: ^0.10
+ dependencies:
+ solid-js: 1.8.16
+ swr-store: 0.10.6
+ dev: false
+
+ /sonner@1.4.3(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-SArYlHbkjqRuLiR0iGY2ZSr09oOrxw081ZZkQPfXrs8aZQLIBOLOdzTYxGJB5yIZ7qL56UEPmrX1YqbODwG0Lw==}
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
+ /space-separated-tokens@1.1.5:
+ resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==}
+ dev: false
+
+ /space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+ dev: false
+
+ /sswr@2.1.0(svelte@4.2.12):
+ resolution: {integrity: sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==}
+ peerDependencies:
+ svelte: ^4.0.0 || ^5.0.0-next.0
+ dependencies:
+ svelte: 4.2.12
+ swrev: 4.0.0
+ dev: false
+
+ /streamsearch@1.1.0:
+ resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
+ engines: {node: '>=10.0.0'}
+ dev: false
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+ dev: true
+
+ /string.prototype.codepointat@0.2.1:
+ resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==}
+ dev: false
+
+ /string.prototype.matchall@4.0.10:
+ resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ regexp.prototype.flags: 1.5.1
+ set-function-name: 2.0.1
+ side-channel: 1.0.4
+ dev: true
+
+ /string.prototype.trim@1.2.8:
+ resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimend@1.0.7:
+ resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimstart@1.0.7:
+ resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+ dev: true
+
+ /strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /style-to-object@0.4.4:
+ resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==}
+ dependencies:
+ inline-style-parser: 0.1.1
+ dev: false
+
+ /styled-jsx@5.1.1(react@18.2.0):
+ resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ '@babel/core': '*'
+ babel-plugin-macros: '*'
+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ babel-plugin-macros:
+ optional: true
+ dependencies:
+ client-only: 0.0.1
+ react: 18.2.0
+ dev: false
+
+ /sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ commander: 4.1.1
+ glob: 10.3.10
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /svelte@4.2.12:
+ resolution: {integrity: sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==}
+ engines: {node: '>=16'}
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.25
+ '@types/estree': 1.0.5
+ acorn: 8.11.3
+ aria-query: 5.3.0
+ axobject-query: 4.0.0
+ code-red: 1.0.4
+ css-tree: 2.3.1
+ estree-walker: 3.0.3
+ is-reference: 3.0.2
+ locate-character: 3.0.0
+ magic-string: 0.30.8
+ periscopic: 3.1.0
+ dev: false
+
+ /swr-store@0.10.6:
+ resolution: {integrity: sha512-xPjB1hARSiRaNNlUQvWSVrG5SirCjk2TmaUyzzvk69SZQan9hCJqw/5rG9iL7xElHU784GxRPISClq4488/XVw==}
+ engines: {node: '>=10'}
+ dependencies:
+ dequal: 2.0.3
+ dev: false
+
+ /swr@2.2.0(react@18.2.0):
+ resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==}
+ peerDependencies:
+ react: ^16.11.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ use-sync-external-store: 1.2.0(react@18.2.0)
+ dev: false
+
+ /swrev@4.0.0:
+ resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==}
+ dev: false
+
+ /swrv@1.0.4(vue@3.4.21):
+ resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==}
+ peerDependencies:
+ vue: '>=3.2.26 < 4'
+ dependencies:
+ vue: 3.4.21(typescript@5.3.3)
+ dev: false
+
+ /tabbable@6.2.0:
+ resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
+ dev: false
+
+ /tailwind-merge@2.2.0:
+ resolution: {integrity: sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: true
+
+ /tailwindcss-animate@1.0.7(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+ dependencies:
+ tailwindcss: 3.4.1
+ dev: true
+
+ /tailwindcss@3.4.1:
+ resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.5.3
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.2
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.0
+ lilconfig: 2.1.0
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-import: 15.1.0(postcss@8.4.33)
+ postcss-js: 4.0.1(postcss@8.4.33)
+ postcss-load-config: 4.0.2(postcss@8.4.33)
+ postcss-nested: 6.0.1(postcss@8.4.33)
+ postcss-selector-parser: 6.0.15
+ resolve: 1.22.8
+ sucrase: 3.35.0
+ transitivePeerDependencies:
+ - ts-node
+ dev: true
+
+ /tapable@2.2.1:
+ resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+ dev: true
+
+ /thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+ dev: true
+
+ /tiny-inflate@1.0.3:
+ resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+ dev: false
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+ dev: false
+
+ /trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+ dev: false
+
+ /trough@2.1.0:
+ resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==}
+ dev: false
+
+ /ts-api-utils@1.0.3(typescript@5.3.3):
+ resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
+ engines: {node: '>=16.13.0'}
+ peerDependencies:
+ typescript: '>=4.2.0'
+ dependencies:
+ typescript: 5.3.3
+ dev: true
+
+ /ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ dev: true
+
+ /tsconfig-paths@3.15.0:
+ resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.2
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+ dev: true
+
+ /tslib@2.6.2:
+ resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ dev: false
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.0:
+ resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-length@1.0.0:
+ resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-offset@1.0.0:
+ resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-length@1.0.4:
+ resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typescript@5.3.3:
+ resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ /unbox-primitive@1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.5
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+ /unicode-trie@2.0.0:
+ resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
+ dependencies:
+ pako: 0.2.9
+ tiny-inflate: 1.0.3
+ dev: false
+
+ /unified@10.1.2:
+ resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
+ dependencies:
+ '@types/unist': 2.0.10
+ bail: 2.0.2
+ extend: 3.0.2
+ is-buffer: 2.0.5
+ is-plain-obj: 4.1.0
+ trough: 2.1.0
+ vfile: 5.3.7
+ dev: false
+
+ /unist-util-generated@2.0.1:
+ resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==}
+ dev: false
+
+ /unist-util-is@5.2.1:
+ resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: false
+
+ /unist-util-position@4.0.4:
+ resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: false
+
+ /unist-util-stringify-position@3.0.3:
+ resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: false
+
+ /unist-util-visit-parents@5.1.3:
+ resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
+ dependencies:
+ '@types/unist': 2.0.10
+ unist-util-is: 5.2.1
+ dev: false
+
+ /unist-util-visit@4.1.2:
+ resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==}
+ dependencies:
+ '@types/unist': 2.0.10
+ unist-util-is: 5.2.1
+ unist-util-visit-parents: 5.1.3
+ dev: false
+
+ /update-browserslist-db@1.0.13(browserslist@4.22.2):
+ resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.22.2
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /use-callback-ref@1.3.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ react: 18.2.0
+ tslib: 2.6.2
+ dev: false
+
+ /use-composed-ref@1.3.0(react@18.2.0):
+ resolution: {integrity: sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ react: 18.2.0
+ dev: false
+
+ /use-latest@1.2.1(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ react: 18.2.0
+ use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.48)(react@18.2.0)
+ dev: false
+
+ /use-sidecar@1.1.2(@types/react@18.2.48)(react@18.2.0):
+ resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@types/react': 18.2.48
+ detect-node-es: 1.1.0
+ react: 18.2.0
+ tslib: 2.6.2
+ dev: false
+
+ /use-sync-external-store@1.2.0(react@18.2.0):
+ resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /usehooks-ts@2.16.0(react@18.2.0):
+ resolution: {integrity: sha512-bez95WqYujxp6hFdM/CpRDiVPirZPxlMzOH2QB8yopoKQMXpscyZoxOjpEdaxvV+CAWUDSM62cWnqHE0E/MZ7w==}
+ engines: {node: '>=16.15.0'}
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18
+ dependencies:
+ lodash.debounce: 4.0.8
+ react: 18.2.0
+ dev: false
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: true
+
+ /uvu@0.5.6:
+ resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ dequal: 2.0.3
+ diff: 5.1.0
+ kleur: 4.1.5
+ sade: 1.8.1
+ dev: false
+
+ /vfile-message@3.1.4:
+ resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==}
+ dependencies:
+ '@types/unist': 2.0.10
+ unist-util-stringify-position: 3.0.3
+ dev: false
+
+ /vfile@5.3.7:
+ resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==}
+ dependencies:
+ '@types/unist': 2.0.10
+ is-buffer: 2.0.5
+ unist-util-stringify-position: 3.0.3
+ vfile-message: 3.1.4
+ dev: false
+
+ /vue@3.4.21(typescript@5.3.3):
+ resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@vue/compiler-dom': 3.4.21
+ '@vue/compiler-sfc': 3.4.21
+ '@vue/runtime-dom': 3.4.21
+ '@vue/server-renderer': 3.4.21(vue@3.4.21)
+ '@vue/shared': 3.4.21
+ typescript: 5.3.3
+ dev: false
+
+ /web-streams-polyfill@3.3.2:
+ resolution: {integrity: sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==}
+ engines: {node: '>= 8'}
+ dev: false
+
+ /web-streams-polyfill@4.0.0-beta.3:
+ resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
+ engines: {node: '>= 14'}
+ dev: false
+
+ /webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+ dev: false
+
+ /whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+ dev: false
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-builtin-type@1.1.3:
+ resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function.prototype.name: 1.1.6
+ has-tostringtag: 1.0.0
+ is-async-function: 2.0.0
+ is-date-object: 1.0.5
+ is-finalizationregistry: 1.0.2
+ is-generator-function: 1.0.10
+ is-regex: 1.1.4
+ is-weakref: 1.0.2
+ isarray: 2.0.5
+ which-boxed-primitive: 1.0.2
+ which-collection: 1.0.1
+ which-typed-array: 1.1.13
+ dev: true
+
+ /which-collection@1.0.1:
+ resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
+ dependencies:
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-weakmap: 2.0.1
+ is-weakset: 2.0.2
+ dev: true
+
+ /which-typed-array@1.1.13:
+ resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+ dev: false
+
+ /yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yaml@2.3.4:
+ resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
+ engines: {node: '>= 14'}
+ dev: true
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yoga-wasm-web@0.3.3:
+ resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
+ dev: false
+
+ /zod-to-json-schema@3.22.5(zod@3.22.4):
+ resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==}
+ peerDependencies:
+ zod: ^3.22.4
+ dependencies:
+ zod: 3.22.4
+ dev: false
+
+ /zod@3.22.4:
+ resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
+ dev: false
+
+ /zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+ dev: false
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..33ad091
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/prettier.config.cjs b/prettier.config.cjs
new file mode 100644
index 0000000..842ca6b
--- /dev/null
+++ b/prettier.config.cjs
@@ -0,0 +1,34 @@
+/** @type {import('prettier').Config} */
+module.exports = {
+ endOfLine: 'lf',
+ semi: false,
+ useTabs: false,
+ singleQuote: true,
+ arrowParens: 'avoid',
+ tabWidth: 2,
+ trailingComma: 'none',
+ importOrder: [
+ '^(react/(.*)$)|^(react$)',
+ '^(next/(.*)$)|^(next$)',
+ '',
+ '',
+ '^types$',
+ '^@/types/(.*)$',
+ '^@/config/(.*)$',
+ '^@/lib/(.*)$',
+ '^@/hooks/(.*)$',
+ '^@/components/ui/(.*)$',
+ '^@/components/(.*)$',
+ '^@/registry/(.*)$',
+ '^@/styles/(.*)$',
+ '^@/app/(.*)$',
+ '',
+ '^[./]'
+ ],
+ importOrderSeparation: false,
+ importOrderSortSpecifiers: true,
+ importOrderBuiltinModulesToTop: true,
+ importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
+ importOrderMergeDuplicateImports: true,
+ importOrderCombineTypeAndValueImports: true
+}
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..0eb831f
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
new file mode 100644
index 0000000..620c7d8
Binary files /dev/null and b/public/favicon-16x16.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..7452b5d
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/images/1.jpg b/public/images/1.jpg
new file mode 100644
index 0000000..cb70321
Binary files /dev/null and b/public/images/1.jpg differ
diff --git a/public/images/2.jpg b/public/images/2.jpg
new file mode 100644
index 0000000..23e845d
Binary files /dev/null and b/public/images/2.jpg differ
diff --git a/public/images/3.jpg b/public/images/3.jpg
new file mode 100644
index 0000000..45db9a8
Binary files /dev/null and b/public/images/3.jpg differ
diff --git a/public/images/gemini.png b/public/images/gemini.png
new file mode 100644
index 0000000..b31a358
Binary files /dev/null and b/public/images/gemini.png differ
diff --git a/public/next.svg b/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/og.png b/public/og.png
new file mode 100644
index 0000000..73d6023
Binary files /dev/null and b/public/og.png differ
diff --git a/public/thirteen.svg b/public/thirteen.svg
new file mode 100644
index 0000000..8977c1b
--- /dev/null
+++ b/public/thirteen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
new file mode 100644
index 0000000..d2f8422
--- /dev/null
+++ b/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/videos/books.mp4 b/public/videos/books.mp4
new file mode 100644
index 0000000..6073a8f
Binary files /dev/null and b/public/videos/books.mp4 differ
diff --git a/tailwind.config.ts b/tailwind.config.ts
new file mode 100644
index 0000000..e328571
--- /dev/null
+++ b/tailwind.config.ts
@@ -0,0 +1,82 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ['class'],
+ content: [
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}',
+ './lib/**/*.{ts,tsx}'
+ ],
+ prefix: '',
+ theme: {
+ container: {
+ center: true,
+ padding: '2rem',
+ screens: {
+ '2xl': '1400px'
+ }
+ },
+ extend: {
+ fontFamily: {
+ sans: ['var(--font-geist-sans)'],
+ mono: ['var(--font-geist-mono)']
+ },
+ colors: {
+ border: 'hsl(var(--border))',
+ input: 'hsl(var(--input))',
+ ring: 'hsl(var(--ring))',
+ background: 'hsl(var(--background))',
+ foreground: 'hsl(var(--foreground))',
+ primary: {
+ DEFAULT: 'hsl(var(--primary))',
+ foreground: 'hsl(var(--primary-foreground))'
+ },
+ secondary: {
+ DEFAULT: 'hsl(var(--secondary))',
+ foreground: 'hsl(var(--secondary-foreground))'
+ },
+ destructive: {
+ DEFAULT: 'hsl(var(--destructive))',
+ foreground: 'hsl(var(--destructive-foreground))'
+ },
+ muted: {
+ DEFAULT: 'hsl(var(--muted))',
+ foreground: 'hsl(var(--muted-foreground))'
+ },
+ accent: {
+ DEFAULT: 'hsl(var(--accent))',
+ foreground: 'hsl(var(--accent-foreground))'
+ },
+ popover: {
+ DEFAULT: 'hsl(var(--popover))',
+ foreground: 'hsl(var(--popover-foreground))'
+ },
+ card: {
+ DEFAULT: 'hsl(var(--card))',
+ foreground: 'hsl(var(--card-foreground))'
+ }
+ },
+ borderRadius: {
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)'
+ },
+ keyframes: {
+ 'accordion-down': {
+ from: { height: '0' },
+ to: { height: 'var(--radix-accordion-content-height)' }
+ },
+ 'accordion-up': {
+ from: { height: 'var(--radix-accordion-content-height)' },
+ to: { height: '0' }
+ }
+ },
+ animation: {
+ 'accordion-down': 'accordion-down 0.2s ease-out',
+ 'accordion-up': 'accordion-up 0.2s ease-out'
+ }
+ }
+ },
+ plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..1f6ba91
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,36 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "incremental": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "target": "esnext",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./*"]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "strictNullChecks": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "next-auth.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": ["node_modules"]
+}