refactor: docubook@latest template nextjs-docker

This commit is contained in:
gitfromwildan
2026-05-30 18:52:21 +07:00
parent bf2ef37f49
commit 80eb49d968
101 changed files with 1759 additions and 4165 deletions

View File

@@ -1,14 +0,0 @@
{
"DocuAccordion": {
"prefix": "accordion",
"body": [
"<Accordion title=\"${1:Plain Text}\">",
" this is an example of plain text content from the accordion component and below is markdown ;",
" 1. number one",
" 2. number two",
" 3. number three",
"</Accordion>"
],
"description": "Create a DocuAccordion component with markdown list."
}
}

View File

@@ -1,16 +0,0 @@
{
"DocuButton": {
"prefix": "button",
"body": [
"<Button",
" text=\"${1:Learn More}\"",
" href=\"${2:https://learn.example.com}\"",
" icon=\"${3:MoveUpRight}\"",
" size=\"${4:md}\"",
" target=\"${5:_blank}\"",
" variation=\"${6:primary}\"",
"/>"
],
"description": "Create a DocuButton component on markdown."
}
}

View File

@@ -1,54 +0,0 @@
{
"Docu Card Group": {
"prefix": "card-group",
"body": [
"<CardGroup cols={${1:2}}>",
" <Card title=\"${2:Card Title}\" icon=\"${3:Home}\">",
" ${4:Card content goes here. You can add **markdown** content.}",
" </Card>",
" <Card title=\"${5:Another Card}\" icon=\"${6:Settings}\">",
" ${7:More content here.}",
" </Card>",
"</CardGroup>"
],
"description": "Create a group of cards in a responsive grid"
},
"Docu Card": {
"prefix": "card",
"body": [
"<Card ",
" title=\"${1:Card Title}\"",
" icon=\"${2:Home}\"",
" href=\"${3:/optional-link}\"",
" ${4:horizontal}>",
" ${5:Card content goes here. You can add **markdown** content.}",
"</Card>"
],
"description": "Create a single card component"
},
"Docu Horizontal Card": {
"prefix": "card-horizontal",
"body": [
"<Card ",
" title=\"${1:Card Title}\"",
" icon=\"${2:Home}\"",
" href=\"${3:/optional-link}\"",
" horizontal>",
" ${4:Content appears next to the icon in a horizontal layout.}",
"</Card>"
],
"description": "Create a horizontal card layout"
},
"Docu Card With Link": {
"prefix": "card-link",
"body": [
"<Card ",
" title=\"${1:Card Title}\"",
" icon=\"${2:ExternalLink}\"",
" href=\"${3:https://example.com}\">",
" ${4:This card is clickable and links to an external URL.}",
"</Card>"
],
"description": "Create a clickable card that links to a URL"
}
}

View File

@@ -1,16 +0,0 @@
{
"DocuCodeBlock": {
"prefix": "codeblock",
"description": "Checks if the rocket is stable and prevents a crash if it's not.",
"body": [
"```${1:javascript:main.js} showLineNumbers {${2:3-4}}",
"function isRocketAboutToCrash() {",
" // Check if the rocket is stable",
" if (!isStable()) {",
" NoCrash(); // Prevent the crash",
" }",
"}",
"```",
],
}
}

View File

@@ -1,53 +0,0 @@
{
"File Tree Component": {
"prefix": "filetree",
"body": [
"<Files>",
" <Folder name=\"${1:folder-name}\">",
" <File name=\"${2:file-name}\" />",
" <Folder name=\"${3:subfolder}\">",
" <File name=\"${4:file.tsx}\" />",
" </Folder>\n$0",
" </Folder>",
"</Files>"
],
"description": "DocuBook File Tree component with nested structure"
},
"File Tree Minimal": {
"prefix": "filetree-mini",
"body": [
"<Files>\n <Folder name=\"${1:folder}\">\n <File name=\"${2:file}\" />\n </Folder>\n</Files>$0"
],
"description": "Minimal DocuBook File Tree component"
},
"File Tree Complex": {
"prefix": "filetree-complex",
"body": [
"<Files>",
" <Folder name=\"${1:project-root}\">",
" <File name=\"package.json\" />",
" <File name=\"tsconfig.json\" />",
" <Folder name=\"src\">",
" <File name=\"index.ts\" />",
" <Folder name=\"components\">",
" <File name=\"${2:Component}.tsx\" />",
" <File name=\"${3:Component}.types.ts\" />",
" <File name=\"index.ts\" />",
" </Folder>\n$0",
" </Folder>",
" </Folder>",
"</Files>"
],
"description": "Complex DocuBook File Tree with common project structure"
},
"File Tree Folder": {
"prefix": "folder",
"body": "<Folder name=\"${1:folder-name}\">\n $0\n</Folder>",
"description": "DocuBook Folder component for file trees"
},
"File Tree File": {
"prefix": "file",
"body": "<File name=\"${1:file-name}\" />$0",
"description": "DocuBook File component for file trees"
}
}

View File

@@ -1,16 +0,0 @@
{
"DocuImage": {
"prefix": "image",
"body": [
"![${1:Alt text for the image}](${2:/images/example-img.png})"
],
"description": "Snippet untuk menampilkan image komponen."
},
"DocuLink": {
"prefix": "link",
"body": [
"[${1:Text Link}](${2:https://www.openai.com})"
],
"description": "Snippet untuk menampilkan link komponen."
}
}

View File

@@ -1,23 +0,0 @@
{
"Keyboard - Mac": {
"prefix": "keymac",
"body": [
"<Kbd show=\"${1:ctrl}\" type=\"mac\" />"
],
"description": "Mac keyboard shortcut."
},
"Keyboard - Windows": {
"prefix": "keywin",
"body": [
"<Kbd show=\"${1:ctrl}\" type=\"windows\" />"
],
"description": "Windows keyboard shortcut."
},
"Keyboard - Custom": {
"prefix": "keycustom",
"body": [
"<Kbd show=\"${1:custom}\">${2:Custom}</Kbd>"
],
"description": "Custom keyboard shortcut."
}
}

View File

@@ -1,13 +0,0 @@
{
"DocuMetadata": {
"prefix": "metadata",
"body": [
"---",
"title : ${1:judul post}",
"description : ${2:deskripsi singkat dari post}",
"date : ${3:10-12-2024}",
"---"
],
"description": "Snippet untuk membuat metadata."
}
}

View File

@@ -1,38 +0,0 @@
{
"DocuNote - General Note": {
"prefix": "note",
"body": [
"<Note type=\"note\" title=\"Note\">",
" ${1:This is a general note to convey information to the user.}",
"</Note>"
],
"description": "Insert a general note"
},
"DocuNote - Danger Note": {
"prefix": "danger",
"body": [
"<Note type=\"danger\" title=\"Danger\">",
" ${1:This is a danger alert to notify the user of a critical issue.}",
"</Note>"
],
"description": "Insert a danger note"
},
"DocuNote - Warning Note": {
"prefix": "warning",
"body": [
"<Note type=\"warning\" title=\"Warning\">",
" ${1:This is a warning alert for issues that require attention.}",
"</Note>"
],
"description": "Insert a warning note"
},
"DocuNote - Success Note": {
"prefix": "success",
"body": [
"<Note type=\"success\" title=\"Success\">",
" ${1:This is a success message to inform the user of successful actions.}",
"</Note>"
],
"description": "Insert a success note"
}
}

View File

@@ -1,49 +0,0 @@
{
"Release Note Component": {
"prefix": "release",
"body": [
"<Release version=\"$1\" date=\"${2:$CURRENT_YEAR-${CURRENT_MONTH}-${CURRENT_DATE}}\" title=\"$3\">",
" <Changes type=\"added\">",
" - $4",
" </Changes>",
"",
" <Changes type=\"fixed\">",
" - $5",
" </Changes>",
"",
" <Changes type=\"improved\">",
" - $6",
" </Changes>",
"",
" <Changes type=\"deprecated\">",
" - $7",
" </Changes>",
"",
" <Changes type=\"removed\">",
" - $8",
" </Changes>",
"</Release>"
],
"description": "DocuBook Release Note component with all change types"
},
"Release Note Simple": {
"prefix": "release-simple",
"body": [
"<Release version=\"$1\" date=\"${2:$CURRENT_YEAR-${CURRENT_MONTH}-${CURRENT_DATE}}\" title=\"$3\">",
" <Changes type=\"$4\">",
" - $5",
" </Changes>\n$0",
"</Release>"
],
"description": "Simple DocuBook Release Note component with one change type"
},
"Changes Only": {
"prefix": "changes",
"body": [
"<Changes type=\"$1\">",
" - $2",
"</Changes>"
],
"description": "DocuBook Changes component for individual change items"
}
}

View File

@@ -1,24 +0,0 @@
{
"DocuStepper": {
"prefix": "stepper",
"body": [
"<Stepper>",
" <StepperItem title=\"${1:Step 1: Clone the DocuBook Repository}\">",
" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec interdum,",
" felis sed efficitur tincidunt, justo nulla viverra enim, et maximus nunc",
" dolor in lorem.",
" </StepperItem>${2:}",
"</Stepper>"
],
"description": "Snippet untuk menampilkan stepper komponen."
},
"DocuStepperItem": {
"prefix": "item",
"body": [
"<StepperItem title=\"${1:Step X: Your Step Title}\">",
" ${2:Your step description here.}",
"</StepperItem>${3:}"
],
"description": "Snippet untuk menambahkan item baru ke dalam Stepper."
}
}

View File

@@ -1,12 +0,0 @@
{
"DocuTable": {
"prefix": "table",
"body": [
"| **${1:Header 1}** | **${2:Header 2}** |",
"| ---------------- | ---------------- |",
"| ${3:Row 1, Col 1} | ${4:Row 1, Col 2} |",
"| ${5:Row 2, Col 1} | ${6:Row 2, Col 2} |"
],
"description": "Create a simple 2x2 markdown table"
}
}

View File

@@ -1,33 +0,0 @@
{
"DocuTabs": {
"prefix": "tabs",
"body": [
"<Tabs defaultValue=\"${1:java}\" className=\"pt-5 pb-1\">",
" <TabsList>",
" <TabsTrigger value=\"${2:java}\">Java</TabsTrigger>",
" <TabsTrigger value=\"${3:typescript}\">TypeScript</TabsTrigger>",
" </TabsList>",
" <TabsContent value=\"${4:java}\">",
" ```java",
" // HelloWorld.java",
" public class HelloWorld {",
" public static void main(String[] args) {",
" System.out.println(\"Hello, World!\");",
" }",
" }",
" ```",
" </TabsContent>",
" <TabsContent value=\"${5:typescript}\">",
" ```typescript",
" // helloWorld.ts",
" function helloWorld(): void {",
" console.log(\"Hello, World!\");",
" }",
" helloWorld();",
" ```",
" </TabsContent>",
"</Tabs>"
],
"description": "Create a DocuTabs component with Java and TypeScript examples."
}
}

View File

@@ -1,9 +0,0 @@
{
"DocuTooltips": {
"prefix": "tooltips",
"body": [
"${1:What do you know about }<Tooltip text=\"${2:DocuBook}\" tip=\"${3:npx @docubook/create@latest}\" /> ${4:? Create interactive nested documentations using MDX.}",
],
"description": "Create a DocuTooltips component with version examples."
}
}

View File

@@ -1,33 +0,0 @@
{
"DocuH2": {
"prefix": "h2",
"body": [
"## Heading 2"
],
"description": "Tag Heading 2 for markdown."
},
"DocuH3": {
"prefix": "h3",
"body": [
"### Heading 3"
],
"description": "Tag Heading 3 for markdown."
},
"DocuText": {
"prefix": "text",
"body": [
"DocuBook is proudly **open-source**! 🎉 We believe in creating an accessible, collaborative platform that thrives on community contributions."
],
"description": "Tag Paragraph for markdown."
},
"Docu-UndorderList": {
"prefix": "unorderlist",
"body": [
"- ${1:**Next.js 14** - The powerful React framework optimized for production.}",
"- **Tailwind CSS** - Utility-first styling for quick, clean designs.",
"- **Shadcn-UI** - Elegant, accessible components for a polished look.",
"- **next-mdx-remote** - Enables MDX support for dynamic, interactive Markdown content."
],
"description": "Tag Undorderlist for markdown."
},
}

View File

@@ -1,9 +0,0 @@
{
"DocuVideo": {
"prefix": "youtube",
"body": [
"<Youtube videoId=\"${1:zQnBQ4tB3ZA}\" />"
],
"description": "Snippet untuk menampilkan komponen video Youtube."
}
}

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2025 Wildan Nursahidan Copyright (c) 2026 Wildan Nursahidan
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,37 +1,45 @@
# DocuBook # DocuBook — Next.js (Docker)
**DocuBook** is a documentation web project designed to provide a simple and user-friendly interface for accessing various types of documentation. This site is crafted for developers and teams who need quick access to references, guides, and essential documents. A documentation starter template with a **production-ready Docker setup** using multi-stage builds and Next.js standalone output. Designed for self-hosted and containerized environments.
[![Deploy with
Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/DocuBook/docubook)
## Features ## Features
- **Easy Navigation**: Simple layout for quick navigation between pages. - **Multi-stage Dockerfile** — build stage compiles, production stage runs on minimal Alpine base
- **Quick Search**: Easily find documentation using a search function. - **Standalone Output** — only runtime artifacts in the final image (~100MB vs ~1GB full node_modules)
- **Responsive Theme**: Responsive design optimized for devices ranging from desktops to mobile. - **Container-native** — single-process design compatible with any orchestrator
- **Markdown Content**: Support for markdown-based documents. - **Platform-agnostic** — works with Coolify, Kubernetes, Railway, Fly.io, Render, or any Docker host
- **SEO Friendly**: Optimized structure for search visibility, enhancing accessibility on search engines. - **MDX Content** — write documentation in Markdown/MDX with full component support
- **SEO Friendly** — automatic sitemap, meta tags, and structured data
- **Responsive Design** — optimized for desktop and mobile devices
- **Quick Search** — fast client-side documentation search
## Installation ## Installation
```bash ```bash
npx @docubook/create@latest npx @docubook/cli@latest
``` ```
#### command output #### command output
![command output](https://github.com/DocuBook/docubook/blob/main/docubook-cli.png)
---
## Deployment
Build and run the Docker image:
```bash ```bash
? Enter a name for your project directory: (docubook) docker build -t docubook:latest .
docker run -p 3000:3000 -e NODE_ENV=production docubook:latest
Creating a new Docubook project in /path/your/docubook from the main branch...
✔ Docubook project successfully created in /path/your/docubook!
Next steps:
1. Navigate to your project directory:
cd docubook
2. Install dependencies:
npm install
3. Start the development server:
npm run dev
``` ```
### Platform notes
| Platform | Notes |
|----------|-------|
| **Coolify / Docker VPS** | Push image to registry, deploy as standard container (PORT=3000) |
| **Kubernetes** | Create Deployment + Service; image runs single process on PORT |
| **Railway / Fly.io / Render** | Auto-detected from Dockerfile; set env vars via provider panel |
For Vercel deployment (no Docker needed), use the [`nextjs`](../nextjs) template instead.

View File

@@ -1,5 +1,5 @@
import { notFound } from "next/navigation" import { notFound } from "next/navigation"
import { getDocsForSlug, getDocsTocs } from "@/lib/markdown" import { getDocsForSlug, getDocsFrontmatterForSlug, getDocsStaticParams } from "@/lib/markdown"
import DocsBreadcrumb from "@/components/DocsBreadcrumb" import DocsBreadcrumb from "@/components/DocsBreadcrumb"
import Pagination from "@/components/pagination" import Pagination from "@/components/pagination"
import Toc from "@/components/toc" import Toc from "@/components/toc"
@@ -17,6 +17,8 @@ type PageProps = {
}> }>
} }
export const dynamicParams = true
// Function to generate metadata dynamically // Function to generate metadata dynamically
export async function generateMetadata(props: PageProps) { export async function generateMetadata(props: PageProps) {
const params = await props.params const params = await props.params
@@ -24,22 +26,24 @@ export async function generateMetadata(props: PageProps) {
const { slug = [] } = params const { slug = [] } = params
const pathName = slug.join("/") const pathName = slug.join("/")
const res = await getDocsForSlug(pathName) // React.cache() deduplicates within this request, so if the page component
// also calls getDocsFrontmatterForSlug, they share the same file read
const frontmatter = await getDocsFrontmatterForSlug(pathName)
if (!res) { if (!frontmatter) {
return { return {
title: "Page Not Found", title: "Page Not Found",
description: "The requested page was not found.", description: "The requested page was not found.",
} }
} }
const { title, description, image } = res.frontmatter const { title, description, image } = frontmatter
// Absolute URL for og:image // Absolute URL for og:image - compute once
const ogImage = image ? `${meta.baseURL}/images/${image}` : `${meta.baseURL}/images/og-image.png` const ogImage = image ? `${meta.baseURL}/images/${image}` : `${meta.baseURL}/images/og-image.png`
return { return {
title: `${title}`, title,
description, description,
openGraph: { openGraph: {
title, title,
@@ -64,6 +68,10 @@ export async function generateMetadata(props: PageProps) {
} }
} }
export async function generateStaticParams() {
return getDocsStaticParams()
}
export default async function DocsPage(props: PageProps) { export default async function DocsPage(props: PageProps) {
const params = await props.params const params = await props.params
@@ -76,11 +84,11 @@ export default async function DocsPage(props: PageProps) {
const { title, description, image: _image, date } = res.frontmatter const { title, description, image: _image, date } = res.frontmatter
const filePath = res.filePath const filePath = res.filePath
const tocs = await getDocsTocs(pathName) const tocs = res.tocs
return ( return (
<div className="flex w-full flex-1 px-0 pb-4 lg:px-8 lg:pb-8 lg:h-[calc(100vh-4rem)]"> <div className="flex w-full flex-1 px-0 pb-4 lg:px-8 lg:pb-8 lg:h-[calc(100vh-4rem)]">
<div id="scroll-container" className="max-lg:scroll-p-54 bg-card dark:bg-card/20 border-muted-foreground/20 flex w-full flex-col items-start lg:h-full lg:rounded-xl rounded-b-3xl border shadow-md backdrop-blur-sm lg:flex-row lg:overflow-y-auto relative"> <div id="scroll-container" className="max-lg:scroll-p-54 bg-card dark:bg-card border-muted-foreground/20 flex w-full flex-col items-start lg:h-full lg:rounded-xl rounded-b-3xl border shadow-md lg:backdrop-blur-sm lg:dark:bg-card/20 lg:flex-row lg:overflow-y-auto relative">
<div className="flex-7 w-full min-w-0 px-4 py-4 lg:px-8 lg:py-8"> <div className="flex-7 w-full min-w-0 px-4 py-4 lg:px-8 lg:py-8">
<MobToc tocs={tocs} title={title} /> <MobToc tocs={tocs} title={title} />
<DocsBreadcrumb paths={slug} /> <DocsBreadcrumb paths={slug} />
@@ -95,7 +103,7 @@ export default async function DocsPage(props: PageProps) {
{docuConfig.repository?.editLink && <EditThisPage filePath={filePath} />} {docuConfig.repository?.editLink && <EditThisPage filePath={filePath} />}
{date && ( {date && (
<p className="text-muted-foreground text-[13px]"> <p className="text-muted-foreground text-[13px]">
Published on {formatDate2(date)} Last updated {formatDate2(date)}
</p> </p>
)} )}
</div> </div>

View File

@@ -11,7 +11,7 @@ export default function DocsLayout({
<div className="docs-layout flex flex-col min-h-screen w-full"> <div className="docs-layout flex flex-col min-h-screen w-full">
<div className="flex flex-1 items-start w-full"> <div className="flex flex-1 items-start w-full">
<Leftbar key="leftbar" /> <Leftbar key="leftbar" />
<main className="flex-1 min-w-0 dark:bg-background/50 min-h-screen flex flex-col"> <main className="flex-1 min-w-0 dark:bg-background min-h-screen flex flex-col">
<DocsNavbar /> <DocsNavbar />
<div className="flex-1 w-full"> <div className="flex-1 w-full">
{children} {children}

View File

@@ -7,6 +7,7 @@ import { Footer } from "@/components/footer";
import { SearchProvider } from "@/components/SearchContext"; import { SearchProvider } from "@/components/SearchContext";
import docuConfig from "@/docu.json"; import docuConfig from "@/docu.json";
import "@docsearch/css"; import "@docsearch/css";
import "@docubook/mdx-content/styles.css";
import "@/styles/algolia.css"; import "@/styles/algolia.css";
import "@/styles/override.css"; import "@/styles/override.css";
import "@/styles/globals.css"; import "@/styles/globals.css";
@@ -35,9 +36,10 @@ const defaultMetadata: Metadata = {
locale: "en_US", locale: "en_US",
type: "website", type: "website",
}, },
other: { /* to implementations domains verification for Algolia with Meta Tag */
"algolia-site-verification": "6E413CE39E56BB62", // other: {
}, // "algolia-site-verification": "value",
// },
}; };
// Dynamic Metadata Getter // Dynamic Metadata Getter
@@ -60,14 +62,16 @@ export function getMetadata({
...defaultMetadata.openGraph, ...defaultMetadata.openGraph,
title: title || defaultMetadata.openGraph?.title, title: title || defaultMetadata.openGraph?.title,
description: description || defaultMetadata.openGraph?.description, description: description || defaultMetadata.openGraph?.description,
images: ogImage ? [ images: ogImage
? [
{ {
url: ogImage, url: ogImage,
width: 1200, width: 1200,
height: 630, height: 630,
alt: String(title || defaultMetadata.openGraph?.title), alt: String(title || defaultMetadata.openGraph?.title),
}, },
] : defaultMetadata.openGraph?.images, ]
: defaultMetadata.openGraph?.images,
}, },
}; };
} }
@@ -91,7 +95,7 @@ export default function RootLayout({
> >
<SearchProvider> <SearchProvider>
<Navbar id="main-navbar" /> <Navbar id="main-navbar" />
<main id="main-content" className="sm:container mx-auto w-[90vw] h-auto scroll-smooth"> <main id="main-content" className="mx-auto h-auto w-[90vw] scroll-smooth sm:container">
{children} {children}
</main> </main>
<Footer id="main-footer" /> <Footer id="main-footer" />

439
bun.lock
View File

@@ -5,10 +5,10 @@
"": { "": {
"name": "docubook", "name": "docubook",
"dependencies": { "dependencies": {
"@docsearch/css": "^3.9.0", "@docsearch/css": "^4.6.2",
"@docsearch/react": "^3.9.0", "@docsearch/react": "^4.6.2",
"@radix-ui/react-accordion": "^1.2.12", "@docubook/core": "^1.7.0",
"@radix-ui/react-avatar": "^1.1.11", "@docubook/mdx-content": "^3.2.1",
"@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -16,45 +16,38 @@
"@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-toggle-group": "^1.1.11",
"algoliasearch": "^5.46.3",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "^1.1.1", "framer-motion": "^12.38.0",
"framer-motion": "^12.26.2", "geist": "^1.7.0",
"geist": "^1.5.1", "lucide-react": "^1.7.0",
"gray-matter": "^4.0.3", "next": "^16.2.6",
"lucide-react": "^0.511.0", "next-themes": "^0.4.6",
"next": "^16.1.6",
"next-mdx-remote": "^6.0.0",
"next-themes": "^0.4.4",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"react-icons": "^5.5.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-code-titles": "^1.2.1",
"rehype-prism-plus": "^2.0.1",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.1",
"sonner": "^1.7.4", "sonner": "^1.7.4",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.1",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"unist-util-visit": "^5.0.0",
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "^4.1.18", "@eslint/js": "^9.39.4",
"@tailwindcss/postcss": "^4.2.2",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@types/node": "^20.19.30", "@types/node": "^20.19.37",
"@types/react": "19.2.8", "@types/react": "19.2.8",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
"autoprefixer": "^10.4.23", "@types/unist": "^3.0.3",
"eslint": "^9.39.2", "autoprefixer": "^10.4.27",
"eslint": "^9.39.4",
"eslint-config-next": "16.1.3", "eslint-config-next": "16.1.3",
"postcss": "^8.5.6", "postcss": "^8.5.8",
"tailwindcss": "^4.1.18", "prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.6.14",
"tailwindcss": "^4.2.2",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.57.2",
}, },
}, },
}, },
@@ -63,85 +56,91 @@
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
}, },
"packages": { "packages": {
"@algolia/abtesting": ["@algolia/abtesting@1.15.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-2yuIC48rUuHGhU1U5qJ9kJHaxYpJ0jpDHJVI5ekOxSMYXlH4+HP+pA31G820lsAznfmu2nzDV7n5RO44zIY1zw=="], "@11ty/gray-matter": ["@11ty/gray-matter@2.0.2", "", { "dependencies": { "js-yaml": "^4.1.1", "section-matter": "^1.0.0" } }, "sha512-+sbmr+BPzzi0z4lFvruKiGQ3D/d5zBssavhH9SzXmWkf7rStnB4gfeEMgz6k1Ac8bpN5NAFCH5GyR3xHk1BGPA=="],
"@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.9", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.9", "@algolia/autocomplete-shared": "1.17.9" } }, "sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ=="], "@algolia/abtesting": ["@algolia/abtesting@1.19.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-Lhnez3hhXHk25lfxLAMxvkP4fmN3+1RgADhD2ssMDBYuAsDVReeyP+3SGRx+ntq8ijMrLqUyfvO72TB6jsTteQ=="],
"@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.17.9", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.9" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ=="], "@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.19.2", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", "@algolia/autocomplete-shared": "1.19.2" } }, "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw=="],
"@algolia/autocomplete-preset-algolia": ["@algolia/autocomplete-preset-algolia@1.17.9", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.9" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ=="], "@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.19.2", "", { "dependencies": { "@algolia/autocomplete-shared": "1.19.2" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg=="],
"@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.17.9", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ=="], "@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.19.2", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w=="],
"@algolia/client-abtesting": ["@algolia/client-abtesting@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-h6M7HzPin+45/l09q0r2dYmocSSt2MMGOOk5c4O5K/bBBlEwf1BKfN6z+iX4b8WXcQQhf7rgQwC52kBZJt/ZZw=="], "@algolia/client-abtesting": ["@algolia/client-abtesting@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-0ZjA5Hcmaoz5Lj6OG0zhfIyeqzJZnLW2CRJA1W17UwMFGRtZAJ9yJKRvPEDA6gkpsIoQxORTSW6sWFiuYncPNQ=="],
"@algolia/client-analytics": ["@algolia/client-analytics@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-048T9/Z8OeLmTk8h76QUqaNFp7Rq2VgS2Zm6Y2tNMYGQ1uNuzePY/udB5l5krlXll7ZGflyCjFvRiOtlPZpE9g=="], "@algolia/client-analytics": ["@algolia/client-analytics@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-kWNodP75iiEaOtemC9F/hlxNBG5E2QUjN1BusnE6m2b4l7Qh/BUO3fGCVsmKJI65VO4VKGGmT43ICvHtTcJ2JQ=="],
"@algolia/client-common": ["@algolia/client-common@5.49.1", "", {}, "sha512-vp5/a9ikqvf3mn9QvHN8PRekn8hW34aV9eX+O0J5mKPZXeA6Pd5OQEh2ZWf7gJY6yyfTlLp5LMFzQUAU+Fpqpg=="], "@algolia/client-common": ["@algolia/client-common@5.53.0", "", {}, "sha512-YPN45TXD9Wrse185t/Ta7nktZsqpv97oOjCzp2sblHnCL6rBc9TDeJAg1IGl2UpdwnSD05Zu/5wLB4watOUMyg=="],
"@algolia/client-insights": ["@algolia/client-insights@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-B6N7PgkvYrul3bntTz/l6uXnhQ2bvP+M7NqTcayh681tSqPaA5cJCUBp/vrP7vpPRpej4Eeyx2qz5p0tE/2N2g=="], "@algolia/client-insights": ["@algolia/client-insights@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-qAcYTDJE6m924FDDUQvdD6vh7DYaqOeSpFS74IP37/JRV0v4cGBauyxTF2WzDnokUylQDbqreoFIJZfg0Fitmw=="],
"@algolia/client-personalization": ["@algolia/client-personalization@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-v+4DN+lkYfBd01Hbnb9ZrCHe7l+mvihyx218INRX/kaCXROIWUDIT1cs3urQxfE7kXBFnLsqYeOflQALv/gA5w=="], "@algolia/client-personalization": ["@algolia/client-personalization@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-fQaY+DkSJOpuUVUe8MQTwrdiKAqkJGhpDarB08duBn/sUv7Bkib6MDRQauCcWTWTe4HIW+EbwQP9R4kci1V/Yw=="],
"@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-Un11cab6ZCv0W+Jiak8UktGIqoa4+gSNgEZNfG8m8eTsXGqwIEr370H3Rqwj87zeNSlFpH2BslMXJ/cLNS1qtg=="], "@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-o72tsiEZGfeS/dxL9IADfzcZWGEwKDEe5CvtrBuT//3JR+SHuTtHRI2ZTf7D7bcKagcbojvO8hnkHdfoakSlYg=="],
"@algolia/client-search": ["@algolia/client-search@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-Nt9hri7nbOo0RipAsGjIssHkpLMHHN/P7QqENywAq5TLsoYDzUyJGny8FEiD/9KJUxtGH8blGpMedilI6kK3rA=="], "@algolia/client-search": ["@algolia/client-search@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-Ds16IyPm/dNJPCU8OzApo2gwGrgWT5BYHhE3NFwZbpCveqyvPDB9sZDDkJ5DsdOGT2aC+R3i0/M1OVXF2qdgPg=="],
"@algolia/ingestion": ["@algolia/ingestion@1.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-b5hUXwDqje0Y4CpU6VL481DXgPgxpTD5sYMnfQTHKgUispGnaCLCm2/T9WbJo1YNUbX3iHtYDArp804eD6CmRQ=="], "@algolia/ingestion": ["@algolia/ingestion@1.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-oNbT6z4NwD8Pou9VPINGlN/tlG1afESh2EbxqnP6rwl95xKVD/Zlciis1PpNeO/9U/rrajc1+7DcfKi03tX1KQ=="],
"@algolia/monitoring": ["@algolia/monitoring@1.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-bvrXwZ0WsL3rN6Q4m4QqxsXFCo6WAew7sAdrpMQMK4Efn4/W920r9ptOuckejOSSvyLr9pAWgC5rsHhR2FYuYw=="], "@algolia/monitoring": ["@algolia/monitoring@1.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-G+KZb/yd+qAOFn/cEvTGeLxQm8aP3a0od50l3z/ylccY+/o4YG3TNcjU1tFQHW4mXC137GPyR7W70R0kRQDLnA=="],
"@algolia/recommend": ["@algolia/recommend@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-h2yz3AGeGkQwNgbLmoe3bxYs8fac4An1CprKTypYyTU/k3Q+9FbIvJ8aS1DoBKaTjSRZVoyQS7SZQio6GaHbZw=="], "@algolia/recommend": ["@algolia/recommend@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-6aVfYd55Un6IUgPLbo84WfgFZlS3L0vA1ttzXL5vahHewUJ8jYgd89TzlWRTeej7w70mb9RWsVlFYGmJ/diQww=="],
"@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1" } }, "sha512-2UPyRuUR/qpqSqH8mxFV5uBZWEpxhGPHLlx9Xf6OVxr79XO2ctzZQAhsmTZ6X22x+N8MBWpB9UEky7YU2HGFgA=="], "@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-ke27DqgzCOlt+RbeEdCxtXxMQOnAOi8ujr2wid0DmDKzR95Kw/f9sBsuhBxtjevCqJRJszfRTLY0B1pbO6IhkA=="],
"@algolia/requester-fetch": ["@algolia/requester-fetch@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1" } }, "sha512-N+xlE4lN+wpuT+4vhNEwPVlrfN+DWAZmSX9SYhbz986Oq8AMsqdntOqUyiOXVxYsQtfLwmiej24vbvJGYv1Qtw=="], "@algolia/requester-fetch": ["@algolia/requester-fetch@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-GngiOqt2Gq4oLno6yXQVj9om+qSO9SWAoduoTOEg79dKZ62brB8OOIvSJG/vDNoanYi6a7Al9uDZwXvi+bcVTg=="],
"@algolia/requester-node-http": ["@algolia/requester-node-http@5.49.1", "", { "dependencies": { "@algolia/client-common": "5.49.1" } }, "sha512-zA5bkUOB5PPtTr182DJmajCiizHp0rCJQ0Chf96zNFvkdESKYlDeYA3tQ7r2oyHbu/8DiohAQ5PZ85edctzbXA=="], "@algolia/requester-node-http": ["@algolia/requester-node-http@5.53.0", "", { "dependencies": { "@algolia/client-common": "5.53.0" } }, "sha512-6mF9LZMUk0QqWvrnxkxBqhswwz6Xfiwy6/gmTzL5HrlhdVG3ITAqGV2k3XmVThP1h0Ulc3VQwiNCD7/Nr4JNlQ=="],
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
"@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="],
"@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="],
"@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], "@babel/generator": ["@babel/generator@7.29.7", "", { "dependencies": { "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ=="],
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="],
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="],
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="],
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="],
"@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="],
"@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], "@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="],
"@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="],
"@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], "@babel/traverse": ["@babel/traverse@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/types": "^7.29.7", "debug": "^4.3.1" } }, "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw=="],
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="],
"@docsearch/css": ["@docsearch/css@3.9.0", "", {}, "sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA=="], "@docsearch/core": ["@docsearch/core@4.6.3", "", { "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", "react": ">= 16.8.0 < 20.0.0", "react-dom": ">= 16.8.0 < 20.0.0" }, "optionalPeers": ["@types/react", "react", "react-dom"] }, "sha512-rUOujwIpxJRgD7+kicVsI3D5sqBvdiRTquzWBpTEXZs8ZXfGbfzpus5HqumaNYTppN2HvH8E2yNuRwYdHJeOlA=="],
"@docsearch/react": ["@docsearch/react@3.9.0", "", { "dependencies": { "@algolia/autocomplete-core": "1.17.9", "@algolia/autocomplete-preset-algolia": "1.17.9", "@docsearch/css": "3.9.0", "algoliasearch": "^5.14.2" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", "react": ">= 16.8.0 < 20.0.0", "react-dom": ">= 16.8.0 < 20.0.0", "search-insights": ">= 1 < 3" }, "optionalPeers": ["@types/react", "react", "react-dom", "search-insights"] }, "sha512-mb5FOZYZIkRQ6s/NWnM98k879vu5pscWqTLubLFBO87igYYT4VzVazh4h5o/zCvTIZgEt3PvsCOMOswOUo9yHQ=="], "@docsearch/css": ["@docsearch/css@4.6.3", "", {}, "sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ=="],
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], "@docsearch/react": ["@docsearch/react@4.6.3", "", { "dependencies": { "@algolia/autocomplete-core": "1.19.2", "@docsearch/core": "4.6.3", "@docsearch/css": "4.6.3" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", "react": ">= 16.8.0 < 20.0.0", "react-dom": ">= 16.8.0 < 20.0.0", "search-insights": ">= 1 < 3" }, "optionalPeers": ["@types/react", "react", "react-dom", "search-insights"] }, "sha512-Bg2wdDsoQVlNCcEKuEJAU04tvHCqgx8rIu+uIoM4pRtcx3TBKJuXutJik3LTA8LRc9YEyHkrYUrmcC0D7BYf+g=="],
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], "@docubook/core": ["@docubook/core@1.7.0", "", { "dependencies": { "@11ty/gray-matter": "^2.0.2", "clsx": "^2.1.1", "next-mdx-remote": "^6.0.0", "rehype-autolink-headings": "^7.1.0", "rehype-code-titles": "^1.2.1", "rehype-prism-plus": "^2.0.2", "rehype-slug": "^6.0.0", "remark-gfm": "^4.0.1", "tailwind-merge": "^2.6.1", "unist-util-visit": "^5.1.0" } }, "sha512-dqSESm7ky9IPoVTnm+44mPZQAry676rYj+9QkCSPzfOG8FGO/Ob8UJARN+Y5yqy9g8YAvTWvoET5MwaHZ5mFgw=="],
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], "@docubook/mdx-content": ["@docubook/mdx-content@3.2.1", "", { "peerDependencies": { "@docubook/core": ">=1.6.0", "lucide-react": "^1.7.0", "react": ">=18", "react-dom": ">=18", "react-icons": "^5.0.0" } }, "sha512-gBZw668kNRoa5g+HalvNrAW5WYvxq3AU6M+gcpmBwuxne0JitSJTfvBIeGEPdpzGpip28h/XF5D/bRIbHV+0jw=="],
"@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
@@ -169,9 +168,11 @@
"@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="],
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="],
"@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="],
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
@@ -241,27 +242,27 @@
"@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="], "@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="],
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],
"@next/env": ["@next/env@16.1.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="], "@next/env": ["@next/env@16.2.6", "", {}, "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw=="],
"@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.3", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-MqBh3ltFAy0AZCRFVdjVjjeV7nEszJDaVIpDAnkQcn8U9ib6OEwkSnuK6xdYxMGPhV/Y4IlY6RbDipPOpLfBqQ=="], "@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.3", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-MqBh3ltFAy0AZCRFVdjVjjeV7nEszJDaVIpDAnkQcn8U9ib6OEwkSnuK6xdYxMGPhV/Y4IlY6RbDipPOpLfBqQ=="],
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="], "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg=="],
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ=="], "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ=="],
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw=="], "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w=="],
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ=="], "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA=="],
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ=="], "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw=="],
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg=="], "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g=="],
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw=="], "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg=="],
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A=="], "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.6", "", { "os": "win32", "cpu": "x64" }, "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
@@ -275,12 +276,8 @@
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
"@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
"@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.11", "", { "dependencies": { "@radix-ui/react-context": "1.1.3", "@radix-ui/react-primitive": "2.1.4", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q=="],
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="], "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
@@ -323,8 +320,6 @@
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
"@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="], "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="],
"@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="], "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="],
@@ -337,8 +332,6 @@
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
"@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
"@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
@@ -351,43 +344,43 @@
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
"@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], "@tailwindcss/node": ["@tailwindcss/node@4.3.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.21.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.0" } }, "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g=="],
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.0", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.0", "@tailwindcss/oxide-darwin-arm64": "4.3.0", "@tailwindcss/oxide-darwin-x64": "4.3.0", "@tailwindcss/oxide-freebsd-x64": "4.3.0", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", "@tailwindcss/oxide-linux-x64-musl": "4.3.0", "@tailwindcss/oxide-wasm32-wasi": "4.3.0", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" } }, "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg=="],
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.0", "", { "os": "android", "cpu": "arm64" }, "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng=="],
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ=="],
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA=="],
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ=="],
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0", "", { "os": "linux", "cpu": "arm" }, "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA=="],
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg=="],
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ=="],
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ=="],
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg=="],
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.0", "", { "dependencies": { "@emnapi/core": "^1.10.0", "@emnapi/runtime": "^1.10.0", "@emnapi/wasi-threads": "^1.2.1", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA=="],
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ=="],
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA=="],
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "postcss": "^8.5.6", "tailwindcss": "4.2.1" } }, "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw=="], "@tailwindcss/postcss": ["@tailwindcss/postcss@4.3.0", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.3.0", "@tailwindcss/oxide": "4.3.0", "postcss": "^8.5.10", "tailwindcss": "4.3.0" } }, "sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w=="],
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="], "@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="],
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
@@ -403,7 +396,7 @@
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="], "@types/node": ["@types/node@20.19.41", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ=="],
"@types/prismjs": ["@types/prismjs@1.26.6", "", {}, "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw=="], "@types/prismjs": ["@types/prismjs@1.26.6", "", {}, "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw=="],
@@ -413,77 +406,83 @@
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.56.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/type-utils": "8.56.1", "@typescript-eslint/utils": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.56.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.60.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/type-utils": "8.60.0", "@typescript-eslint/utils": "8.60.0", "@typescript-eslint/visitor-keys": "8.60.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.60.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw=="],
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.56.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.60.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/types": "8.60.0", "@typescript-eslint/typescript-estree": "8.60.0", "@typescript-eslint/visitor-keys": "8.60.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg=="],
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.56.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.56.1", "@typescript-eslint/types": "^8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ=="], "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.60.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.60.0", "@typescript-eslint/types": "^8.60.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1" } }, "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w=="], "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.60.0", "", { "dependencies": { "@typescript-eslint/types": "8.60.0", "@typescript-eslint/visitor-keys": "8.60.0" } }, "sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw=="],
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.56.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ=="], "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.60.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ=="],
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg=="], "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.60.0", "", { "dependencies": { "@typescript-eslint/types": "8.60.0", "@typescript-eslint/typescript-estree": "8.60.0", "@typescript-eslint/utils": "8.60.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg=="],
"@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="], "@typescript-eslint/types": ["@typescript-eslint/types@8.60.0", "", {}, "sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA=="],
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.56.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.56.1", "@typescript-eslint/tsconfig-utils": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg=="], "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.60.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.60.0", "@typescript-eslint/tsconfig-utils": "8.60.0", "@typescript-eslint/types": "8.60.0", "@typescript-eslint/visitor-keys": "8.60.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g=="],
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.56.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA=="], "@typescript-eslint/utils": ["@typescript-eslint/utils@8.60.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.60.0", "@typescript-eslint/types": "8.60.0", "@typescript-eslint/typescript-estree": "8.60.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA=="],
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw=="], "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.60.0", "", { "dependencies": { "@typescript-eslint/types": "8.60.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.1", "", {}, "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ=="],
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.12.2", "", { "os": "android", "cpu": "arm" }, "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w=="],
"@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.12.2", "", { "os": "android", "cpu": "arm64" }, "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ=="],
"@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.12.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w=="],
"@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.12.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA=="],
"@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.12.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg=="],
"@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A=="],
"@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.12.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g=="],
"@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.12.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg=="],
"@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.12.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA=="],
"@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], "@unrs/resolver-binding-linux-loong64-gnu": ["@unrs/resolver-binding-linux-loong64-gnu@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q=="],
"@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], "@unrs/resolver-binding-linux-loong64-musl": ["@unrs/resolver-binding-linux-loong64-musl@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew=="],
"@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.12.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg=="],
"@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A=="],
"@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w=="],
"@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.12.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw=="],
"@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.12.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ=="],
"@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.12.2", "", { "os": "linux", "cpu": "x64" }, "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A=="],
"@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], "@unrs/resolver-binding-openharmony-arm64": ["@unrs/resolver-binding-openharmony-arm64@1.12.2", "", { "os": "none", "cpu": "arm64" }, "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ=="],
"@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.12.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A=="],
"@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.12.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g=="],
"@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.12.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g=="],
"@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.12.2", "", { "os": "win32", "cpu": "x64" }, "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA=="],
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
"algoliasearch": ["algoliasearch@5.49.1", "", { "dependencies": { "@algolia/abtesting": "1.15.1", "@algolia/client-abtesting": "5.49.1", "@algolia/client-analytics": "5.49.1", "@algolia/client-common": "5.49.1", "@algolia/client-insights": "5.49.1", "@algolia/client-personalization": "5.49.1", "@algolia/client-query-suggestions": "5.49.1", "@algolia/client-search": "5.49.1", "@algolia/ingestion": "1.49.1", "@algolia/monitoring": "1.49.1", "@algolia/recommend": "5.49.1", "@algolia/requester-browser-xhr": "5.49.1", "@algolia/requester-fetch": "5.49.1", "@algolia/requester-node-http": "5.49.1" } }, "sha512-X3Pp2aRQhg4xUC6PQtkubn5NpRKuUPQ9FPDQlx36SmpFwwH2N0/tw4c+NXV3nw3PsgeUs+BuWGP0gjz3TvENLQ=="], "algoliasearch": ["algoliasearch@5.53.0", "", { "dependencies": { "@algolia/abtesting": "1.19.0", "@algolia/client-abtesting": "5.53.0", "@algolia/client-analytics": "5.53.0", "@algolia/client-common": "5.53.0", "@algolia/client-insights": "5.53.0", "@algolia/client-personalization": "5.53.0", "@algolia/client-query-suggestions": "5.53.0", "@algolia/client-search": "5.53.0", "@algolia/ingestion": "1.53.0", "@algolia/monitoring": "1.53.0", "@algolia/recommend": "5.53.0", "@algolia/requester-browser-xhr": "5.53.0", "@algolia/requester-fetch": "5.53.0", "@algolia/requester-node-http": "5.53.0" } }, "sha512-OGW1q6b91CRSSeiOnM8LxuR5NYJ2esvw66jUZ4IIvdv+ItNkx3pwLuyR+jaCdbGee4ov5WgUnyPryyh11xvByQ=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
@@ -511,11 +510,11 @@
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
"autoprefixer": ["autoprefixer@10.4.27", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA=="], "autoprefixer": ["autoprefixer@10.5.0", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong=="],
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
"axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="], "axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="],
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
@@ -523,15 +522,15 @@
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.32", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg=="],
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="],
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
@@ -539,7 +538,7 @@
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
"caniuse-lite": ["caniuse-lite@1.0.30001777", "", {}, "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ=="], "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
@@ -559,8 +558,6 @@
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="],
"collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
@@ -609,23 +606,23 @@
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"electron-to-chromium": ["electron-to-chromium@1.5.307", "", {}, "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg=="], "electron-to-chromium": ["electron-to-chromium@1.5.364", "", {}, "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw=="],
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="], "enhanced-resolve": ["enhanced-resolve@5.22.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww=="],
"entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
"es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="], "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="],
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
"es-iterator-helpers": ["es-iterator-helpers@1.2.2", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.1", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "safe-array-concat": "^1.1.3" } }, "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w=="], "es-iterator-helpers": ["es-iterator-helpers@1.3.2", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="],
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
@@ -645,11 +642,11 @@
"eslint-config-next": ["eslint-config-next@16.1.3", "", { "dependencies": { "@next/eslint-plugin-next": "16.1.3", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-q2Z87VSsoJcv+vgR+Dm8NPRf+rErXcRktuBR5y3umo/j5zLjIWH7rqBCh3X804gUGKbOrqbgsLUkqDE35C93Gw=="], "eslint-config-next": ["eslint-config-next@16.1.3", "", { "dependencies": { "@next/eslint-plugin-next": "16.1.3", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-q2Z87VSsoJcv+vgR+Dm8NPRf+rErXcRktuBR5y3umo/j5zLjIWH7rqBCh3X804gUGKbOrqbgsLUkqDE35C93Gw=="],
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="],
"eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
"eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="], "eslint-module-utils": ["eslint-module-utils@2.13.0", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ=="],
"eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="],
@@ -657,7 +654,7 @@
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="], "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="],
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
@@ -665,8 +662,6 @@
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
@@ -713,13 +708,13 @@
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
"flatted": ["flatted@3.4.1", "", {}, "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ=="], "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
"fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
"framer-motion": ["framer-motion@12.35.2", "", { "dependencies": { "motion-dom": "^12.35.2", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-dhfuEMaNo0hc+AEqyHiIfiJRNb9U9UQutE9FoKm5pjf7CMitp9xPEF1iWZihR1q86LBmo6EJ7S8cN8QXEy49AA=="], "framer-motion": ["framer-motion@12.40.0", "", { "dependencies": { "motion-dom": "^12.40.0", "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
@@ -727,7 +722,7 @@
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
"geist": ["geist@1.7.0", "", { "peerDependencies": { "next": ">=13.2.0" } }, "sha512-ZaoiZwkSf0DwwB1ncdLKp+ggAldqxl5L1+SXaNIBGkPAqcu+xjVJLxlf3/S8vLt9UHx1xu5fz3lbzKCj5iOVdQ=="], "geist": ["geist@1.7.1", "", { "peerDependencies": { "next": ">=13.2.0" } }, "sha512-XF8DM30ODhDu0Ng5S2kOS8j4ZkG/6z2fKWAiFJA7wG0Hc92ZXgjYLrwbD9bVU4nGVzwboPtG+QtaPGsfgnXLaA=="],
"generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
@@ -741,7 +736,7 @@
"get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
"get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="], "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="],
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
@@ -755,8 +750,6 @@
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
@@ -769,7 +762,7 @@
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
"hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="],
@@ -821,7 +814,7 @@
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="],
"is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
@@ -875,11 +868,11 @@
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
@@ -903,29 +896,29 @@
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
"lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
@@ -937,7 +930,7 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"lucide-react": ["lucide-react@0.511.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w=="], "lucide-react": ["lucide-react@1.17.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
@@ -1057,19 +1050,19 @@
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
"motion-dom": ["motion-dom@12.35.2", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-pWXFMTwvGDbx1Fe9YL5HZebv2NhvGBzRtiNUv58aoK7+XrsuaydQ0JGRKK2r+bTKlwgSWwWxHbP5249Qr/BNpg=="], "motion-dom": ["motion-dom@12.40.0", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg=="],
"motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="], "motion-utils": ["motion-utils@12.39.0", "", {}, "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
"napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
"next": ["next@16.1.6", "", { "dependencies": { "@next/env": "16.1.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.6", "@next/swc-darwin-x64": "16.1.6", "@next/swc-linux-arm64-gnu": "16.1.6", "@next/swc-linux-arm64-musl": "16.1.6", "@next/swc-linux-x64-gnu": "16.1.6", "@next/swc-linux-x64-musl": "16.1.6", "@next/swc-win32-arm64-msvc": "16.1.6", "@next/swc-win32-x64-msvc": "16.1.6", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw=="], "next": ["next@16.2.6", "", { "dependencies": { "@next/env": "16.2.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.6", "@next/swc-darwin-x64": "16.2.6", "@next/swc-linux-arm64-gnu": "16.2.6", "@next/swc-linux-arm64-musl": "16.2.6", "@next/swc-linux-x64-gnu": "16.2.6", "@next/swc-linux-x64-musl": "16.2.6", "@next/swc-win32-arm64-msvc": "16.2.6", "@next/swc-win32-x64-msvc": "16.2.6", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw=="],
"next-mdx-remote": ["next-mdx-remote@6.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ=="], "next-mdx-remote": ["next-mdx-remote@6.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ=="],
@@ -1077,7 +1070,7 @@
"node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="], "node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="],
"node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], "node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="],
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
@@ -1119,11 +1112,11 @@
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
@@ -1131,6 +1124,10 @@
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="],
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.14", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg=="],
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
@@ -1189,7 +1186,7 @@
"remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], "resolve": ["resolve@2.0.0-next.7", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ=="],
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
@@ -1199,7 +1196,7 @@
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="],
"safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
@@ -1227,7 +1224,7 @@
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
@@ -1241,8 +1238,6 @@
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
"stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
"stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
@@ -1263,8 +1258,6 @@
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
"style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
@@ -1279,13 +1272,13 @@
"tailwind-merge": ["tailwind-merge@2.6.1", "", {}, "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="], "tailwind-merge": ["tailwind-merge@2.6.1", "", {}, "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="],
"tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], "tailwindcss": ["tailwindcss@4.3.0", "", {}, "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q=="],
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
@@ -1293,7 +1286,7 @@
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
"ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
@@ -1307,11 +1300,11 @@
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"typescript-eslint": ["typescript-eslint@8.56.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.56.1", "@typescript-eslint/parser": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ=="], "typescript-eslint": ["typescript-eslint@8.60.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.60.0", "@typescript-eslint/parser": "8.60.0", "@typescript-eslint/typescript-estree": "8.60.0", "@typescript-eslint/utils": "8.60.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw=="],
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
@@ -1335,7 +1328,7 @@
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
"unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], "unrs-resolver": ["unrs-resolver@1.12.2", "", { "dependencies": { "napi-postinstall": "^0.3.4" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.12.2", "@unrs/resolver-binding-android-arm64": "1.12.2", "@unrs/resolver-binding-darwin-arm64": "1.12.2", "@unrs/resolver-binding-darwin-x64": "1.12.2", "@unrs/resolver-binding-freebsd-x64": "1.12.2", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", "@unrs/resolver-binding-linux-x64-musl": "1.12.2", "@unrs/resolver-binding-openharmony-arm64": "1.12.2", "@unrs/resolver-binding-wasm32-wasi": "1.12.2", "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" } }, "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ=="],
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
@@ -1345,8 +1338,6 @@
"use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
@@ -1367,17 +1358,17 @@
"which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
"which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="], "which-typed-array": ["which-typed-array@1.1.21", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw=="],
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
"zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
@@ -1389,12 +1380,6 @@
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
"@eslint/eslintrc/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
"@radix-ui/react-avatar/@radix-ui/react-context": ["@radix-ui/react-context@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw=="],
"@radix-ui/react-avatar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
@@ -1407,43 +1392,39 @@
"@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="], "@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="],
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="],
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@typescript-eslint/typescript-estree/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="],
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
"cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-plugin-react/resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"is-bun-module/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "is-bun-module/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="],
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
@@ -1451,11 +1432,9 @@
"rehype-code-titles/unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], "rehype-code-titles/unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
"sharp/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "sharp/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="],
"@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
} }

View File

@@ -4,7 +4,7 @@
"rsc": true, "rsc": true,
"tsx": true, "tsx": true,
"tailwind": { "tailwind": {
"config": "tailwind.config.ts", "config": "",
"css": "app/globals.css", "css": "app/globals.css",
"baseColor": "zinc", "baseColor": "zinc",
"cssVariables": true, "cssVariables": true,

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import { usePathname, useRouter } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { useState, useEffect } from "react"; import { useState, useEffect, useLayoutEffect, useRef } from "react";
import { ROUTES, EachRoute } from "@/lib/routes"; import { ROUTES, EachRoute } from "@/lib/routes";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
@@ -41,8 +41,20 @@ function getIcon(name: string) {
export default function ContextPopover({ className }: ContextPopoverProps) { export default function ContextPopover({ className }: ContextPopoverProps) {
const pathname = usePathname(); const pathname = usePathname();
const router = useRouter(); const router = useRouter();
const [mounted, setMounted] = useState(false);
const [activeRoute, setActiveRoute] = useState<EachRoute>(); const [activeRoute, setActiveRoute] = useState<EachRoute>();
const [useDefaultTitle, setUseDefaultTitle] = useState(false);
const [triggerWidth, setTriggerWidth] = useState<number | null>(null);
const triggerRef = useRef<HTMLButtonElement>(null);
const contextRoutes = getContextRoutes(); const contextRoutes = getContextRoutes();
const fallbackRoute = ROUTES[0];
const displayRoute = useDefaultTitle ? fallbackRoute : activeRoute;
useEffect(() => {
// Mount-only state (used for client-only rendering) and intentionally set after first render.
// eslint-disable-next-line react-hooks/set-state-in-effect
setMounted(true);
}, []);
useEffect(() => { useEffect(() => {
if (pathname.startsWith("/docs")) { if (pathname.startsWith("/docs")) {
@@ -53,7 +65,66 @@ export default function ContextPopover({ className }: ContextPopoverProps) {
} }
}, [pathname]); }, [pathname]);
if (!pathname.startsWith("/docs") || contextRoutes.length === 0) { useEffect(() => {
const hasTitle = Boolean(
activeRoute?.context?.title ||
activeRoute?.title
);
if (!hasTitle) {
const timer = window.setTimeout(() => {
setUseDefaultTitle(true);
}, 300);
return () => window.clearTimeout(timer);
}
// Avoid calling setState synchronously inside the effect body.
// Using a micro task to reset state avoids the react-hooks/set-state-in-effect lint error.
const resetTimer = window.setTimeout(() => {
setUseDefaultTitle(false);
}, 0);
return () => window.clearTimeout(resetTimer);
}, [activeRoute?.context?.title, activeRoute?.title]);
// Keep the popover width in sync with the trigger width when the trigger text changes
// (e.g. when navigating between docs contexts) and when the window/resizing changes.
useLayoutEffect(() => {
if (!triggerRef.current) return;
const updateWidth = () => {
if (triggerRef.current) {
setTriggerWidth(triggerRef.current.offsetWidth);
}
};
// Make sure the width is updated when the trigger text/route changes.
updateWidth();
if (typeof ResizeObserver !== "undefined") {
const observer = new ResizeObserver(() => {
updateWidth();
});
observer.observe(triggerRef.current);
return () => {
observer.disconnect();
};
} else {
const handleResize = () => {
updateWidth();
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}
}, [displayRoute]);
if (!mounted || !pathname.startsWith("/docs") || contextRoutes.length === 0) {
return null; return null;
} }
@@ -61,6 +132,7 @@ export default function ContextPopover({ className }: ContextPopoverProps) {
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button <Button
ref={triggerRef}
variant="ghost" variant="ghost"
className={cn( className={cn(
"w-full cursor-pointer flex items-center justify-between font-semibold text-foreground px-2 py-4 border border-muted", "w-full cursor-pointer flex items-center justify-between font-semibold text-foreground px-2 py-4 border border-muted",
@@ -69,22 +141,29 @@ export default function ContextPopover({ className }: ContextPopoverProps) {
)} )}
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{activeRoute?.context?.icon && ( {displayRoute?.context?.icon && (
<span className="text-primary bg-primary/10 border border-primary dark:border dark:border-accent dark:bg-accent/10 dark:text-accent rounded p-0.5"> <span className="text-primary bg-primary/10 border border-primary dark:border dark:border-accent dark:bg-accent/10 dark:text-accent rounded p-0.5">
{getIcon(activeRoute.context.icon)} {getIcon(displayRoute.context.icon)}
</span> </span>
)} )}
<span className="truncate text-sm"> <span className="truncate text-sm">
{activeRoute?.context?.title || activeRoute?.title || <Skeleton className="h-3.5 w-24" />} {displayRoute?.context?.title ||
displayRoute?.title ||
(useDefaultTitle
? fallbackRoute?.context?.title || fallbackRoute?.title
: <Skeleton className="h-3.5 w-24" />)}
</span> </span>
</div> </div>
<ChevronsUpDown className="h-4 w-4 text-foreground/50" /> <ChevronsUpDown className="h-4 w-4 text-foreground/50" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent <PopoverContent
className="w-64 p-2" className="p-2"
align="start" align="start"
sideOffset={6} sideOffset={6}
style={{
width: triggerWidth !== null ? `${triggerWidth}px` : "auto"
}}
> >
<div className="space-y-1"> <div className="space-y-1">
{contextRoutes.map((route) => { {contextRoutes.map((route) => {

View File

@@ -1,6 +1,7 @@
"use client" "use client"
import { DocSearch } from "@docsearch/react" import { DocSearch } from "@docsearch/react"
import "@docsearch/css"
import { algoliaConfig } from "@/lib/search/algolia" import { algoliaConfig } from "@/lib/search/algolia"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
@@ -9,7 +10,7 @@ interface AlgoliaSearchProps {
} }
export default function AlgoliaSearch({ className }: AlgoliaSearchProps) { export default function AlgoliaSearch({ className }: AlgoliaSearchProps) {
const { appId, apiKey, indexName } = algoliaConfig const { appId, apiKey, indexName, askAiAssistantId } = algoliaConfig
if (!appId || !apiKey || !indexName) { if (!appId || !apiKey || !indexName) {
console.error("DocSearch credentials are not set in the environment variables.") console.error("DocSearch credentials are not set in the environment variables.")
@@ -26,7 +27,15 @@ export default function AlgoliaSearch({ className }: AlgoliaSearchProps) {
appId={appId} appId={appId}
apiKey={apiKey} apiKey={apiKey}
indexName={indexName} indexName={indexName}
placeholder="Type something to search..." placeholder="Search docs..."
askAi={
askAiAssistantId
? {
assistantId: askAiAssistantId,
suggestedQuestions: true,
} as const
: undefined
}
/> />
</div> </div>
) )

View File

@@ -1,7 +1,6 @@
import { import {
Breadcrumb, Breadcrumb,
BreadcrumbItem, BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList, BreadcrumbList,
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
@@ -14,20 +13,16 @@ export default function DocsBreadcrumb({ paths }: { paths: string[] }) {
<Breadcrumb> <Breadcrumb>
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink>Docs</BreadcrumbLink> <span>Docs</span>
</BreadcrumbItem> </BreadcrumbItem>
{paths.map((path, index) => ( {paths.map((path, index) => (
<Fragment key={`${path}-${index}`}> <Fragment key={`${path}-${index}`}>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
{index < paths.length - 1 ? ( {index < paths.length - 1 ? (
<BreadcrumbLink className="a"> <span>{toTitleCase(path)}</span>
{toTitleCase(path)}
</BreadcrumbLink>
) : ( ) : (
<BreadcrumbPage className="b"> <BreadcrumbPage>{toTitleCase(path)}</BreadcrumbPage>
{toTitleCase(path)}
</BreadcrumbPage>
)} )}
</BreadcrumbItem> </BreadcrumbItem>
</Fragment> </Fragment>
@@ -38,10 +33,23 @@ export default function DocsBreadcrumb({ paths }: { paths: string[] }) {
); );
} }
const acronyms = new Set([
"mdx",
"api",
"pdf",
"cli",
"ui",
"css",
"html",
"yaml",
"json",
"ssr",
"ssg",
]);
function toTitleCase(input: string): string { function toTitleCase(input: string): string {
const words = input.split("-"); return input
const capitalizedWords = words.map( .split("-")
(word) => word.charAt(0).toUpperCase() + word.slice(1) .map((w) => (acronyms.has(w) ? w.toUpperCase() : w.charAt(0).toUpperCase() + w.slice(1)))
); .join(" ");
return capitalizedWords.join(" ");
} }

View File

@@ -34,7 +34,10 @@ export default function DocsMenu({ isSheet = false, className = "" }: DocsMenuPr
if (!pathname.startsWith("/docs")) return null; if (!pathname.startsWith("/docs")) return null;
// Get the current context // Get the current context
const currentContext = getCurrentContext(pathname); const isDocsRoot = pathname === "/docs" || pathname === "/docs/";
const currentContext = isDocsRoot
? ROUTES[0]?.href.replace(/^\/+|\/+$/g, "")
: getCurrentContext(pathname);
// Get the route for the current context // Get the route for the current context
const contextRoute = currentContext ? getContextRoute(currentContext) : undefined; const contextRoute = currentContext ? getContextRoute(currentContext) : undefined;
@@ -52,9 +55,10 @@ export default function DocsMenu({ isSheet = false, className = "" }: DocsMenuPr
<li key={contextRoute.title}> <li key={contextRoute.title}>
<SubLink <SubLink
{...contextRoute} {...contextRoute}
href={`/docs${contextRoute.href}`} href={contextRoute.href}
level={0} level={0}
isSheet={isSheet} isSheet={isSheet}
parentHref="/docs"
/> />
</li> </li>
</ul> </ul>

View File

@@ -1,6 +1,7 @@
"use client"; "use client";
import { ArrowUpRight } from "lucide-react"; import { ArrowUpRight } from "lucide-react";
import GitHubButton from "@/components/Github";
import Anchor from "@/components/anchor"; import Anchor from "@/components/anchor";
import docuConfig from "@/docu.json"; import docuConfig from "@/docu.json";
@@ -36,6 +37,7 @@ export function DocsNavbar() {
</Anchor> </Anchor>
); );
})} })}
<GitHubButton />
</div> </div>
</div> </div>
); );

View File

@@ -1,120 +1,99 @@
"use client" "use client";
import { ChevronDown, ChevronUp, PanelRight, MoreVertical } from "lucide-react" import { ChevronDown, ChevronUp, PanelRight, MoreVertical, FileText } from "lucide-react";
import { Sheet, SheetClose, SheetContent, SheetHeader, SheetTrigger } from "@/components/ui/sheet" import { Sheet, SheetClose, SheetContent, SheetHeader, SheetTrigger } from "@/components/ui/sheet";
import DocsMenu from "@/components/DocsMenu" import DocsMenu from "@/components/DocsMenu";
import { ModeToggle } from "@/components/ThemeToggle" import { ModeToggle } from "@/components/ThemeToggle";
import { DialogTitle, DialogDescription } from "@/components/ui/dialog" import { DialogTitle, DialogDescription } from "@/components/ui/dialog";
import ContextPopover from "@/components/ContextPopover" import ContextPopover from "@/components/ContextPopover";
import TocObserver from "./TocObserver" import TocObserver from "./TocObserver";
import * as React from "react" import * as React from "react";
import { useRef, useMemo } from "react" import { useRef, useMemo } from "react";
import { usePathname } from "next/navigation" import { usePathname } from "next/navigation";
import { Button } from "./ui/button" import { Button } from "./ui/button";
import { motion, AnimatePresence } from "framer-motion" import { useActiveSection } from "@/hooks";
import { useActiveSection } from "@/hooks" import { TocItem } from "@/lib/toc";
import { TocItem } from "@/lib/toc" import Search from "@/components/SearchBox";
import Search from "@/components/SearchBox" import GitHubButton from "@/components/Github";
import { NavMenu } from "@/components/navbar" import { NavMenu } from "@/components/navbar";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu" } from "@/components/ui/dropdown-menu";
interface MobTocProps { interface MobTocProps {
tocs: TocItem[] tocs: TocItem[];
title?: string title?: string;
} }
const subscribe = () => () => undefined;
const getMountedSnapshot = () => true;
const getServerSnapshot = () => false;
const useClickOutside = (ref: React.RefObject<HTMLElement | null>, callback: () => void) => { const useClickOutside = (ref: React.RefObject<HTMLElement | null>, callback: () => void) => {
const handleClick = React.useCallback( const callbackRef = useRef(callback);
(event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback()
}
},
[ref, callback]
)
React.useEffect(() => { React.useEffect(() => {
document.addEventListener("mousedown", handleClick) callbackRef.current = callback;
return () => { });
document.removeEventListener("mousedown", handleClick)
React.useEffect(() => {
const handleClick = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callbackRef.current();
} }
}, [handleClick]) };
} document.addEventListener("mousedown", handleClick);
return () => document.removeEventListener("mousedown", handleClick);
}, [ref]);
};
export default function MobToc({ tocs, title }: MobTocProps) { export default function MobToc({ tocs, title }: MobTocProps) {
const pathname = usePathname() const pathname = usePathname();
const [isExpanded, setIsExpanded] = React.useState(false) const [isExpanded, setIsExpanded] = React.useState(false);
const tocRef = useRef<HTMLDivElement>(null) const tocRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null) const contentRef = useRef<HTMLDivElement>(null);
// Use custom hooks // Use custom hooks
const { activeId, setActiveId } = useActiveSection(tocs) const { activeId, setActiveId } = useActiveSection(tocs);
// Only show on /docs pages // Only show on /docs pages
const isDocsPage = useMemo(() => pathname?.startsWith("/docs"), [pathname]) const isDocsPage = useMemo(() => pathname?.startsWith("/docs"), [pathname]);
// Get title from active section if available, otherwise document title // Get title from active section if available, otherwise document title
const activeSection = useMemo(() => { const activeSection = useMemo(() => {
return tocs.find((toc) => toc.href.slice(1) === activeId) return tocs.find((toc) => toc.href.slice(1) === activeId);
}, [tocs, activeId]) }, [tocs, activeId]);
const displayTitle = activeSection?.text || title || "On this page" const displayTitle = activeSection?.text || title || "On this page";
const [mounted, setMounted] = React.useState(false) const mounted = React.useSyncExternalStore(subscribe, getMountedSnapshot, getServerSnapshot);
React.useEffect(() => {
setMounted(true)
}, [])
// Toggle expanded state // Toggle expanded state
const toggleExpanded = React.useCallback((e: React.MouseEvent) => { const toggleExpanded = React.useCallback((e: React.MouseEvent) => {
e.stopPropagation() e.stopPropagation();
setIsExpanded((prev) => !prev) setIsExpanded((prev) => !prev);
}, []) }, []);
// Close TOC when clicking outside // Close TOC when clicking outside
useClickOutside(tocRef, () => { useClickOutside(tocRef, () => {
if (isExpanded) { if (isExpanded) {
setIsExpanded(false) setIsExpanded(false);
} }
}) });
// Handle body overflow when TOC is expanded
React.useEffect(() => {
if (isExpanded) {
document.body.style.overflow = "hidden"
} else {
document.body.style.overflow = ""
}
return () => {
document.body.style.overflow = ""
}
}, [isExpanded])
// Don't render anything if not on docs page // Don't render anything if not on docs page
if (!isDocsPage || !mounted) return null if (!isDocsPage || !mounted) return null;
const chevronIcon = isExpanded ? ( const chevronIcon = isExpanded ? (
<ChevronUp className="text-muted-foreground h-4 w-4 shrink-0" /> <ChevronUp className="text-muted-foreground h-4 w-4 shrink-0" />
) : ( ) : (
<ChevronDown className="text-muted-foreground h-4 w-4 shrink-0" /> <ChevronDown className="text-muted-foreground h-4 w-4 shrink-0" />
) );
return ( return (
<AnimatePresence> <div ref={tocRef} className="sticky top-0 z-50 -mx-4 -mt-4 mb-4 lg:hidden">
<motion.div
ref={tocRef}
className="sticky top-0 z-50 -mx-4 -mt-4 mb-4 lg:hidden"
initial={{ y: -100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -100, opacity: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
>
<div className="bg-background/95 border-muted dark:border-foreground/10 dark:bg-background w-full border-b shadow-sm backdrop-blur-sm"> <div className="bg-background/95 border-muted dark:border-foreground/10 dark:bg-background w-full border-b shadow-sm backdrop-blur-sm">
<div className="p-2"> <div className="p-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -129,22 +108,21 @@ export default function MobToc({ tocs, title }: MobTocProps) {
<MoreVertical className="text-muted-foreground h-5 w-5" /> <MoreVertical className="text-muted-foreground h-5 w-5" />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent <DropdownMenuContent align="start" className="flex min-w-40 flex-col gap-1 p-2">
align="start"
className="flex min-w-[160px] flex-col gap-1 p-2"
>
<NavMenu /> <NavMenu />
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
className="-mx-1 h-auto flex-1 justify-between rounded-md px-2 py-2 hover:bg-transparent hover:text-inherit" className="-mx-1 h-auto min-w-0 flex-1 justify-between rounded-md px-2 py-2 hover:bg-transparent hover:text-inherit"
onClick={toggleExpanded} onClick={toggleExpanded}
aria-label={isExpanded ? "Collapse table of contents" : "Expand table of contents"} aria-label={isExpanded ? "Collapse table of contents" : "Expand table of contents"}
> >
<div className="flex items-center gap-2"> <div className="flex min-w-0 items-center gap-2">
<span className="text-sm font-medium capitalize">{displayTitle}</span> <span className="line-clamp-1 truncate text-sm font-medium capitalize">
{displayTitle}
</span>
</div> </div>
{chevronIcon} {chevronIcon}
</Button> </Button>
@@ -163,6 +141,7 @@ export default function MobToc({ tocs, title }: MobTocProps) {
<SheetHeader> <SheetHeader>
<SheetClose className="px-4" asChild> <SheetClose className="px-4" asChild>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<GitHubButton />
<div className="mr-8"> <div className="mr-8">
<ModeToggle /> <ModeToggle />
</div> </div>
@@ -179,27 +158,31 @@ export default function MobToc({ tocs, title }: MobTocProps) {
</Sheet> </Sheet>
</div> </div>
<AnimatePresence> <div
{isExpanded && ( className="grid transition-[grid-template-rows,opacity] duration-200 ease-in-out"
<motion.div style={{
ref={contentRef} gridTemplateRows: isExpanded ? "1fr" : "0fr",
className="-mx-1 mt-2 max-h-[60vh] overflow-y-auto px-1 pb-2" opacity: isExpanded ? 1 : 0,
initial={{ opacity: 0, height: 0 }} }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
> >
<div ref={contentRef} className="overflow-hidden">
<div className="mt-2 max-h-[60vh] overflow-y-auto px-4 pb-2">
{tocs?.length ? ( {tocs?.length ? (
<TocObserver data={tocs} activeId={activeId} onActiveIdChange={setActiveId} /> <TocObserver data={tocs} activeId={activeId} onActiveIdChange={setActiveId} />
) : ( ) : (
<p className="text-muted-foreground py-2 text-sm">No headings</p> <div className="flex flex-col items-center justify-center px-2 py-8 text-center">
<FileText className="text-muted-foreground/40 mb-3 h-8 w-8" />
<p className="text-muted-foreground mb-1 text-sm font-medium">No headings</p>
<p className="text-muted-foreground/70 text-xs leading-relaxed">
{`This page doesn't have section headings yet.`}
</p>
</div>
)} )}
</motion.div>
)}
</AnimatePresence>
</div> </div>
</div> </div>
</motion.div> </div>
</AnimatePresence> </div>
) </div>
</div>
);
} }

View File

@@ -1,6 +1,7 @@
"use client"; "use client";
import { createContext, useContext, useState, useEffect, useCallback } from "react"; import { createContext, useContext, useState, useEffect, useCallback } from "react";
import { searchConfig } from "@/lib/search/config";
interface SearchContextType { interface SearchContextType {
isOpen: boolean; isOpen: boolean;
@@ -18,6 +19,9 @@ export function SearchProvider({ children }: { children: React.ReactNode }) {
}, []); }, []);
useEffect(() => { useEffect(() => {
// Only add keyboard shortcut for default search, not Algolia (Algolia handles its own)
if (searchConfig.type === "algolia") return;
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if ((event.ctrlKey || event.metaKey) && event.key === "k") { if ((event.ctrlKey || event.metaKey) && event.key === "k") {
event.preventDefault(); event.preventDefault();

View File

@@ -1,13 +1,13 @@
"use client" "use client";
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState, useRef } from "react" import { useEffect, useMemo, useState, useRef } from "react";
import { ArrowUpIcon, ArrowDownIcon, CornerDownLeftIcon, FileTextIcon } from "lucide-react" import { ArrowUpIcon, ArrowDownIcon, CornerDownLeftIcon, FileTextIcon } from "lucide-react";
import Anchor from "./anchor" import Anchor from "./anchor";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
import { advanceSearch } from "@/lib/search/built-in" import { advanceSearch } from "@/lib/search/built-in";
import { ScrollArea } from "@/components/ui/scroll-area" import { ScrollArea } from "@/components/ui/scroll-area";
import { page_routes } from "@/lib/routes" import { page_routes } from "@/lib/routes";
import { import {
DialogContent, DialogContent,
DialogHeader, DialogHeader,
@@ -15,49 +15,48 @@ import {
DialogClose, DialogClose,
DialogTitle, DialogTitle,
DialogDescription, DialogDescription,
} from "@/components/ui/dialog" } from "@/components/ui/dialog";
type ContextInfo = { type ContextInfo = {
icon: string icon: string;
description: string description: string;
title?: string title?: string;
} };
type SearchResult = { type SearchResult = {
title: string title: string;
href: string href: string;
noLink?: boolean noLink?: boolean;
items?: undefined items?: undefined;
score?: number score?: number;
context?: ContextInfo context?: ContextInfo;
} };
const paddingMap = { const paddingMap = {
1: "pl-2", 1: "pl-2",
2: "pl-4", 2: "pl-4",
3: "pl-10", 3: "pl-10",
} as const } as const;
interface SearchModalProps { interface SearchModalProps {
isOpen: boolean isOpen: boolean;
setIsOpen: (open: boolean) => void setIsOpen: (open: boolean) => void;
} }
export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) { export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
const router = useRouter() const router = useRouter();
const [searchedInput, setSearchedInput] = useState("") const [searchedInput, setSearchedInput] = useState("");
const [selectedIndex, setSelectedIndex] = useState(0) const [selectedIndex, setSelectedIndex] = useState(0);
const itemRefs = useRef<(HTMLDivElement | null)[]>([]) const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => { useEffect(() => {
if (!isOpen) { if (!isOpen) {
// eslint-disable-next-line react-hooks/set-state-in-effect queueMicrotask(() => setSearchedInput(""));
setSearchedInput("")
} }
}, [isOpen]) }, [isOpen]);
const filteredResults = useMemo<SearchResult[]>(() => { const filteredResults = useMemo<SearchResult[]>(() => {
const trimmedInput = searchedInput.trim() const trimmedInput = searchedInput.trim();
if (trimmedInput.length < 3) { if (trimmedInput.length < 3) {
return page_routes return page_routes
@@ -68,50 +67,50 @@ export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
href: route.href, href: route.href,
noLink: route.noLink, noLink: route.noLink,
context: route.context, context: route.context,
})) }));
} }
return advanceSearch(trimmedInput) as unknown as SearchResult[] return advanceSearch(trimmedInput) as unknown as SearchResult[];
}, [searchedInput]) }, [searchedInput]);
// useEffect(() => { useEffect(() => {
// setSelectedIndex(0); queueMicrotask(() => setSelectedIndex(0));
// }, [filteredResults]); }, [filteredResults]);
useEffect(() => { useEffect(() => {
const handleNavigation = (event: KeyboardEvent) => { const handleNavigation = (event: KeyboardEvent) => {
if (!isOpen || filteredResults.length === 0) return if (!isOpen || filteredResults.length === 0) return;
if (event.key === "ArrowDown") { if (event.key === "ArrowDown") {
event.preventDefault() event.preventDefault();
setSelectedIndex((prev) => (prev + 1) % filteredResults.length) setSelectedIndex((prev) => (prev + 1) % filteredResults.length);
} else if (event.key === "ArrowUp") { } else if (event.key === "ArrowUp") {
event.preventDefault() event.preventDefault();
setSelectedIndex((prev) => (prev - 1 + filteredResults.length) % filteredResults.length) setSelectedIndex((prev) => (prev - 1 + filteredResults.length) % filteredResults.length);
} else if (event.key === "Enter") { } else if (event.key === "Enter") {
event.preventDefault() event.preventDefault();
const selectedItem = filteredResults[selectedIndex] const selectedItem = filteredResults[selectedIndex];
if (selectedItem) { if (selectedItem) {
router.push(`/docs${selectedItem.href}`) router.push(`/docs${selectedItem.href}`);
setIsOpen(false) setIsOpen(false);
}
} }
} }
};
window.addEventListener("keydown", handleNavigation) window.addEventListener("keydown", handleNavigation);
return () => window.removeEventListener("keydown", handleNavigation) return () => window.removeEventListener("keydown", handleNavigation);
}, [isOpen, filteredResults, selectedIndex, router, setIsOpen]) }, [isOpen, filteredResults, selectedIndex, router, setIsOpen]);
useEffect(() => { useEffect(() => {
if (itemRefs.current[selectedIndex]) { if (itemRefs.current[selectedIndex]) {
itemRefs.current[selectedIndex]?.scrollIntoView({ itemRefs.current[selectedIndex]?.scrollIntoView({
behavior: "smooth", behavior: "smooth",
block: "nearest", block: "nearest",
}) });
} }
}, [selectedIndex]) }, [selectedIndex]);
return ( return (
<DialogContent className="rounded-md! top-[45%] max-w-[650px] p-0 sm:top-[38%]"> <DialogContent className="top-[45%] max-w-[650px] rounded-md! p-0 sm:top-[38%]">
<DialogHeader> <DialogHeader>
<DialogTitle className="sr-only">Search Documentation</DialogTitle> <DialogTitle className="sr-only">Search Documentation</DialogTitle>
<DialogDescription className="sr-only">Search through the documentation</DialogDescription> <DialogDescription className="sr-only">Search through the documentation</DialogDescription>
@@ -120,8 +119,8 @@ export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
<input <input
value={searchedInput} value={searchedInput}
onChange={(e) => { onChange={(e) => {
setSearchedInput(e.target.value) setSearchedInput(e.target.value);
setSelectedIndex(0) setSelectedIndex(0);
}} }}
placeholder="Type something to search..." placeholder="Type something to search..."
autoFocus autoFocus
@@ -137,15 +136,15 @@ export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
<ScrollArea className="max-h-[400px] overflow-y-auto"> <ScrollArea className="max-h-[400px] overflow-y-auto">
<div className="flex flex-col items-start overflow-y-auto px-1 pb-4 sm:px-2"> <div className="flex flex-col items-start overflow-y-auto px-1 pb-4 sm:px-2">
{filteredResults.map((item, index) => { {filteredResults.map((item, index) => {
const level = (item.href.split("/").slice(1).length - 1) as keyof typeof paddingMap const level = (item.href.split("/").slice(1).length - 1) as keyof typeof paddingMap;
const paddingClass = paddingMap[level] || "pl-2" const paddingClass = paddingMap[level] || "pl-2";
const isActive = index === selectedIndex const isActive = index === selectedIndex;
return ( return (
<DialogClose key={item.href} asChild> <DialogClose key={item.href} asChild>
<Anchor <Anchor
ref={(el) => { ref={(el) => {
itemRefs.current[index] = el as HTMLDivElement | null itemRefs.current[index] = el as HTMLDivElement | null;
}} }}
className={cn( className={cn(
"dark:hover:bg-accent/15 hover:bg-accent/10 flex w-full items-center gap-2.5 rounded-sm px-3 text-sm", "dark:hover:bg-accent/15 hover:bg-accent/10 flex w-full items-center gap-2.5 rounded-sm px-3 text-sm",
@@ -174,7 +173,7 @@ export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
</div> </div>
</Anchor> </Anchor>
</DialogClose> </DialogClose>
) );
})} })}
</div> </div>
</ScrollArea> </ScrollArea>
@@ -196,5 +195,5 @@ export function SearchModal({ isOpen, setIsOpen }: SearchModalProps) {
</div> </div>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
) );
} }

View File

@@ -2,7 +2,6 @@ import docuData from "@/docu.json";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
// Define types for docu.json
interface SponsorItem { interface SponsorItem {
url: string; url: string;
image: string; image: string;
@@ -10,116 +9,31 @@ interface SponsorItem {
description?: string; description?: string;
} }
interface NavbarConfig { const docuConfig = docuData as { sponsor?: { title?: string; item?: SponsorItem } };
title?: string;
logo?: {
light?: string;
dark?: string;
};
links?: Array<{
title: string;
href: string;
external?: boolean;
}>;
}
interface FooterConfig {
text?: string;
links?: Array<{
title: string;
href: string;
external?: boolean;
}>;
}
interface MetaConfig {
title?: string;
description?: string;
favicon?: string;
socialBanner?: string;
}
interface RepositoryConfig {
url: string;
editUrl?: string;
branch?: string;
directory?: string;
}
interface RouteItem {
title: string;
href: string;
noLink?: boolean;
context?: {
icon: string;
description: string;
title: string;
};
items?: RouteItem[];
}
interface RouteConfig {
title: string;
href: string;
noLink?: boolean;
context?: {
icon: string;
description: string;
title: string;
};
items?: RouteItem[];
}
interface DocuConfig {
sponsor?: {
title?: string;
item?: SponsorItem;
};
navbar: NavbarConfig;
footer: FooterConfig;
meta: MetaConfig;
repository: RepositoryConfig;
routes: RouteConfig[];
}
// Type assertion for docu.json
const docuConfig = docuData as DocuConfig;
export function Sponsor() { export function Sponsor() {
// Safely get sponsor data with optional chaining and default values
const sponsor = docuConfig?.sponsor || {}; const sponsor = docuConfig?.sponsor || {};
const item = sponsor?.item; const item = sponsor?.item;
// Return null if required fields are missing
if (!item?.url || !item?.image || !item?.title) { if (!item?.url || !item?.image || !item?.title) {
return null; return null;
} }
return ( return (
<div className="mt-4"> <div className="mt-4">
{sponsor?.title && ( {sponsor?.title && <h2 className="mb-4 text-sm font-medium">{sponsor.title}</h2>}
<h2 className="mb-4 text-sm font-medium">{sponsor.title}</h2>
)}
<Link <Link
href={item.url} href={item.url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="flex flex-col justify-center gap-2 p-4 border rounded-lg hover:shadow transition-shadow" className="flex flex-col justify-center gap-2 rounded-lg border p-4 transition-shadow hover:shadow"
> >
<div className="relative w-8 h-8 shrink-0"> <div className="relative h-8 w-8 shrink-0">
<Image <Image src={item.image} alt={item.title} fill className="object-contain" sizes="32px" />
src={item.image}
alt={item.title}
fill
className="object-contain"
sizes="32px"
/>
</div> </div>
<div className="text-center sm:text-left"> <div className="text-center sm:text-left">
<h3 className="text-sm font-medium">{item.title}</h3> <h3 className="text-sm font-medium">{item.title}</h3>
{item.description && ( {item.description && <p className="text-muted-foreground text-sm">{item.description}</p>}
<p className="text-muted-foreground text-sm">{item.description}</p>
)}
</div> </div>
</Link> </Link>
</div> </div>

View File

@@ -2,7 +2,12 @@
import { ThemeProvider as NextThemesProvider } from "next-themes"; import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes"; import { type ThemeProviderProps } from "next-themes";
import type { ReactNode } from "react";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) { interface Props extends ThemeProviderProps {
children: ReactNode;
}
export function ThemeProvider({ children, ...props }: Props) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>; return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
} }

View File

@@ -7,35 +7,27 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
export function ModeToggle() { export function ModeToggle() {
const { theme, setTheme, resolvedTheme } = useTheme(); const { theme, setTheme, resolvedTheme } = useTheme();
const [mounted, setMounted] = React.useState(false); const mounted = React.useSyncExternalStore(
() => () => {},
() => true,
() => false
);
// Untuk menghindari hydration mismatch // If not mounted, do not render anything to avoid mismatch
React.useEffect(() => {
setMounted(true);
}, []);
// Jika belum mounted, jangan render apapun untuk menghindari mismatch
if (!mounted) { if (!mounted) {
return ( return (
<div className="flex items-center gap-1 rounded-full border border-border bg-background/50 p-0.5"> <div className="border-border bg-background/50 flex items-center gap-1 rounded-full border p-0.5">
<div className="rounded-full p-0 w-1 h-1" /> <div className="h-1 w-1 rounded-full p-0" />
<div className="rounded-full p-0 w-1 h-1" /> <div className="h-1 w-1 rounded-full p-0" />
</div> </div>
); );
} }
// Tentukan theme yang aktif: gunakan resolvedTheme untuk menampilkan ikon yang sesuai
// jika theme === "system", resolvedTheme akan menjadi "light" atau "dark" sesuai device
const activeTheme = theme === "system" || !theme ? resolvedTheme : theme; const activeTheme = theme === "system" || !theme ? resolvedTheme : theme;
const handleToggle = () => { const handleToggle = (value: string) => {
// Toggle antara light dan dark if (!value) return;
// Jika sekarang light, ganti ke dark, dan sebaliknya setTheme(value);
if (activeTheme === "light") {
setTheme("dark");
} else {
setTheme("light");
}
}; };
return ( return (
@@ -43,29 +35,31 @@ export function ModeToggle() {
type="single" type="single"
value={activeTheme} value={activeTheme}
onValueChange={handleToggle} onValueChange={handleToggle}
className="flex items-center gap-1 rounded-full border border-border bg-background/50 p-0.5 transition-all" className="border-border bg-background/50 flex items-center gap-1 rounded-full border p-0.5 transition-all"
> >
<ToggleGroupItem <ToggleGroupItem
value="light" value="light"
size="xs" size="xs"
aria-label="Light Mode" aria-label="Light Mode"
className={`rounded-full cursor-pointer p-0.5 transition-all ${activeTheme === "light" className={`cursor-pointer rounded-full p-0.5 transition-all ${
activeTheme === "light"
? "bg-primary text-primary-foreground" ? "bg-primary text-primary-foreground"
: "bg-transparent hover:bg-muted/50" : "hover:bg-muted/50 bg-transparent"
}`} }`}
> >
<Sun className="h-0.5 w-0.5" /> <Sun className="h-4 w-4" />
</ToggleGroupItem> </ToggleGroupItem>
<ToggleGroupItem <ToggleGroupItem
value="dark" value="dark"
size="xs" size="xs"
aria-label="Dark Mode" aria-label="Dark Mode"
className={`rounded-full cursor-pointer p-0.5 transition-all ${activeTheme === "dark" className={`cursor-pointer rounded-full p-0.5 transition-all ${
activeTheme === "dark"
? "bg-primary text-primary-foreground" ? "bg-primary text-primary-foreground"
: "bg-transparent hover:bg-muted/50" : "hover:bg-muted/50 bg-transparent"
}`} }`}
> >
<Moon className="h-0.5 w-0.5" /> <Moon className="h-4 w-4" />
</ToggleGroupItem> </ToggleGroupItem>
</ToggleGroup> </ToggleGroup>
); );

View File

@@ -1,16 +1,15 @@
"use client" "use client";
import clsx from "clsx" import clsx from "clsx";
import Link from "next/link" import Link from "next/link";
import { useState, useRef, useEffect, useCallback } from "react" import { useRef, useCallback } from "react";
import { motion } from "framer-motion" import { ScrollToTop } from "./ScrollToTop";
import { ScrollToTop } from "./ScrollToTop" import { TocItem } from "@/lib/toc";
import { TocItem } from "@/lib/toc"
interface TocObserverProps { interface TocObserverProps {
data: TocItem[] data: TocItem[];
activeId?: string | null activeId?: string | null;
onActiveIdChange?: (id: string | null) => void onActiveIdChange?: (id: string | null) => void;
} }
export default function TocObserver({ export default function TocObserver({
@@ -18,180 +17,95 @@ export default function TocObserver({
activeId: externalActiveId, activeId: externalActiveId,
onActiveIdChange, onActiveIdChange,
}: TocObserverProps) { }: TocObserverProps) {
const itemRefs = useRef<Map<string, HTMLAnchorElement>>(new Map()) const itemRefs = useRef<Map<string, HTMLAnchorElement>>(new Map());
const activeId = externalActiveId ?? null const activeId = externalActiveId ?? null;
const handleLinkClick = useCallback( const handleLinkClick = useCallback(
(id: string) => { (id: string) => {
onActiveIdChange?.(id) onActiveIdChange?.(id);
}, },
[onActiveIdChange] [onActiveIdChange]
) );
// Function to check if an item has children
const hasChildren = (currentId: string, currentLevel: number) => {
const currentIndex = data.findIndex((item) => item.href.slice(1) === currentId)
if (currentIndex === -1 || currentIndex === data.length - 1) return false
const nextItem = data[currentIndex + 1]
return nextItem.level > currentLevel
}
// Calculate scroll progress for the active section
const [scrollProgress, setScrollProgress] = useState(0)
useEffect(() => {
const handleScroll = () => {
if (!activeId) return
const activeElement = document.getElementById(activeId)
if (!activeElement) return
const rect = activeElement.getBoundingClientRect()
const windowHeight = window.innerHeight
const elementTop = rect.top
const elementHeight = rect.height
// Calculate how much of the element is visible
let progress = 0
if (elementTop < windowHeight) {
progress = Math.min(1, (windowHeight - elementTop) / (windowHeight + elementHeight))
}
setScrollProgress(progress)
}
const container = document.getElementById("scroll-container") || window
container.addEventListener("scroll", handleScroll, { passive: true })
// Initial calculation
handleScroll()
return () => container.removeEventListener("scroll", handleScroll)
}, [activeId])
return ( return (
<div className="relative"> <div className="relative">
<div className="text-foreground/70 hover:text-foreground relative text-sm transition-colors"> <div className="text-foreground/70 hover:text-foreground relative text-sm transition-colors">
{/* Single vertical line on the left */}
<div className="bg-border/40 dark:bg-border/30 absolute top-0 left-0 h-full w-px" />
<div className="flex flex-col gap-0"> <div className="flex flex-col gap-0">
{data.map(({ href, level, text }, index) => { {data.map(({ href, level, text }) => {
const id = href.slice(1) const id = href.slice(1);
const isActive = activeId === id const isActive = activeId === id;
const indent = level > 1 ? (level - 1) * 20 : 0 // Calculate padding based on level for indentation
// Prefix with underscore to indicate intentionally unused const levelPadding = (level - 2) * 16; // 0px for level 2, 16px for level 3, 32px for level 4, etc
const _isParent = hasChildren(id, level)
const _isLastInLevel = index === data.length - 1 || data[index + 1].level <= level
return ( return (
<div key={href} className="relative">
{/* Simple L-shaped connector */}
{level > 1 && (
<div <div
className={clsx("absolute top-0 h-full w-6", { key={href}
"left-[6px]": indent === 20, // Level 2 className={clsx(
"left-[22px]": indent === 40, // Level 3 "relative flex items-center transition-all duration-200",
"left-[38px]": indent === 60, // Level 4 isActive ? "bg-primary/5 dark:bg-primary/10" : ""
})} )}
> >
{/* Vertical line */} {/* Horizontal line connected to vertical line + Dot */}
<div <div
className={clsx( className={clsx(
"absolute left-0 top-0 h-full w-px", "flex shrink-0 items-center px-1 pt-2 pb-2 transition-all duration-200",
isActive isActive ? "border-primary -ml-px border-l-[3px]" : ""
? "bg-primary/20 dark:bg-primary/30"
: "bg-border/50 dark:bg-border/50"
)} )}
> >
{isActive && ( {/* Horizontal line from vertical line to dot */}
<motion.div
className="bg-primary absolute left-0 top-0 h-full w-full origin-top"
initial={{ scaleY: 0 }}
animate={{ scaleY: scrollProgress }}
transition={{ duration: 0.3 }}
/>
)}
</div>
{/* Horizontal line */}
<div <div
className={clsx( className={clsx(
"absolute left-0 top-1/2 h-px w-6", "h-px transition-colors duration-200",
isActive isActive
? "bg-primary/20 dark:bg-primary/30" ? "bg-primary dark:bg-primary w-3"
: "bg-border/50 dark:bg-border/50" : "bg-border/40 dark:bg-border/30 w-2"
)} )}
>
{isActive && (
<motion.div
className="bg-primary dark:bg-accent absolute left-0 top-0 h-full w-full origin-left"
initial={{ scaleX: 0 }}
animate={{ scaleX: scrollProgress }}
transition={{ duration: 0.3, delay: 0.1 }}
/> />
{/* Dot */}
<div
className={clsx(
"h-1.5 w-1.5 shrink-0 rounded-full transition-colors duration-300",
{
"bg-primary dark:bg-primary": isActive,
"bg-border/50 dark:bg-border/40": !isActive,
}
)} )}
/>
</div> </div>
</div>
)}
{/* Text link with indentation padding */}
<Link <Link
href={href} href={href}
onClick={() => handleLinkClick(id)} onClick={() => handleLinkClick(id)}
className={clsx("relative flex items-center py-2 transition-colors", { aria-current={isActive ? "location" : undefined}
className={clsx("flex flex-1 items-center py-2 transition-all duration-200", {
"text-primary dark:text-primary font-medium": isActive, "text-primary dark:text-primary font-medium": isActive,
"text-muted-foreground hover:text-foreground dark:hover:text-foreground/90": "text-muted-foreground hover:text-foreground dark:hover:text-foreground/90":
!isActive, !isActive,
})} })}
style={{ style={{ paddingLeft: `${levelPadding + 6}px` }}
paddingLeft: `${indent}px`, ref={(el: HTMLAnchorElement | null) => {
marginLeft: level > 1 ? "12px" : "0", const map = itemRefs.current;
}}
ref={(el) => {
const map = itemRefs.current
if (el) { if (el) {
map.set(id, el) map.set(id, el);
} else { } else {
map.delete(id) map.delete(id);
} }
}} }}
> >
{/* Circle indicator */} <span className="line-clamp-2 text-sm break-words">{text}</span>
<div className="relative flex h-4 w-4 shrink-0 items-center justify-center">
<div
className={clsx(
"relative z-10 h-1.5 w-1.5 rounded-full transition-all duration-300",
{
"bg-primary dark:bg-primary/90 scale-100": isActive,
"bg-muted-foreground/30 dark:bg-muted-foreground/30 group-hover:bg-primary/50 dark:group-hover:bg-primary/50 scale-75 group-hover:scale-100":
!isActive,
}
)}
>
{isActive && (
<motion.div
className="bg-primary/20 dark:bg-primary/30 absolute inset-0 rounded-full"
initial={{ scale: 1 }}
animate={{ scale: 1.8 }}
transition={{
duration: 2,
repeat: Infinity,
repeatType: "reverse",
}}
/>
)}
</div>
</div>
<span className="truncate text-sm">{text}</span>
</Link> </Link>
</div> </div>
) );
})} })}
</div> </div>
</div> </div>
{/* Add scroll to top link at the bottom of TOC */} {/* Add scroll to top link at the bottom of TOC */}
<ScrollToTop className="mt-6" /> <ScrollToTop className="mt-6" />
</div> </div>
) );
} }

View File

@@ -14,7 +14,8 @@ type AnchorProps = LinkProps & {
} & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps>; } & Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps>;
const Anchor = forwardRef<HTMLAnchorElement, AnchorProps>( const Anchor = forwardRef<HTMLAnchorElement, AnchorProps>(
({ (
{
absolute = false, absolute = false,
className = "", className = "",
activeClassName = "", activeClassName = "",
@@ -22,34 +23,29 @@ const Anchor = forwardRef<HTMLAnchorElement, AnchorProps>(
children, children,
href, href,
...props ...props
}, ref) => { },
ref
) => {
const path = usePathname(); const path = usePathname();
const hrefStr = href?.toString() || ''; const hrefStr = href?.toString() || "";
// Check if URL is external // Check if URL is external
const isExternal = /^(https?:\/\/|\/\/)/.test(hrefStr); const isExternal = /^(https?:\/\/|\/\/)/.test(hrefStr);
// Check if current path matches the link // Check if current path matches the link
const isActive = absolute const isActive = absolute ? hrefStr.split("/")[1] === path?.split("/")[1] : path === hrefStr;
? hrefStr.split("/")[1] === path?.split("/")[1]
: path === hrefStr;
// Apply active class only for internal links // Apply active class only for internal links
const linkClassName = cn( const linkClassName = cn(
'transition-colors hover:text-primary', "transition-colors hover:text-primary",
className, className,
!isExternal && isActive && activeClassName !isExternal && isActive && activeClassName
); );
if (disabled) { if (disabled) {
return ( return <span className={cn(linkClassName, "cursor-not-allowed opacity-50")}>{children}</span>;
<span className={cn(linkClassName, "cursor-not-allowed opacity-50")}>
{children}
</span>
);
} }
if (isExternal) { if (isExternal) {
return ( return (
<a <a
@@ -65,12 +61,12 @@ const Anchor = forwardRef<HTMLAnchorElement, AnchorProps>(
); );
} }
return ( return (
<Link <Link
ref={ref} ref={ref}
href={hrefStr} href={hrefStr}
className={linkClassName} className={linkClassName}
aria-current={isActive ? "page" : undefined}
{...props} {...props}
> >
{children} {children}

View File

@@ -1,13 +1,12 @@
import Link from "next/link"; import Link from "next/link";
import { ModeToggle } from "@/components/ThemeToggle"; import { ModeToggle } from "@/components/ThemeToggle";
import docuData from "@/docu.json"; import docuData from "@/docu.json";
import * as LucideIcons from "lucide-react"; import { getSocialIconByName } from "@/lib/icon";
// Define types for docu.json // Define types for docu.json
interface SocialItem { interface SocialItem {
name: string; name: string;
url: string; url: string;
iconName: string;
} }
interface FooterConfig { interface FooterConfig {
@@ -48,7 +47,7 @@ export function Footer({ id }: FooterProps) {
export function FooterButtons() { export function FooterButtons() {
const footer = docuConfig?.footer; const footer = docuConfig?.footer;
// Jangan render apapun jika tidak ada data sosial // Don't render anything if there is no social data
if (!footer || !Array.isArray(footer.social) || footer.social.length === 0) { if (!footer || !Array.isArray(footer.social) || footer.social.length === 0) {
return null; return null;
} }
@@ -56,9 +55,7 @@ export function FooterButtons() {
return ( return (
<> <>
{footer.social.map((item) => { {footer.social.map((item) => {
const IconComponent = const IconComponent = getSocialIconByName(item.name);
(LucideIcons[item.iconName as keyof typeof LucideIcons] ??
LucideIcons["Globe"]) as React.FC<{ className?: string }>;
return ( return (
<Link <Link

View File

@@ -9,6 +9,7 @@ import DocsMenu from "@/components/DocsMenu"
import { ModeToggle } from "@/components/ThemeToggle" import { ModeToggle } from "@/components/ThemeToggle"
import ContextPopover from "@/components/ContextPopover" import ContextPopover from "@/components/ContextPopover"
import Search from "@/components/SearchBox" import Search from "@/components/SearchBox"
import GitHubButton from "@/components/Github"
export function Leftbar() { export function Leftbar() {
return ( return (
@@ -54,8 +55,11 @@ export function SheetLeftbar() {
<SheetHeader> <SheetHeader>
<SheetClose className="px-4" asChild> <SheetClose className="px-4" asChild>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<GitHubButton />
<div className="mr-8">
<ModeToggle /> <ModeToggle />
</div> </div>
</div>
</SheetClose> </SheetClose>
</SheetHeader> </SheetHeader>
<div className="flex flex-col gap-4 overflow-y-auto"> <div className="flex flex-col gap-4 overflow-y-auto">

View File

@@ -1,21 +0,0 @@
import { createContext, useState, useId } from "react"
type AccordionGroupContextType = {
inGroup: boolean
groupId: string
openTitle: string | null
setOpenTitle: (title: string | null) => void
}
export const AccordionGroupContext = createContext<AccordionGroupContextType | null>(null)
export function AccordionGroupProvider({ children }: { children: React.ReactNode }) {
const [openTitle, setOpenTitle] = useState<string | null>(null)
const groupId = useId()
return (
<AccordionGroupContext.Provider value={{ inGroup: true, groupId, openTitle, setOpenTitle }}>
{children}
</AccordionGroupContext.Provider>
)
}

View File

@@ -1,20 +0,0 @@
"use client"
import React, { ReactNode } from "react"
import clsx from "clsx"
import { AccordionGroupProvider } from "@/components/markdown/AccordionContext"
interface AccordionGroupProps {
children: ReactNode
className?: string
}
const AccordionGroup: React.FC<AccordionGroupProps> = ({ children, className }) => {
return (
<AccordionGroupProvider>
<div className={clsx("overflow-hidden rounded-lg border", className)}>{children}</div>
</AccordionGroupProvider>
)
}
export default AccordionGroup

View File

@@ -1,61 +0,0 @@
"use client"
import { ReactNode, useContext, useState } from "react"
import { ChevronRight } from "lucide-react"
import * as Icons from "lucide-react"
import { cn } from "@/lib/utils"
import { AccordionGroupContext } from "@/components/markdown/AccordionContext"
type AccordionProps = {
title: string
children?: ReactNode
icon?: keyof typeof Icons
}
const Accordion: React.FC<AccordionProps> = ({ title, children, icon }: AccordionProps) => {
const groupContext = useContext(AccordionGroupContext)
const isInGroup = groupContext?.inGroup === true
const groupOpen = groupContext?.openTitle === title
const setGroupOpen = groupContext?.setOpenTitle
const [localOpen, setLocalOpen] = useState(false)
const isOpen = isInGroup ? groupOpen : localOpen
const handleToggle = () => {
if (isInGroup && setGroupOpen) {
setGroupOpen(groupOpen ? null : title)
} else {
setLocalOpen(!localOpen)
}
}
const Icon = icon ? (Icons[icon] as React.FC<{ className?: string }>) : null
return (
<div
className={cn(
!isInGroup && "rounded-lg border shadow-sm",
isInGroup && "border-border border-b last:border-b-0"
)}
>
<button
type="button"
onClick={handleToggle}
className="bg-muted/40 dark:bg-muted/20 hover:bg-muted/70 dark:hover:bg-muted/70 flex w-full cursor-pointer items-center gap-2 px-4 py-3 text-start transition-colors"
>
<ChevronRight
className={cn(
"text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200",
isOpen && "rotate-90"
)}
/>
{Icon && <Icon className="text-foreground h-4 w-4 shrink-0" />}
<h3 className="text-foreground m-0! text-base font-medium">{title}</h3>
</button>
{isOpen && <div className="dark:bg-muted/10 bg-muted/15 px-4 py-3">{children}</div>}
</div>
)
}
export default Accordion

View File

@@ -1,50 +0,0 @@
import React from "react";
import * as Icons from "lucide-react";
import Link from "next/link";
type ButtonProps = {
icon?: keyof typeof Icons;
text?: string;
href: string;
target?: "_blank" | "_self" | "_parent" | "_top";
size?: "sm" | "md" | "lg";
variation?: "primary" | "accent" | "outline";
};
const Button: React.FC<ButtonProps> = ({
icon,
text,
href,
target,
size = "md",
variation = "primary",
}) => {
const baseStyles = "inline-flex items-center justify-center rounded font-medium focus:outline-none transition no-underline";
const sizeStyles = {
sm: "px-3 py-1 my-6 text-sm",
md: "px-4 py-2 my-6 text-base",
lg: "px-5 py-3 my-6 text-lg",
};
const variationStyles = {
primary: "bg-primary text-white hover:bg-primary/90",
accent: "bg-accent text-white hover:bg-accent/90",
outline: "border border-accent text-accent hover:bg-accent/10",
};
const Icon = icon ? (Icons[icon] as React.FC<{ className?: string }>) : null; // Tipe eksplisit sebagai React.FC
return (
<Link
href={href}
target={target}
rel={target === "_blank" ? "noopener noreferrer" : undefined}
className={`${baseStyles} ${sizeStyles[size]} ${variationStyles[variation]}`}
>
{text && <span>{text}</span>}
{Icon && <Icon className="mr-2 h-5 w-5" />}
</Link>
);
};
export default Button;

View File

@@ -1,36 +0,0 @@
import React, { ReactNode } from "react";
import clsx from "clsx";
interface CardGroupProps {
children: ReactNode;
cols?: number;
className?: string;
}
const CardGroup: React.FC<CardGroupProps> = ({ children, cols = 2, className }) => {
const cardsArray = React.Children.toArray(children);
// Static grid column classes for Tailwind v4 compatibility
const gridColsClass = {
1: "grid-cols-1",
2: "grid-cols-1 sm:grid-cols-2",
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
}[cols] || "grid-cols-1 sm:grid-cols-2";
return (
<div
className={clsx(
"grid gap-4 text-foreground",
gridColsClass,
className
)}
>
{cardsArray.map((card, index) => (
<div key={index}>{card}</div>
))}
</div>
);
};
export default CardGroup;

View File

@@ -1,42 +0,0 @@
import React, { ReactNode } from "react";
import * as Icons from "lucide-react";
import Link from "next/link";
import clsx from "clsx";
type IconName = keyof typeof Icons;
interface CardProps {
title: string;
icon?: IconName;
href?: string;
horizontal?: boolean;
children: ReactNode;
className?: string;
}
const Card: React.FC<CardProps> = ({ title, icon, href, horizontal, children, className }) => {
const Icon = icon ? (Icons[icon] as React.FC<{ className?: string }>) : null;
const content = (
<div
className={clsx(
"border rounded-lg shadow-sm p-4 transition-all duration-200",
"bg-card text-card-foreground border-border",
"hover:bg-accent/5 hover:border-accent/30",
"flex gap-2",
horizontal ? "flex-row items-start gap-1" : "flex-col space-y-1",
className
)}
>
{Icon && <Icon className={clsx("w-5 h-5 text-primary shrink-0", horizontal && "mt-0.5")} />}
<div className="flex-1 min-w-0">
<div className="text-base font-semibold text-foreground leading-6">{title}</div>
<div className="text-sm text-muted-foreground -mt-3">{children}</div>
</div>
</div>
);
return href ? <Link className="no-underline block" href={href}>{content}</Link> : content;
};
export default Card;

View File

@@ -1,33 +0,0 @@
"use client";
import { CheckIcon, CopyIcon } from "lucide-react";
import { Button } from "../ui/button";
import { useState } from "react";
export default function Copy({ content }: { content: string }) {
const [isCopied, setIsCopied] = useState(false);
async function handleCopy() {
await navigator.clipboard.writeText(content);
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, 2000);
}
return (
<Button
variant="secondary"
className="border cursor-copy"
size="xs"
onClick={handleCopy}
>
{isCopied ? (
<CheckIcon className="w-3 h-3" />
) : (
<CopyIcon className="w-3 h-3" />
)}
</Button>
);
}

View File

@@ -1,138 +0,0 @@
'use client';
import React, { useState, ReactNode, Children, isValidElement, cloneElement } from 'react';
import { ChevronRight, File as FileIcon, Folder as FolderIcon, FolderOpen } from 'lucide-react';
interface FileProps {
name: string;
children?: ReactNode;
}
const FileComponent = ({ name }: FileProps) => {
const [isHovered, setIsHovered] = useState(false);
const fileExtension = name.split('.').pop()?.toUpperCase();
return (
<div
className={`
flex items-center gap-2 py-1.5 pl-7 pr-3 text-sm rounded-md
transition-colors duration-150 cursor-default select-none
${isHovered ? 'bg-accent/10' : 'hover:bg-muted/50'}
`}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
tabIndex={-1}
>
<FileIcon className={`
h-3.5 w-3.5 shrink-0 transition-colors
${isHovered ? 'text-accent' : 'text-muted-foreground'}
`} />
<span className="font-mono text-sm text-foreground truncate">{name}</span>
{isHovered && fileExtension && (
<span className="ml-auto text-xs text-muted-foreground/80">
{fileExtension}
</span>
)}
</div>
);
};
const FolderComponent = ({ name, children }: FileProps) => {
const [isOpen, setIsOpen] = useState(true); // Set to true by default
const [isHovered, setIsHovered] = useState(false);
const hasChildren = React.Children.count(children) > 0;
return (
<div className="relative">
<div
className={`
flex items-center gap-2 py-1.5 pl-4 pr-3 rounded-md
transition-colors duration-150 select-none
${isHovered ? 'bg-muted/60' : ''}
${isOpen ? 'text-foreground' : 'text-foreground/80'}
${hasChildren ? 'cursor-pointer' : 'cursor-default'}
`}
onClick={() => hasChildren && setIsOpen(!isOpen)}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
tabIndex={-1}
onKeyDown={(e) => e.preventDefault()}
>
{hasChildren ? (
<ChevronRight
className={`
h-3.5 w-3.5 shrink-0 transition-transform duration-200
${isOpen ? 'rotate-90' : ''}
${isHovered ? 'text-foreground/70' : 'text-muted-foreground'}
`}
/>
) : (
<div className="w-3.5" />
)}
{isOpen ? (
<FolderOpen className={`
h-4 w-4 shrink-0 transition-colors
${isHovered ? 'text-accent' : 'text-muted-foreground'}
`} />
) : (
<FolderIcon className={`
h-4 w-4 shrink-0 transition-colors
${isHovered ? 'text-accent/80' : 'text-muted-foreground/80'}
`} />
)}
<span className={`
font-medium transition-colors duration-150
${isHovered ? 'text-accent' : ''}
`}>
{name}
</span>
</div>
{isOpen && hasChildren && (
<div className="ml-5 border-l-2 border-muted/50 pl-2">
{children}
</div>
)}
</div>
);
};
export const Files = ({ children }: { children: ReactNode }) => {
return (
<div
className="
rounded-xl border border-muted/20
bg-card/20 backdrop-blur-sm
shadow-sm overflow-hidden
transition-all duration-200
hover:shadow-md hover:border-muted/60
"
onKeyDown={(e) => e.preventDefault()}
>
<div className="p-2">
{Children.map(children, (child, index) => {
if (isValidElement(child)) {
return cloneElement(child, { key: index });
}
return null;
})}
</div>
</div>
);
};
export const Folder = ({ name, children }: FileProps) => {
return <FolderComponent name={name}>{children}</FolderComponent>;
};
export const File = ({ name }: FileProps) => {
return <FileComponent name={name} />;
};
// MDX Components
export const FileTreeMdx = {
Files,
File,
Folder,
};
export default FileTreeMdx;

View File

@@ -1,129 +0,0 @@
"use client";
import { ComponentProps, useState, useEffect } from "react";
import NextImage from "next/image";
import { createPortal } from "react-dom";
import { motion, AnimatePresence } from "framer-motion";
import { X, ZoomIn } from "lucide-react";
type Height = ComponentProps<typeof NextImage>["height"];
type Width = ComponentProps<typeof NextImage>["width"];
type ImageProps = Omit<ComponentProps<"img">, "src"> & {
src?: ComponentProps<typeof NextImage>["src"];
};
export default function Image({
src,
alt = "alt",
width = 800,
height = 350,
...props
}: ImageProps) {
const [isOpen, setIsOpen] = useState(false);
// Lock scroll when open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
// Check for Escape key
const handleEsc = (e: KeyboardEvent) => {
if (e.key === "Escape") setIsOpen(false);
};
window.addEventListener("keydown", handleEsc);
return () => {
document.body.style.overflow = "auto";
window.removeEventListener("keydown", handleEsc);
};
}
}, [isOpen]);
if (!src) return null;
return (
<>
<button
type="button"
className="relative group cursor-zoom-in my-6 w-full flex justify-center rounded-lg"
onClick={() => setIsOpen(true)}
aria-label="Zoom image"
>
<span className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors z-10 flex items-center justify-center opacity-0 group-hover:opacity-100 rounded-lg">
<ZoomIn className="w-8 h-8 text-white drop-shadow-md" />
</span>
<NextImage
src={src}
alt={alt}
width={width as Width}
height={height as Height}
quality={85}
className="w-full h-auto rounded-lg transition-transform duration-300 group-hover:scale-[1.01]"
{...props}
/>
</button>
<AnimatePresence>
{isOpen && (
<Portal>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-99999 flex items-center justify-center bg-black/90 backdrop-blur-md p-4 md:p-10 cursor-zoom-out"
onClick={() => setIsOpen(false)}
>
{/* Close Button */}
<button
className="absolute top-4 right-4 z-50 p-2 text-white/70 hover:text-white bg-black/20 hover:bg-white/10 rounded-full transition-colors"
onClick={(e) => {
e.stopPropagation();
setIsOpen(false);
}}
>
<X className="w-6 h-6" />
</button>
{/* Image Container */}
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
className="relative max-w-7xl w-full h-full flex items-center justify-center"
onClick={(e) => e.stopPropagation()}
>
<div className="relative w-full h-full flex items-center justify-center" onClick={() => setIsOpen(false)}>
<NextImage
src={src}
alt={alt}
width={1920}
height={1080}
className="object-contain max-h-[90vh] w-auto h-auto rounded-md shadow-2xl"
quality={95}
/>
</div>
</motion.div>
{/* Caption */}
{alt && alt !== "alt" && (
<motion.div
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
className="absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/60 text-white px-4 py-2 rounded-full text-sm font-medium backdrop-blur-md border border-white/10"
>
{alt}
</motion.div>
)}
</motion.div>
</Portal>
)}
</AnimatePresence>
</>
);
}
const Portal = ({ children }: { children: React.ReactNode }) => {
if (typeof window === "undefined") return null;
return createPortal(children, document.body);
};

View File

@@ -1,102 +0,0 @@
import React from 'react';
// Map of special keys to their Mac symbols
const macKeyMap: Record<string, string> = {
command: '⌘',
cmd: '⌘',
option: '⌥',
alt: '⌥',
shift: '⇧',
ctrl: '⌃',
control: '⌃',
tab: '⇥',
caps: '⇪',
enter: '⏎',
return: '⏎',
delete: '⌫',
escape: '⎋',
esc: '⎋',
up: '↑',
down: '↓',
left: '←',
right: '→',
space: '␣',
};
// Map of special keys to their Windows display text
const windowsKeyMap: Record<string, string> = {
command: 'Win',
cmd: 'Win',
option: 'Alt',
alt: 'Alt',
ctrl: 'Ctrl',
control: 'Ctrl',
delete: 'Del',
escape: 'Esc',
esc: 'Esc',
enter: 'Enter',
return: 'Enter',
tab: 'Tab',
caps: 'Caps',
shift: 'Shift',
space: 'Space',
up: '↑',
down: '↓',
left: '←',
right: '→',
};
export interface KbdProps extends React.HTMLAttributes<HTMLElement> {
/** The key to display (e.g., 'cmd', 'ctrl', 'a') */
show?: string;
/** Platform style - 'window' or 'mac' */
type?: 'window' | 'mac';
/** Custom content to display (overrides automatic rendering) */
children?: React.ReactNode;
}
const KbdComponent: React.FC<KbdProps> = ({
show: keyProp,
type = 'window',
children,
...props
}) => {
// Get the display text based on the key and type
const getKeyDisplay = (): React.ReactNode => {
if (!keyProp || typeof keyProp !== 'string') return null;
const lowerKey = keyProp.toLowerCase();
// For Mac type, return the symbol if it exists
if (type === 'mac') {
return macKeyMap[lowerKey] || keyProp;
}
// For Windows, return the formatted key if it exists, otherwise capitalize the first letter
return windowsKeyMap[lowerKey] || (keyProp.charAt(0).toUpperCase() + keyProp.slice(1));
};
// Determine what to render
const renderContent = () => {
// If children are provided, always use them
if (children !== undefined && children !== null && children !== '') {
return children;
}
// Otherwise use the generated display
return getKeyDisplay() || keyProp || '';
};
return (
<kbd
className="inline-flex items-center justify-center px-2 py-1 mx-0.5 text-xs font-mono font-medium text-foreground bg-secondary/70 border rounded-md"
{...props}
>
{renderContent()}
</kbd>
);
};
// Export the component
export const Kbd = KbdComponent;
// Default export for backward compatibility
export default KbdComponent;

View File

@@ -1,14 +0,0 @@
import NextLink from "next/link";
import { ComponentProps } from "react";
export default function Link({ href, ...props }: ComponentProps<"a">) {
if (!href) return null;
return (
<NextLink
href={href}
{...props}
target="_blank"
rel="noopener noreferrer"
/>
);
}

View File

@@ -1,69 +0,0 @@
"use client";
import { cn } from "@/lib/utils";
import { cva, type VariantProps } from "class-variance-authority";
import {
Info,
AlertTriangle,
ShieldAlert,
CheckCircle2,
} from "lucide-react";
import React from "react";
const noteVariants = cva(
"relative w-full rounded-lg border border-l-4 p-4 mb-4 [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
{
variants: {
variant: {
note: "bg-muted/30 border-border border-l-primary/50 text-foreground [&>svg]:text-primary",
danger: "border-destructive/20 border-l-destructive/60 bg-destructive/5 text-destructive [&>svg]:text-destructive dark:border-destructive/30",
warning: "border-orange-500/20 border-l-orange-500/60 bg-orange-500/5 text-orange-600 dark:text-orange-400 [&>svg]:text-orange-600 dark:[&>svg]:text-orange-400",
success: "border-emerald-500/20 border-l-emerald-500/60 bg-emerald-500/5 text-emerald-600 dark:text-emerald-400 [&>svg]:text-emerald-600 dark:[&>svg]:text-emerald-400",
},
},
defaultVariants: {
variant: "note",
},
}
);
const iconMap = {
note: Info,
danger: ShieldAlert,
warning: AlertTriangle,
success: CheckCircle2,
};
interface NoteProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof noteVariants> {
title?: string;
type?: "note" | "danger" | "warning" | "success";
}
export default function Note({
className,
title = "Note",
type = "note",
children,
...props
}: NoteProps) {
const Icon = iconMap[type] || Info;
return (
<div
className={cn(noteVariants({ variant: type }), className)}
{...props}
>
<Icon className="h-5 w-5" />
<div className="pl-8">
<h5 className="mb-1 font-medium leading-none tracking-tight">
{title}
</h5>
<div className="text-sm [&_p]:leading-relaxed opacity-90">
{children}
</div>
</div>
</div>
);
}

View File

@@ -1,29 +0,0 @@
import { BaseMdxFrontmatter, getAllChilds } from "@/lib/markdown";
import Link from "next/link";
export default async function Outlet({ path }: { path: string }) {
if (!path) throw new Error("path not provided");
const output = await getAllChilds(path);
return (
<div className="grid md:grid-cols-2 gap-5">
{output.map((child) => (
<ChildCard {...child} key={child.title} />
))}
</div>
);
}
type ChildCardProps = BaseMdxFrontmatter & { href: string };
function ChildCard({ description, href, title }: ChildCardProps) {
return (
<Link
href={href}
className="border rounded-md p-4 no-underline flex flex-col gap-0.5"
>
<h4 className="!my-0">{title}</h4>
<p className="text-sm text-muted-foreground !my-0">{description}</p>
</Link>
);
}

View File

@@ -1,109 +0,0 @@
import { type ComponentProps, type JSX } from "react";
import Copy from "./CopyMdx";
import {
SiJavascript,
SiTypescript,
SiReact,
SiPython,
SiGo,
SiPhp,
SiRuby,
SiSwift,
SiKotlin,
SiHtml5,
SiCss,
SiSass,
SiPostgresql,
SiGraphql,
SiYaml,
SiToml,
SiDocker,
SiNginx,
SiGit,
SiGnubash,
SiMarkdown,
} from "react-icons/si";
import { FaJava, FaCode } from "react-icons/fa";
import { TbJson } from "react-icons/tb";
type PreProps = ComponentProps<"pre"> & {
raw?: string;
"data-title"?: string;
};
// Component to display an icon based on the programming language
const LanguageIcon = ({ lang }: { lang: string }) => {
const iconProps = { className: "w-4 h-4" };
const languageToIconMap: Record<string, JSX.Element> = {
gitignore: <SiGit {...iconProps} />,
docker: <SiDocker {...iconProps} />,
dockerfile: <SiDocker {...iconProps} />,
nginx: <SiNginx {...iconProps} />,
sql: <SiPostgresql {...iconProps} />,
graphql: <SiGraphql {...iconProps} />,
yaml: <SiYaml {...iconProps} />,
yml: <SiYaml {...iconProps} />,
toml: <SiToml {...iconProps} />,
json: <TbJson {...iconProps} />,
md: <SiMarkdown {...iconProps} />,
markdown: <SiMarkdown {...iconProps} />,
bash: <SiGnubash {...iconProps} />,
sh: <SiGnubash {...iconProps} />,
shell: <SiGnubash {...iconProps} />,
swift: <SiSwift {...iconProps} />,
kotlin: <SiKotlin {...iconProps} />,
kt: <SiKotlin {...iconProps} />,
kts: <SiKotlin {...iconProps} />,
rb: <SiRuby {...iconProps} />,
ruby: <SiRuby {...iconProps} />,
php: <SiPhp {...iconProps} />,
go: <SiGo {...iconProps} />,
py: <SiPython {...iconProps} />,
python: <SiPython {...iconProps} />,
java: <FaJava {...iconProps} />,
tsx: <SiReact {...iconProps} />,
typescript: <SiTypescript {...iconProps} />,
ts: <SiTypescript {...iconProps} />,
jsx: <SiReact {...iconProps} />,
js: <SiJavascript {...iconProps} />,
javascript: <SiJavascript {...iconProps} />,
html: <SiHtml5 {...iconProps} />,
css: <SiCss {...iconProps} />,
scss: <SiSass {...iconProps} />,
sass: <SiSass {...iconProps} />,
};
return languageToIconMap[lang] || <FaCode {...iconProps} />;
};
// Function to extract the language from className
function getLanguage(className: string = ""): string {
const match = className.match(/language-(\w+)/);
return match ? match[1] : "default";
}
export default function Pre({ children, raw, ...rest }: PreProps) {
const { "data-title": title, className, ...restProps } = rest;
const language = getLanguage(className);
const hasTitle = !!title;
return (
<div className="code-block-container">
<div className="code-block-actions">
{raw && <Copy content={raw} />}
</div>
{hasTitle && (
<div className="code-block-header">
<div className="flex items-center gap-2">
<LanguageIcon lang={language} />
<span>{title}</span>
</div>
</div>
)}
<div className="code-block-body">
<pre className={className} {...restProps}>
{children}
</pre>
</div>
</div>
);
}

View File

@@ -1,113 +0,0 @@
import React, { PropsWithChildren } from 'react';
import { cn } from '@/lib/utils';
import { PlusCircle, Wrench, Zap, AlertTriangle, XCircle } from 'lucide-react';
interface ReleaseProps extends PropsWithChildren {
version: string;
title: string;
date?: string;
}
function Release({ version, title, date, children }: ReleaseProps) {
return (
<div className="mb-16 group">
<div className="flex items-center gap-3 mt-6 mb-2">
<div
id={version}
className="inline-flex items-center rounded-full border border-primary/20 bg-primary/10 px-3 py-1 text-sm font-semibold text-primary transition-colors hover:bg-primary/15 scroll-m-20 backdrop-blur-sm"
>
v{version}
</div>
{date && (
<div className="flex items-center gap-3 text-sm font-medium text-muted-foreground">
<span className="h-1 w-1 rounded-full bg-muted-foreground/30"></span>
<time dateTime={date}>
{new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</time>
</div>
)}
</div>
<h3 className="text-2xl font-bold text-foreground/90 mb-6 mt-0!">
{title}
</h3>
<div className="space-y-8">
{children}
</div>
</div>
);
}
interface ChangesProps extends PropsWithChildren {
type: 'added' | 'fixed' | 'improved' | 'deprecated' | 'removed';
}
const typeConfig = {
added: {
label: 'Added',
className: 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300',
icon: PlusCircle,
},
fixed: {
label: 'Fixed',
className: 'bg-yellow-100 dark:bg-yellow-900/50 text-yellow-700 dark:text-yellow-300',
icon: Wrench,
},
improved: {
label: 'Improved',
className: 'bg-cyan-100 dark:bg-cyan-900/50 text-cyan-700 dark:text-cyan-300',
icon: Zap,
},
deprecated: {
label: 'Deprecated',
className: 'bg-orange-100 dark:bg-orange-900/50 text-orange-700 dark:text-orange-300',
icon: AlertTriangle,
},
removed: {
label: 'Removed',
className: 'bg-pink-100 dark:bg-pink-900/50 text-pink-700 dark:text-pink-300',
icon: XCircle,
},
} as const;
function Changes({ type, children }: ChangesProps) {
const config = typeConfig[type] || typeConfig.added;
return (
<div className="space-y-3 mb-8">
<div className="flex items-center gap-2">
<div className={cn("px-3 py-1 rounded-full text-sm font-medium flex items-center gap-1.5", config.className)}>
<config.icon className="h-3.5 w-3.5" />
<span>{config.label}</span>
</div>
</div>
<ul className="list-none pl-0 space-y-2 text-foreground/80">
{React.Children.map(children, (child, index) => {
// Jika teks dimulai dengan - atau *, hapus karakter tersebut
const processedChild = typeof child === 'string'
? child.trim().replace(/^[-*]\s+/, '')
: child;
return (
<li key={index} className="leading-relaxed">
{processedChild}
</li>
);
})}
</ul>
</div>
);
}
export { Release, Changes };
const ReleaseMdx = {
Release,
Changes
};
export default ReleaseMdx;

View File

@@ -1,41 +0,0 @@
import { cn } from "@/lib/utils";
import clsx from "clsx";
import { Children, PropsWithChildren } from "react";
export function Stepper({ children }: PropsWithChildren) {
const length = Children.count(children);
return (
<div className="flex flex-col">
{Children.map(children, (child, index) => {
return (
<div
className={cn(
"border-l border-muted pl-9 ml-3 relative",
clsx({
"pb-5 ": index < length - 1,
})
)}
>
<div className="bg-muted text-muted-foreground w-8 h-8 text-xs font-medium rounded-md border border-border/50 flex items-center justify-center absolute -left-4 font-code">
{index + 1}
</div>
{child}
</div>
);
})}
</div>
);
}
export function StepperItem({
children,
title,
}: PropsWithChildren & { title?: string }) {
return (
<div className="pt-0.5">
<h4 className="mt-0">{title}</h4>
<div>{children}</div>
</div>
);
}

View File

@@ -1,31 +0,0 @@
"use client";
import React, { useState } from "react";
interface TooltipProps {
text: string;
tip: string;
}
const Tooltip: React.FC<TooltipProps> = ({ text, tip }) => {
const [visible, setVisible] = useState(false);
return (
<span
className="relative inline-flex items-center cursor-help text-primary hover:text-primary/80 transition-colors"
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
>
<span className="border-b border-dashed border-primary/60 pb-0.5">
{text}
</span>
{visible && (
<span className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-64 bg-popover text-popover-foreground text-sm p-3 rounded-md shadow-lg border border-border/50 wrap-break-word text-left z-50">
{tip}
<span className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-popover rotate-45 border-b border-r border-border/50 -z-10" />
</span>
)}
</span>
);
};
export default Tooltip;

View File

@@ -1,22 +0,0 @@
import React from "react";
interface YoutubeProps {
videoId: string;
className?: string;
}
const Youtube: React.FC<YoutubeProps> = ({ videoId, className }) => {
return (
<div className={`youtube ${className || ""}`}>
<iframe
src={`https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1&showinfo=0&autohide=1&controls=1`}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</div>
);
};
export default Youtube;

View File

@@ -1,29 +0,0 @@
'use client';
import { MDXRemote } from 'next-mdx-remote/rsc';
import { Kbd } from './KeyboardMdx';
// Define components mapping
const components = {
// Keyboard components
Kbd: Kbd as React.ComponentType<React.HTMLAttributes<HTMLElement> & { type?: 'window' | 'mac' }>,
kbd: Kbd as React.ComponentType<React.HTMLAttributes<HTMLElement> & { type?: 'window' | 'mac' }>,
};
interface MDXProviderWrapperProps {
source: string;
}
export function MDXProviderWrapper({ source }: MDXProviderWrapperProps) {
return (
<div className="prose dark:prose-invert max-w-none">
<MDXRemote
source={source}
components={components}
options={{
parseFrontmatter: true,
}}
/>
</div>
);
}

View File

@@ -1,30 +1,82 @@
"use client" "use client";
import { ArrowUpRight, ChevronDown, ChevronUp } from "lucide-react" import { ArrowUpRight, ChevronDown, ChevronUp } from "lucide-react";
import Link from "next/link" import Link from "next/link";
import Image from "next/image" import Image from "next/image";
import Search from "@/components/SearchBox" import Search from "@/components/SearchBox";
import Anchor from "@/components/anchor" import Anchor from "@/components/anchor";
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator";
import docuConfig from "@/docu.json" import docuConfig from "@/docu.json";
import { Button } from "@/components/ui/button" import GitHubButton from "@/components/Github";
import { useState, useCallback } from "react" import { Button } from "@/components/ui/button";
import { motion, AnimatePresence } from "framer-motion" import { useState, useCallback, useRef, useEffect } from "react";
import { ModeToggle } from "@/components/ThemeToggle" import { ModeToggle } from "@/components/ThemeToggle";
interface NavbarProps { interface NavbarProps {
id?: string id?: string;
} }
export function Navbar({ id }: NavbarProps) { export function Navbar({ id }: NavbarProps) {
const [isMenuOpen, setIsMenuOpen] = useState(false) const [isMenuOpen, setIsMenuOpen] = useState(false);
const navRef = useRef<HTMLDivElement>(null);
const menuRef = useRef<HTMLDivElement>(null);
const toggleMenu = useCallback(() => { const toggleMenu = useCallback(() => {
setIsMenuOpen((prev) => !prev) setIsMenuOpen((prev) => !prev);
}, []) }, []);
// Close menu when the user clicks/taps anywhere outside the navbar, or presses Escape
useEffect(() => {
if (!isMenuOpen) return;
const handleClickOutside = (event: MouseEvent) => {
if (navRef.current && !navRef.current.contains(event.target as Node)) {
setIsMenuOpen(false);
}
};
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") setIsMenuOpen(false);
};
document.addEventListener("mousedown", handleClickOutside);
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
document.removeEventListener("keydown", handleKeyDown);
};
}, [isMenuOpen]);
// Focus trap: keep Tab within the mobile menu when open
useEffect(() => {
if (!isMenuOpen || !menuRef.current) return;
const menu = menuRef.current;
const focusableSelector =
'a[href], button, input, textarea, select, [tabindex]:not([tabindex="-1"])';
const handleTrap = (e: KeyboardEvent) => {
if (e.key !== "Tab") return;
const focusables = menu.querySelectorAll<HTMLElement>(focusableSelector);
if (focusables.length === 0) return;
const first = focusables[0];
const last = focusables[focusables.length - 1];
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
};
// Move focus into the menu
const focusables = menu.querySelectorAll<HTMLElement>(focusableSelector);
if (focusables.length > 0) focusables[0].focus();
menu.addEventListener("keydown", handleTrap);
return () => menu.removeEventListener("keydown", handleTrap);
}, [isMenuOpen]);
return ( return (
<div className="sticky top-0 z-50 w-full"> <div ref={navRef} className="sticky top-0 z-50 w-full">
<nav id={id} className="bg-background h-16 w-full border-b"> <nav id={id} className="bg-background h-16 w-full border-b">
<div className="mx-auto flex h-full w-[95vw] items-center justify-between sm:container md:gap-2"> <div className="mx-auto flex h-full w-[95vw] items-center justify-between sm:container md:gap-2">
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
@@ -42,6 +94,7 @@ export function Navbar({ id }: NavbarProps) {
onClick={toggleMenu} onClick={toggleMenu}
aria-label={isMenuOpen ? "Close navigation menu" : "Open navigation menu"} aria-label={isMenuOpen ? "Close navigation menu" : "Open navigation menu"}
aria-expanded={isMenuOpen} aria-expanded={isMenuOpen}
aria-controls="mobile-nav-menu"
className="flex items-center gap-1 px-2 text-sm font-medium md:hidden" className="flex items-center gap-1 px-2 text-sm font-medium md:hidden"
> >
{isMenuOpen ? ( {isMenuOpen ? (
@@ -50,38 +103,47 @@ export function Navbar({ id }: NavbarProps) {
<ChevronDown className="text-muted-foreground h-6 w-6" /> <ChevronDown className="text-muted-foreground h-6 w-6" />
)} )}
</Button> </Button>
<Separator className="my-4 hidden h-9 md:flex" orientation="vertical" /> <Separator className="my-4 hidden h-9 md:flex" orientation="vertical" />
<Search /> <Search />
<div className="hidden md:flex">
<GitHubButton />
</div>
</div> </div>
</div> </div>
</nav> </nav>
<AnimatePresence> <div
{isMenuOpen && ( id="mobile-nav-menu"
<motion.div ref={menuRef}
initial={{ opacity: 0, height: 0 }} role="dialog"
animate={{ opacity: 1, height: "auto" }} aria-modal={isMenuOpen ? true : undefined}
exit={{ opacity: 0, height: 0 }} aria-label="Navigation menu"
transition={{ duration: 0.2, ease: "easeInOut" }} className="bg-background/95 grid w-full border-b shadow-sm backdrop-blur-sm transition-[grid-template-rows,opacity] duration-200 ease-in-out md:hidden"
className="bg-background/95 w-full border-b shadow-sm backdrop-blur-sm md:hidden" style={{
gridTemplateRows: isMenuOpen ? "1fr" : "0fr",
opacity: isMenuOpen ? 1 : 0,
borderBottomWidth: isMenuOpen ? undefined : 0,
}}
> >
<div className="overflow-hidden">
<div className="mx-auto w-[95vw] sm:container"> <div className="mx-auto w-[95vw] sm:container">
<ul className="flex flex-col py-2"> <ul className="flex flex-col py-2">
<NavMenuCollapsible onItemClick={() => setIsMenuOpen(false)} /> <NavMenuCollapsible onItemClick={() => setIsMenuOpen(false)} />
</ul> </ul>
<div className="flex items-center justify-between border-t px-1 py-3"> <div className="flex items-center justify-between border-t px-1 py-3">
<GitHubButton />
<ModeToggle /> <ModeToggle />
</div> </div>
</div> </div>
</motion.div>
)}
</AnimatePresence>
</div> </div>
) </div>
</div>
);
} }
export function Logo() { export function Logo() {
const { navbar } = docuConfig const { navbar } = docuConfig;
return ( return (
<Link href="/" className="flex items-center gap-1.5"> <Link href="/" className="flex items-center gap-1.5">
@@ -98,17 +160,17 @@ export function Logo() {
{navbar.logoText} {navbar.logoText}
</h2> </h2>
</Link> </Link>
) );
} }
// Desktop NavMenu — horizontal list // Desktop NavMenu — horizontal list
export function NavMenu() { export function NavMenu() {
const { navbar } = docuConfig const { navbar } = docuConfig;
return ( return (
<> <>
{navbar?.menu?.map((item) => { {navbar?.menu?.map((item) => {
const isExternal = item.href.startsWith("http") const isExternal = item.href.startsWith("http");
return ( return (
<Anchor <Anchor
key={`${item.title}-${item.href}`} key={`${item.title}-${item.href}`}
@@ -122,20 +184,20 @@ export function NavMenu() {
{item.title} {item.title}
{isExternal && <ArrowUpRight className="text-foreground/80 h-4 w-4" />} {isExternal && <ArrowUpRight className="text-foreground/80 h-4 w-4" />}
</Anchor> </Anchor>
) );
})} })}
</> </>
) );
} }
// Mobile Collapsible NavMenu — vertical list items // Mobile Collapsible NavMenu — vertical list items
function NavMenuCollapsible({ onItemClick }: { onItemClick: () => void }) { function NavMenuCollapsible({ onItemClick }: { onItemClick: () => void }) {
const { navbar } = docuConfig const { navbar } = docuConfig;
return ( return (
<> <>
{navbar?.menu?.map((item) => { {navbar?.menu?.map((item) => {
const isExternal = item.href.startsWith("http") const isExternal = item.href.startsWith("http");
return ( return (
<li key={item.title + item.href}> <li key={item.title + item.href}>
<Anchor <Anchor
@@ -151,8 +213,8 @@ function NavMenuCollapsible({ onItemClick }: { onItemClick: () => void }) {
{isExternal && <ArrowUpRight className="text-foreground/60 h-4 w-4 shrink-0" />} {isExternal && <ArrowUpRight className="text-foreground/60 h-4 w-4 shrink-0" />}
</Anchor> </Anchor>
</li> </li>
) );
})} })}
</> </>
) );
} }

View File

@@ -1,14 +1,10 @@
import { EachRoute } from "@/lib/routes"; import { EachRoute } from "@/lib/routes";
import Anchor from "./anchor"; import Anchor from "./anchor";
import { import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { SheetClose } from "@/components/ui/sheet"; import { SheetClose } from "@/components/ui/sheet";
import { ChevronDown, ChevronRight } from "lucide-react"; import { ChevronDown, ChevronRight } from "lucide-react";
import { useEffect, useState, useMemo } from "react"; import { useState, useMemo } from "react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
interface SubLinkProps extends EachRoute { interface SubLinkProps extends EachRoute {
@@ -27,42 +23,44 @@ export default function SubLink({
parentHref = "", parentHref = "",
}: SubLinkProps) { }: SubLinkProps) {
const path = usePathname(); const path = usePathname();
const [isOpen, setIsOpen] = useState(level === 0);
// Full path including parent's href // Full path including parent's href
const fullHref = `${parentHref}${href}`; const fullHref = parentHref ? `${parentHref}${href}` : `/docs${href}`;
const shouldBeOpen = level === 0 || (!!items && path.startsWith(fullHref) && path !== fullHref);
const [isOpen, setIsOpen] = useState(shouldBeOpen);
// Check if any child is active (for parent items) // Check if any child is active (for parent items)
const hasActiveChild = useMemo(() => { const hasActiveChild = useMemo(() => {
if (!items) return false; if (!items) return false;
return items.some(item => { return items.some((item) => {
const childHref = `${fullHref}${item.href}`; const childHref = `${fullHref}${item.href}`;
return path.startsWith(childHref) && path !== fullHref; return path.startsWith(childHref) && path !== fullHref;
}); });
}, [items, path, fullHref]); }, [items, path, fullHref]);
// Auto-expand if current path is a child of this item // Sync open state when path changes (expand if child becomes active)
useEffect(() => { if (shouldBeOpen && !isOpen) {
if (items && (path.startsWith(fullHref) && path !== fullHref)) {
// eslint-disable-next-line react-hooks/set-state-in-effect
setIsOpen(true); setIsOpen(true);
} }
}, [path, fullHref, items]);
// Only apply active styles if it's an exact match and not a parent with active children // Only apply active styles if it's an exact match and not a parent with active children
const Comp = useMemo(() => ( const Comp = useMemo(
() => (
<Anchor <Anchor
activeClassName={!hasActiveChild ? "dark:text-accent text-primary font-medium" : ""} activeClassName={!hasActiveChild ? "dark:text-accent text-primary font-medium" : ""}
href={fullHref} href={fullHref}
data-search-lvl0={level === 0 && hasActiveChild ? "true" : undefined} data-search-lvl0={level === 0 && hasActiveChild ? "true" : undefined}
className={cn( className={cn(
"text-foreground/80 hover:text-foreground transition-colors", "text-foreground/80 hover:text-foreground transition-colors",
hasActiveChild && "font-medium text-foreground" hasActiveChild && "text-foreground font-medium"
)} )}
> >
{title} {title}
</Anchor> </Anchor>
), [title, fullHref, hasActiveChild, level]); ),
[title, fullHref, hasActiveChild, level]
);
const titleOrLink = !noLink ? ( const titleOrLink = !noLink ? (
isSheet ? ( isSheet ? (
@@ -74,7 +72,7 @@ export default function SubLink({
<h4 <h4
data-search-lvl0={level === 0 && hasActiveChild ? "true" : undefined} data-search-lvl0={level === 0 && hasActiveChild ? "true" : undefined}
className={cn( className={cn(
"font-medium sm:text-sm text-foreground/90 hover:text-foreground transition-colors", "text-foreground/90 hover:text-foreground font-medium transition-colors sm:text-sm",
hasActiveChild ? "text-foreground" : "text-foreground/80" hasActiveChild ? "text-foreground" : "text-foreground/80"
)} )}
> >
@@ -87,26 +85,25 @@ export default function SubLink({
} }
return ( return (
<div className={cn("flex flex-col gap-1 w-full")}> <div className={cn("flex w-full flex-col gap-1")}>
<Collapsible open={isOpen} onOpenChange={setIsOpen}> <Collapsible open={isOpen} onOpenChange={setIsOpen}>
<CollapsibleTrigger <div className="flex w-full items-center justify-between">
className="w-full pr-5 text-left cursor-pointer"
aria-expanded={isOpen}
aria-controls={`collapsible-${fullHref.replace(/[^a-zA-Z0-9]/g, '-')}`}
>
<div className="flex items-center justify-between w-full">
{titleOrLink} {titleOrLink}
<span className="ml-2 text-muted-foreground"> <CollapsibleTrigger
className="text-muted-foreground ml-2 cursor-pointer"
aria-expanded={isOpen}
aria-label={`Toggle ${title} section`}
aria-controls={`collapsible-${fullHref.replace(/[^a-zA-Z0-9]/g, "-")}`}
>
{!isOpen ? ( {!isOpen ? (
<ChevronRight className="h-[0.9rem] w-[0.9rem]" aria-hidden="true" /> <ChevronRight className="h-[0.9rem] w-[0.9rem]" aria-hidden="true" />
) : ( ) : (
<ChevronDown className="h-[0.9rem] w-[0.9rem]" aria-hidden="true" /> <ChevronDown className="h-[0.9rem] w-[0.9rem]" aria-hidden="true" />
)} )}
</span>
</div>
</CollapsibleTrigger> </CollapsibleTrigger>
</div>
<CollapsibleContent <CollapsibleContent
id={`collapsible-${fullHref.replace(/[^a-zA-Z0-9]/g, '-')}`} id={`collapsible-${fullHref.replace(/[^a-zA-Z0-9]/g, "-")}`}
className={cn( className={cn(
"overflow-hidden transition-all duration-200 ease-in-out", "overflow-hidden transition-all duration-200 ease-in-out",
isOpen ? "animate-collapsible-down" : "animate-collapsible-up" isOpen ? "animate-collapsible-down" : "animate-collapsible-up"
@@ -114,8 +111,8 @@ export default function SubLink({
> >
<div <div
className={cn( className={cn(
"flex flex-col items-start sm:text-sm text-foreground/80 ml-0.5 mt-2.5 gap-3 hover:[&_a]:text-foreground transition-colors", "text-foreground/80 hover:[&_a]:text-foreground mt-2.5 ml-0.5 flex flex-col items-start gap-3 transition-colors sm:text-sm",
level > 0 && "pl-4 border-l border-border ml-1.5" level > 0 && "border-border ml-1.5 border-l pl-4"
)} )}
> >
{items?.map((innerLink) => ( {items?.map((innerLink) => (

View File

@@ -6,24 +6,46 @@ import { ListIcon } from "lucide-react"
import Sponsor from "./Sponsor" import Sponsor from "./Sponsor"
import { useActiveSection } from "@/hooks" import { useActiveSection } from "@/hooks"
import { TocItem } from "@/lib/toc" import { TocItem } from "@/lib/toc"
import { cn } from "@/lib/utils"
export default function Toc({ tocs }: { tocs: TocItem[] }) { export default function Toc({ tocs }: { tocs: TocItem[] }) {
const { activeId, setActiveId } = useActiveSection(tocs) const { activeId, setActiveId } = useActiveSection(tocs)
const hasTocs = Boolean(tocs?.length)
const wrapperClassName = cn(
hasTocs ? "toc" : "",
"flex-3 sticky top-4 hidden h-[calc(100vh-8rem)] min-w-[240px] self-start lg:flex lg:p-8"
)
return ( return (
<div className="toc flex-3 sticky top-4 hidden h-[calc(100vh-8rem)] min-w-[238px] self-start lg:flex lg:p-8"> <div className={wrapperClassName}>
<div className="mb-auto flex h-full w-full flex-col gap-2 px-2"> <div className="flex h-full w-full flex-col gap-2 px-2">
{hasTocs && (
<>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<ListIcon className="h-4 w-4" /> <ListIcon className="h-4 w-4" />
<h3 className="text-sm font-medium">On this page</h3> <h3 className="text-sm font-medium">On this page</h3>
</div> </div>
<div className="max-h-[calc(70vh-2rem)] min-h-0 shrink-0"> <div className="flex-1 min-h-0">
<ScrollArea className="h-full"> <ScrollArea className="h-full">
<TocObserver data={tocs} activeId={activeId} onActiveIdChange={setActiveId} /> <TocObserver data={tocs} activeId={activeId} onActiveIdChange={setActiveId} />
<div className="mt-4">
<Sponsor />
</div>
</ScrollArea> </ScrollArea>
</div> </div>
</>
)}
{!hasTocs && (
<div className="flex-1 min-h-0">
<ScrollArea className="h-full">
<div className="mt-4">
<Sponsor /> <Sponsor />
</div> </div>
</ScrollArea>
</div>
)}
</div>
</div> </div>
) )
} }

View File

@@ -1,58 +0,0 @@
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }

View File

@@ -24,12 +24,12 @@ const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({
"mx-auto max-w-md text-neutral-600/70 dark:text-neutral-400/70", "mx-auto max-w-md text-neutral-600/70 dark:text-neutral-400/70",
// Shine effect // Shine effect
"animate-shiny-text bg-clip-text bg-no-repeat [background-position:0_0] [background-size:var(--shiny-width)_100%] [transition:background-position_1s_cubic-bezier(.6,.6,0,1)_infinite]", "animate-shiny-text [background-size:var(--shiny-width)_100%] bg-clip-text [background-position:0_0] bg-no-repeat",
// Shine gradient // Shine gradient (aurora colors)
"bg-gradient-to-r from-transparent via-black/80 via-50% to-transparent dark:via-white/80", "bg-gradient-to-r from-[#FF0080] via-[#0070F3] via-[#7928CA] to-[#38bdf8] dark:from-[#FF0080] dark:via-[#0070F3] dark:via-[#7928CA] dark:to-[#38bdf8]",
className, className
)} )}
> >
{children} {children}

View File

@@ -1,45 +0,0 @@
"use client";
import React, { memo } from "react";
interface AuroraTextProps {
children: React.ReactNode;
className?: string;
colors?: string[];
speed?: number;
}
export const AuroraText = memo(
({
children,
className = "",
colors = ["#FF0080", "#7928CA", "#0070F3", "#38bdf8"],
speed = 1,
}: AuroraTextProps) => {
const gradientStyle = {
backgroundImage: `linear-gradient(135deg, ${colors.join(", ")}, ${
colors[0]
})`,
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
animationDuration: `${10 / speed}s`,
};
return (
<span className={`relative inline-block ${className}`}>
<span className="sr-only">{children}</span>
<span
className="relative animate-aurora bg-[length:200%_auto] bg-clip-text text-transparent"
style={gradientStyle}
aria-hidden="true"
>
{children}
</span>
</span>
);
},
);
AuroraText.displayName = "AuroraText";
export default AuroraText;

View File

@@ -1,50 +0,0 @@
"use client"
import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"
import { cn } from "@/lib/utils"
const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName
const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName
const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
)}
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
export { Avatar, AvatarImage, AvatarFallback }

View File

@@ -1,37 +0,0 @@
"use client";
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-full 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 hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };

View File

@@ -1,82 +1,68 @@
import * as React from "react" import * as React from "react";
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot";
import { ChevronRight, MoreHorizontal } from "lucide-react" import { ChevronRight, MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
const Breadcrumb = React.forwardRef< const Breadcrumb = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<"nav">>(
HTMLElement, ({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />
React.ComponentPropsWithoutRef<"nav"> & { );
separator?: React.ReactNode Breadcrumb.displayName = "Breadcrumb";
}
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
Breadcrumb.displayName = "Breadcrumb"
const BreadcrumbList = React.forwardRef< const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>(
HTMLOListElement, ({ className, ...props }, ref) => (
React.ComponentPropsWithoutRef<"ol">
>(({ className, ...props }, ref) => (
<ol <ol
ref={ref} ref={ref}
className={cn( className={cn(
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", "text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5",
className className
)} )}
{...props} {...props}
/> />
)) )
BreadcrumbList.displayName = "BreadcrumbList" );
BreadcrumbList.displayName = "BreadcrumbList";
const BreadcrumbItem = React.forwardRef< const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>(
HTMLLIElement, ({ className, ...props }, ref) => (
React.ComponentPropsWithoutRef<"li"> <li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} />
>(({ className, ...props }, ref) => ( )
<li );
ref={ref} BreadcrumbItem.displayName = "BreadcrumbItem";
className={cn("inline-flex items-center gap-1.5", className)}
{...props}
/>
))
BreadcrumbItem.displayName = "BreadcrumbItem"
const BreadcrumbLink = React.forwardRef< const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement, HTMLAnchorElement,
React.ComponentPropsWithoutRef<"a"> & { React.ComponentPropsWithoutRef<"a"> & {
asChild?: boolean asChild?: boolean;
} }
>(({ asChild, className, ...props }, ref) => { >(({ asChild, className, ...props }, ref) => {
const Comp = asChild ? Slot : "a" const Comp = asChild ? Slot : "a";
return ( return (
<Comp <Comp
ref={ref} ref={ref}
className={cn("transition-colors hover:text-foreground", className)} className={cn("hover:text-foreground transition-colors", className)}
{...props} {...props}
/> />
) );
}) });
BreadcrumbLink.displayName = "BreadcrumbLink" BreadcrumbLink.displayName = "BreadcrumbLink";
const BreadcrumbPage = React.forwardRef< const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>(
HTMLSpanElement, ({ className, ...props }, ref) => (
React.ComponentPropsWithoutRef<"span">
>(({ className, ...props }, ref) => (
<span <span
ref={ref} ref={ref}
role="link" role="link"
aria-disabled="true" aria-disabled="true"
aria-current="page" aria-current="page"
className={cn("font-normal text-foreground", className)} className={cn("text-foreground font-normal", className)}
{...props} {...props}
/> />
)) )
BreadcrumbPage.displayName = "BreadcrumbPage" );
BreadcrumbPage.displayName = "BreadcrumbPage";
const BreadcrumbSeparator = ({ const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => (
children,
className,
...props
}: React.ComponentProps<"li">) => (
<li <li
role="presentation" role="presentation"
aria-hidden="true" aria-hidden="true"
@@ -85,13 +71,10 @@ const BreadcrumbSeparator = ({
> >
{children ?? <ChevronRight />} {children ?? <ChevronRight />}
</li> </li>
) );
BreadcrumbSeparator.displayName = "BreadcrumbSeparator" BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
const BreadcrumbEllipsis = ({ const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (
className,
...props
}: React.ComponentProps<"span">) => (
<span <span
role="presentation" role="presentation"
aria-hidden="true" aria-hidden="true"
@@ -101,8 +84,8 @@ const BreadcrumbEllipsis = ({
<MoreHorizontal className="h-4 w-4" /> <MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span> <span className="sr-only">More</span>
</span> </span>
) );
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
export { export {
Breadcrumb, Breadcrumb,
@@ -112,4 +95,4 @@ export {
BreadcrumbPage, BreadcrumbPage,
BreadcrumbSeparator, BreadcrumbSeparator,
BreadcrumbEllipsis, BreadcrumbEllipsis,
} };

View File

@@ -1,153 +0,0 @@
"use client"
import * as React from "react"
import { type DialogProps } from "@radix-ui/react-dialog"
import { Command as CommandPrimitive } from "cmdk"
import { Search } from "lucide-react"
import { cn } from "@/lib/utils"
import { Dialog, DialogContent } from "@/components/ui/dialog"
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
)}
{...props}
/>
))
Command.displayName = CommandPrimitive.displayName
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children}
</Command>
</DialogContent>
</Dialog>
)
}
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
</div>
))
CommandInput.displayName = CommandPrimitive.Input.displayName
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...props}
/>
))
CommandList.displayName = CommandPrimitive.List.displayName
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
<CommandPrimitive.Empty
ref={ref}
className="py-6 text-center text-sm"
{...props}
/>
))
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className
)}
{...props}
/>
))
CommandGroup.displayName = CommandPrimitive.Group.displayName
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
{...props}
/>
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className
)}
{...props}
/>
))
CommandItem.displayName = CommandPrimitive.Item.displayName
const CommandShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
)}
{...props}
/>
)
}
CommandShortcut.displayName = "CommandShortcut"
export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
}

View File

@@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay <DialogPrimitive.Overlay
ref={ref} ref={ref}
className={cn( className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
className className
)} )}
{...props} {...props}
@@ -38,46 +38,29 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content <DialogPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<DialogPrimitive.Close className="absolute right-3 top-3.5 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-3.5 right-3 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none">
<div className="hidden md:flex rounded-sm text-xs border py-1 px-2 hover:bg-muted"> <div className="hover:bg-muted hidden rounded-sm border px-2 py-1 text-xs md:flex">Esc</div>
Esc <X className="hidden h-5 w-5 max-md:flex" />
</div>
<X className="h-5 w-5 hidden max-md:flex" />
</DialogPrimitive.Close> </DialogPrimitive.Close>
</DialogPrimitive.Content> </DialogPrimitive.Content>
</DialogPortal> </DialogPortal>
)); ));
DialogContent.displayName = DialogPrimitive.Content.displayName; DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({ const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
className, <div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} />
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
className
)}
{...props}
/>
); );
DialogHeader.displayName = "DialogHeader"; DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({ const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props} {...props}
/> />
); );
@@ -89,10 +72,7 @@ const DialogTitle = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Title <DialogPrimitive.Title
ref={ref} ref={ref}
className={cn( className={cn("text-lg leading-none font-semibold tracking-tight", className)}
"text-lg font-semibold leading-none tracking-tight",
className
)}
{...props} {...props}
/> />
)); ));
@@ -104,7 +84,7 @@ const DialogDescription = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Description <DialogPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-muted-foreground text-sm", className)}
{...props} {...props}
/> />
)); ));

View File

@@ -1,353 +0,0 @@
"use client";
import React, { useEffect, useRef, useState, useMemo } from "react";
import { renderToString } from "react-dom/server";
interface Icon {
x: number;
y: number;
z: number;
scale: number;
opacity: number;
id: number;
}
interface IconCloudProps {
icons?: React.ReactNode[];
images?: string[];
}
function easeOutCubic(t: number): number {
return 1 - Math.pow(1 - t, 3);
}
export function IconCloud({ icons, images }: IconCloudProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
// const [iconPositions, setIconPositions] = useState<Icon[]>([]);
const iconPositions = useMemo<Icon[]>(() => {
const items = icons || images || [];
const newIcons: Icon[] = [];
const numIcons = items.length || 20;
// Fibonacci sphere parameters
const offset = 2 / numIcons;
const increment = Math.PI * (3 - Math.sqrt(5));
for (let i = 0; i < numIcons; i++) {
const y = i * offset - 1 + offset / 2;
const r = Math.sqrt(1 - y * y);
const phi = i * increment;
const x = Math.cos(phi) * r;
const z = Math.sin(phi) * r;
newIcons.push({
x: x * 100,
y: y * 100,
z: z * 100,
scale: 1,
opacity: 1,
id: i,
});
}
return newIcons;
}, [icons, images]);
const [rotation] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 });
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
const [targetRotation, setTargetRotation] = useState<{
x: number;
y: number;
startX: number;
startY: number;
distance: number;
startTime: number;
duration: number;
} | null>(null);
const animationFrameRef = useRef<number>(undefined);
const rotationRef = useRef(rotation);
const iconCanvasesRef = useRef<HTMLCanvasElement[]>([]);
const imagesLoadedRef = useRef<boolean[]>([]);
// Create icon canvases once when icons/images change
useEffect(() => {
if (!icons && !images) return;
const items = icons || images || [];
imagesLoadedRef.current = new Array(items.length).fill(false);
const newIconCanvases = items.map((item, index) => {
const offscreen = document.createElement("canvas");
offscreen.width = 40;
offscreen.height = 40;
const offCtx = offscreen.getContext("2d");
if (offCtx) {
if (images) {
// Handle image URLs directly
const img = new Image();
img.crossOrigin = "anonymous";
img.src = items[index] as string;
img.onload = () => {
offCtx.clearRect(0, 0, offscreen.width, offscreen.height);
// Create circular clipping path
offCtx.beginPath();
offCtx.arc(20, 20, 20, 0, Math.PI * 2);
offCtx.closePath();
offCtx.clip();
// Draw the image
offCtx.drawImage(img, 0, 0, 40, 40);
imagesLoadedRef.current[index] = true;
};
} else {
// Handle SVG icons
offCtx.scale(0.4, 0.4);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const svgString = renderToString(item as React.ReactElement<any>);
const img = new Image();
img.src = "data:image/svg+xml;base64," + btoa(svgString);
img.onload = () => {
offCtx.clearRect(0, 0, offscreen.width, offscreen.height);
offCtx.drawImage(img, 0, 0);
imagesLoadedRef.current[index] = true;
};
}
}
return offscreen;
});
iconCanvasesRef.current = newIconCanvases;
}, [icons, images]);
// Generate initial icon positions on a sphere
// useEffect(() => {
// const items = icons || images || [];
// const newIcons: Icon[] = [];
// const numIcons = items.length || 20;
// // Fibonacci sphere parameters
// const offset = 2 / numIcons;
// const increment = Math.PI * (3 - Math.sqrt(5));
// for (let i = 0; i < numIcons; i++) {
// const y = i * offset - 1 + offset / 2;
// const r = Math.sqrt(1 - y * y);
// const phi = i * increment;
// const x = Math.cos(phi) * r;
// const z = Math.sin(phi) * r;
// newIcons.push({
// x: x * 100,
// y: y * 100,
// z: z * 100,
// scale: 1,
// opacity: 1,
// id: i,
// });
// }
// setIconPositions(newIcons);
// }, [icons, images]);
// Handle mouse events
const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
const rect = canvasRef.current?.getBoundingClientRect();
if (!rect || !canvasRef.current) return;
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ctx = canvasRef.current.getContext("2d");
if (!ctx) return;
iconPositions.forEach((icon) => {
const cosX = Math.cos(rotationRef.current.x);
const sinX = Math.sin(rotationRef.current.x);
const cosY = Math.cos(rotationRef.current.y);
const sinY = Math.sin(rotationRef.current.y);
const rotatedX = icon.x * cosY - icon.z * sinY;
const rotatedZ = icon.x * sinY + icon.z * cosY;
const rotatedY = icon.y * cosX + rotatedZ * sinX;
const screenX = canvasRef.current!.width / 2 + rotatedX;
const screenY = canvasRef.current!.height / 2 + rotatedY;
const scale = (rotatedZ + 200) / 300;
const radius = 20 * scale;
const dx = x - screenX;
const dy = y - screenY;
if (dx * dx + dy * dy < radius * radius) {
const targetX = -Math.atan2(
icon.y,
Math.sqrt(icon.x * icon.x + icon.z * icon.z),
);
const targetY = Math.atan2(icon.x, icon.z);
const currentX = rotationRef.current.x;
const currentY = rotationRef.current.y;
const distance = Math.sqrt(
Math.pow(targetX - currentX, 2) + Math.pow(targetY - currentY, 2),
);
const duration = Math.min(2000, Math.max(800, distance * 1000));
setTargetRotation({
x: targetX,
y: targetY,
startX: currentX,
startY: currentY,
distance,
startTime: performance.now(),
duration,
});
return;
}
});
setIsDragging(true);
setLastMousePos({ x: e.clientX, y: e.clientY });
};
const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
const rect = canvasRef.current?.getBoundingClientRect();
if (rect) {
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
setMousePos({ x, y });
}
if (isDragging) {
const deltaX = e.clientX - lastMousePos.x;
const deltaY = e.clientY - lastMousePos.y;
rotationRef.current = {
x: rotationRef.current.x + deltaY * 0.002,
y: rotationRef.current.y + deltaX * 0.002,
};
setLastMousePos({ x: e.clientX, y: e.clientY });
}
};
const handleMouseUp = () => {
setIsDragging(false);
};
// Animation and rendering
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
if (!canvas || !ctx) return;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const maxDistance = Math.sqrt(centerX * centerX + centerY * centerY);
const dx = mousePos.x - centerX;
const dy = mousePos.y - centerY;
const distance = Math.sqrt(dx * dx + dy * dy);
const speed = 0.003 + (distance / maxDistance) * 0.01;
if (targetRotation) {
const elapsed = performance.now() - targetRotation.startTime;
const progress = Math.min(1, elapsed / targetRotation.duration);
const easedProgress = easeOutCubic(progress);
rotationRef.current = {
x:
targetRotation.startX +
(targetRotation.x - targetRotation.startX) * easedProgress,
y:
targetRotation.startY +
(targetRotation.y - targetRotation.startY) * easedProgress,
};
if (progress >= 1) {
setTargetRotation(null);
}
} else if (!isDragging) {
rotationRef.current = {
x: rotationRef.current.x + (dy / canvas.height) * speed,
y: rotationRef.current.y + (dx / canvas.width) * speed,
};
}
iconPositions.forEach((icon, index) => {
const cosX = Math.cos(rotationRef.current.x);
const sinX = Math.sin(rotationRef.current.x);
const cosY = Math.cos(rotationRef.current.y);
const sinY = Math.sin(rotationRef.current.y);
const rotatedX = icon.x * cosY - icon.z * sinY;
const rotatedZ = icon.x * sinY + icon.z * cosY;
const rotatedY = icon.y * cosX + rotatedZ * sinX;
const scale = (rotatedZ + 200) / 300;
const opacity = Math.max(0.2, Math.min(1, (rotatedZ + 150) / 200));
ctx.save();
ctx.translate(
canvas.width / 2 + rotatedX,
canvas.height / 2 + rotatedY,
);
ctx.scale(scale, scale);
ctx.globalAlpha = opacity;
if (icons || images) {
// Only try to render icons/images if they exist
if (
iconCanvasesRef.current[index] &&
imagesLoadedRef.current[index]
) {
ctx.drawImage(iconCanvasesRef.current[index], -20, -20, 40, 40);
}
} else {
// Show numbered circles if no icons/images are provided
ctx.beginPath();
ctx.arc(0, 0, 20, 0, Math.PI * 2);
ctx.fillStyle = "#4444ff";
ctx.fill();
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "16px Arial";
ctx.fillText(`${icon.id + 1}`, 0, 0);
}
ctx.restore();
});
animationFrameRef.current = requestAnimationFrame(animate);
};
animate();
return () => {
if (animationFrameRef.current) {
cancelAnimationFrame(animationFrameRef.current);
}
};
}, [icons, images, iconPositions, isDragging, mousePos, targetRotation]);
return (
<canvas
ref={canvasRef}
width={400}
height={400}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
className="rounded-full"
aria-label="Interactive 3D Icon Cloud"
role="img"
/>
);
}

View File

@@ -1,34 +0,0 @@
import React from "react";
import { ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils";
type InteractiveHoverButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
export const InteractiveHoverButton = React.forwardRef<
HTMLButtonElement,
InteractiveHoverButtonProps
>(({ children, className, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(
"group relative w-auto cursor-pointer overflow-hidden rounded-full border bg-background p-2 px-6 text-center font-semibold",
className,
)}
{...props}
>
<div className="flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-primary transition-all duration-300 group-hover:scale-[100.8]"></div>
<span className="inline-block transition-all duration-300 group-hover:translate-x-12 group-hover:opacity-0">
{children}
</span>
</div>
<div className="absolute top-0 z-10 flex h-full w-full translate-x-12 items-center justify-center gap-2 text-primary-foreground opacity-0 transition-all duration-300 group-hover:-translate-x-5 group-hover:opacity-100">
<span>{children}</span>
<ArrowRight className="w-4 h-4" />
</div>
</button>
);
});
InteractiveHoverButton.displayName = "InteractiveHoverButton";

View File

@@ -21,7 +21,7 @@ const SheetOverlay = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay <SheetPrimitive.Overlay
className={cn( className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
className className
)} )}
{...props} {...props}
@@ -50,8 +50,9 @@ const sheetVariants = cva(
); );
interface SheetContentProps interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, extends
VariantProps<typeof sheetVariants> { } React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {}
const SheetContent = React.forwardRef< const SheetContent = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Content>, React.ElementRef<typeof SheetPrimitive.Content>,
@@ -59,14 +60,10 @@ const SheetContent = React.forwardRef<
>(({ side = "right", className, children, ...props }, ref) => ( >(({ side = "right", className, children, ...props }, ref) => (
<SheetPortal> <SheetPortal>
<SheetOverlay /> <SheetOverlay />
<SheetPrimitive.Content <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
ref={ref}
className={cn(sheetVariants({ side }), className)}
{...props}
>
{children} {children}
<SheetPrimitive.Close className="absolute top-7 right-4 z-50 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-7 right-4 z-50 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none">
<PanelRightClose className="w-6 h-6 shrink-0 text-muted-foreground" /> <PanelRightClose className="text-muted-foreground h-6 w-6 shrink-0" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</SheetPrimitive.Close> </SheetPrimitive.Close>
</SheetPrimitive.Content> </SheetPrimitive.Content>
@@ -74,29 +71,14 @@ const SheetContent = React.forwardRef<
)); ));
SheetContent.displayName = SheetPrimitive.Content.displayName; SheetContent.displayName = SheetPrimitive.Content.displayName;
const SheetHeader = ({ const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
className, <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
); );
SheetHeader.displayName = "SheetHeader"; SheetHeader.displayName = "SheetHeader";
const SheetFooter = ({ const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div <div
className={cn( className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props} {...props}
/> />
); );
@@ -108,7 +90,7 @@ const SheetTitle = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Title <SheetPrimitive.Title
ref={ref} ref={ref}
className={cn("text-lg font-semibold text-foreground", className)} className={cn("text-foreground text-lg font-semibold", className)}
{...props} {...props}
/> />
)); ));
@@ -120,7 +102,7 @@ const SheetDescription = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Description <SheetPrimitive.Description
ref={ref} ref={ref}
className={cn("text-sm text-muted-foreground", className)} className={cn("text-muted-foreground text-sm", className)}
{...props} {...props}
/> />
)); ));

View File

@@ -1,64 +0,0 @@
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
interface ShineBorderProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Width of the border in pixels
* @default 1
*/
borderWidth?: number;
/**
* Duration of the animation in seconds
* @default 14
*/
duration?: number;
/**
* Color of the border, can be a single color or an array of colors
* @default "#000000"
*/
shineColor?: string | string[];
}
/**
* Shine Border
*
* An animated background border effect component with configurable properties.
*/
export function ShineBorder({
borderWidth = 1,
duration = 14,
shineColor = "#000000",
className,
style,
...props
}: ShineBorderProps) {
return (
<div
style={
{
"--border-width": `${borderWidth}px`,
"--duration": `${duration}s`,
backgroundImage: `radial-gradient(transparent,transparent, ${
Array.isArray(shineColor) ? shineColor.join(",") : shineColor
},transparent,transparent)`,
backgroundSize: "300% 300%",
mask: `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
WebkitMask: `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
WebkitMaskComposite: "xor",
maskComposite: "exclude",
padding: "var(--border-width)",
...style,
} as React.CSSProperties
}
className={cn(
"pointer-events-none absolute inset-0 size-full rounded-[inherit] will-change-[background-position] motion-safe:animate-shine",
className,
)}
{...props}
/>
);
}
export default ShineBorder;

View File

@@ -1,31 +0,0 @@
"use client"
import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"
type ToasterProps = React.ComponentProps<typeof Sonner>
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
)
}
export { Toaster }

View File

@@ -1,117 +0,0 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto border border-border rounded-lg">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm !my-0", className)}
{...props}
/>
</div>
))
Table.displayName = "Table"
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b bg-muted", className)} {...props} />
))
TableHeader.displayName = "TableHeader"
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
))
TableBody.displayName = "TableBody"
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
)}
{...props}
/>
))
TableFooter.displayName = "TableFooter"
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
)}
{...props}
/>
))
TableRow.displayName = "TableRow"
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className
)}
{...props}
/>
))
TableHead.displayName = "TableHead"
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props}
/>
))
TableCell.displayName = "TableCell"
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
))
TableCaption.displayName = "TableCaption"
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}

View File

@@ -1,55 +0,0 @@
"use client";
import * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { cn } from "@/lib/utils";
const Tabs = TabsPrimitive.Root;
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-10 items-center gap-2 text-muted-foreground font-mono -mb-28 w-full border-b",
className
)}
{...props}
/>
));
TabsList.displayName = TabsPrimitive.List.displayName;
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap px-1.5 py-[0.58rem] text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-primary border-b-2 border-transparent data-[state=active]:text-foreground font-code cursor-pointer",
className
)}
{...props}
/>
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ",
className
)}
{...props}
/>
));
TabsContent.displayName = TabsPrimitive.Content.displayName;
export { Tabs, TabsList, TabsTrigger, TabsContent };

View File

@@ -7,7 +7,7 @@ description: Extend and customize WooNooW.
WooNooW is built with extensibility in mind. WooNooW is built with extensibility in mind.
<CardGroup cols={2}> <Cards cols={2}>
<Card title="Addons System" icon="Package" href="/docs/developer/addons/module-integration"> <Card title="Addons System" icon="Package" href="/docs/developer/addons/module-integration">
Learn how to create custom modules that plug into the WooNooW ecosystem. Learn how to create custom modules that plug into the WooNooW ecosystem.
</Card> </Card>
@@ -17,4 +17,4 @@ WooNooW is built with extensibility in mind.
<Card title="API Reference" icon="Zap" href="/docs/developer/api/licensing"> <Card title="API Reference" icon="Zap" href="/docs/developer/api/licensing">
Detailed documentation of our REST API endpoints. Detailed documentation of our REST API endpoints.
</Card> </Card>
</CardGroup> </Cards>

View File

@@ -21,14 +21,14 @@ date: 2024-01-31
If you are a plugin developer or a digital store owner using WooCommerce, WooNooW simplifies the complex parts of your business logic. If you are a plugin developer or a digital store owner using WooCommerce, WooNooW simplifies the complex parts of your business logic.
<CardGroup> <Cards>
<Card title="For Developers" icon="Terminal"> <Card title="For Developers" icon="Terminal">
Built with extensibility in mind. Use our hooks, filters, and REST API to build custom integrations. Built with extensibility in mind. Use our hooks, filters, and REST API to build custom integrations.
</Card> </Card>
<Card title="For Store Owners" icon="Box"> <Card title="For Store Owners" icon="Box">
Manage your digital products, verified customers, and subscriptions all in one place. Manage your digital products, verified customers, and subscriptions all in one place.
</Card> </Card>
</CardGroup> </Cards>
## Getting Help ## Getting Help

View File

@@ -23,8 +23,8 @@ The flow involves three parties:
2. **Vendor Portal**: The WooNooW dashboard where the user manages licenses 2. **Vendor Portal**: The WooNooW dashboard where the user manages licenses
3. **Vendor API**: The backend handling the activation logic 3. **Vendor API**: The backend handling the activation logic
<Stepper> <Steps>
<StepperItem title="Step 1: Client Requests Activation"> <Step title="Step 1: Client Requests Activation">
The client sends a request to the activation API with `activation_mode: "oauth"`. The client sends a request to the activation API with `activation_mode: "oauth"`.
```bash ```bash
@@ -35,9 +35,9 @@ The flow involves three parties:
"activation_mode": "oauth" "activation_mode": "oauth"
} }
``` ```
</StepperItem> </Step>
<StepperItem title="Step 2: API Request Authorization"> <Step title="Step 2: API Request Authorization">
The API responds with `oauth_required: true` and a redirect URL. The API responds with `oauth_required: true` and a redirect URL.
```json ```json
@@ -47,9 +47,9 @@ The flow involves three parties:
"state": "abc12345" "state": "abc12345"
} }
``` ```
</StepperItem> </Step>
<StepperItem title="Step 3: User Authorizes Request"> <Step title="Step 3: User Authorizes Request">
The client redirects the user to the `oauth_redirect` URL. The user logs in and sees a confirmation screen: The client redirects the user to the `oauth_redirect` URL. The user logs in and sees a confirmation screen:
> **Authorize this Request?** > **Authorize this Request?**
@@ -57,9 +57,9 @@ The flow involves three parties:
> License: XXXX-YYYY-ZZZZ-WWWW > License: XXXX-YYYY-ZZZZ-WWWW
Once confirmed, the vendor generates a temporary **activation token**. Once confirmed, the vendor generates a temporary **activation token**.
</StepperItem> </Step>
<StepperItem title="Step 4: Token Exchange"> <Step title="Step 4: Token Exchange">
The user is redirected back to the client site with the token. The client exchanges this token for the final activation. The user is redirected back to the client site with the token. The client exchanges this token for the final activation.
```bash ```bash
@@ -68,8 +68,8 @@ The flow involves three parties:
"activation_token": "temporary-token-123" "activation_token": "temporary-token-123"
} }
``` ```
</StepperItem> </Step>
</Stepper> </Steps>
--- ---

View File

@@ -6,7 +6,7 @@ date: 2024-01-31
## General ## General
<AccordionGroup> <Accordions>
<Accordion title="What is WooNooW?"> <Accordion title="What is WooNooW?">
WooNooW is a WooCommerce plugin that transforms your store into a modern Single Page Application (SPA). It provides instant page loads, a beautiful UI, and seamless shopping experience. WooNooW is a WooCommerce plugin that transforms your store into a modern Single Page Application (SPA). It provides instant page loads, a beautiful UI, and seamless shopping experience.
</Accordion> </Accordion>
@@ -16,13 +16,13 @@ date: 2024-01-31
<Accordion title="Will WooNooW affect my existing products?"> <Accordion title="Will WooNooW affect my existing products?">
No. WooNooW reads from WooCommerce. Your products, orders, and settings remain untouched. No. WooNooW reads from WooCommerce. Your products, orders, and settings remain untouched.
</Accordion> </Accordion>
</AccordionGroup> </Accordions>
--- ---
## SPA Mode ## SPA Mode
<AccordionGroup> <Accordions>
<Accordion title="What's the difference between Full and Disabled mode?"> <Accordion title="What's the difference between Full and Disabled mode?">
| Mode | Behavior | | Mode | Behavior |
|------|----------| |------|----------|
@@ -36,13 +36,13 @@ date: 2024-01-31
- **Full**: For the best customer experience with instant loads - **Full**: For the best customer experience with instant loads
- **Disabled**: If you have theme customizations you want to keep - **Disabled**: If you have theme customizations you want to keep
</Accordion> </Accordion>
</AccordionGroup> </Accordions>
--- ---
## Compatibility ## Compatibility
<AccordionGroup> <Accordions>
<Accordion title="Does WooNooW work with my theme?"> <Accordion title="Does WooNooW work with my theme?">
WooNooW's SPA is independent of your WordPress theme. In Full mode, the SPA uses its own styling. Your theme affects the rest of your site normally. WooNooW's SPA is independent of your WordPress theme. In Full mode, the SPA uses its own styling. Your theme affects the rest of your site normally.
</Accordion> </Accordion>
@@ -57,13 +57,13 @@ date: 2024-01-31
- Cash on Delivery - Cash on Delivery
- And more... - And more...
</Accordion> </Accordion>
</AccordionGroup> </Accordions>
--- ---
## SEO ## SEO
<AccordionGroup> <Accordions>
<Accordion title="Is WooNooW SEO-friendly?"> <Accordion title="Is WooNooW SEO-friendly?">
Yes. WooNooW uses: Yes. WooNooW uses:
- Clean URLs (`/store/product/product-name`) - Clean URLs (`/store/product/product-name`)
@@ -76,13 +76,13 @@ date: 2024-01-31
<Accordion title="Will my product pages be indexed?"> <Accordion title="Will my product pages be indexed?">
Yes. Search engines index the WooCommerce URLs. When users click from search results, they're redirected to the fast SPA experience. Yes. Search engines index the WooCommerce URLs. When users click from search results, they're redirected to the fast SPA experience.
</Accordion> </Accordion>
</AccordionGroup> </Accordions>
--- ---
## Performance ## Performance
<AccordionGroup> <Accordions>
<Accordion title="Is WooNooW faster than regular WooCommerce?"> <Accordion title="Is WooNooW faster than regular WooCommerce?">
Yes, for navigation. After the initial load, page transitions are instant because the SPA doesn't reload the entire page. Yes, for navigation. After the initial load, page transitions are instant because the SPA doesn't reload the entire page.
</Accordion> </Accordion>
@@ -92,13 +92,13 @@ date: 2024-01-31
<Accordion title="Does WooNooW work with caching?"> <Accordion title="Does WooNooW work with caching?">
Yes. Use page caching and object caching for best results. Yes. Use page caching and object caching for best results.
</Accordion> </Accordion>
</AccordionGroup> </Accordions>
--- ---
## Customization ## Customization
<AccordionGroup> <Accordions>
<Accordion title="Can I customize colors and fonts?"> <Accordion title="Can I customize colors and fonts?">
Yes. Go to **WooNooW → Appearance** to customize: Yes. Go to **WooNooW → Appearance** to customize:
- Primary, secondary, and accent colors - Primary, secondary, and accent colors
@@ -111,4 +111,4 @@ date: 2024-01-31
<Accordion title="Can I modify the SPA templates?"> <Accordion title="Can I modify the SPA templates?">
The SPA is built with React. Advanced customizations require development knowledge. The SPA is built with React. Advanced customizations require development knowledge.
</Accordion> </Accordion>
</AccordionGroup> </Accordions>

View File

@@ -9,24 +9,24 @@ date: 2024-01-31
WooCommerce pages (shop, cart, checkout) show blank content. WooCommerce pages (shop, cart, checkout) show blank content.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Check SPA Mode Setting"> <Step title="Check SPA Mode Setting">
- Go to **WooNooW → Appearance → General** - Go to **WooNooW → Appearance → General**
- Ensure **SPA Mode** is set to "Full" - Ensure **SPA Mode** is set to "Full"
- If you want native WooCommerce, set to "Disabled" - If you want native WooCommerce, set to "Disabled"
</StepperItem> </Step>
<StepperItem title="Flush Permalinks"> <Step title="Flush Permalinks">
- Go to **Settings → Permalinks** - Go to **Settings → Permalinks**
- Click **Save Changes** (no changes needed) - Click **Save Changes** (no changes needed)
- This refreshes rewrite rules - This refreshes rewrite rules
</StepperItem> </Step>
<StepperItem title="Clear Cache"> <Step title="Clear Cache">
- If using a caching plugin: - If using a caching plugin:
- Clear page cache - Clear page cache
- Clear object cache - Clear object cache
- Purge CDN cache (if applicable) - Purge CDN cache (if applicable)
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -36,21 +36,21 @@ WooCommerce pages (shop, cart, checkout) show blank content.
Visiting `/store/shop` or `/store/product/...` shows a 404 error. Visiting `/store/shop` or `/store/product/...` shows a 404 error.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Flush Permalinks"> <Step title="Flush Permalinks">
- Go to **Settings → Permalinks** - Go to **Settings → Permalinks**
- Click **Save Changes** - Click **Save Changes**
</StepperItem> </Step>
<StepperItem title="Check Store Page Exists"> <Step title="Check Store Page Exists">
- Go to **Pages** - Go to **Pages**
- Verify "Store" page exists and is published - Verify "Store" page exists and is published
- The page should contain `[woonoow_spa]` shortcode - The page should contain `[woonoow_spa]` shortcode
</StepperItem> </Step>
<StepperItem title="Check SPA Page Setting"> <Step title="Check SPA Page Setting">
- Go to **WooNooW → Appearance → General** - Go to **WooNooW → Appearance → General**
- Ensure **SPA Page** is set to the Store page - Ensure **SPA Page** is set to the Store page
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -60,16 +60,16 @@ Visiting `/store/shop` or `/store/product/...` shows a 404 error.
Products show placeholder images instead of actual images. Products show placeholder images instead of actual images.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Regenerate Thumbnails"> <Step title="Regenerate Thumbnails">
- Install "Regenerate Thumbnails" plugin - Install "Regenerate Thumbnails" plugin
- Run regeneration for all images - Run regeneration for all images
</StepperItem> </Step>
<StepperItem title="Check Image URLs"> <Step title="Check Image URLs">
- Ensure images have valid URLs - Ensure images have valid URLs
- Check for mixed content (HTTP vs HTTPS) - Check for mixed content (HTTP vs HTTPS)
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -79,21 +79,21 @@ Products show placeholder images instead of actual images.
SPA feels slow or laggy. SPA feels slow or laggy.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Enable Caching"> <Step title="Enable Caching">
- Install a caching plugin (WP Super Cache, W3 Total Cache) - Install a caching plugin (WP Super Cache, W3 Total Cache)
- Enable object caching (Redis/Memcached) - Enable object caching (Redis/Memcached)
</StepperItem> </Step>
<StepperItem title="Optimize Images"> <Step title="Optimize Images">
- Use WebP format - Use WebP format
- Compress images before upload - Compress images before upload
- Use lazy loading - Use lazy loading
</StepperItem> </Step>
<StepperItem title="Check Server Resources"> <Step title="Check Server Resources">
- Upgrade hosting if on shared hosting - Upgrade hosting if on shared hosting
- Consider VPS or managed WordPress hosting - Consider VPS or managed WordPress hosting
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -103,22 +103,22 @@ SPA feels slow or laggy.
Checkout page won't load or payment fails. Checkout page won't load or payment fails.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Check Payment Gateway"> <Step title="Check Payment Gateway">
- Go to **WooCommerce → Settings → Payments** - Go to **WooCommerce → Settings → Payments**
- Verify payment method is enabled - Verify payment method is enabled
- Check API credentials - Check API credentials
</StepperItem> </Step>
<StepperItem title="Check SSL Certificate"> <Step title="Check SSL Certificate">
- Checkout requires HTTPS - Checkout requires HTTPS
- Verify SSL is properly installed - Verify SSL is properly installed
</StepperItem> </Step>
<StepperItem title="Check for JavaScript Errors"> <Step title="Check for JavaScript Errors">
- Open browser Developer Tools (F12) - Open browser Developer Tools (F12)
- Check Console for errors - Check Console for errors
- Look for blocked scripts - Look for blocked scripts
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -128,20 +128,20 @@ Checkout page won't load or payment fails.
Order confirmation emails not being received. Order confirmation emails not being received.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Check Email Settings"> <Step title="Check Email Settings">
- Go to **WooNooW → Settings → Notifications** - Go to **WooNooW → Settings → Notifications**
- Verify email types are enabled - Verify email types are enabled
</StepperItem> </Step>
<StepperItem title="Check WordPress Email"> <Step title="Check WordPress Email">
- Test with a plugin like "Check & Log Email" - Test with a plugin like "Check & Log Email"
- Consider using SMTP plugin (WP Mail SMTP) - Consider using SMTP plugin (WP Mail SMTP)
</StepperItem> </Step>
<StepperItem title="Check Spam Folder"> <Step title="Check Spam Folder">
- Emails may be in recipient's spam folder - Emails may be in recipient's spam folder
- Add sender to whitelist - Add sender to whitelist
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -151,22 +151,22 @@ Order confirmation emails not being received.
WooNooW doesn't work after installing another plugin. WooNooW doesn't work after installing another plugin.
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Steps to Diagnose"> <Step title="Steps to Diagnose">
- Deactivate other plugins one by one - Deactivate other plugins one by one
- Switch to default theme (Twenty Twenty-Three) - Switch to default theme (Twenty Twenty-Three)
- Check error logs in `wp-content/debug.log` - Check error logs in `wp-content/debug.log`
</StepperItem> </Step>
<StepperItem title="Check WordPress Email"> <Step title="Check WordPress Email">
- Test with a plugin like "Check & Log Email" - Test with a plugin like "Check & Log Email"
- Consider using SMTP plugin (WP Mail SMTP) - Consider using SMTP plugin (WP Mail SMTP)
</StepperItem> </Step>
<StepperItem title="Common Conflicting Plugins"> <Step title="Common Conflicting Plugins">
- Other WooCommerce template overrides - Other WooCommerce template overrides
- Page builder plugins (sometimes) - Page builder plugins (sometimes)
- Heavy caching plugins (misconfigured) - Heavy caching plugins (misconfigured)
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>
--- ---
@@ -176,23 +176,23 @@ WooNooW doesn't work after installing another plugin.
If you can't resolve the issue: If you can't resolve the issue:
<div className="pl-4"> <div className="pl-4">
<Stepper> <Steps>
<StepperItem title="Collect Information"> <Step title="Collect Information">
- WordPress version - WordPress version
- WooCommerce version - WooCommerce version
- WooNooW version - WooNooW version
- PHP version - PHP version
- Error messages (from debug.log) - Error messages (from debug.log)
</StepperItem> </Step>
<StepperItem title="Enable Debug Mode"> <Step title="Enable Debug Mode">
- Add to `wp-config.php`: - Add to `wp-config.php`:
```php ```php
define('WP_DEBUG', true); define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true); define('WP_DEBUG_LOG', true);
``` ```
</StepperItem> </Step>
<StepperItem title="Contact Support"> <Step title="Contact Support">
- Provide the collected information for faster resolution. - Provide the collected information for faster resolution.
</StepperItem> </Step>
</Stepper> </Steps>
</div> </div>

View File

@@ -4,6 +4,9 @@ import js from "@eslint/js";
import tseslint from "typescript-eslint"; import tseslint from "typescript-eslint";
export default tseslint.config( export default tseslint.config(
{
ignores: ["node_modules", ".next", "postcss.config.cjs", ".eslintignore"],
},
js.configs.recommended, js.configs.recommended,
...nextCoreWebVitals, ...nextCoreWebVitals,
...nextTypescript, ...nextTypescript,

121
lib/icon.ts Normal file
View File

@@ -0,0 +1,121 @@
import { createElement, type ComponentType, type SVGProps } from "react";
export type IconComponent = ComponentType<SVGProps<SVGSVGElement>>;
function createSocialIcon(title: string, pathData: string): IconComponent {
return function SocialIcon(props) {
return createElement(
"svg",
{
role: "img",
viewBox: "0 0 24 24",
xmlns: "http://www.w3.org/2000/svg",
fill: "currentColor",
...props,
},
createElement("title", null, title),
createElement("path", { d: pathData })
);
};
}
const FacebookIcon = createSocialIcon(
"Facebook",
"M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"
);
const InstagramIcon = createSocialIcon(
"Instagram",
"M7.0301.084c-1.2768.0602-2.1487.264-2.911.5634-.7888.3075-1.4575.72-2.1228 1.3877-.6652.6677-1.075 1.3368-1.3802 2.127-.2954.7638-.4956 1.6365-.552 2.914-.0564 1.2775-.0689 1.6882-.0626 4.947.0062 3.2586.0206 3.6671.0825 4.9473.061 1.2765.264 2.1482.5635 2.9107.308.7889.72 1.4573 1.388 2.1228.6679.6655 1.3365 1.0743 2.1285 1.38.7632.295 1.6361.4961 2.9134.552 1.2773.056 1.6884.069 4.9462.0627 3.2578-.0062 3.668-.0207 4.9478-.0814 1.28-.0607 2.147-.2652 2.9098-.5633.7889-.3086 1.4578-.72 2.1228-1.3881.665-.6682 1.0745-1.3378 1.3795-2.1284.2957-.7632.4966-1.636.552-2.9124.056-1.2809.0692-1.6898.063-4.948-.0063-3.2583-.021-3.6668-.0817-4.9465-.0607-1.2797-.264-2.1487-.5633-2.9117-.3084-.7889-.72-1.4568-1.3876-2.1228C21.2982 1.33 20.628.9208 19.8378.6165 19.074.321 18.2017.1197 16.9244.0645 15.6471.0093 15.236-.005 11.977.0014 8.718.0076 8.31.0215 7.0301.0839m.1402 21.6932c-1.17-.0509-1.8053-.2453-2.2287-.408-.5606-.216-.96-.4771-1.3819-.895-.422-.4178-.6811-.8186-.9-1.378-.1644-.4234-.3624-1.058-.4171-2.228-.0595-1.2645-.072-1.6442-.079-4.848-.007-3.2037.0053-3.583.0607-4.848.05-1.169.2456-1.805.408-2.2282.216-.5613.4762-.96.895-1.3816.4188-.4217.8184-.6814 1.3783-.9003.423-.1651 1.0575-.3614 2.227-.4171 1.2655-.06 1.6447-.072 4.848-.079 3.2033-.007 3.5835.005 4.8495.0608 1.169.0508 1.8053.2445 2.228.408.5608.216.96.4754 1.3816.895.4217.4194.6816.8176.9005 1.3787.1653.4217.3617 1.056.4169 2.2263.0602 1.2655.0739 1.645.0796 4.848.0058 3.203-.0055 3.5834-.061 4.848-.051 1.17-.245 1.8055-.408 2.2294-.216.5604-.4763.96-.8954 1.3814-.419.4215-.8181.6811-1.3783.9-.4224.1649-1.0577.3617-2.2262.4174-1.2656.0595-1.6448.072-4.8493.079-3.2045.007-3.5825-.006-4.848-.0608M16.953 5.5864A1.44 1.44 0 1 0 18.39 4.144a1.44 1.44 0 0 0-1.437 1.4424M5.8385 12.012c.0067 3.4032 2.7706 6.1557 6.173 6.1493 3.4026-.0065 6.157-2.7701 6.1506-6.1733-.0065-3.4032-2.771-6.1565-6.174-6.1498-3.403.0067-6.156 2.771-6.1496 6.1738M8 12.0077a4 4 0 1 1 4.008 3.9921A3.9996 3.9996 0 0 1 8 12.0077"
);
const TwitterIcon = createSocialIcon(
"X",
"M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z"
);
const YoutubeIcon = createSocialIcon(
"YouTube",
"M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
);
const ThreadsIcon = createSocialIcon(
"Threads",
"M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164 1.43 1.783 3.631 2.698 6.54 2.717 2.623-.02 4.358-.631 5.8-2.045 1.647-1.613 1.618-3.593 1.09-4.798-.31-.71-.873-1.3-1.634-1.75-.192 1.352-.622 2.446-1.284 3.272-.886 1.102-2.14 1.704-3.73 1.79-1.202.065-2.361-.218-3.259-.801-1.063-.689-1.685-1.74-1.752-2.964-.065-1.19.408-2.285 1.33-3.082.88-.76 2.119-1.207 3.583-1.291a13.853 13.853 0 0 1 3.02.142c-.126-.742-.375-1.332-.75-1.757-.513-.586-1.308-.883-2.359-.89h-.029c-.844 0-1.992.232-2.721 1.32L7.734 7.847c.98-1.454 2.568-2.256 4.478-2.256h.044c3.194.02 5.097 1.975 5.287 5.388.108.046.216.094.321.142 1.49.7 2.58 1.761 3.154 3.07.797 1.82.871 4.79-1.548 7.158-1.85 1.81-4.094 2.628-7.277 2.65Zm1.003-11.69c-.242 0-.487.007-.739.021-1.836.103-2.98.946-2.916 2.143.067 1.256 1.452 1.839 2.784 1.767 1.224-.065 2.818-.543 3.086-3.71a10.5 10.5 0 0 0-2.215-.221z"
);
const GithubIcon = createSocialIcon(
"GitHub",
"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
);
const GitlabIcon = createSocialIcon(
"GitLab",
"m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z"
);
const DiscordIcon = createSocialIcon(
"Discord",
"M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"
);
const NpmIcon = createSocialIcon(
"npm",
"M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z"
);
const TelegramIcon = createSocialIcon(
"Telegram",
"M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"
);
const GlobeIcon = createSocialIcon(
"Website",
"M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm7.93 9h-3.06a15.7 15.7 0 0 0-1.19-5.03A8.02 8.02 0 0 1 19.93 11ZM12 4.07c.85 1.18 1.63 3.13 1.86 5.93h-3.72c.23-2.8 1.01-4.75 1.86-5.93ZM8.32 5.97A15.7 15.7 0 0 0 7.13 11H4.07a8.02 8.02 0 0 1 4.25-5.03ZM4.07 13h3.06c.16 1.83.6 3.56 1.19 5.03A8.02 8.02 0 0 1 4.07 13Zm5.99 0h3.88c-.24 2.8-1.02 4.75-1.94 5.97-.92-1.22-1.7-3.17-1.94-5.97Zm5.62 5.03c.59-1.47 1.03-3.2 1.19-5.03h3.06a8.02 8.02 0 0 1-4.25 5.03Z"
);
export const SOCIAL_ICONS: Record<string, IconComponent> = {
facebook: FacebookIcon,
instagram: InstagramIcon,
twitter: TwitterIcon,
x: TwitterIcon,
youtube: YoutubeIcon,
threads: ThreadsIcon,
github: GithubIcon,
gitlab: GitlabIcon,
discord: DiscordIcon,
npm: NpmIcon,
telegram: TelegramIcon,
};
const SOCIAL_NAME_TO_KEY: Record<string, keyof typeof SOCIAL_ICONS> = {
facebook: "facebook",
instagram: "instagram",
twitter: "twitter",
x: "x",
youtube: "youtube",
threads: "threads",
github: "github",
gitlab: "gitlab",
discord: "discord",
npm: "npm",
telegram: "telegram",
};
function normalizeName(name: string): string {
return name.trim().toLowerCase().replace(/[^a-z0-9]/g, "");
}
function getSocialKeyByName(name: string): keyof typeof SOCIAL_ICONS | null {
const normalized = normalizeName(name);
return SOCIAL_NAME_TO_KEY[normalized] ?? (SOCIAL_ICONS[normalized] ? (normalized as keyof typeof SOCIAL_ICONS) : null);
}
export function getSocialIconByName(name?: string): IconComponent {
if (!name) {
return GlobeIcon;
}
const key = getSocialKeyByName(name);
return key ? SOCIAL_ICONS[key] : GlobeIcon;
}

View File

@@ -1,217 +1,214 @@
import { compileMDX } from "next-mdx-remote/rsc"; import {
createMdxContentService,
type MdxCompileResult as CoreMdxCompileResult,
} from "@docubook/core";
import { cache } from "react";
import path from "path"; import path from "path";
import { promises as fs } from "fs"; import { execFile } from "child_process";
import remarkGfm from "remark-gfm"; import { promisify } from "util";
import rehypePrism from "rehype-prism-plus";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeSlug from "rehype-slug";
import rehypeCodeTitles from "rehype-code-titles";
import { page_routes, ROUTES } from "./routes"; import { page_routes, ROUTES } from "./routes";
import { visit } from "unist-util-visit"; import type { TocItem } from "./toc";
import type { Node, Parent } from "unist"; import { mdxComponents as components } from "./mdx-components";
import matter from "gray-matter"; import { toIsoDateOnly } from "./utils";
// Type definitions for unist-util-visit export type MdxCompileResult<Frontmatter> = CoreMdxCompileResult<Frontmatter>;
interface Element extends Node {
type: string;
tagName?: string;
properties?: Record<string, unknown> & {
className?: string[];
raw?: string;
};
children?: Node[];
value?: string;
raw?: string; // For internal use in processing
}
interface TextNode extends Node { export type DocsForSlugResult = MdxCompileResult<BaseMdxFrontmatter> & {
type: 'text'; filePath: string;
value: string; tocs: TocItem[];
}
// custom components imports
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell } from "@/components/ui/table";
import Pre from "@/components/markdown/PreMdx";
import Note from "@/components/markdown/NoteMdx";
import { Stepper, StepperItem } from "@/components/markdown/StepperMdx";
import Image from "@/components/markdown/ImageMdx";
import Link from "@/components/markdown/LinkMdx";
import Outlet from "@/components/markdown/OutletMdx";
import Youtube from "@/components/markdown/YoutubeMdx";
import Tooltip from "@/components/markdown/TooltipsMdx";
import Card from "@/components/markdown/CardMdx";
import Button from "@/components/markdown/ButtonMdx";
import Accordion from "@/components/markdown/AccordionMdx";
import CardGroup from "@/components/markdown/CardGroupMdx";
import Kbd from "@/components/markdown/KeyboardMdx";
import { Release, Changes } from "@/components/markdown/ReleaseMdx";
import { File, Files, Folder } from "@/components/markdown/FileTreeMdx";
import AccordionGroup from "@/components/markdown/AccordionGroupMdx";
// add custom components
const components = {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Youtube,
Tooltip,
Card,
Button,
Accordion,
AccordionGroup,
CardGroup,
Kbd,
// Table Components
table: Table,
thead: TableHeader,
tbody: TableBody,
tfoot: TableFooter,
tr: TableRow,
th: TableHead,
td: TableCell,
// Release Note Components
Release,
Changes,
// File Tree Components
File,
Files,
Folder,
pre: Pre,
Note,
Stepper,
StepperItem,
img: Image,
a: Link,
Outlet,
}; };
// helper function to handle rehype code titles, since by default we can't inject into the className of rehype-code-titles // Shared frontmatter shape used by docs pages.
const handleCodeTitles = () => (tree: Node) => { // Keep this close to exported result types for easier discovery.
visit(tree, "element", (node: Element, index: number | null, parent: Parent | null) => {
// Ensure the visited node is valid
if (!parent || index === null || node.tagName !== 'div') {
return;
}
// Check if this is the title div from rehype-code-titles
const isTitleDiv = node.properties?.className?.includes('rehype-code-title');
if (!isTitleDiv) {
return;
}
// Find the next <pre> element, skipping over other nodes like whitespace text
let nextElement = null;
for (let i = index + 1; i < parent.children.length; i++) {
const sibling = parent.children[i];
if (sibling.type === 'element') {
nextElement = sibling as Element;
break;
}
}
// If the next element is a <pre>, move the title to it
if (nextElement && nextElement.tagName === 'pre') {
const titleNode = node.children?.[0] as TextNode;
if (titleNode && titleNode.type === 'text') {
if (!nextElement.properties) {
nextElement.properties = {};
}
nextElement.properties['data-title'] = titleNode.value;
// Remove the original title div
parent.children.splice(index, 1);
// Return the same index to continue visiting from the correct position
return index;
}
}
});
};
// can be used for other pages like blogs, Guides etc
async function parseMdx<Frontmatter>(rawMdx: string) {
return await compileMDX<Frontmatter>({
source: rawMdx,
options: {
parseFrontmatter: true,
mdxOptions: {
rehypePlugins: [
preProcess,
rehypeCodeTitles,
handleCodeTitles,
rehypePrism,
rehypeSlug,
rehypeAutolinkHeadings,
postProcess,
],
remarkPlugins: [remarkGfm],
},
},
components,
});
}
// logic for docs
export type BaseMdxFrontmatter = { export type BaseMdxFrontmatter = {
title: string; title: string;
description: string; description: string;
image: string; image: string;
date: string; date?: string | Date;
}; };
export async function getDocsForSlug(slug: string) { // `React.cache` deduplicates calls within a single server-render pass.
// Keep request-level cache in app layer, while markdown pipeline lives in core.
const FILE_GIT_DATE_CACHE_MAX = 1000;
const fileGitDateCache = new Map<string, Date | undefined>();
function cacheSet(key: string, value: Date | undefined) {
if (fileGitDateCache.size >= FILE_GIT_DATE_CACHE_MAX) {
const firstKey = fileGitDateCache.keys().next().value!;
fileGitDateCache.delete(firstKey);
}
fileGitDateCache.set(key, value);
}
let repoLastCommitDateCache: Date | undefined | null = null;
let gitRootCache: string | undefined;
const execFileAsync = promisify(execFile);
async function getGitRootDir(): Promise<string | undefined> {
if (gitRootCache !== undefined) return gitRootCache;
try { try {
const { content, filePath } = await getRawMdx(slug); const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"]);
const mdx = await parseMdx<BaseMdxFrontmatter>(content); gitRootCache = stdout.trim() || "";
return { return gitRootCache || undefined;
...mdx, } catch {
filePath, gitRootCache = "";
}; return undefined;
} catch (err) {
console.log(err);
} }
} }
async function getFileLastCommitDate(absoluteFilePath: string): Promise<Date | undefined> {
if (fileGitDateCache.has(absoluteFilePath)) {
return fileGitDateCache.get(absoluteFilePath);
}
try {
const gitRoot = await getGitRootDir();
if (!gitRoot) {
cacheSet(absoluteFilePath, undefined);
return undefined;
}
const relativePath = path.relative(gitRoot, absoluteFilePath);
if (
relativePath.startsWith("..") ||
!/^[a-zA-Z0-9\-_/.\s]+$/.test(relativePath) ||
/(^|\/)\.\.($|\/)/.test(relativePath)
) {
cacheSet(absoluteFilePath, undefined);
return undefined;
}
const { stdout } = await execFileAsync(
"git",
["log", "-1", "--format=%cI", "--", relativePath],
{ cwd: gitRoot }
);
const rawDate = stdout.trim();
if (!rawDate) {
cacheSet(absoluteFilePath, undefined);
return undefined;
}
const parsed = new Date(rawDate);
if (Number.isNaN(parsed.getTime())) {
cacheSet(absoluteFilePath, undefined);
return undefined;
}
cacheSet(absoluteFilePath, parsed);
return parsed;
} catch {
cacheSet(absoluteFilePath, undefined);
return undefined;
}
}
async function getRepoLastCommitDate(): Promise<Date | undefined> {
if (repoLastCommitDateCache !== null) {
return repoLastCommitDateCache ?? undefined;
}
try {
const gitRoot = await getGitRootDir();
if (!gitRoot) {
repoLastCommitDateCache = undefined;
return undefined;
}
const { stdout } = await execFileAsync("git", ["log", "-1", "--format=%cI"], {
cwd: gitRoot,
});
const rawDate = stdout.trim();
if (!rawDate) {
repoLastCommitDateCache = undefined;
return undefined;
}
const parsed = new Date(rawDate);
if (Number.isNaN(parsed.getTime())) {
repoLastCommitDateCache = undefined;
return undefined;
}
repoLastCommitDateCache = parsed;
return parsed;
} catch {
repoLastCommitDateCache = undefined;
return undefined;
}
}
const docsService = createMdxContentService<BaseMdxFrontmatter, TocItem>({
parseOptions: { components },
cacheFn: cache,
frontmatterEnricher: async (frontmatter, absoluteFilePath) => {
if (!frontmatter.date) {
const gitDate = await getFileLastCommitDate(absoluteFilePath);
if (gitDate) return { ...frontmatter, date: toIsoDateOnly(gitDate) };
const repoDate = await getRepoLastCommitDate();
if (repoDate) return { ...frontmatter, date: toIsoDateOnly(repoDate) };
// Keep `date` non-empty even outside git context.
return { ...frontmatter, date: "12-12-2025" };
}
return frontmatter;
},
});
// Return frontmatter only for a docs slug.
export async function getDocsFrontmatterForSlug(
slug: string
): Promise<BaseMdxFrontmatter | undefined> {
try {
return await docsService.getFrontmatterForSlug(slug);
} catch (error) {
console.error(error);
}
}
/**
* Get full compiled documentation (public API)
* Returns: JSX content, frontmatter, TOCs, file path
*/
export async function getDocsForSlug(slug: string): Promise<DocsForSlugResult | undefined> {
try {
return await docsService.getCompiledForSlug(slug);
} catch (error) {
console.error(error);
}
}
/**
* Get only table of contents for a slug
*/
export async function getDocsTocs(slug: string) { export async function getDocsTocs(slug: string) {
const { content } = await getRawMdx(slug); try {
const rawMdx = content; return await docsService.getTocsForSlug(slug);
} catch {
// Regex to match code blocks (```...```), standard markdown headings (##), and <Release> tags return [];
const combinedRegex = /(```[\s\S]*?```)|^(#{2,4})\s(.+)$|<Release[^>]*version="([^"]+)"/gm;
let match;
const extractedHeadings = [];
while ((match = combinedRegex.exec(rawMdx)) !== null) {
// match[1] -> Code block content (ignore)
if (match[1]) continue;
// match[2] & match[3] -> Markdown headings
if (match[2]) {
const headingLevel = match[2].length;
const headingText = match[3].trim();
const slug = sluggify(headingText);
extractedHeadings.push({
level: headingLevel,
text: headingText,
href: `#${slug}`,
});
} }
// match[4] -> Release component version
else if (match[4]) {
const version = match[4];
extractedHeadings.push({
level: 2,
text: `v${version}`,
href: `#${version}`,
});
}
}
return extractedHeadings;
} }
// Build static params for the docs route segment.
export function getDocsStaticParams() {
// Ensure the root docs page (docs/index.mdx) is statically generated at /docs.
// This page is not part of the generated docs tree routes by default.
// Filter out routes marked as noLink (parent categories that don't have their own page)
return [
{ slug: [] },
...page_routes
.map((page) => ({
slug: page.href.split("/").filter(Boolean),
}))
.filter(({ slug }) => slug.length > 0), // Exclude empty slugs
];
}
// Get previous and next page entries from the route list.
export function getPreviousNext(path: string) { export function getPreviousNext(path: string) {
const index = page_routes.findIndex(({ href }) => href == `/${path}`); const index = page_routes.findIndex(({ href }) => href == `/${path}`);
return { return {
@@ -220,85 +217,36 @@ export function getPreviousNext(path: string) {
}; };
} }
function sluggify(text: string) { // Collect frontmatter of direct child pages under the given docs path.
const slug = text.toLowerCase().replace(/\s+/g, "-");
return slug.replace(/[^a-z0-9-]/g, "");
}
async function getRawMdx(slug: string) {
const commonPath = path.join(process.cwd(), "/docs/");
const paths = [
path.join(commonPath, `${slug}.mdx`),
path.join(commonPath, slug, "index.mdx"),
];
for (const p of paths) {
try {
const content = await fs.readFile(p, "utf-8");
return {
content,
filePath: `docs/${path.relative(commonPath, p)}`,
};
} catch {
// ignore and try next
}
}
throw new Error(`Could not find mdx file for slug: ${slug}`);
}
function justGetFrontmatterFromMD<Frontmatter>(rawMd: string): Frontmatter {
return matter(rawMd).data as Frontmatter;
}
export async function getAllChilds(pathString: string) { export async function getAllChilds(pathString: string) {
const items = pathString.split("/").filter((it) => it !== ""); const items = pathString.split("/").filter((it) => it !== "");
let page_routes_copy = ROUTES; let nestedRoutes = ROUTES;
let prevHref = ""; // Resolve the nested route branch for the requested path.
let resolvedHref = "";
for (const it of items) { for (const it of items) {
const found = page_routes_copy.find((innerIt) => innerIt.href == `/${it}`); const found = nestedRoutes.find((innerIt) => innerIt.href === `/${it}`);
if (!found) break; if (!found) break;
prevHref += found.href; resolvedHref += found.href;
page_routes_copy = found.items ?? []; nestedRoutes = found.items ?? [];
}
if (!resolvedHref) return [];
const children = await Promise.all(
nestedRoutes.map(async (it) => {
const slug = `${resolvedHref}${it.href}`.replace(/^\/+/, "");
const frontmatter = await docsService.getFrontmatterForSlug(slug).catch(() => undefined);
if (!frontmatter) {
return null;
} }
if (!prevHref) return [];
return await Promise.all(
page_routes_copy.map(async (it) => {
const slug = path.join(prevHref, it.href);
const { content } = await getRawMdx(slug);
return { return {
...justGetFrontmatterFromMD<BaseMdxFrontmatter>(content), ...frontmatter,
href: `/docs${prevHref}${it.href}`, href: `/docs${resolvedHref}${it.href}`,
}; };
}) })
); );
return children.filter((child): child is BaseMdxFrontmatter & { href: string } => child !== null);
} }
// for copying the code in pre
const preProcess = () => (tree: Node) => {
visit(tree, (node: Node) => {
const element = node as Element;
if (element?.type === "element" && element?.tagName === "pre" && element.children) {
const [codeEl] = element.children as Element[];
if (codeEl.tagName !== "code" || !codeEl.children?.[0]) return;
const textNode = codeEl.children[0] as TextNode;
if (textNode.type === 'text' && textNode.value) {
element.raw = textNode.value;
}
}
});
};
const postProcess = () => (tree: Node) => {
visit(tree, "element", (node: Node) => {
const element = node as Element;
if (element?.type === "element" && element?.tagName === "pre") {
if (element.properties && element.raw) {
element.properties.raw = element.raw;
}
}
});
};

67
lib/mdx-components.ts Normal file
View File

@@ -0,0 +1,67 @@
import {
createMdxComponents,
type MdxComponentMap,
AccordionsMdx,
AccordionMdx,
CardsMdx,
ChangesMdx,
CodeBlock,
FileMdx,
FilesMdx,
FolderMdx,
KbdMdx,
NoteMdx,
ReleaseMdx,
StepsMdx,
StepMdx,
TabMdx,
TabsMdx,
TableBodyMdx,
TableCellMdx,
TableFooterMdx,
TableHeadMdx,
TableHeaderMdx,
TableMdx,
TableRowMdx,
TooltipMdx,
YoutubeMdx,
} from "@docubook/mdx-content";
import { ImageMdx, LinkMdx, ButtonMdx, CardMdx } from "@docubook/mdx-content/next";
import { customMdxComponents } from "@/lib/mdx";
const builtInOverrides: MdxComponentMap = {
Tabs: TabsMdx,
Tab: TabMdx,
table: TableMdx,
thead: TableHeaderMdx,
tbody: TableBodyMdx,
tfoot: TableFooterMdx,
tr: TableRowMdx,
th: TableHeadMdx,
td: TableCellMdx,
pre: CodeBlock,
Button: ButtonMdx,
Note: NoteMdx,
Step: StepMdx,
Steps: StepsMdx,
Accordion: AccordionMdx,
Accordions: AccordionsMdx,
Card: CardMdx,
Cards: CardsMdx,
Kbd: KbdMdx,
Release: ReleaseMdx,
Changes: ChangesMdx,
File: FileMdx,
Files: FilesMdx,
Folder: FolderMdx,
Youtube: YoutubeMdx,
Tooltip: TooltipMdx,
img: ImageMdx,
a: LinkMdx,
Link: LinkMdx,
};
export const mdxComponents = createMdxComponents({
...builtInOverrides,
...customMdxComponents,
});

33
lib/mdx/Outlet.tsx Normal file
View File

@@ -0,0 +1,33 @@
import Link from "next/link";
import { getAllChilds, type BaseMdxFrontmatter } from "@/lib/markdown";
type OutletProps = {
path: string;
};
type ChildCardProps = BaseMdxFrontmatter & { href: string };
export default async function Outlet({ path }: OutletProps) {
if (!path) {
throw new Error("path not provided");
}
const output = await getAllChilds(path);
return (
<div className="grid md:grid-cols-2 gap-5">
{output.map((child) => (
<ChildCard {...child} key={child.title} />
))}
</div>
);
}
function ChildCard({ description, href, title }: ChildCardProps) {
return (
<Link href={href} className="border rounded-md p-4 no-underline flex flex-col gap-0.5">
<h4 className="!my-0">{title}</h4>
<p className="text-sm text-muted-foreground !my-0">{description}</p>
</Link>
);
}

11
lib/mdx/index.ts Normal file
View File

@@ -0,0 +1,11 @@
import type { MdxComponentMap } from "@docubook/mdx-content";
import Outlet from "@/lib/mdx/Outlet";
// import your custom MDX components here and add them to the `customMdxComponents` object below to make them available in your MDX files. For example:
// import { MyCustomComponent } from "@/lib/mdx/MyCustomComponent";
export const customMdxComponents: MdxComponentMap = {
Outlet,
// MyCustomComponent, --- IGNORE ---
};
// you must also add MyCustomComponent.tsx to lib/mdx/MyCustomComponent.tsx and export it from there, and then export it from this file as well to make it available for import in mdx-components.ts.

View File

@@ -1,4 +1,4 @@
import docuConfig from "@/docu.json"; // Import JSON file import docuConfig from "@/docu.json";
export type ContextInfo = { export type ContextInfo = {
icon: string; icon: string;
@@ -14,7 +14,7 @@ export type EachRoute = {
items?: EachRoute[]; items?: EachRoute[];
}; };
export const ROUTES: EachRoute[] = docuConfig.routes; export const ROUTES: EachRoute[] = (docuConfig as { routes: EachRoute[] }).routes;
type Page = { title: string; href: string }; type Page = { title: string; href: string };

View File

@@ -1,5 +1,11 @@
export const algoliaConfig = { export const algoliaConfig: {
appId: string | undefined
apiKey: string | undefined
indexName: string | undefined
askAiAssistantId: string | undefined
} = {
appId: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_APP_ID, appId: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_APP_ID,
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_API_KEY, apiKey: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_API_KEY,
indexName: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_INDEX_NAME, indexName: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_INDEX_NAME,
askAiAssistantId: process.env.NEXT_PUBLIC_ALGOLIA_DOCSEARCH_ASKAI_ASSISTANT_ID,
} }

View File

@@ -1,8 +1,5 @@
export interface TocItem { export type { TocItem } from "@docubook/core";
level: number; import type { TocItem } from "@docubook/core";
text: string;
href: string;
}
export interface MobTocProps { export interface MobTocProps {
tocs: TocItem[]; tocs: TocItem[];

View File

@@ -5,35 +5,46 @@ export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs))
} }
// Thursday, May 23, 2024 /** Parse both `dd-MM-yyyy` and ISO 8601 date strings into a Date object. */
export function formatDate(dateStr: string): string { function parseDate(dateStr: string): Date {
const [day, month, year] = dateStr.split("-").map(Number) // ISO 8601: starts with 4-digit year (e.g. "2026-04-05" or "2026-04-05T00:00:00.000Z")
const date = new Date(year, month - 1, day) if (/^\d{4}-/.test(dateStr)) return new Date(dateStr);
// Legacy dd-MM-yyyy (e.g. "05-04-2026")
const [day, month, year] = dateStr.split("-").map(Number);
return new Date(year, month - 1, day);
}
// "Thursday, April 5, 2026"
export function formatDate(dateStrOrDate: string | Date): string {
const date = dateStrOrDate instanceof Date ? dateStrOrDate : parseDate(dateStrOrDate);
const options: Intl.DateTimeFormatOptions = { const options: Intl.DateTimeFormatOptions = {
weekday: "long", weekday: "long",
year: "numeric", year: "numeric",
month: "long", month: "long",
day: "numeric", day: "numeric",
} };
return date.toLocaleDateString("en-US", options) return date.toLocaleDateString("en-US", options);
} }
// May 23, 2024 // "Apr 5, 2026"
export function formatDate2(dateStr: string): string { export function formatDate2(dateStrOrDate: string | Date): string {
const [day, month, year] = dateStr.split("-").map(Number) const date = dateStrOrDate instanceof Date ? dateStrOrDate : parseDate(dateStrOrDate);
const date = new Date(year, month - 1, day)
const options: Intl.DateTimeFormatOptions = { const options: Intl.DateTimeFormatOptions = {
month: "short", month: "short",
day: "numeric", day: "numeric",
year: "numeric", year: "numeric",
} };
return date.toLocaleDateString("en-US", options) return date.toLocaleDateString("en-US", options);
} }
export function stringToDate(date: string) { export function stringToDate(date: string | Date) {
const [day, month, year] = date.split("-").map(Number) return date instanceof Date ? date : parseDate(date);
return new Date(year, month - 1, day) }
export function toIsoDateOnly(dateStrOrDate: string | Date): string {
const date = stringToDate(dateStrOrDate)
return date.toISOString().slice(0, 10)
} }

View File

@@ -9,6 +9,24 @@ const nextConfig = {
}, },
], ],
}, },
experimental: {
optimizePackageImports: ["lucide-react", "react-icons"],
},
async headers() {
return [
{
source: "/(.*)",
headers: [
{ key: "Content-Security-Policy", value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; font-src 'self' data:; connect-src 'self' https:; frame-src https://www.youtube-nocookie.com; frame-ancestors 'none'" },
{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
],
},
]
},
} }
export default nextConfig export default nextConfig

View File

@@ -1,6 +1,9 @@
{ {
"name": "docubook", "name": "docubook",
"version": "2.5.1", "template": "nextjs-docker",
"description": "Next.js standalone with docker image documentation template for DocuBook",
"version": "1.0.0",
"type": "module",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -9,10 +12,10 @@
"lint": "eslint ." "lint": "eslint ."
}, },
"dependencies": { "dependencies": {
"@docsearch/css": "^3.9.0", "@docsearch/css": "^4.6.2",
"@docsearch/react": "^3.9.0", "@docsearch/react": "^4.6.2",
"@radix-ui/react-accordion": "^1.2.12", "@docubook/core": "^1.7.0",
"@radix-ui/react-avatar": "^1.1.11", "@docubook/mdx-content": "^3.2.1",
"@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -20,45 +23,38 @@
"@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-toggle-group": "^1.1.11",
"algoliasearch": "^5.46.3",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "^1.1.1", "framer-motion": "^12.38.0",
"framer-motion": "^12.26.2", "geist": "^1.7.0",
"geist": "^1.5.1", "lucide-react": "^1.7.0",
"gray-matter": "^4.0.3", "next": "^16.2.6",
"lucide-react": "^0.511.0", "next-themes": "^0.4.6",
"next": "^16.1.6",
"next-mdx-remote": "^6.0.0",
"next-themes": "^0.4.4",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"react-icons": "^5.5.0",
"rehype-autolink-headings": "^7.1.0",
"rehype-code-titles": "^1.2.1",
"rehype-prism-plus": "^2.0.1",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.1",
"sonner": "^1.7.4", "sonner": "^1.7.4",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.1",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7"
"unist-util-visit": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "^4.1.18", "@eslint/js": "^9.39.4",
"@tailwindcss/postcss": "^4.2.2",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@types/node": "^20.19.30", "@types/node": "^20.19.37",
"@types/react": "19.2.8", "@types/react": "19.2.8",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
"autoprefixer": "^10.4.23", "@types/unist": "^3.0.3",
"eslint": "^9.39.2", "autoprefixer": "^10.4.27",
"eslint": "^9.39.4",
"eslint-config-next": "16.1.3", "eslint-config-next": "16.1.3",
"postcss": "^8.5.6", "postcss": "^8.5.8",
"tailwindcss": "^4.1.18", "prettier": "^3.8.1",
"typescript": "^5.9.3" "prettier-plugin-tailwindcss": "^0.6.14",
"tailwindcss": "^4.2.2",
"typescript": "^5.9.3",
"typescript-eslint": "^8.57.2"
}, },
"overrides": { "overrides": {
"@types/react": "19.2.8", "@types/react": "19.2.8",

5
postcss.config.cjs Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
};

View File

@@ -1,6 +0,0 @@
module.exports = {
plugins: {
'@tailwindcss/postcss': {},
autoprefixer: {},
},
};

View File

@@ -9,13 +9,14 @@
--docsearch-logo-color: hsl(var(--primary-foreground)); --docsearch-logo-color: hsl(var(--primary-foreground));
/* Modal */ /* Modal */
--docsearch-modal-width: 560px; --docsearch-modal-width: 800px;
--docsearch-modal-height: 600px; --docsearch-modal-height: 600px;
--docsearch-modal-background: hsl(var(--background)); --docsearch-modal-background: hsl(var(--background));
--docsearch-modal-shadow: 0 0 0 1px hsl(var(--border)), 0 8px 20px rgba(0, 0, 0, 0.2); --docsearch-modal-shadow: 0 0 0 1px hsl(var(--border)), 0 8px 20px rgba(0, 0, 0, 0.2);
/* SearchBox */ /* SearchBox */
--docsearch-searchbox-height: 56px; --docsearch-searchbox-width: 230px;
--docsearch-searchbox-height: 35px;
--docsearch-searchbox-background: hsl(var(--input)); --docsearch-searchbox-background: hsl(var(--input));
--docsearch-searchbox-focus-background: hsl(var(--card)); --docsearch-searchbox-focus-background: hsl(var(--card));
--docsearch-searchbox-shadow: none; --docsearch-searchbox-shadow: none;
@@ -42,8 +43,8 @@
background-color: hsl(var(--secondary)); background-color: hsl(var(--secondary));
border: 1px solid hsl(var(--border)); border: 1px solid hsl(var(--border));
border-radius: 9999px; border-radius: 9999px;
width: 250px; width: var(--docsearch-searchbox-width);
height: 35px; height: var(--docsearch-searchbox-height);
color: hsl(var(--muted-foreground)); color: hsl(var(--muted-foreground));
transition: width 0.3s ease; transition: width 0.3s ease;
margin: 0; margin: 0;
@@ -98,6 +99,27 @@
border-top: 1px solid hsl(var(--border)); border-top: 1px solid hsl(var(--border));
} }
.dark .DocSearch-Footer .DocSearch-Label {
color: var(--docsearch-muted-color);
}
.dark button.DocSearch-Action.DocSearch-Close {
color: var(--docsearch-muted-color);
}
.dark .DocSearch-Hit-Container .DocSearch-Hit-icon {
color: var(--docsearch-muted-color);
}
.dark .DocSearch-Hit[aria-selected="true"] .DocSearch-Hit-Container .DocSearch-Hit-icon,
.dark .DocSearch-Hit[aria-selected="true"] .DocSearch-Hit-action {
color: var(--docsearch-highlight-color);
}
.dark .DocSearch-Hit-Container .DocSearch-Hit-path {
color: var(--docsearch-muted-color);
}
.DocSearch-Footer--commands kbd { .DocSearch-Footer--commands kbd {
background-color: hsl(var(--secondary)); background-color: hsl(var(--secondary));
border: 1px solid hsl(var(--border)); border: 1px solid hsl(var(--border));
@@ -115,7 +137,7 @@
color: hsl(var(--muted-foreground)); color: hsl(var(--muted-foreground));
border: 1px solid hsl(var(--border)); border: 1px solid hsl(var(--border));
box-shadow: none; box-shadow: none;
padding: 2px 4px; padding: 4px 8px;
margin-right: 0.4em; margin-right: 0.4em;
height: 20px; height: 20px;
width: 32px; width: 32px;

View File

@@ -1,7 +1,6 @@
@import 'tailwindcss'; @import "tailwindcss";
@plugin '@tailwindcss/typography'; @plugin '@tailwindcss/typography';
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
@utility container { @utility container {
@@ -85,8 +84,27 @@
} }
} }
@keyframes shiny-text { @keyframes collapsible-down {
from {
height: 0;
}
to {
height: var(--radix-collapsible-content-height);
}
}
@keyframes collapsible-up {
from {
height: var(--radix-collapsible-content-height);
}
to {
height: 0;
}
}
@keyframes shiny-text {
0%, 0%,
90%, 90%,
100% { 100% {
@@ -109,7 +127,6 @@
color utility to any element that depends on these defaults. color utility to any element that depends on these defaults.
*/ */
@layer base { @layer base {
*, *,
::after, ::after,
::before, ::before,
@@ -119,6 +136,14 @@
} }
} }
@utility animate-collapsible-down {
animation: collapsible-down 0.2s ease-out;
}
@utility animate-collapsible-up {
animation: collapsible-up 0.2s ease-out;
}
@utility animate-shine { @utility animate-shine {
--animate-shine: shine var(--duration) infinite linear; --animate-shine: shine var(--duration) infinite linear;
animation: var(--animate-shine); animation: var(--animate-shine);
@@ -206,7 +231,7 @@
overflow-x: auto; overflow-x: auto;
} }
pre>code { pre > code {
display: grid; display: grid;
max-width: inherit !important; max-width: inherit !important;
padding: 14px 0 !important; padding: 14px 0 !important;
@@ -230,20 +255,19 @@
} }
.highlight-line { .highlight-line {
@apply bg-primary/5 border-l-2 border-primary/30; @apply bg-primary/5 border-primary/30 border-l-2;
} }
.rehype-code-title { .rehype-code-title {
@apply px-2 -mb-8 w-full text-sm pb-5 font-medium mt-5 font-code; @apply font-code mt-5 -mb-8 w-full px-2 pb-5 text-sm font-medium;
} }
.highlight-comp>code { .highlight-comp > code {
background-color: transparent !important; background-color: transparent !important;
} }
} }
@layer utilities { @layer utilities {
@keyframes shine { @keyframes shine {
0% { 0% {
background-position: 0% 0%; background-position: 0% 0%;

View File

@@ -87,121 +87,8 @@
} }
.dark .punctuation { .dark .punctuation {
color: hsl(85 20% 70%); color: #9ca3af;
/* Light gray-green */ /* Lighter gray for dark mode */
}
/* Custom styling for code blocks */
.code-block-container {
position: relative;
margin: 1.5rem 0;
border: 1px solid hsl(var(--border));
overflow: hidden;
font-size: 0.875rem;
border-radius: 0.75rem;
}
.code-block-header {
display: flex;
align-items: center;
gap: 0.5rem;
background-color: hsl(var(--muted));
padding: 0.5rem 1rem;
border-bottom: 1px solid hsl(var(--border));
color: hsl(var(--muted-foreground));
font-family: monospace;
font-size: 0.8rem;
}
.code-block-actions {
position: absolute;
top: 0.5rem;
right: 0.75rem;
z-index: 10;
}
.code-block-actions button {
color: hsl(var(--muted-foreground));
transition: color 0.2s ease-in-out;
}
.code-block-actions button:hover {
color: hsl(var(--foreground));
}
.code-block-body pre[class*="language-"] {
margin: 0 !important;
padding: 0 !important;
background: transparent !important;
}
.line-numbers-wrapper {
position: absolute;
top: 0;
left: 0;
width: 3rem;
padding-top: 1rem;
text-align: right;
color: var(--line-number-color);
user-select: none;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
background: hsl(var(--primary) / 0.1);
border-left: 2px solid hsl(var(--primary));
pointer-events: none;
}
.code-block-body pre[data-line-numbers="true"] .line-highlight {
padding-left: 3.5rem;
}
.code-block-body::-webkit-scrollbar {
height: 8px;
}
.code-block-body::-webkit-scrollbar-track {
background: transparent;
}
.code-block-body::-webkit-scrollbar-thumb {
background: hsl(var(--border));
border-radius: 4px;
}
.code-block-body::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted));
}
/* Custom styling for youtube blocks */
.youtube {
position: relative;
padding-bottom: 56.25%;
/* Aspect Ratio 16:9 */
height: 0;
overflow: hidden;
background: #000;
/* Black background to blend the player */
border-radius: 8px;
/* Rounded corners */
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
/* Soft shadow */
}
.youtube iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
border-radius: 8px;
/* Rounded corners on iframe */
} }
/* Hide main navbar and footer when docs layout is active */ /* Hide main navbar and footer when docs layout is active */

View File

@@ -1,14 +0,0 @@
import typography from "@tailwindcss/typography"
const config = {
darkMode: ["class"],
content: [
"./app/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./contents/**/*.{md,mdx}",
"../../packages/ui/src/**/*.{ts,tsx}",
],
plugins: [typography],
}
export default config

22
template.config.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "nextjs-docker",
"id": "nextjs-docker",
"description": "Next.js standalone with Docker image (optimized for coolify, etc.)",
"framework": "nextjs",
"base": "nextjs",
"packageManagers": ["npm", "yarn", "pnpm", "bun"],
"features": [
"Next.js 16",
"React 19",
"TypeScript",
"Tailwind CSS",
"MDX Support",
"Dark Mode",
"Search (Algolia)",
"Responsive Design",
"Docker Deployment"
],
"author": "wildan.nrs",
"repository": "https://github.com/DocuBook/packages/template/nextjs-docker",
"homepage": "https://docubook.pro"
}

23
tsconfig.base.json Normal file
View File

@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Base",
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"exclude": ["node_modules"]
}

Some files were not shown because too many files have changed in this diff Show More