diff --git a/.github/ISSUE_TEMPLATE/library-request.yml b/.github/ISSUE_TEMPLATE/library-request.yml
index af18e56..e485cc0 100644
--- a/.github/ISSUE_TEMPLATE/library-request.yml
+++ b/.github/ISSUE_TEMPLATE/library-request.yml
@@ -48,13 +48,6 @@ body:
placeholder: React, Vue, TypeScript
validations:
required: true
- - type: input
- id: use-cases
- attributes:
- label: Use cases
- placeholder: Dashboards, Rapid Prototyping
- validations:
- required: true
- type: checkboxes
id: checks
attributes:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index c7c08a0..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Verify
-
-on:
- push:
- pull_request:
-
-jobs:
- check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-node@v4
- with:
- node-version: '20.9'
- cache: npm
- - run: npm ci
- - run: npm run check
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3b0f906..2198a81 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,7 +18,7 @@ npm install
npm run dev
```
-Run `npm run check` before submitting changes.
+Run `npm run build` before submitting changes.
## Add a library
diff --git a/PRODUCT.md b/PRODUCT.md
index 32ff4c9..f339b39 100644
--- a/PRODUCT.md
+++ b/PRODUCT.md
@@ -8,11 +8,11 @@ web
## Users
-Frontend developers and product designers finding UI libraries for an active project, plus contributors maintaining the directory.
+Frontend developers and product designers comparing UI libraries for an active project, plus contributors maintaining the directory.
## Product Purpose
-Col is a community-maintained directory for finding, filtering, sorting, and saving UI libraries without opening many disconnected sources.
+Col is a community-maintained directory for finding, filtering, and comparing UI libraries without opening many disconnected sources.
## Positioning
diff --git a/README.md b/README.md
index 7e97339..b72cbfa 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@
## What Col does
-Col organizes UI libraries by category, stack, and use case. Search from the homepage, then filter, sort, and save matching libraries in the directory.
+Col organizes UI libraries by category, stack, and use case. Search from the homepage, then compare matching libraries in the directory.
- Search by name, keyword, category, stack, or use case.
- Filter libraries without leaving the directory.
@@ -57,7 +57,7 @@ Open the local URL printed in the terminal (usually [http://localhost:3000](http
Before opening a pull request:
```bash
-npm run check
+npm run build
```
## Request something
@@ -74,7 +74,7 @@ Include:
- what it provides and who it helps;
- its supported stacks;
- the closest Col category and use cases;
-- confirmation that it is publicly accessible.
+- confirmation that it is maintained and publicly accessible.
Search [existing libraries](data/libraries.ts), [issues](https://github.com/screen-gd/Col/issues), and [pull requests](https://github.com/screen-gd/Col/pulls) first.
@@ -105,7 +105,7 @@ Library-only pull requests should be small and should not redesign unrelated par
3. Reuse the existing category, stack, and use-case values when possible.
4. Keep the description factual and short.
5. Confirm the URL points to the official project.
-6. Run `npm run check`.
+6. Run `npm run build`.
7. Open a pull request using the provided template.
```ts
@@ -163,8 +163,6 @@ When contributing a future detail page, keep the prompt specific to that library
app/ Routes, layout, and global styles
components/ Search, filters, cards, header, and shared UI
data/libraries.ts The curated library registry
-lib/ Shared helpers and route metadata
-tests/ Registry and discovery checks
public/brand/ Col brand assets
public/hero-logos/ Library artwork used by the homepage
.github/ Issue forms and pull request guidance
diff --git a/app/docs/page.tsx b/app/docs/page.tsx
index 7347f26..9b6aa2f 100644
--- a/app/docs/page.tsx
+++ b/app/docs/page.tsx
@@ -59,7 +59,7 @@ export default function DocsPage() {
Fork the repository, create a focused branch, and keep unrelated changes out. Library additions belong in data/libraries.ts with a unique kebab-case slug, canonical URL, factual description, and existing taxonomy values where possible.
- {`npm install\nnpm run dev\nnpm run check`}
+ {`npm install\nnpm run dev\nnpm run build`}
Explain what changed, why it changed, and how you verified it. Include screenshots for visible interface changes.
Read the contribution guide
diff --git a/app/globals.css b/app/globals.css
index be0b9a1..dc8dbe9 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -179,10 +179,26 @@ html.light .docs-copy pre {
color: #111;
}
+.gooey-surface {
+ background: #090909;
+ color: #fff;
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,.14);
+}
+.hero-search-surface { box-shadow: none; }
+.gooey-input-text { color: #fff; }
+.gooey-key { border-color: rgba(255,255,255,.12); color: rgba(255,255,255,.75); }
+
+html.light .gooey-surface {
+ background: #fff;
+ color: #111;
+ box-shadow: inset 0 0 0 1px rgba(17,17,17,.16);
+}
+html.light .hero-search-surface { box-shadow: none; }
+html.light .gooey-input-text { color: #111; }
+html.light .gooey-key { border-color: rgba(17,17,17,.14); color: rgba(17,17,17,.65); }
html.light .hero-stat { background: transparent !important; border-color: rgba(17,17,17,.14) !important; }
.hero-search { border-color: rgba(255,255,255,.15); background: #090909; color: #fff; }
-.hero-search:focus-within { outline: 1px solid #fff; outline-offset: 2px; }
.hero-search-icon { color: rgba(255,255,255,.72); transition: transform 220ms ease; }
.hero-search:focus-within .hero-search-icon { transform: translateX(2px); }
.hero-search-input { color: #fff; }
@@ -209,7 +225,6 @@ html.light .hero-stat { background: transparent !important; border-color: rgba(1
}
html.light .hero-search { border-color: rgba(17,17,17,.16); background: #fff; color: #111; }
-html.light .hero-search:focus-within { outline-color: #111; }
html.light .hero-search-icon { color: rgba(17,17,17,.68); }
html.light .hero-search-input { color: #111; }
html.light .hero-search-hints { color: rgba(17,17,17,.48); }
@@ -387,6 +402,28 @@ html.light .site-header-search kbd { border-color: rgba(17,17,17,.14); color: rg
html.light .site-header-mobile-menu a:hover, html.light .site-header-mobile-menu a[aria-current="page"] { background: rgba(17,17,17,.06); }
}
+html.light .gooey-filter-layer { filter: none !important; }
+html.light .gooey-orb { display: none !important; }
+
+html.light [data-slot="select-content"] {
+ border-color: rgba(17,17,17,.14);
+ background: #fff;
+ color: #111;
+ box-shadow: none;
+}
+
+html.dark [data-slot="select-content"] { box-shadow: none; }
+html.dark [data-slot="select-item"][data-highlighted],
+html.dark [data-slot="select-item"]:focus {
+ background: #191919;
+ color: #fff;
+}
+
+html.light [data-slot="select-item"][data-highlighted] {
+ background: #f0f0ed;
+ color: #111;
+}
+
.popular-filter-button {
border-color: rgba(255,255,255,.18);
background: #050505;
@@ -460,9 +497,9 @@ html.light .filter-shell {
.coss-menu-item:focus,
.coss-menu-item:focus-visible,
.coss-menu-item[data-highlighted] {
- background: #303030;
+ background: transparent;
color: #fff;
- outline: 1px solid #fff;
+ outline: none;
}
html.light .coss-input,
@@ -475,9 +512,9 @@ html.light .coss-menu-item { color: rgba(17,17,17,.76); }
html.light .coss-menu-item:focus,
html.light .coss-menu-item:focus-visible,
html.light .coss-menu-item[data-highlighted] {
- background: #e8e8e5;
+ background: transparent;
color: #111;
- outline: 1px solid #111;
+ outline: none;
}
@keyframes coss-menu-in {
@@ -492,11 +529,11 @@ html.light .coss-menu-item[data-highlighted] {
.filter-tab { color: rgba(255,255,255,.72); }
.filter-tab:hover { background: rgba(255,255,255,.06); color: #fff; }
-.filter-tab[aria-pressed="true"] { border-color: rgba(255,255,255,.24); background: #fff; color: #080808; }
+.filter-tab[data-state="active"] { border-color: rgba(255,255,255,.24); background: #fff; color: #080808; }
html.light .filter-tab { color: rgba(17,17,17,.68); }
html.light .filter-tab:hover { background: rgba(17,17,17,.05); color: #111; }
-html.light .filter-tab[aria-pressed="true"] { border-color: #111; background: #111; color: #fff; }
+html.light .filter-tab[data-state="active"] { border-color: #111; background: #111; color: #fff; }
.library-card { border-color: rgba(255,255,255,.14); background: #050505; color: #fff; }
.library-card:hover { border-color: rgba(255,255,255,.3); background: #090909; }
@@ -507,7 +544,7 @@ html.light .filter-tab[aria-pressed="true"] { border-color: #111; background: #1
html.light .library-card { border-color: rgba(17,17,17,.14); background: #fff; color: #111; }
html.light .library-card:hover { border-color: rgba(17,17,17,.3); background: #fcfcfb; }
html.light .library-muted { color: rgba(17,17,17,.7); }
-html.light .library-subtle { color: rgba(17,17,17,.65); }
+html.light .library-subtle { color: rgba(17,17,17,.52); }
html.light .library-chip { border-color: rgba(17,17,17,.12); background: rgba(17,17,17,.045); color: rgba(17,17,17,.72); }
html.light [class~="text-white"] { color: #111; }
@@ -551,6 +588,26 @@ html.light .hero-logo-card {
filter: blur(3px) brightness(.85) saturate(0);
}
+.hero-background-card--mid {
+ opacity: 0.62;
+ filter: blur(1.5px) brightness(0.94) saturate(0);
+}
+
+.hero-background-card--far {
+ opacity: 0.4;
+ filter: blur(4px) brightness(0.82) saturate(0);
+}
+
+@keyframes star-border-movement-bottom {
+ 0% { transform: translate(0%, 0%); opacity: 1; }
+ 100% { transform: translate(-100%, 0%); opacity: 0; }
+}
+
+@keyframes star-border-movement-top {
+ 0% { transform: translate(0%, 0%); opacity: 1; }
+ 100% { transform: translate(100%, 0%); opacity: 0; }
+}
+
/* Entrance */
@keyframes fade-up {
from {
@@ -571,6 +628,22 @@ html.light .hero-logo-card {
.delay-2 {
animation-delay: 0.24s;
}
+.delay-3 {
+ animation-delay: 0.36s;
+}
+
+/* Infinite marquee */
+@keyframes marquee {
+ from {
+ transform: translateX(0);
+ }
+ to {
+ transform: translateX(-50%);
+ }
+}
+.animate-marquee {
+ animation: marquee 60s linear infinite;
+}
:focus-visible:not(input) {
outline: 1px solid rgba(255, 255, 255, 0.7);
@@ -607,6 +680,16 @@ html.light ::-webkit-scrollbar-thumb { border-color: #f7f7f5; background: #aaa;
scroll-behavior: auto !important;
}
}
+.marquee-mask {
+ mask-image: linear-gradient(
+ to right,
+ transparent,
+ black 12%,
+ black 88%,
+ transparent
+ );
+}
+
@theme inline {
--animate-rainbow: rainbow var(--speed, 2s) infinite linear;
--color-color-5: var(--color-5);
diff --git a/app/layout.tsx b/app/layout.tsx
index 94b3378..267896b 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -19,7 +19,7 @@ const geistMono = Geist_Mono({
export const metadata: Metadata = {
title: "Col — Collection of Libraries",
- description: "Browse UI libraries by category, stack, and use case.",
+ description: "We curate all the best libraries, so you don't have to.",
icons: { icon: "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/brand/col-mark.png" },
keywords: [
"ui libraries",
@@ -39,7 +39,7 @@ export default function RootLayout({
return (
-
+
}) {
- const { q } = await searchParams;
- const initialQuery = firstQuery(q);
+export default async function LibrariesPage({ searchParams }: { searchParams: Promise<{ q?: string }> }) {
+ const { q = "" } = await searchParams;
return (
<>
-
+
-
>
);
}
diff --git a/components/AsciiFluid.tsx b/components/AsciiFluid.tsx
new file mode 100644
index 0000000..1eb9f7f
--- /dev/null
+++ b/components/AsciiFluid.tsx
@@ -0,0 +1,126 @@
+"use client";
+
+import { useEffect, useRef } from "react";
+
+const RAMP = " .·:;-~=+*x#%@";
+const CELL = 16;
+
+// Coolors palette: #45A29E (deep) -> #66FCF1 (bright)
+const DEEP: [number, number, number] = [69, 162, 158];
+const BRIGHT: [number, number, number] = [102, 252, 241];
+
+/**
+ * ASCII fluid background (21st.dev style).
+ * A monospace character field with an ambient wave; the cursor injects
+ * energy that ripples and decays like fluid. Dependency-free canvas.
+ */
+export function AsciiFluid({ className = "" }: { className?: string }) {
+ const canvasRef = useRef(null);
+
+ useEffect(() => {
+ const canvas = canvasRef.current;
+ const parent = canvas?.parentElement;
+ const ctx = canvas?.getContext("2d");
+ if (!canvas || !parent || !ctx) return;
+
+ let raf = 0;
+ let cols = 0;
+ let rows = 0;
+ let field = new Float32Array(0);
+ let t = 0;
+ const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
+ const mouse = { x: -9999, y: -9999 };
+
+ const resize = () => {
+ const rect = parent.getBoundingClientRect();
+ canvas.width = rect.width * dpr;
+ canvas.height = rect.height * dpr;
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+ ctx.font = `${CELL * 0.85}px ui-monospace, SFMono-Regular, monospace`;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ cols = Math.ceil(rect.width / CELL);
+ rows = Math.ceil(rect.height / CELL);
+ field = new Float32Array(cols * rows);
+ };
+
+ const onMove = (e: MouseEvent) => {
+ const rect = canvas.getBoundingClientRect();
+ mouse.x = e.clientX - rect.left;
+ mouse.y = e.clientY - rect.top;
+ };
+
+ const onLeave = () => {
+ mouse.x = -9999;
+ mouse.y = -9999;
+ };
+
+ const render = () => {
+ t += 0.02;
+ ctx.clearRect(0, 0, cols * CELL, rows * CELL);
+
+ // Inject energy around the cursor — a soft radial splat.
+ if (mouse.x > -999) {
+ const mc = mouse.x / CELL;
+ const mr = mouse.y / CELL;
+ const R = 6;
+ const y0 = Math.max(0, Math.floor(mr - R));
+ const y1 = Math.min(rows, Math.ceil(mr + R));
+ const x0 = Math.max(0, Math.floor(mc - R));
+ const x1 = Math.min(cols, Math.ceil(mc + R));
+ for (let y = y0; y < y1; y++) {
+ for (let x = x0; x < x1; x++) {
+ const d = Math.hypot(x - mc, y - mr);
+ if (d < R) {
+ const i = y * cols + x;
+ field[i] = Math.min(1, field[i] + (1 - d / R) * 0.4);
+ }
+ }
+ }
+ }
+
+ for (let y = 0; y < rows; y++) {
+ for (let x = 0; x < cols; x++) {
+ const i = y * cols + x;
+ field[i] *= 0.94; // fluid decay
+
+ // Ambient drifting wave keeps the field alive without input.
+ const ambient =
+ 0.08 + 0.06 * Math.sin(x * 0.22 + t) * Math.cos(y * 0.28 - t * 0.8);
+ const v = Math.min(1, Math.max(0, ambient + field[i]));
+
+ const ch = RAMP[Math.min(RAMP.length - 1, (v * RAMP.length) | 0)];
+ if (ch === " ") continue;
+
+ const r = (DEEP[0] + (BRIGHT[0] - DEEP[0]) * v) | 0;
+ const g = (DEEP[1] + (BRIGHT[1] - DEEP[1]) * v) | 0;
+ const b = (DEEP[2] + (BRIGHT[2] - DEEP[2]) * v) | 0;
+ ctx.fillStyle = `rgba(${r},${g},${b},${(0.18 + v * 0.7).toFixed(3)})`;
+ ctx.fillText(ch, x * CELL + CELL / 2, y * CELL + CELL / 2);
+ }
+ }
+
+ raf = requestAnimationFrame(render);
+ };
+
+ resize();
+ render();
+ window.addEventListener("resize", resize);
+ window.addEventListener("mousemove", onMove);
+ document.addEventListener("mouseleave", onLeave);
+ return () => {
+ cancelAnimationFrame(raf);
+ window.removeEventListener("resize", resize);
+ window.removeEventListener("mousemove", onMove);
+ document.removeEventListener("mouseleave", onLeave);
+ };
+ }, []);
+
+ return (
+
+ );
+}
diff --git a/components/CategoryBento.tsx b/components/CategoryBento.tsx
new file mode 100644
index 0000000..01bf389
--- /dev/null
+++ b/components/CategoryBento.tsx
@@ -0,0 +1,85 @@
+"use client";
+
+import {
+ Activity,
+ ArrowUpRight,
+ BarChart3,
+ Box,
+ Cuboid,
+ ImageIcon,
+ PanelsTopLeft,
+ Palette,
+ type LucideIcon,
+} from "lucide-react";
+import { CATEGORIES, libraries, type Category } from "@/data/libraries";
+import GlareHover from "./GlareHover";
+
+const CATEGORY_ICONS: Record = {
+ "Component Library": Cuboid,
+ "Animation & Motion": Activity,
+ "Templates & Blocks": PanelsTopLeft,
+ Icons: ImageIcon,
+ "Charts & Data Viz": BarChart3,
+ "3D & WebGL": Box,
+ "CSS Framework": Palette,
+};
+
+interface CategoryBentoProps {
+ active: Category | null;
+ onSelect: (category: Category | null) => void;
+}
+
+export function CategoryBento({ active, onSelect }: CategoryBentoProps) {
+ return (
+
+
+ {CATEGORIES.map((category) => {
+ const matches = libraries.filter((library) => library.category === category);
+ const isActive = active === category;
+ const Icon = CATEGORY_ICONS[category];
+
+ return (
+
+ {
+ onSelect(isActive ? null : category);
+ document.getElementById("directory")?.scrollIntoView({
+ behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth",
+ });
+ }}
+ aria-pressed={isActive}
+ className="relative z-10 flex h-full w-full flex-col justify-between p-5 text-left"
+ >
+
+
+
+ {matches.length.toString().padStart(2, "0")}
+
+
{category}
+
+ {matches.slice(0, 3).map((library) => library.name).join(" · ") || "More soon"}
+
+
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/components/DirectoryExplorer.tsx b/components/DirectoryExplorer.tsx
index d04e2ed..f24d558 100644
--- a/components/DirectoryExplorer.tsx
+++ b/components/DirectoryExplorer.tsx
@@ -1,20 +1,30 @@
"use client";
-import { useEffect, useMemo, useRef, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import { Heart, SearchX } from "lucide-react";
import {
libraries,
type Category,
+ type Library,
type Stack,
type UseCase,
} from "@/data/libraries";
import { Button } from "@/components/ui/button";
-import { filterLibraries, nextSaved, readSaved } from "@/lib/directory";
import { FilterBar, FilterDropdown } from "./FilterBar";
import { LibraryCard } from "./LibraryCard";
const SAVED_LIBRARIES_KEY = "col:saved-libraries";
-const validSlugs = new Set(libraries.map(({ slug }) => slug));
+
+function matchesQuery(library: Library, tokens: string[]): boolean {
+ return tokens.every((token) => [
+ library.name,
+ library.description,
+ library.category,
+ ...library.stacks,
+ ...library.useCases,
+ ...(library.tags ?? []),
+ ].join(" ").toLowerCase().includes(token));
+}
export function DirectoryExplorer({ initialQuery = "" }: { initialQuery?: string }) {
const [query, setQuery] = useState(initialQuery);
@@ -24,42 +34,41 @@ export function DirectoryExplorer({ initialQuery = "" }: { initialQuery?: string
const [saved, setSaved] = useState>(new Set());
const [showSaved, setShowSaved] = useState(false);
const [sort, setSort] = useState<"curated" | "name">("curated");
- const searchRef = useRef(null);
useEffect(() => {
- try { setSaved(readSaved(localStorage.getItem(SAVED_LIBRARIES_KEY), validSlugs)); } catch { /* Session state remains available. */ }
- const sync = (event: StorageEvent) => {
- if (event.key === SAVED_LIBRARIES_KEY || event.key === null) setSaved(readSaved(event.key === null ? null : event.newValue, validSlugs));
- };
- window.addEventListener("storage", sync);
- return () => window.removeEventListener("storage", sync);
- }, []);
-
- useEffect(() => {
- const shortcut = (event: KeyboardEvent) => {
- if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "k") {
- event.preventDefault();
- searchRef.current?.focus();
- }
- };
- window.addEventListener("keydown", shortcut);
- return () => window.removeEventListener("keydown", shortcut);
+ try {
+ const stored: unknown = JSON.parse(localStorage.getItem(SAVED_LIBRARIES_KEY) ?? "[]");
+ if (Array.isArray(stored)) setSaved(new Set(stored.filter((slug): slug is string => typeof slug === "string")));
+ } catch {
+ localStorage.removeItem(SAVED_LIBRARIES_KEY);
+ }
}, []);
- const results = useMemo(() => filterLibraries(libraries, query, category, stacks, useCases, sort), [query, category, stacks, useCases, sort]);
+ const results = useMemo(() => {
+ const tokens = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
+ return libraries.filter((library) =>
+ (tokens.length === 0 || matchesQuery(library, tokens)) &&
+ (category === null || library.category === category) &&
+ (stacks.length === 0 || stacks.every((stack) => library.stacks.includes(stack))) &&
+ (useCases.length === 0 || useCases.every((useCase) => library.useCases.includes(useCase))),
+ );
+ }, [query, category, stacks, useCases]);
- const visibleResults = showSaved ? results.filter(({ slug }) => saved.has(slug)) : results;
+ const visibleResults = (showSaved ? results.filter(({ slug }) => saved.has(slug)) : results)
+ .toSorted((a, b) => sort === "name" ? a.name.localeCompare(b.name) : 0);
const toggleSaved = (slug: string) => {
- let stored: string | null | undefined;
- try { stored = localStorage.getItem(SAVED_LIBRARIES_KEY); } catch { /* Use session state. */ }
- const next = nextSaved(saved, stored, slug, validSlugs);
- try {
- localStorage.setItem(SAVED_LIBRARIES_KEY, JSON.stringify([...next]));
- } catch {
- // Keep the selection for this session when storage is unavailable.
- }
- setSaved(next);
+ setSaved((current) => {
+ const next = new Set(current);
+ if (next.has(slug)) next.delete(slug);
+ else next.add(slug);
+ try {
+ localStorage.setItem(SAVED_LIBRARIES_KEY, JSON.stringify([...next]));
+ } catch {
+ // Keep the selection for this session when storage is unavailable.
+ }
+ return next;
+ });
};
const clearFilters = () => {
@@ -67,7 +76,6 @@ export function DirectoryExplorer({ initialQuery = "" }: { initialQuery?: string
setCategory(null);
setStacks([]);
setUseCases([]);
- searchRef.current?.focus();
};
return (
@@ -78,7 +86,7 @@ export function DirectoryExplorer({ initialQuery = "" }: { initialQuery?: string
Search and filter the complete Col library directory.
-
{visibleResults.length} {visibleResults.length === 1 ? "library" : "libraries"}{visibleResults.length === 0 ? " found" : ""}
+
{visibleResults.length} libraries
;
onQueryChange: (query: string) => void;
onCategoryChange: (category: Category | null) => void;
onStackChange: (stack: Stack | null) => void;
@@ -56,7 +55,7 @@ interface FilterBarProps {
onClearAll: () => void;
}
-export function FilterBar({ activeCategory, activeStacks, activeUseCases, query, searchRef, onQueryChange, onCategoryChange, onStackChange, onUseCaseChange, onClearAll }: FilterBarProps) {
+export function FilterBar({ activeCategory, activeStacks, activeUseCases, query, onQueryChange, onCategoryChange, onStackChange, onUseCaseChange, onClearAll }: FilterBarProps) {
const hasFilters = query.trim() !== "" || activeCategory !== null || activeStacks.length > 0 || activeUseCases.length > 0;
return (
@@ -64,8 +63,8 @@ export function FilterBar({ activeCategory, activeStacks, activeUseCases, query,
- onQueryChange(event.target.value)} placeholder="Search libraries, tags, or keywords..." aria-label="Search libraries" className="coss-input h-10 w-full pr-16 pl-10" />
- Ctrl/⌘ K
+ onQueryChange(event.target.value)} placeholder="Search libraries, tags, or keywords..." aria-label="Search libraries" className="coss-input h-10 w-full pr-16 pl-10" />
+ Ctrl K
Clear}
-
- onCategoryChange(null)} className="filter-tab flex-none rounded-md border border-transparent px-3 py-1.5">All
- {CATEGORIES.map((category) => onCategoryChange(category)} className="filter-tab flex-none rounded-md border border-transparent px-3 py-1.5">{category} )}
-
+ onCategoryChange(value === "all" ? null : value as Category)}>
+
+ All
+ {CATEGORIES.map((category) => {category} )}
+
+
);
}
diff --git a/components/GlareHover.tsx b/components/GlareHover.tsx
new file mode 100644
index 0000000..d5b12c6
--- /dev/null
+++ b/components/GlareHover.tsx
@@ -0,0 +1,108 @@
+import React, { useRef } from 'react';
+
+interface GlareHoverProps {
+ width?: string;
+ height?: string;
+ background?: string;
+ borderRadius?: string;
+ borderColor?: string;
+ children?: React.ReactNode;
+ glareColor?: string;
+ glareOpacity?: number;
+ glareAngle?: number;
+ glareSize?: number;
+ transitionDuration?: number;
+ playOnce?: boolean;
+ className?: string;
+ style?: React.CSSProperties;
+}
+
+const GlareHover: React.FC = ({
+ width = '500px',
+ height = '500px',
+ background = '#000',
+ borderRadius = '10px',
+ borderColor = '#333',
+ children,
+ glareColor = '#ffffff',
+ glareOpacity = 0.5,
+ glareAngle = -45,
+ glareSize = 250,
+ transitionDuration = 650,
+ playOnce = false,
+ className = '',
+ style = {}
+}) => {
+ const hex = glareColor.replace('#', '');
+ let rgba = glareColor;
+ if (/^[\dA-Fa-f]{6}$/.test(hex)) {
+ const r = parseInt(hex.slice(0, 2), 16);
+ const g = parseInt(hex.slice(2, 4), 16);
+ const b = parseInt(hex.slice(4, 6), 16);
+ rgba = `rgba(${r}, ${g}, ${b}, ${glareOpacity})`;
+ } else if (/^[\dA-Fa-f]{3}$/.test(hex)) {
+ const r = parseInt(hex[0] + hex[0], 16);
+ const g = parseInt(hex[1] + hex[1], 16);
+ const b = parseInt(hex[2] + hex[2], 16);
+ rgba = `rgba(${r}, ${g}, ${b}, ${glareOpacity})`;
+ }
+
+ const overlayRef = useRef(null);
+
+ const animateIn = () => {
+ const el = overlayRef.current;
+ if (!el) return;
+
+ el.style.transition = 'none';
+ el.style.backgroundPosition = '-100% -100%, 0 0';
+ el.style.transition = `${transitionDuration}ms ease`;
+ el.style.backgroundPosition = '100% 100%, 0 0';
+ };
+
+ const animateOut = () => {
+ const el = overlayRef.current;
+ if (!el) return;
+
+ if (playOnce) {
+ el.style.transition = 'none';
+ el.style.backgroundPosition = '-100% -100%, 0 0';
+ } else {
+ el.style.transition = `${transitionDuration}ms ease`;
+ el.style.backgroundPosition = '-100% -100%, 0 0';
+ }
+ };
+
+ const overlayStyle: React.CSSProperties = {
+ position: 'absolute',
+ inset: 0,
+ background: `linear-gradient(${glareAngle}deg,
+ hsla(0,0%,0%,0) 60%,
+ ${rgba} 70%,
+ hsla(0,0%,0%,0) 100%)`,
+ backgroundSize: `${glareSize}% ${glareSize}%, 100% 100%`,
+ backgroundRepeat: 'no-repeat',
+ backgroundPosition: '-100% -100%, 0 0',
+ pointerEvents: 'none'
+ };
+
+ return (
+
+ );
+};
+
+export default GlareHover;
diff --git a/components/Header.tsx b/components/Header.tsx
index 9189469..bd5208c 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -115,7 +115,7 @@ export function Header() {
>
{links.map(([label, href]) => {
- const active = !href.includes("#") && (pathname === href || pathname.startsWith(`${href}/`));
+ const active = pathname === href || pathname.startsWith(`${href}/`);
return (
setMenuOpen(false)} aria-current={!href.includes("#") && (pathname === href || pathname.startsWith(`${href}/`)) ? "page" : undefined}>{label} )}
- {
- setMenuOpen(false);
- if (pathname === "/") document.querySelector("#hero-search input")?.focus();
- }}>Search libraries
+ {links.map(([label, href]) => {label} )}
+ Search libraries
)}
diff --git a/components/HeroLogoTrail.tsx b/components/HeroLogoTrail.tsx
new file mode 100644
index 0000000..1b80ee2
--- /dev/null
+++ b/components/HeroLogoTrail.tsx
@@ -0,0 +1,99 @@
+"use client";
+
+import { useEffect, useRef } from "react";
+
+const DOMAINS = [
+ "ui.shadcn.com",
+ "reactbits.dev",
+ "21st.dev",
+ "magicui.design",
+ "ui.aceternity.com",
+ "motion.dev",
+ "www.radix-ui.com",
+ "mui.com",
+ "mantine.dev",
+ "chakra-ui.com",
+ "lucide.dev",
+ "gsap.com",
+];
+
+const favicon = (domain: string) =>
+ `https://www.google.com/s2/favicons?domain=${domain}&sz=128`;
+
+export function HeroLogoTrail() {
+ const trailRef = useRef(null);
+
+ useEffect(() => {
+ const trail = trailRef.current;
+ const hero = trail?.parentElement;
+ if (
+ !trail ||
+ !hero ||
+ !matchMedia(
+ "(hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)",
+ ).matches
+ )
+ return;
+
+ const logos = [...trail.querySelectorAll("img")];
+ const safeZones = [
+ ...hero.querySelectorAll("[data-trail-safe]"),
+ ];
+ let index = 0;
+ let previousX = -100;
+ let previousY = -100;
+
+ const showLogo = (event: PointerEvent) => {
+ if (Math.hypot(event.clientX - previousX, event.clientY - previousY) < 72)
+ return;
+
+ const overContent = safeZones.some((element) => {
+ const rect = element.getBoundingClientRect();
+ return (
+ event.clientX >= rect.left - 32 &&
+ event.clientX <= rect.right + 32 &&
+ event.clientY >= rect.top - 32 &&
+ event.clientY <= rect.bottom + 32
+ );
+ });
+ if (overContent) return;
+
+ const bounds = hero.getBoundingClientRect();
+ const logo = logos[index++ % logos.length];
+ previousX = event.clientX;
+ previousY = event.clientY;
+ logo.style.left = `${event.clientX - bounds.left}px`;
+ logo.style.top = `${event.clientY - bounds.top}px`;
+ logo.animate(
+ [
+ { opacity: 0, transform: "translate(-50%, -50%) scale(.45) rotate(-8deg)" },
+ { opacity: 0.95, offset: 0.12, transform: "translate(-50%, -50%) scale(1) rotate(0deg)" },
+ { opacity: 0.85, offset: 0.68, transform: "translate(-50%, calc(-50% - 14px)) scale(.96) rotate(3deg)" },
+ { opacity: 0, transform: "translate(-50%, calc(-50% - 38px)) scale(.82) rotate(8deg)" },
+ ],
+ { duration: 1800, easing: "cubic-bezier(.16, 1, .3, 1)" },
+ );
+ };
+
+ hero.addEventListener("pointermove", showLogo);
+ return () => hero.removeEventListener("pointermove", showLogo);
+ }, []);
+
+ return (
+
+ {DOMAINS.map((domain) => (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ ))}
+
+ );
+}
diff --git a/components/LibraryCard.tsx b/components/LibraryCard.tsx
index e1acd5e..5148550 100644
--- a/components/LibraryCard.tsx
+++ b/components/LibraryCard.tsx
@@ -48,8 +48,8 @@ export function LibraryCard({ library, saved, onToggleSaved }: LibraryCardProps)
- {library.stacks.length} {library.stacks.length === 1 ? "stack" : "stacks"}
- {library.useCases.length} {library.useCases.length === 1 ? "use" : "uses"}
+ {library.stacks.length} stacks
+ {library.useCases.length} uses
diff --git a/components/LibraryExplorer.tsx b/components/LibraryExplorer.tsx
index dddf1e2..65ec4c3 100644
--- a/components/LibraryExplorer.tsx
+++ b/components/LibraryExplorer.tsx
@@ -2,7 +2,7 @@
import { useEffect, useState } from "react";
import Image from "next/image";
-import { BookOpen, Layers3, LayoutGrid } from "lucide-react";
+import { BookOpen, GitFork, Layers3, LayoutGrid } from "lucide-react";
import { CATEGORIES, STACKS, libraries } from "@/data/libraries";
import { SearchBar } from "./SearchBar";
import { Button } from "@/components/ui/button";
@@ -88,6 +88,7 @@ export function LibraryExplorer() {
{ value: `${libraries.length}`, label: "Curated libraries", Icon: BookOpen },
{ value: `${CATEGORIES.length}`, label: "Categories", Icon: LayoutGrid },
{ value: `${STACKS.length}`, label: "Tech stacks", Icon: Layers3 },
+ { value: "100%", label: "Open source", Icon: GitFork },
];
return (
@@ -112,7 +113,7 @@ export function LibraryExplorer() {
the libraries that developers love, all in one place
- Discover UI libraries, components, and tools by stack and use case.
+ Discover, explore, and use the best open source libraries, components, and tools in one place. Curated by developers for developers.
-
+
{stats.map(({ value, label, Icon }, index) => (
0 ? "border-l" : ""}`}>
diff --git a/components/Marquee.tsx b/components/Marquee.tsx
new file mode 100644
index 0000000..9a5d1a1
--- /dev/null
+++ b/components/Marquee.tsx
@@ -0,0 +1,22 @@
+import { libraries } from "@/data/libraries";
+
+export function Marquee() {
+ const names = libraries.map((l) => l.name);
+ // Rendered twice side-by-side so translateX(-50%) loops seamlessly.
+ const row = [...names, ...names];
+
+ return (
+
+
+ {row.map((name, i) => (
+
+
+ {name}
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/components/RevealText.tsx b/components/RevealText.tsx
new file mode 100644
index 0000000..8295f3a
--- /dev/null
+++ b/components/RevealText.tsx
@@ -0,0 +1,53 @@
+"use client";
+
+import { useRef } from "react";
+import gsap from "gsap";
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import { useGSAP } from "@gsap/react";
+
+gsap.registerPlugin(ScrollTrigger);
+
+interface RevealTextProps {
+ text: string;
+ className?: string;
+}
+
+/** Words scrub from dim to fully lit as the user scrolls through them. */
+export function RevealText({ text, className = "" }: RevealTextProps) {
+ const ref = useRef(null);
+
+ useGSAP(
+ () => {
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
+ const words = ref.current?.querySelectorAll("[data-word]");
+ if (!words?.length) return;
+ gsap.fromTo(
+ words,
+ { opacity: 0.12 },
+ {
+ opacity: 1,
+ stagger: 0.06,
+ ease: "none",
+ scrollTrigger: {
+ trigger: ref.current,
+ start: "top 82%",
+ end: "bottom 45%",
+ scrub: 0.6,
+ },
+ },
+ );
+ },
+ { scope: ref },
+ );
+
+ return (
+
+ {text.split(" ").map((word, i) => (
+
+ {word}
+ {i < text.split(" ").length - 1 ? "\u00A0" : ""}
+
+ ))}
+
+ );
+}
diff --git a/components/ScreendevShader.tsx b/components/ScreendevShader.tsx
index 92fc48f..7757b1a 100644
--- a/components/ScreendevShader.tsx
+++ b/components/ScreendevShader.tsx
@@ -236,7 +236,7 @@ export function ScreendevShader({ theme = "dark", background, time, onError, cla
const UNIFORM_FLOATS = 12;
-async function createShader(canvas: HTMLCanvasElement, options: ShaderOptions = {}): Promise {
+export async function createShader(canvas: HTMLCanvasElement, options: ShaderOptions = {}): Promise {
const dark = parseHex(options.background?.dark ?? "#090909");
const light = parseHex(options.background?.light ?? "#ffffff");
options.signal?.throwIfAborted();
diff --git a/components/SearchBar.tsx b/components/SearchBar.tsx
index 9413853..f19949a 100644
--- a/components/SearchBar.tsx
+++ b/components/SearchBar.tsx
@@ -19,11 +19,6 @@ export function SearchBar({ value, onChange, onSubmit }: SearchBarProps) {
const inputRef = useRef(null);
useEffect(() => {
- const focusHash = () => {
- if (window.location.hash === "#hero-search") inputRef.current?.focus();
- };
- focusHash();
- window.addEventListener("hashchange", focusHash);
const handleShortcut = (event: KeyboardEvent) => {
const isTyping = event.target instanceof HTMLElement && (
event.target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(event.target.tagName)
@@ -37,10 +32,7 @@ export function SearchBar({ value, onChange, onSubmit }: SearchBarProps) {
};
window.addEventListener("keydown", handleShortcut);
- return () => {
- window.removeEventListener("keydown", handleShortcut);
- window.removeEventListener("hashchange", focusHash);
- };
+ return () => window.removeEventListener("keydown", handleShortcut);
}, []);
const submit = (event: FormEvent) => {
@@ -76,7 +68,7 @@ export function SearchBar({ value, onChange, onSubmit }: SearchBarProps) {
aria-label="Search UI libraries"
className="hero-search-input h-full min-w-0 flex-1 bg-transparent text-[15px] outline-none placeholder:text-transparent focus:placeholder:text-white/45 [&::-webkit-search-cancel-button]:hidden"
/>
- Ctrl/⌘ K
+ ⌘ K
diff --git a/components/ThemeToggle.tsx b/components/ThemeToggle.tsx
index 3767f99..38d6e72 100644
--- a/components/ThemeToggle.tsx
+++ b/components/ThemeToggle.tsx
@@ -30,8 +30,8 @@ export function ThemeToggle() {
const applyTheme = () => {
root.classList.toggle("light", nextLight);
root.classList.toggle("dark", !nextLight);
+ localStorage.setItem("col:theme", nextLight ? "light" : "dark");
setLight(nextLight);
- try { localStorage.setItem("col:theme", nextLight ? "light" : "dark"); } catch { /* Keep the theme for this session. */ }
};
const startViewTransition = (document as DocumentWithViewTransitions).startViewTransition;
@@ -59,14 +59,7 @@ export function ThemeToggle() {
const radius = (maxRadius / (Math.hypot(viewportWidth, viewportHeight) / Math.SQRT2)) * 100;
transitioning.current = true;
- let transition: ThemeViewTransition;
- try {
- transition = startViewTransition.call(document, () => flushSync(applyTheme));
- } catch {
- transitioning.current = false;
- applyTheme();
- return;
- }
+ const transition = startViewTransition.call(document, () => flushSync(applyTheme));
transition.ready
.then(() => {
root.animate(
diff --git a/components/shader-runtime.test.mjs b/components/shader-runtime.test.mjs
index ea32683..7ea9075 100644
--- a/components/shader-runtime.test.mjs
+++ b/components/shader-runtime.test.mjs
@@ -1,8 +1,6 @@
import assert from "node:assert/strict";
import { test } from "node:test";
-import { loadTs } from "../tests/load-ts.mjs";
-
-const { parseHex } = await loadTs("../components/shader-runtime.ts");
+import { parseHex } from "./shader-runtime.ts";
test("shader backgrounds require six digit hex colours", () => {
assert.deepEqual(parseHex(" #ff8000 "), [1, 128 / 255, 0]);
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
index 5b23277..1a94cc5 100644
--- a/components/ui/badge.tsx
+++ b/components/ui/badge.tsx
@@ -1,6 +1,6 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
-import { cn } from "@/lib/utils"
+import { cn } from "cn"
import { Slot } from "radix-ui"
const badgeVariants = cva(
@@ -44,4 +44,4 @@ function Badge({
)
}
-export { Badge }
+export { Badge, badgeVariants }
diff --git a/components/ui/border-beam-search.tsx b/components/ui/border-beam-search.tsx
new file mode 100644
index 0000000..caddeb4
--- /dev/null
+++ b/components/ui/border-beam-search.tsx
@@ -0,0 +1,17 @@
+import { BorderBeam } from "border-beam";
+import type {
+ BorderBeamProps,
+ BorderBeamSize,
+ BorderBeamTheme,
+ BorderBeamColorVariant,
+} from "border-beam";
+
+export type {
+ BorderBeamProps,
+ BorderBeamSize,
+ BorderBeamTheme,
+ BorderBeamColorVariant,
+};
+
+export { BorderBeam };
+export default BorderBeam;
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
index 19f9910..e3345d9 100644
--- a/components/ui/button.tsx
+++ b/components/ui/button.tsx
@@ -1,6 +1,6 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
-import { cn } from "@/lib/utils"
+import { cn } from "cn"
import { Slot } from "radix-ui"
const buttonVariants = cva(
@@ -60,4 +60,4 @@ function Button({
)
}
-export { Button }
+export { Button, buttonVariants }
diff --git a/components/ui/card.tsx b/components/ui/card.tsx
index 0db7230..6aebd4c 100644
--- a/components/ui/card.tsx
+++ b/components/ui/card.tsx
@@ -1,5 +1,5 @@
import * as React from "react"
-import { cn } from "@/lib/utils"
+import { cn } from "cn"
function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
@@ -37,6 +37,16 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
)
}
+function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
) {
- return
+function DropdownMenu({
+ ...props
+}: React.ComponentProps
) {
+ return
}
-function DropdownMenuTrigger(props: React.ComponentProps) {
- return
+function DropdownMenuPortal({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuTrigger({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
}
-function DropdownMenuContent({ className, sideOffset = 4, ...props }: React.ComponentProps) {
+function DropdownMenuContent({
+ className,
+ sideOffset = 4,
+ ...props
+}: React.ComponentProps) {
return (
-
-
+
-
+
)
}
-function DropdownMenuRadioGroup(props: React.ComponentProps) {
- return
+function DropdownMenuGroup({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
}
-function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps) {
+function DropdownMenuItem({
+ className,
+ inset,
+ variant = "default",
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+ variant?: "default" | "destructive"
+}) {
return (
-
+ )
+}
+
+function DropdownMenuCheckboxItem({
+ className,
+ children,
+ checked,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function DropdownMenuRadioGroup({
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuRadioItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
-
+
+
+
{children}
-
+
+ )
+}
+
+function DropdownMenuLabel({
+ className,
+ inset,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ )
+}
+
+function DropdownMenuSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function DropdownMenuShortcut({
+ className,
+ ...props
+}: React.ComponentProps<"span">) {
+ return (
+
+ )
+}
+
+function DropdownMenuSub({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function DropdownMenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: React.ComponentProps & {
+ inset?: boolean
+}) {
+ return (
+
+ {children}
+
+
)
}
-export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem }
+function DropdownMenuSubContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export {
+ DropdownMenu,
+ DropdownMenuPortal,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuGroup,
+ DropdownMenuLabel,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuSub,
+ DropdownMenuSubTrigger,
+ DropdownMenuSubContent,
+}
diff --git a/components/ui/glowing-effect.tsx b/components/ui/glowing-effect.tsx
new file mode 100644
index 0000000..f7ebdd7
--- /dev/null
+++ b/components/ui/glowing-effect.tsx
@@ -0,0 +1,190 @@
+"use client";
+
+import { memo, useCallback, useEffect, useRef } from "react";
+import { cn } from "@/lib/utils";
+import { animate } from "motion/react";
+
+interface GlowingEffectProps {
+ blur?: number;
+ inactiveZone?: number;
+ proximity?: number;
+ spread?: number;
+ variant?: "default" | "white";
+ glow?: boolean;
+ className?: string;
+ disabled?: boolean;
+ movementDuration?: number;
+ borderWidth?: number;
+}
+const GlowingEffect = memo(
+ ({
+ blur = 0,
+ inactiveZone = 0.7,
+ proximity = 0,
+ spread = 20,
+ variant = "default",
+ glow = false,
+ className,
+ movementDuration = 2,
+ borderWidth = 1,
+ disabled = true,
+ }: GlowingEffectProps) => {
+ const containerRef = useRef(null);
+ const lastPosition = useRef({ x: 0, y: 0 });
+ const animationFrameRef = useRef(0);
+
+ const handleMove = useCallback(
+ (e?: MouseEvent | { x: number; y: number }) => {
+ if (!containerRef.current) return;
+
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ }
+
+ animationFrameRef.current = requestAnimationFrame(() => {
+ const element = containerRef.current;
+ if (!element) return;
+
+ const { left, top, width, height } = element.getBoundingClientRect();
+ const mouseX = e?.x ?? lastPosition.current.x;
+ const mouseY = e?.y ?? lastPosition.current.y;
+
+ if (e) {
+ lastPosition.current = { x: mouseX, y: mouseY };
+ }
+
+ const center = [left + width * 0.5, top + height * 0.5];
+ const distanceFromCenter = Math.hypot(
+ mouseX - center[0],
+ mouseY - center[1]
+ );
+ const inactiveRadius = 0.5 * Math.min(width, height) * inactiveZone;
+
+ if (distanceFromCenter < inactiveRadius) {
+ element.style.setProperty("--active", "0");
+ return;
+ }
+
+ const isActive =
+ mouseX > left - proximity &&
+ mouseX < left + width + proximity &&
+ mouseY > top - proximity &&
+ mouseY < top + height + proximity;
+
+ element.style.setProperty("--active", isActive ? "1" : "0");
+
+ if (!isActive) return;
+
+ const currentAngle =
+ parseFloat(element.style.getPropertyValue("--start")) || 0;
+ let targetAngle =
+ (180 * Math.atan2(mouseY - center[1], mouseX - center[0])) /
+ Math.PI +
+ 90;
+
+ const angleDiff = ((targetAngle - currentAngle + 180) % 360) - 180;
+ const newAngle = currentAngle + angleDiff;
+
+ animate(currentAngle, newAngle, {
+ duration: movementDuration,
+ ease: [0.16, 1, 0.3, 1],
+ onUpdate: (value) => {
+ element.style.setProperty("--start", String(value));
+ },
+ });
+ });
+ },
+ [inactiveZone, proximity, movementDuration]
+ );
+
+ useEffect(() => {
+ if (disabled) return;
+
+ const handleScroll = () => handleMove();
+ const handlePointerMove = (e: PointerEvent) => handleMove(e);
+
+ window.addEventListener("scroll", handleScroll, { passive: true });
+ document.body.addEventListener("pointermove", handlePointerMove, {
+ passive: true,
+ });
+
+ return () => {
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ }
+ window.removeEventListener("scroll", handleScroll);
+ document.body.removeEventListener("pointermove", handlePointerMove);
+ };
+ }, [handleMove, disabled]);
+
+ return (
+ <>
+
+ 0 && "blur-[var(--blur)] ",
+ className,
+ disabled && "!hidden"
+ )}
+ >
+
+
+ >
+ );
+ }
+);
+
+GlowingEffect.displayName = "GlowingEffect";
+
+export { GlowingEffect };
diff --git a/components/ui/hover-border-gradient.tsx b/components/ui/hover-border-gradient.tsx
new file mode 100644
index 0000000..1afdd19
--- /dev/null
+++ b/components/ui/hover-border-gradient.tsx
@@ -0,0 +1,99 @@
+"use client";
+import React, { useState, useEffect, useRef } from "react";
+
+import { motion } from "motion/react";
+import { cn } from "@/lib/utils";
+
+type Direction = "TOP" | "LEFT" | "BOTTOM" | "RIGHT";
+
+export function HoverBorderGradient({
+ children,
+ containerClassName,
+ className,
+ as: Tag = "button",
+ duration = 1,
+ clockwise = true,
+ ...props
+}: React.PropsWithChildren<
+ {
+ as?: React.ElementType;
+ containerClassName?: string;
+ className?: string;
+ duration?: number;
+ clockwise?: boolean;
+ } & React.HTMLAttributes
+>) {
+ const [hovered, setHovered] = useState(false);
+ const [direction, setDirection] = useState("TOP");
+
+ const rotateDirection = (currentDirection: Direction): Direction => {
+ const directions: Direction[] = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
+ const currentIndex = directions.indexOf(currentDirection);
+ const nextIndex = clockwise
+ ? (currentIndex - 1 + directions.length) % directions.length
+ : (currentIndex + 1) % directions.length;
+ return directions[nextIndex];
+ };
+
+ const movingMap: Record = {
+ TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
+ LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
+ BOTTOM:
+ "radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
+ RIGHT:
+ "radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
+ };
+
+ const highlight =
+ "radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
+
+ useEffect(() => {
+ if (!hovered) {
+ const interval = setInterval(() => {
+ setDirection((prevState) => rotateDirection(prevState));
+ }, duration * 1000);
+ return () => clearInterval(interval);
+ }
+ }, [hovered]);
+ return (
+ ) => {
+ setHovered(true);
+ }}
+ onMouseLeave={() => setHovered(false)}
+ className={cn(
+ "relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap gap-10 h-min justify-center overflow-visible p-px decoration-clone w-fit",
+ containerClassName
+ )}
+ {...props}
+ >
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
index 1e3b932..ddb9b31 100644
--- a/components/ui/input.tsx
+++ b/components/ui/input.tsx
@@ -1,5 +1,5 @@
import * as React from "react"
-import { cn } from "@/lib/utils"
+import { cn } from "cn"
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
diff --git a/components/ui/magnet.tsx b/components/ui/magnet.tsx
new file mode 100644
index 0000000..468d6cb
--- /dev/null
+++ b/components/ui/magnet.tsx
@@ -0,0 +1,88 @@
+"use client";
+
+import React, {
+ useEffect,
+ useRef,
+ useState,
+ type HTMLAttributes,
+ type ReactNode,
+} from "react";
+
+interface MagnetProps extends HTMLAttributes {
+ children: ReactNode;
+ padding?: number;
+ disabled?: boolean;
+ magnetStrength?: number;
+ activeTransition?: string;
+ inactiveTransition?: string;
+ wrapperClassName?: string;
+ innerClassName?: string;
+}
+
+export default function Magnet({
+ children,
+ padding = 100,
+ disabled = false,
+ magnetStrength = 2,
+ activeTransition = "transform 0.3s ease-out",
+ inactiveTransition = "transform 0.5s ease-in-out",
+ wrapperClassName = "",
+ innerClassName = "",
+ ...props
+}: MagnetProps) {
+ const [isActive, setIsActive] = useState(false);
+ const [position, setPosition] = useState({ x: 0, y: 0 });
+ const magnetRef = useRef(null);
+
+ useEffect(() => {
+ if (disabled) {
+ setPosition({ x: 0, y: 0 });
+ return;
+ }
+
+ const handleMouseMove = (event: MouseEvent) => {
+ if (!magnetRef.current) return;
+
+ const { left, top, width, height } =
+ magnetRef.current.getBoundingClientRect();
+ const centerX = left + width / 2;
+ const centerY = top + height / 2;
+ const distX = Math.abs(centerX - event.clientX);
+ const distY = Math.abs(centerY - event.clientY);
+
+ if (distX < width / 2 + padding && distY < height / 2 + padding) {
+ setIsActive(true);
+ setPosition({
+ x: (event.clientX - centerX) / magnetStrength,
+ y: (event.clientY - centerY) / magnetStrength,
+ });
+ } else {
+ setIsActive(false);
+ setPosition({ x: 0, y: 0 });
+ }
+ };
+
+ window.addEventListener("mousemove", handleMouseMove);
+ return () => window.removeEventListener("mousemove", handleMouseMove);
+ }, [padding, disabled, magnetStrength]);
+
+ return (
+
+ );
+}
diff --git a/components/ui/rainbow-button.tsx b/components/ui/rainbow-button.tsx
index 84fb678..3cb9b37 100644
--- a/components/ui/rainbow-button.tsx
+++ b/components/ui/rainbow-button.tsx
@@ -58,4 +58,4 @@ const RainbowButton = React.forwardRef(
RainbowButton.displayName = "RainbowButton"
-export { RainbowButton }
+export { RainbowButton, rainbowButtonVariants, type RainbowButtonProps }
diff --git a/components/ui/select.tsx b/components/ui/select.tsx
new file mode 100644
index 0000000..8058e26
--- /dev/null
+++ b/components/ui/select.tsx
@@ -0,0 +1,189 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
+import { Select as SelectPrimitive } from "radix-ui"
+
+function Select({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectGroup({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectValue({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: React.ComponentProps & {
+ size?: "sm" | "default"
+}) {
+ return (
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectContent({
+ className,
+ children,
+ position = "item-aligned",
+ align = "center",
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectLabel({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+}
diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx
new file mode 100644
index 0000000..6a553b9
--- /dev/null
+++ b/components/ui/separator.tsx
@@ -0,0 +1,27 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { Separator as SeparatorPrimitive } from "radix-ui"
+
+function Separator({
+ className,
+ orientation = "horizontal",
+ decorative = true,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Separator }
diff --git a/components/ui/star-border.tsx b/components/ui/star-border.tsx
new file mode 100644
index 0000000..35af2aa
--- /dev/null
+++ b/components/ui/star-border.tsx
@@ -0,0 +1,48 @@
+import type { CSSProperties, HTMLAttributes, ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+interface StarBorderProps extends Omit, "color"> {
+ children: ReactNode;
+ color?: string;
+ speed?: CSSProperties["animationDuration"];
+ thickness?: number;
+}
+
+export function StarBorder({
+ children,
+ className,
+ color = "white",
+ speed = "6s",
+ style,
+ thickness = 1,
+ ...props
+}: StarBorderProps) {
+ const starStyle: CSSProperties = {
+ background: `radial-gradient(circle, ${color}, transparent 10%)`,
+ animationDuration: speed,
+ animationTimingFunction: "linear",
+ animationIterationCount: "infinite",
+ animationDirection: "alternate",
+ filter: "drop-shadow(0 0 8px var(--col-blue))",
+ };
+
+ return (
+
+ );
+}
diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx
new file mode 100644
index 0000000..6e17474
--- /dev/null
+++ b/components/ui/tabs.tsx
@@ -0,0 +1,90 @@
+"use client"
+
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+import { cn } from "cn"
+import { Tabs as TabsPrimitive } from "radix-ui"
+
+function Tabs({
+ className,
+ orientation = "horizontal",
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+const tabsListVariants = cva(
+ "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none",
+ {
+ variants: {
+ variant: {
+ default: "bg-muted",
+ line: "gap-1 bg-transparent",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+function TabsList({
+ className,
+ variant = "default",
+ ...props
+}: React.ComponentProps &
+ VariantProps) {
+ return (
+
+ )
+}
+
+function TabsTrigger({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function TabsContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
diff --git a/data/libraries.ts b/data/libraries.ts
index 9460dfd..5da2cbc 100644
--- a/data/libraries.ts
+++ b/data/libraries.ts
@@ -63,7 +63,7 @@ export const libraries: Library[] = [
name: "21st.dev",
slug: "21st-dev",
description:
- "A marketplace of community-built React components, installable in one command.",
+ "A marketplace of production-ready React components built by the community, installable in one command.",
url: "https://21st.dev",
category: "Component Library",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -82,11 +82,11 @@ export const libraries: Library[] = [
tags: ["animated", "text effects", "backgrounds"],
},
{
- name: "Transitions.dev",
- slug: "transitions-dev",
+ name: "Transition.dev",
+ slug: "transition-dev",
description:
- "A collection of copyable UI transitions for web applications.",
- url: "https://transitions.dev",
+ "Ready-to-use animated transitions and motion primitives for modern React apps.",
+ url: "https://transition.dev",
category: "Animation & Motion",
stacks: ["React", "TypeScript"],
useCases: ["Micro-interactions", "Marketing Sites"],
@@ -96,7 +96,7 @@ export const libraries: Library[] = [
name: "shadcn/ui",
slug: "shadcn-ui",
description:
- "Accessible components you copy into your project, built on Radix UI and Tailwind CSS.",
+ "Beautifully designed, accessible components you copy into your project. Built on Radix UI and Tailwind CSS.",
url: "https://ui.shadcn.com",
category: "Component Library",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -118,7 +118,7 @@ export const libraries: Library[] = [
name: "Aceternity UI",
slug: "aceternity-ui",
description:
- "Animated components and sections, including hero effects, 3D cards, and scroll experiences.",
+ "Trendy animated components and sections — hero effects, 3D cards, and scroll experiences for modern websites.",
url: "https://ui.aceternity.com",
category: "Animation & Motion",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -129,10 +129,10 @@ export const libraries: Library[] = [
name: "Motion",
slug: "motion",
description:
- "An animation library for React, Vue, and JavaScript (formerly Framer Motion).",
+ "A powerful, production-ready animation library for React and JavaScript (formerly Framer Motion).",
url: "https://motion.dev",
category: "Animation & Motion",
- stacks: ["React", "Vue", "Vanilla JS", "TypeScript"],
+ stacks: ["React", "Vanilla JS", "TypeScript"],
useCases: ["Micro-interactions", "Creative & Experimental"],
tags: ["framer motion", "gestures", "spring"],
},
@@ -140,7 +140,7 @@ export const libraries: Library[] = [
name: "GSAP",
slug: "gsap",
description:
- "A JavaScript animation library with ScrollTrigger, timelines, and physics-based motion.",
+ "The industry-standard JavaScript animation library with ScrollTrigger, timelines, and physics-based motion.",
url: "https://gsap.com",
category: "Animation & Motion",
stacks: ["Vanilla JS", "React", "Vue", "TypeScript"],
@@ -151,7 +151,7 @@ export const libraries: Library[] = [
name: "Radix UI",
slug: "radix-ui",
description:
- "Unstyled, accessible primitives for building design systems and web apps in React.",
+ "Unstyled, accessible primitives for building high-quality design systems and web apps in React.",
url: "https://www.radix-ui.com",
category: "Component Library",
stacks: ["React", "TypeScript"],
@@ -173,7 +173,7 @@ export const libraries: Library[] = [
name: "HeroUI",
slug: "heroui",
description:
- "A React UI library with built-in theming (formerly NextUI).",
+ "Beautiful, fast and modern React UI library with built-in theming (formerly NextUI).",
url: "https://www.heroui.com",
category: "Component Library",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -206,7 +206,7 @@ export const libraries: Library[] = [
name: "Material UI (MUI)",
slug: "mui",
description:
- "A React implementation of Google's Material Design with components and customization tools.",
+ "The most popular React implementation of Google's Material Design, with a huge ecosystem.",
url: "https://mui.com",
category: "Component Library",
stacks: ["React", "TypeScript"],
@@ -217,7 +217,7 @@ export const libraries: Library[] = [
name: "Ant Design",
slug: "ant-design",
description:
- "A React UI design system with components for enterprise applications.",
+ "An enterprise-class React UI design system with a rich set of high-quality components.",
url: "https://ant.design",
category: "Component Library",
stacks: ["React", "TypeScript"],
@@ -228,7 +228,7 @@ export const libraries: Library[] = [
name: "daisyUI",
slug: "daisyui",
description:
- "A Tailwind CSS component plugin with semantic class names and no JavaScript requirement.",
+ "The most popular component library plugin for Tailwind CSS — semantic class names, zero JS required.",
url: "https://daisyui.com",
category: "CSS Framework",
stacks: ["Tailwind CSS", "Vanilla JS"],
@@ -272,7 +272,7 @@ export const libraries: Library[] = [
name: "Origin UI",
slug: "origin-ui",
description:
- "Copy-and-paste components built with Tailwind CSS and React, focused on inputs and application UI.",
+ "Beautiful copy-and-paste components built with Tailwind CSS and React, focused on inputs and application UI.",
url: "https://originui.com",
category: "Component Library",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -283,7 +283,7 @@ export const libraries: Library[] = [
name: "Motion Primitives",
slug: "motion-primitives",
description:
- "Animated components powered by Motion that you can copy and customize.",
+ "Beautifully designed, animated components powered by Motion — copy, paste, and customize.",
url: "https://motion-primitives.com",
category: "Animation & Motion",
stacks: ["React", "Tailwind CSS", "TypeScript"],
@@ -305,7 +305,7 @@ export const libraries: Library[] = [
name: "Lucide",
slug: "lucide",
description:
- "Open-source icons available for React, Vue, Svelte, Angular, and vanilla JavaScript.",
+ "Beautiful, consistent open-source icons — a community fork of Feather Icons for every framework.",
url: "https://lucide.dev",
category: "Icons",
stacks: ["React", "Vue", "Svelte", "Angular", "Vanilla JS"],
@@ -317,7 +317,7 @@ export const libraries: Library[] = [
slug: "recharts",
description:
"A composable, React-native charting library built on SVG components.",
- url: "https://recharts.github.io/en-US/",
+ url: "https://recharts.org",
category: "Charts & Data Viz",
stacks: ["React", "TypeScript"],
useCases: ["Data Visualization", "Dashboards"],
@@ -360,7 +360,7 @@ export const libraries: Library[] = [
name: "PrimeVue",
slug: "primevue",
description:
- "A Vue component suite with 90+ components, themes, and blocks.",
+ "The most complete UI component suite for Vue — 90+ components, themes, and blocks.",
url: "https://primevue.org",
category: "Component Library",
stacks: ["Vue", "TypeScript"],
diff --git a/documents/cleanups/repository-audit-remediation.md b/documents/cleanups/repository-audit-remediation.md
deleted file mode 100644
index 98746ed..0000000
--- a/documents/cleanups/repository-audit-remediation.md
+++ /dev/null
@@ -1,508 +0,0 @@
-# Col repository audit remediation
-
-## Objective
-
-Fix the confirmed release, runtime, accessibility, metadata, testing, and dead-code problems found during the repository audit.
-
-Work through the units in order. Finish and verify one unit before starting the next so later changes do not rely on a broken foundation.
-
-## Working rules
-
-- Preserve the current product design and behavior unless a unit explicitly changes them.
-- Keep the diff focused on the unit being completed.
-- Do not redesign the site while completing maintenance work.
-- Use npm as the package manager because `README.md` and `CONTRIBUTING.md` already instruct contributors to use npm.
-- Preserve unrelated user changes. Do not reset or overwrite work that appears while this plan is being executed.
-- Do not add compatibility wrappers for code that can be deleted cleanly.
-- Do not commit or push unless the user explicitly requests it.
-- Keep `@webgpu/types`; the shader code and `tsconfig.json` require it.
-- Prefer deletion over new abstractions.
-- Add or update tests when a change has a stable test seam.
-
-## Baseline findings
-
-The following were confirmed before this plan was written:
-
-- `npm run build` passes.
-- `npx tsc --noEmit` passes.
-- `node --test` passes under the current Node version after a build.
-- `npm audit` reports zero known vulnerabilities.
-- `npm ci --dry-run` fails because `package-lock.json` is missing `@webgpu/types`.
-- `/libraries?q=react&q=vue` returns HTTP 500.
-- The shader test fails under Node 20.20.2 because it imports TypeScript directly.
-- Knip reports unused application files and four dependencies used only by dead files.
-
-A clean dependency install must work before any dependency cleanup is considered reliable.
-
----
-
-## Unit 1: Repair the package-management baseline
-
-### Problems
-
-- `package.json:32` declares `@webgpu/types`.
-- `package-lock.json:26-33` does not contain `@webgpu/types`.
-- The repository contains both `package-lock.json` and `pnpm-lock.yaml`.
-- `pnpm-workspace.yaml` contains release-age exclusions but the contributor documentation uses npm.
-- `package.json:2` and the lockfile still name the package `coc` instead of `col`.
-- There is no `packageManager` declaration or dedicated type-check/test script.
-
-### Work
-
-1. Rename the package from `coc` to a valid lowercase npm name, preferably `col`.
-2. Regenerate `package-lock.json` so it includes `@webgpu/types` and matches `package.json`.
-3. Verify no workflow or script depends on pnpm.
-4. Remove `pnpm-lock.yaml` and `pnpm-workspace.yaml` after the npm lockfile passes a clean-install check.
-5. Add an explicit package-manager version only if the selected npm version is intended to be enforced.
-6. Add `typecheck`, `test`, and a combined verification script.
-
-Suggested scripts:
-
-```json
-{
- "typecheck": "tsc --noEmit",
- "test": "node --test",
- "check": "npm run typecheck && npm run test && npm run build"
-}
-```
-
-Adjust the test script only if Unit 2 introduces a required build fixture.
-
-### Completion criteria
-
-- `npm ci` succeeds from a clean dependency state.
-- `npm run typecheck` succeeds.
-- The package and lockfile use the same valid package name.
-- Exactly one supported lockfile remains.
-- `git diff --check` passes.
-
----
-
-## Unit 2: Make the test suite reliable and supported
-
-### Problems
-
-- `package.json` has no `test` script.
-- The documented contributor workflow runs only `npm run build`.
-- `tests/discovery.test.mjs` reads private `.next/server/app/*.body` files and fails on a clean checkout unless a build ran first.
-- The discovery test duplicates route expectations instead of using the route source of truth.
-- `components/shader-runtime.test.mjs` imports `shader-runtime.ts` directly and fails under the documented Node.js 20.9+ minimum.
-- There is no CI workflow.
-- Core search, filtering, local saving, theme behavior, route input, and accessibility flows have no coverage.
-
-### Work
-
-1. Make `components/shader-runtime.test.mjs` compatible with the minimum supported Node version. Transpile the small TypeScript module in the test instead of relying on Node's direct TypeScript loader.
-2. Refactor `tests/discovery.test.mjs` so it does not depend on private Next.js build-output paths or run-order state.
-3. Prefer testing route functions and registry data directly. Keep a separate production smoke test for rendered routes if needed.
-4. Import shared route metadata from its source of truth instead of hard-coding it in the test.
-5. Add a CI workflow that installs with `npm ci`, type-checks, tests, and builds.
-6. Update `README.md` and `CONTRIBUTING.md` to use the supported verification command.
-7. Add focused tests for:
- - repeated and malformed `q` route input;
- - search token matching;
- - stack and use-case filter intersection;
- - sorting;
- - local-save parsing and stale slug reconciliation;
- - registry slug, URL, and taxonomy invariants.
-
-### Completion criteria
-
-- `npm test` succeeds under the current environment.
-- The shader test succeeds under Node 20.
-- The discovery test succeeds without relying on a previous ad hoc build.
-- A clean CI run passes `npm ci`, type-check, tests, and build.
-- The documented verification command runs every required check.
-
----
-
-## Unit 3: Fix route input and saved-library state
-
-### Problems
-
-#### Duplicate query crash
-
-`app/libraries/page.tsx:4-5` types `q` as a string, but Next.js can supply `string[]`. The value reaches `components/DirectoryExplorer.tsx:48`, where `query.toLowerCase()` throws.
-
-Confirmed failure:
-
-```text
-/libraries?q=react&q=vue
-HTTP 500
-TypeError: b.toLowerCase is not a function
-```
-
-#### Cross-tab save loss
-
-`components/DirectoryExplorer.tsx:38-45` loads saved slugs once. Each tab then writes its complete stale `Set` at `components/DirectoryExplorer.tsx:60-67`, so one tab can erase another tab's saves.
-
-#### Stale saved slugs
-
-The saved count accepts any string and never checks whether the slug still exists in `libraries`. Removed or renamed entries can inflate the count and produce an empty saved view.
-
-### Work
-
-1. Parse `q` at the route boundary using the smallest boundary type that represents Next.js input.
-2. Define one deterministic policy for repeated values, such as accepting the first string.
-3. Add a regression test for the confirmed repeated-query URL.
-4. Reconcile stored saved slugs with the current registry when loading them.
-5. Write saves using the latest local storage value rather than only the component's initial state.
-6. Listen for the browser `storage` event so open tabs update their UI.
-7. Keep saved state functional for the current session when storage is unavailable.
-
-### Completion criteria
-
-- Repeated `q` parameters return a valid filtered page rather than HTTP 500.
-- A removed slug no longer contributes to the saved count.
-- Two tabs can save different libraries without erasing each other's changes.
-- Regression tests cover the repeated-query and stale-slug cases.
-
----
-
-## Unit 4: Correct product claims and stale registry data
-
-### Problems
-
-#### Open-source claim
-
-`components/LibraryExplorer.tsx:87-92` displays `100% Open source`, and `components/LibraryExplorer.tsx:115-117` describes every entry as open source.
-
-The registry has no license field. GSAP uses Webflow's proprietary no-charge license, which is not an OSI open-source license. 21st.dev is a marketplace whose entries can have different licenses.
-
-#### Stale entries
-
-- `data/libraries.ts:85-93` uses `Transition.dev` and `https://transition.dev`; the current project is `Transitions.dev` at `https://transitions.dev`.
-- `data/libraries.ts:316-324` uses `https://recharts.org`; that address now says the project has moved and points to `https://recharts.github.io/en-US/`.
-- Motion at `data/libraries.ts:129-137` omits its first-class Vue target.
-- Lucide's description says it works with every framework, while the registry taxonomy cannot represent several official targets.
-
-#### Promotional copy
-
-Several descriptions use subjective claims that conflict with the repository's factual-copy policy.
-
-### Work
-
-1. Remove the hardcoded `100% Open source` percentage and replace it with a factual, supportable label such as `Curated libraries`.
-2. Rewrite the hero copy so it does not claim every listed resource is open source.
-3. Correct the Transitions.dev name, slug, and canonical URL.
-4. Update the Recharts URL to its current canonical documentation.
-5. Add Vue to Motion's supported stacks after confirming the official project documentation.
-6. Resolve the Lucide mismatch by either narrowing its description to the supported taxonomy or expanding the taxonomy intentionally. Do not claim coverage the filters cannot express.
-7. Replace subjective terms such as `trendy`, `powerful`, `industry-standard`, `most popular`, and `most complete` with factual descriptions.
-8. Add registry validation for:
- - unique lowercase kebab-case slugs;
- - unique names;
- - non-empty required fields;
- - HTTPS URLs;
- - values drawn from the declared taxonomy;
- - no duplicate values inside stack or use-case arrays.
-9. Add a test for these local invariants. Do not add network-dependent link-health checks to the normal test suite.
-
-### Completion criteria
-
-- The site makes no unsupported universal open-source claim.
-- Transitions.dev and Recharts resolve to their current canonical projects.
-- Motion is discoverable through the Vue filter.
-- Registry validation fails on malformed or duplicate metadata.
-- Registry descriptions remain factual and do not present unverified popularity or quality claims.
-
----
-
-## Unit 5: Fix keyboard and screen-reader behavior
-
-### Problems
-
-#### Filter focus
-
-`app/globals.css:496-518` makes focused dropdown items transparent and removes their outline. Keyboard users cannot see the focused option.
-
-#### Search focus
-
-`components/Header.tsx:36-47` and `components/Header.tsx:135-142` navigate to `/#hero-search` but do not focus the search input.
-
-The directory displays a `Ctrl K` hint at `components/FilterBar.tsx:67`, but the shortcut is only implemented by the homepage search component.
-
-#### Wrong category semantics
-
-`components/FilterBar.tsx:86-90` renders category filters as Radix Tabs without tab panels. They are filters, not tabs.
-
-#### Result announcements
-
-`components/DirectoryExplorer.tsx:89-130` changes result counts and empty states without a live status announcement.
-
-#### Focus loss
-
-Activating Clear unmounts the focused Clear button, dropping focus to the document body.
-
-#### Mobile hash navigation
-
-On the homepage, same-page hash links do not change `pathname`, so the mobile menu can remain open after navigation.
-
-### Work
-
-1. Give focused and highlighted dropdown items a visible background or outline in both themes.
-2. Make the header search link and `/` shortcut focus the homepage search input after navigation.
-3. Implement the advertised `Ctrl K`/`Cmd K` behavior on the directory search input.
-4. Replace the category Tabs pattern with controls whose ARIA semantics match filtering.
-5. Add a concise live status for the current result count and empty state.
-6. Move focus to a stable control after Clear removes the focused button.
-7. Close the mobile menu for every navigation action, including same-page hash links.
-8. Mark fragment-only navigation appropriately without incorrectly using `aria-current="page"` for a section that is not a route.
-
-### Completion criteria
-
-- Every interactive filter has a visible keyboard-focus state.
-- Search links and advertised shortcuts focus the search input.
-- Category filters expose correct accessible semantics.
-- Search result changes are announced.
-- Triggering Clear or mobile navigation never leaves focus on a removed control or an open overlay.
-- Keyboard checks are added where the project has a stable browser-test seam.
-
----
-
-## Unit 6: Make theme behavior resilient
-
-### Problems
-
-- The initialization script in `app/layout.tsx:40-42` catches storage errors without applying the system theme fallback.
-- `components/ThemeToggle.tsx:25-39` changes root classes before `localStorage.setItem`.
-- If storage throws, React state is not updated, leaving the control label and icon stale.
-- View-transition state can remain inconsistent if the theme callback throws.
-
-### Work
-
-1. Separate reading storage, resolving the preferred theme, and applying the theme.
-2. Fall back to `prefers-color-scheme` when storage is unavailable.
-3. Apply the UI state even when persistence fails.
-4. Keep persistence failure session-local rather than allowing it to corrupt theme state.
-5. Ensure a rejected view transition cannot leave the toggle permanently blocked.
-6. Add focused tests for the pure theme-resolution and persistence-failure behavior where possible.
-
-### Completion criteria
-
-- The root theme, React state, icon, and accessible label always agree.
-- Blocked storage does not break toggling.
-- A failed view transition does not lock future toggles.
-- The system theme is respected when no saved preference exists.
-
----
-
-## Unit 7: Remove dead components and dependencies
-
-### Dead component files
-
-Confirm imports once more immediately before deletion, then remove:
-
-- `components/AsciiFluid.tsx`
-- `components/CategoryBento.tsx`
-- `components/GlareHover.tsx`
-- `components/HeroLogoTrail.tsx`
-- `components/Marquee.tsx`
-- `components/RevealText.tsx`
-- `components/ui/border-beam-search.tsx`
-- `components/ui/glowing-effect.tsx`
-- `components/ui/hover-border-gradient.tsx`
-- `components/ui/magnet.tsx`
-- `components/ui/select.tsx`
-- `components/ui/separator.tsx`
-- `components/ui/star-border.tsx`
-
-`CategoryBento` and `GlareHover` are one dead subtree and should be removed together.
-
-### Dead dependencies
-
-After deleting the files that import them, remove:
-
-- `@gsap/react`
-- `gsap`
-- `border-beam`
-- `motion`
-
-Regenerate the selected lockfile after dependency removal.
-
-### Dead CSS
-
-Remove selectors used only by deleted components, including:
-
-- old `gooey-*` and `hero-search-surface` rules;
-- unused hero background modifiers;
-- unused `.delay-3`;
-- marquee-specific rules;
-- any CSS made unreferenced by the deleted components.
-
-Use source searches after deletion to confirm each selector is unused.
-
-### Completion criteria
-
-- The listed files no longer exist.
-- No route, component, test, configuration, or documented pattern references them.
-- The four dead dependencies are absent from `package.json` and the lockfile.
-- CSS made dead by the removals is also removed.
-- Type-check, tests, build, and route smoke tests pass after dependency regeneration.
-
----
-
-## Unit 8: Consolidate utilities and prune generated dead exports
-
-### Problems
-
-The project has a local `cn` implementation in `lib/utils.ts`, while active generated components import the separate `cn` package.
-
-Unused generated exports include `CardDescription`, `TabsContent`, several dropdown-menu exports, and public variant exports that are only used inside their own files.
-
-`components/ui/border-beam-search.tsx` is a pure package re-export wrapper and is removed in Unit 7.
-
-Hostname parsing is duplicated across four locations.
-
-### Work
-
-1. Confirm the local and package `cn` implementations are behaviorally equivalent for current usage.
-2. Replace active imports of the external `cn` package with `@/lib/utils`.
-3. Remove the external `cn` package and regenerate the lockfile.
-4. Remove unused generated components and exports only where the application does not intentionally expose a reusable component API.
-5. Keep conventional shadcn exports if the repository is later declared as a component distribution package. The current product is an application, so unused local surface should be pruned.
-6. Add one small hostname helper only if it centralizes meaningful invalid-URL and `www.` behavior across all callers.
-
-Do not merge the WebGL and WebGPU shader implementations. Their backend-specific rendering logic should remain separate.
-
-### Completion criteria
-
-- One `cn` implementation remains.
-- Type-check, tests, build, and route smoke tests pass.
-- The hostname helper has focused tests for valid, invalid, and `www.` URLs if it is introduced.
-- The shader backends remain independently understandable and testable.
-
----
-
-## Unit 9: Resolve dependency updates conservatively
-
-### Available updates found during the audit
-
-- Next.js `16.3.5` to `16.3.6`
-- border-beam `1.4.0` to `1.4.1`, unless removed with dead code
-- motion `13.4.0` to `13.4.2`, unless removed with dead code
-- TypeScript `5.9.3` to `7.0.2`
-- `@types/node` `24.13.6` to `26.6.2`
-
-### Work
-
-1. Complete dead dependency removal first.
-2. Apply relevant patch updates through the canonical lockfile.
-3. Evaluate TypeScript 7 and Node 26 type updates as separate compatibility work.
-4. Keep the documented Node minimum and installed type packages aligned.
-5. Do not perform major upgrades inside the cleanup branch without compatibility evidence.
-
-### Completion criteria
-
-- `npm outdated` contains no relevant patch update that can be applied safely.
-- Major-version upgrades are either completed with full verification or explicitly left out.
-- The build, tests, type-check, and route smoke tests pass after lockfile changes.
-- `npm audit` still reports no known vulnerabilities.
-
----
-
-## Unit 10: Align documentation and UI consistency
-
-### Problems
-
-- `README.md:34` and `PRODUCT.md:15` promise comparison, but the application has no comparison feature.
-- `README.md:160-169` omits `lib/` and `tests/`.
-- `/libraries` omits the site footer used by the other content routes.
-- The library request form does not collect all metadata requested by the documentation.
-- Sponsors is a hash section, not a page route, so it should not use route-level active-state logic.
-
-### Work
-
-1. Use the smallest truthful change: describe current behavior as search, filter, sort, save, and open unless comparison is explicitly approved as a new feature.
-2. Keep dedicated library pages labeled as future work unless their routes and data model are implemented.
-3. Add `lib/` and `tests/` to the project structure.
-4. Add `SiteFooter` to `/libraries` if the route is intended to have the same site chrome as the other content pages.
-5. Align the library request form with the documented required metadata, or simplify the documentation to match the form.
-6. Update screenshots or product copy only where the completed units changed actual behavior.
-
-### Completion criteria
-
-- README and product documentation describe only shipped behavior as current.
-- Future features remain clearly marked as future work.
-- All top-level content routes use consistent site chrome.
-- The contribution form collects every field required by the contributor documentation.
-
----
-
-## Unit 11: Final low-risk polish
-
-### Problems
-
-- Light-mode `.library-subtle` text at `app/globals.css:547` is approximately 3.8:1 contrast on white and is used at 10-11px.
-- `components/LibraryCard.tsx:51-52` renders `1 stacks` and `1 uses`.
-- The mobile directory's advertised keyboard hint should match actual behavior after Unit 5.
-- Sponsors active-state behavior should reflect fragment navigation without pretending it is a separate page.
-
-### Work
-
-1. Increase small metadata text contrast to at least 4.5:1 in light mode.
-2. Add correct singular and plural labels for stack and use-case counts.
-3. Re-run a dead-code and unused-export scan after all behavior changes.
-4. Review unreferenced public brand assets separately from application code. Delete abandoned design explorations only when their purpose is clear.
-5. Re-run contrast, keyboard, and responsive checks on the final artifact.
-
-### Completion criteria
-
-- Small text meets WCAG AA contrast requirements.
-- Counts read naturally for one and multiple values.
-- The final dead-code scan contains no unexplained application files or dependencies.
-- No public asset is deleted solely because it is not referenced by the application.
-
----
-
-## Final verification gate
-
-Run the repository's supported verification command after every unit. Before declaring the remediation complete, run the equivalent of:
-
-```bash
-npm ci
-npm run typecheck
-npm test
-npm run build
-npm audit
-npx --yes knip --reporter compact
-git diff --check
-```
-
-Then start the production server and smoke-test:
-
-- `/`
-- `/libraries`
-- `/libraries?q=react`
-- `/libraries?q=react&q=vue`
-- `/docs`
-- `/contributors`
-- `/robots.txt`
-- `/sitemap.xml`
-- `/llms.txt`
-
-Required outcomes:
-
-- Every route returns the expected status.
-- Repeated `q` parameters return a valid page.
-- Search, category, stack, use-case, sort, clear, and saved-library flows work.
-- Light and dark themes remain usable when storage is blocked.
-- Keyboard focus is visible and search shortcuts focus the input.
-- The final dependency audit has no known vulnerabilities.
-- Every remaining warning from Knip is explained as framework convention, test discovery, public API surface, or an accepted follow-up.
-- `git status` shows only intended changes.
-- The final response lists changed files, verification evidence, remaining risks, and anything intentionally deferred.
-
-## Explicitly deferred work
-
-Do not add these unless the user requests a new product feature after the cleanup is complete:
-
-- Side-by-side library comparison
-- Dedicated library detail routes
-- Agent setup prompts
-- Expanded library metadata beyond what the cleanup requires
-- Public component-library packaging
-- Visual redesign
-- Additional shader abstractions
-
-Keeping these deferred preserves the cleanup's focus and prevents documentation promises from turning into unrelated implementation work.
diff --git a/lib/directory.ts b/lib/directory.ts
deleted file mode 100644
index 23a0344..0000000
--- a/lib/directory.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import type { Category, Library, Stack, UseCase } from "@/data/libraries";
-
-export function firstQuery(value: string | string[] | undefined): string {
- return Array.isArray(value) ? value[0] ?? "" : value ?? "";
-}
-
-export function readSaved(raw: string | null, validSlugs: ReadonlySet): Set {
- try {
- const value: unknown = JSON.parse(raw ?? "[]");
- return new Set(Array.isArray(value) ? value.filter((slug): slug is string => typeof slug === "string" && validSlugs.has(slug)) : []);
- } catch {
- return new Set();
- }
-}
-
-export function nextSaved(current: ReadonlySet, stored: string | null | undefined, slug: string, validSlugs: ReadonlySet): Set {
- const next = stored === undefined ? new Set(current) : readSaved(stored, validSlugs);
- if (next.has(slug)) next.delete(slug);
- else next.add(slug);
- return next;
-}
-
-export function filterLibraries(libraries: Library[], query: string, category: Category | null, stacks: Stack[], useCases: UseCase[], sort: "curated" | "name") {
- const tokens = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
- const results = libraries.filter((library) =>
- tokens.every((token) => [library.name, library.description, library.category, ...library.stacks, ...library.useCases, ...(library.tags ?? [])].join(" ").toLowerCase().includes(token)) &&
- (category === null || library.category === category) &&
- stacks.every((stack) => library.stacks.includes(stack)) &&
- useCases.every((useCase) => library.useCases.includes(useCase)),
- );
- return sort === "name" ? results.toSorted((a, b) => a.name.localeCompare(b.name)) : results;
-}
diff --git a/package-lock.json b/package-lock.json
index 70db00a..f9cd227 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,18 +1,23 @@
{
- "name": "col",
+ "name": "coc",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "col",
+ "name": "coc",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
+ "@gsap/react": "^2.1.2",
+ "border-beam": "^1.4.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "cn": "^0.4.0",
+ "gsap": "^3.15.0",
"lucide-react": "^1.47.0",
- "next": "^16.3.6",
+ "motion": "^13.4.0",
+ "next": "^16.3.5",
"radix-ui": "^1.6.7",
"react": "^19.3.0",
"react-dom": "^19.3.0",
@@ -20,10 +25,9 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4.3.3",
- "@types/node": "^20.19.43",
+ "@types/node": "^24.3.1",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
- "@webgpu/types": "^0.1.74",
"tailwindcss": "^4.3.3",
"typescript": "^5.9.2"
}
@@ -89,6 +93,16 @@
"integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
"license": "MIT"
},
+ "node_modules/@gsap/react": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@gsap/react/-/react-2.1.2.tgz",
+ "integrity": "sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==",
+ "license": "SEE LICENSE AT https://gsap.com/standard-license",
+ "peerDependencies": {
+ "gsap": "^3.12.5",
+ "react": ">=17"
+ }
+ },
"node_modules/@img/colour": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
@@ -689,15 +703,15 @@
}
},
"node_modules/@next/env": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.6.tgz",
- "integrity": "sha512-x9Vblze1EbtltQYnNH38xCPWU3TVfBd1eXqA3+w9+BTpedkkdNpAaltXlGQ/nsc1+E0mVTNrtcbX3GoO09zeLQ==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.5.tgz",
+ "integrity": "sha512-NWEXVDMqoEo0ktmU6u0sE2Vg0LOcsD7NnOTJNo3/fEaTfsg+F1bMIxuDmQbda4e3yTIQwVdUREF2yIuMOusKtg==",
"license": "MIT"
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.6.tgz",
- "integrity": "sha512-E/7GEqaUkt8mk/T8v9lAnrhzR06kdq1ZBkC12F8tAMkdIadwNp3H1KqHynDHrpcTlGCUdq/qu6vUL2aYVyYBdw==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.5.tgz",
+ "integrity": "sha512-pMmGgETfKvElucLHtVaeiMRbp2zUbvKx7b1yGko0liBz3cw1mKSggWN/Rp/wPz8z+E1O82u3r4L1Co+ZS5hokQ==",
"cpu": [
"arm64"
],
@@ -711,9 +725,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.6.tgz",
- "integrity": "sha512-yBE893/nDWTlaiBD1p+qgt7NUen4U5R6FXyH0s67Npq1S3E0cVSef1WIXC2xBRgQvwAvJq6DnS6Y6PrY0cy4Ew==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.5.tgz",
+ "integrity": "sha512-76VaGYvf6HPa5/w12yLkE3dXTn9AfdEviI79oEL3aZoAmRLc9rWitjWqyjViVysK/ht/y9YKzFkBrUdi/wGkow==",
"cpu": [
"x64"
],
@@ -727,9 +741,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.6.tgz",
- "integrity": "sha512-KJDpjBqBPYlvkivmyrp+Qys6k/7ksbqGQvRVc6ZEGfR+cjQxx+nUkJaWmNZJsmoOrqYNbaXByF8wa0lBwDhB3Q==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.5.tgz",
+ "integrity": "sha512-zKDELJ5jSQMHeO/hmXUQsAzagX4bQD4OiMi3pQ5FbUj+yK506oLVHnKA2YXMlbg1EHHqJYtyePOgByIDXD1lqw==",
"cpu": [
"arm64"
],
@@ -746,9 +760,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.6.tgz",
- "integrity": "sha512-mqNg2K+hvWskSRb/QM+Ix412DvBsuSF0XV+frTSw5vmoucNnIlynFwKYew8D01bfATErMOM7Bujrf0BA5DRKFA==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.5.tgz",
+ "integrity": "sha512-7Vql0pgzCoHagv6+FNOZoqmJqA52c6zeVbhtS/47qFozO1MSx4ms7x7GHiciY8R5CDsSMKMQjJEryoJLcsBIbA==",
"cpu": [
"arm64"
],
@@ -765,9 +779,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.6.tgz",
- "integrity": "sha512-nFncBNGAYouRHjRVaITs9beZRfhX4ssVwpnvPIAbkZVH6LtGoAVlH4bJ8Cnf9SOo9bsXgPFer/GdHtEE3JNOkw==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.5.tgz",
+ "integrity": "sha512-NH/xzehyHEFWE2nlcZon7TB/0+H4shfWCi7S1zka815XCOhJDYZhoeJtOYy0dh0WVRWACVXSyGNFFytoMxUhRg==",
"cpu": [
"x64"
],
@@ -784,9 +798,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.6.tgz",
- "integrity": "sha512-5Mf3cHDGR/Iz0ng2Bj3zUR3p5QS9YK3Hn2QiAfavFmyF48zwThAjpFoiTKNIcOHLYS4zEk+gzyJ/9deQ2ZB8yQ==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.5.tgz",
+ "integrity": "sha512-lV4+EhWMfS8jcC+EH2nn/Cm5cn6XsgbE07bU9tMH8fCo0tNAqhyzi1b5wQ/Tn6NGFTvKDY65w3ZH95EjwBRAnQ==",
"cpu": [
"x64"
],
@@ -803,9 +817,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.6.tgz",
- "integrity": "sha512-0jkJy0C2kbrJWTk4YLa3xk80pVBpx8FCHJym7CnUfDAXe/FWv5qT7SQJbR0KuemyxaEDlEx5WT4VQJoTW+/9Qw==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.5.tgz",
+ "integrity": "sha512-/wKzAREX2RF++MhicjDbg8tGn2AiBIM0+EFeTFKoUEUbW5D6amCJehd5Z5G1H5/gxNdgnwoXMcHz24H/c2tGkQ==",
"cpu": [
"arm64"
],
@@ -819,9 +833,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.6.tgz",
- "integrity": "sha512-/YXjI1e5OXcZ7YpxRwgP/1jAV/SBKTzeVKqN2mk7mLpcICsyn3Gl5+dIfDTJp70M0ccMhyMMRso4v6mPDCGepg==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.5.tgz",
+ "integrity": "sha512-LNdCHzgLFc+UeqMS84LzXPaeBRKyqDN9OMyFAr1OrB0XrNw78IRrEVtZvvA7245W/HsaoeVOQX9jPjPk8jojwA==",
"cpu": [
"x64"
],
@@ -2623,13 +2637,13 @@
}
},
"node_modules/@types/node": {
- "version": "20.19.43",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
- "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "version": "24.13.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.6.tgz",
+ "integrity": "sha512-SGrw/h3KPFshy3OE6ZL53LMBG5vGQQ8/gIpiqz/kRZhPJ7HgwCEs8LBuNtWLa8dvGZVpSF7+Bf+c11HUrCb/yg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~6.21.0"
+ "undici-types": "~7.18.0"
}
},
"node_modules/@types/react": {
@@ -2652,13 +2666,6 @@
"@types/react": "^19.3.0"
}
},
- "node_modules/@webgpu/types": {
- "version": "0.1.74",
- "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.74.tgz",
- "integrity": "sha512-lgiI4hbuLcI9unnm2cL/tvCaQU45dp0xcLWJh5uB/9MBGvIA4F8XIk7nSiBeg+K4xWGYwgZKn80LmERI5CxoTA==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
"node_modules/aria-hidden": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
@@ -2683,6 +2690,16 @@
"node": ">=6.0.0"
}
},
+ "node_modules/border-beam": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/border-beam/-/border-beam-1.4.0.tgz",
+ "integrity": "sha512-BsRqN5GQB76V5BlaJd64d8F0lW13HzNt/08cdxzAjlaVMV5/nb9nk0GuZKTF3qLWV2fmfbuUzXxvXisxNnw2TA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
"node_modules/caniuse-lite": {
"version": "1.0.30001810",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz",
@@ -2730,6 +2747,18 @@
"node": ">=6"
}
},
+ "node_modules/cn": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cn/-/cn-0.4.0.tgz",
+ "integrity": "sha512-qOAeUhPwPzBxx6jaeQdo646XIKliKHc2j1ZF7Ngb1o0pJZKH5gq8FkA0aVdUdPFUDXNXyUCXpCtoJISo6dhizg==",
+ "license": "MIT",
+ "bin": {
+ "cn": "bin/cn.mjs"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -2767,6 +2796,29 @@
"node": ">=10.13.0"
}
},
+ "node_modules/framer-motion": {
+ "version": "13.4.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-13.4.0.tgz",
+ "integrity": "sha512-HCpqKM9BTu6UYKtj0u6J1QNxojnnirNcghcSDZ+SkpiL3myxvtsgXPS3ZGEELC2eSma7YiA937rAEXtRyydSXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^13.3.0",
+ "motion-utils": "^13.3.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
@@ -2783,6 +2835,12 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/gsap": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz",
+ "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==",
+ "license": "Standard 'no charge' license: https://gsap.com/standard-license."
+ },
"node_modules/jiti": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
@@ -3085,6 +3143,43 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
+ "node_modules/motion": {
+ "version": "13.4.0",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-13.4.0.tgz",
+ "integrity": "sha512-aiNSA29N+vgV5p5cJSB5cFzx8KTuuxB99z8zGtxsaqlwKtBK6sq8YgPRpkVQLkbJMOcLDU0q/ShdT95qpBy/0g==",
+ "license": "MIT",
+ "dependencies": {
+ "framer-motion": "^13.4.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-13.3.0.tgz",
+ "integrity": "sha512-AmAnB6pHdZ1vHGzWzuzteG6Q3j1lHKeX/lbST6jGlgm0cjvLUgaCk1xhOuPMOy5SgovN6wnnUdwFrkcsus7Ftg==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^13.3.0"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-13.3.0.tgz",
+ "integrity": "sha512-sgSschQp7EseHInIlR7hBbMuvet3RA0bs28KPZAXJcGKGdxHGvh1ogpYDilY3bOMtl73EqPNmp75sAKHYPU5sg==",
+ "license": "MIT"
+ },
"node_modules/nanoid": {
"version": "3.3.19",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
@@ -3104,12 +3199,12 @@
}
},
"node_modules/next": {
- "version": "16.3.6",
- "resolved": "https://registry.npmjs.org/next/-/next-16.3.6.tgz",
- "integrity": "sha512-L+otWM/aQbYTx98aZhgEoMb4bZAXx1YVW4UMA/vuCyCoWG5HJyZUili8QAkqzrcC+5///tsz3s0M+SlyB5bLMw==",
+ "version": "16.3.5",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.3.5.tgz",
+ "integrity": "sha512-MdtsTgzyfCPRLC6uJ1mN8ao7lyJ4BB0U6Inhnx3gta1UcCIdHK3yxLG0E8OWQteWD8/Q0qb8A5o7wJaL8M9y2w==",
"license": "MIT",
"dependencies": {
- "@next/env": "16.3.6",
+ "@next/env": "16.3.5",
"@swc/helpers": "0.5.23",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
@@ -3123,14 +3218,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "16.3.6",
- "@next/swc-darwin-x64": "16.3.6",
- "@next/swc-linux-arm64-gnu": "16.3.6",
- "@next/swc-linux-arm64-musl": "16.3.6",
- "@next/swc-linux-x64-gnu": "16.3.6",
- "@next/swc-linux-x64-musl": "16.3.6",
- "@next/swc-win32-arm64-msvc": "16.3.6",
- "@next/swc-win32-x64-msvc": "16.3.6",
+ "@next/swc-darwin-arm64": "16.3.5",
+ "@next/swc-darwin-x64": "16.3.5",
+ "@next/swc-linux-arm64-gnu": "16.3.5",
+ "@next/swc-linux-arm64-musl": "16.3.5",
+ "@next/swc-linux-x64-gnu": "16.3.5",
+ "@next/swc-linux-x64-musl": "16.3.5",
+ "@next/swc-win32-arm64-msvc": "16.3.5",
+ "@next/swc-win32-x64-msvc": "16.3.5",
"sharp": "^0.35.4"
},
"peerDependencies": {
@@ -3539,9 +3634,9 @@
}
},
"node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
+ "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
},
diff --git a/package.json b/package.json
index 21439c7..33833b7 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "col",
+ "name": "coc",
"version": "0.1.0",
"private": true,
"description": "A community-maintained directory for discovering UI libraries.",
@@ -7,16 +7,18 @@
"scripts": {
"dev": "next dev",
"build": "next build",
- "start": "next start",
- "typecheck": "tsc --noEmit",
- "test": "node --test",
- "check": "npm run typecheck && npm test && npm run build"
+ "start": "next start"
},
"dependencies": {
+ "@gsap/react": "^2.1.2",
+ "border-beam": "^1.4.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "cn": "^0.4.0",
+ "gsap": "^3.15.0",
"lucide-react": "^1.47.0",
- "next": "^16.3.6",
+ "motion": "^13.4.0",
+ "next": "^16.3.5",
"radix-ui": "^1.6.7",
"react": "^19.3.0",
"react-dom": "^19.3.0",
@@ -24,7 +26,7 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4.3.3",
- "@types/node": "^20.19.43",
+ "@types/node": "^24.3.1",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@webgpu/types": "^0.1.74",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..0ed9f7d
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2818 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@gsap/react':
+ specifier: ^2.1.2
+ version: 2.1.2(gsap@3.15.0)(react@19.3.0)
+ border-beam:
+ specifier: ^1.4.0
+ version: 1.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ cn:
+ specifier: ^0.4.0
+ version: 0.4.0
+ gsap:
+ specifier: ^3.15.0
+ version: 3.15.0
+ lucide-react:
+ specifier: ^1.47.0
+ version: 1.47.0(react@19.3.0)
+ motion:
+ specifier: ^13.4.0
+ version: 13.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ next:
+ specifier: ^16.3.5
+ version: 16.3.5(@types/node@24.13.6)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ radix-ui:
+ specifier: ^1.6.7
+ version: 1.6.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react:
+ specifier: ^19.3.0
+ version: 19.3.0
+ react-dom:
+ specifier: ^19.3.0
+ version: 19.3.0(react@19.3.0)
+ tailwind-merge:
+ specifier: ^3.7.0
+ version: 3.7.0
+ devDependencies:
+ '@tailwindcss/postcss':
+ specifier: ^4.3.3
+ version: 4.3.3
+ '@types/node':
+ specifier: ^24.3.1
+ version: 24.13.6
+ '@types/react':
+ specifier: ^19.3.0
+ version: 19.3.0
+ '@types/react-dom':
+ specifier: ^19.3.0
+ version: 19.3.0(@types/react@19.3.0)
+ '@webgpu/types':
+ specifier: ^0.1.74
+ version: 0.1.74
+ tailwindcss:
+ specifier: ^4.3.3
+ version: 4.3.3
+ typescript:
+ specifier: ^5.9.2
+ version: 5.9.3
+
+packages:
+
+ '@alloc/quick-lru@5.3.0':
+ resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==}
+ engines: {node: '>=10'}
+
+ '@emnapi/runtime@1.11.3':
+ resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+
+ '@floating-ui/core@1.8.0':
+ resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==}
+
+ '@floating-ui/dom@1.8.0':
+ resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==}
+
+ '@floating-ui/react-dom@2.1.9':
+ resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
+ '@floating-ui/utils@0.2.12':
+ resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
+
+ '@gsap/react@2.1.2':
+ resolution: {integrity: sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==}
+ peerDependencies:
+ gsap: ^3.12.5
+ react: '>=17'
+
+ '@img/colour@1.1.0':
+ resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
+ engines: {node: '>=18'}
+
+ '@img/sharp-darwin-arm64@0.35.4':
+ resolution: {integrity: sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-darwin-x64@0.35.4':
+ resolution: {integrity: sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-freebsd-wasm32@0.35.4':
+ resolution: {integrity: sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==}
+ engines: {node: '>=20.9.0'}
+ os: [freebsd]
+
+ '@img/sharp-libvips-darwin-arm64@1.3.3':
+ resolution: {integrity: sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-libvips-darwin-x64@1.3.3':
+ resolution: {integrity: sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-libvips-linux-arm64@1.3.3':
+ resolution: {integrity: sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linux-arm@1.3.3':
+ resolution: {integrity: sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linux-ppc64@1.3.3':
+ resolution: {integrity: sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linux-riscv64@1.3.3':
+ resolution: {integrity: sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linux-s390x@1.3.3':
+ resolution: {integrity: sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linux-x64@1.3.3':
+ resolution: {integrity: sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
+ resolution: {integrity: sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
+ resolution: {integrity: sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@img/sharp-linux-arm64@0.35.4':
+ resolution: {integrity: sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-arm@0.35.4':
+ resolution: {integrity: sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-ppc64@0.35.4':
+ resolution: {integrity: sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-riscv64@0.35.4':
+ resolution: {integrity: sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-s390x@0.35.4':
+ resolution: {integrity: sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linux-x64@0.35.4':
+ resolution: {integrity: sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@img/sharp-linuxmusl-arm64@0.35.4':
+ resolution: {integrity: sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@img/sharp-linuxmusl-x64@0.35.4':
+ resolution: {integrity: sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@img/sharp-wasm32@0.35.4':
+ resolution: {integrity: sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==}
+ engines: {node: '>=20.9.0'}
+
+ '@img/sharp-webcontainers-wasm32@0.35.4':
+ resolution: {integrity: sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [wasm32]
+
+ '@img/sharp-win32-arm64@0.35.4':
+ resolution: {integrity: sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@img/sharp-win32-ia32@0.35.4':
+ resolution: {integrity: sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==}
+ engines: {node: ^20.9.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@img/sharp-win32-x64@0.35.4':
+ resolution: {integrity: sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.6.0':
+ resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@next/env@16.3.5':
+ resolution: {integrity: sha512-NWEXVDMqoEo0ktmU6u0sE2Vg0LOcsD7NnOTJNo3/fEaTfsg+F1bMIxuDmQbda4e3yTIQwVdUREF2yIuMOusKtg==}
+
+ '@next/swc-darwin-arm64@16.3.5':
+ resolution: {integrity: sha512-pMmGgETfKvElucLHtVaeiMRbp2zUbvKx7b1yGko0liBz3cw1mKSggWN/Rp/wPz8z+E1O82u3r4L1Co+ZS5hokQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@next/swc-darwin-x64@16.3.5':
+ resolution: {integrity: sha512-76VaGYvf6HPa5/w12yLkE3dXTn9AfdEviI79oEL3aZoAmRLc9rWitjWqyjViVysK/ht/y9YKzFkBrUdi/wGkow==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@next/swc-linux-arm64-gnu@16.3.5':
+ resolution: {integrity: sha512-zKDELJ5jSQMHeO/hmXUQsAzagX4bQD4OiMi3pQ5FbUj+yK506oLVHnKA2YXMlbg1EHHqJYtyePOgByIDXD1lqw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@next/swc-linux-arm64-musl@16.3.5':
+ resolution: {integrity: sha512-7Vql0pgzCoHagv6+FNOZoqmJqA52c6zeVbhtS/47qFozO1MSx4ms7x7GHiciY8R5CDsSMKMQjJEryoJLcsBIbA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@next/swc-linux-x64-gnu@16.3.5':
+ resolution: {integrity: sha512-NH/xzehyHEFWE2nlcZon7TB/0+H4shfWCi7S1zka815XCOhJDYZhoeJtOYy0dh0WVRWACVXSyGNFFytoMxUhRg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@next/swc-linux-x64-musl@16.3.5':
+ resolution: {integrity: sha512-lV4+EhWMfS8jcC+EH2nn/Cm5cn6XsgbE07bU9tMH8fCo0tNAqhyzi1b5wQ/Tn6NGFTvKDY65w3ZH95EjwBRAnQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@next/swc-win32-arm64-msvc@16.3.5':
+ resolution: {integrity: sha512-/wKzAREX2RF++MhicjDbg8tGn2AiBIM0+EFeTFKoUEUbW5D6amCJehd5Z5G1H5/gxNdgnwoXMcHz24H/c2tGkQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@next/swc-win32-x64-msvc@16.3.5':
+ resolution: {integrity: sha512-LNdCHzgLFc+UeqMS84LzXPaeBRKyqDN9OMyFAr1OrB0XrNw78IRrEVtZvvA7245W/HsaoeVOQX9jPjPk8jojwA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@radix-ui/number@1.1.3':
+ resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==}
+
+ '@radix-ui/primitive@1.1.7':
+ resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==}
+
+ '@radix-ui/react-accessible-icon@1.1.15':
+ resolution: {integrity: sha512-WTQwcAvQf5sOcuUyi90lKPbhwcvQ+j55cjrSmeaN+L2vKU3DooOvlKw2MDeiJ5IkV5N905KW0/fGojKOBhD11A==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-accordion@1.2.20':
+ resolution: {integrity: sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-alert-dialog@1.1.23':
+ resolution: {integrity: sha512-VAYOiQRqj3GPpYJE0I9J+X8Ip05cyVlNdKOFeiGS2Ou1HHGfpl0BxOyZm6nmVDyU+W+NF3/XLzmjHmVGydhwgA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-arrow@1.1.15':
+ resolution: {integrity: sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-aspect-ratio@1.1.15':
+ resolution: {integrity: sha512-fy+dyVR+90nelK8rqIznFlxzx7uPcGbhxH8Nfr2bHb4UfSe+e3hklOC0luK0hDwVwnRX7xTRySpsrQVeW+/oNQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-avatar@1.2.6':
+ resolution: {integrity: sha512-4ULOTJ/mqy2hT9GlWa/MFHxHSvH3nJzHnZM1waNsc5Bonv7i70aNenghXmD97S6OJ81ekXONGGt4nT1r0PfEdA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-checkbox@1.3.11':
+ resolution: {integrity: sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-collapsible@1.1.20':
+ resolution: {integrity: sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-collection@1.1.15':
+ resolution: {integrity: sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-compose-refs@1.1.5':
+ resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-context-menu@2.3.7':
+ resolution: {integrity: sha512-CtXP35dxaB5T3zXSd+E3uHe/QpXcpYnZmxp6OaIbfthtfW4wyb77M23BG+bwIJDtsMwEP/YssdsmNyZu7jhWew==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-context@1.2.2':
+ resolution: {integrity: sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-dialog@1.1.23':
+ resolution: {integrity: sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-direction@1.1.4':
+ resolution: {integrity: sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-dismissable-layer@1.1.19':
+ resolution: {integrity: sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-dropdown-menu@2.1.24':
+ resolution: {integrity: sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-focus-guards@1.1.6':
+ resolution: {integrity: sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-focus-scope@1.1.16':
+ resolution: {integrity: sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-form@0.1.16':
+ resolution: {integrity: sha512-Q4TLEn2A7TAypxwmd6R9EwrlXDvkfYSDMrq9/887AXAGh+G1rH+kYJKSTv+Si9Y0JPKTwKYv6PviAJosysNimA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-hover-card@1.1.23':
+ resolution: {integrity: sha512-H8qONfZd3ltrU3+jHCIgITbWo6e1iTKvP9DHdrvYbX48ooRM5FjEDTn16AMwdfuOGkWdZEhpl3PLL/Wk/AnHDQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-id@1.1.4':
+ resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-label@2.1.15':
+ resolution: {integrity: sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menu@2.1.24':
+ resolution: {integrity: sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menubar@1.1.24':
+ resolution: {integrity: sha512-eeVs0vf7cuqXaM0qLQCPcufImiJNVBXdJDLu7ZGYl2732UH23Qat/foNGrr6vYV3/DdTsBqASoggUFgH14OcZA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-navigation-menu@1.2.22':
+ resolution: {integrity: sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-one-time-password-field@0.1.16':
+ resolution: {integrity: sha512-Tj9P6ntAJEw52oq/F0AGknXR4XncxEt7XU47O3xJQOiWfLzEy3d9gtgKfvjSzGxzHkfL+VzvxGu2KTFsloJqXw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-password-toggle-field@0.1.11':
+ resolution: {integrity: sha512-4gvFnmDXu3dgj21CqsufzIameRvlRd4SBqaWhcrlrNhRo0Y5i/49AmRJYe1fdAM3G2VNBbmin4b0D6cdQocwgw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-popover@1.1.23':
+ resolution: {integrity: sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-popper@1.3.7':
+ resolution: {integrity: sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-portal@1.1.17':
+ resolution: {integrity: sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-presence@1.1.10':
+ resolution: {integrity: sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-primitive@2.1.10':
+ resolution: {integrity: sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-progress@1.1.16':
+ resolution: {integrity: sha512-5XnomAsoZZCY+KNTxbIghpGqPruZvKFNlvcAljVAOdDRDsH4/OZQxhtwo5wdtoDM5R6MhJBb2sPnDuRFep3lzg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-radio-group@1.4.7':
+ resolution: {integrity: sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-roving-focus@1.1.19':
+ resolution: {integrity: sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-scroll-area@1.2.18':
+ resolution: {integrity: sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-select@2.3.7':
+ resolution: {integrity: sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-separator@1.1.15':
+ resolution: {integrity: sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-slider@1.4.7':
+ resolution: {integrity: sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-slot@1.3.3':
+ resolution: {integrity: sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-switch@1.3.7':
+ resolution: {integrity: sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-tabs@1.1.21':
+ resolution: {integrity: sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toast@1.2.23':
+ resolution: {integrity: sha512-ofhyAsYaocRGOs/n0XWdUOSVzEAG6BfrMVM8z0c0kLEWY38w/0WuMFPTJP/HVaZPYkMvHZoKIIhNcjbTCBILPg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toggle-group@1.1.19':
+ resolution: {integrity: sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toggle@1.1.18':
+ resolution: {integrity: sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-toolbar@1.1.19':
+ resolution: {integrity: sha512-Ph0IvtYw4VB12ZnZg+YtrGs8yJQsnizwo/zu0R4Y/nWugtJzA7Pg1eWeuDR9+LSqn+xjamss+UOSOJJJ4gx8jw==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-tooltip@1.2.16':
+ resolution: {integrity: sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-use-callback-ref@1.1.4':
+ resolution: {integrity: sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-controllable-state@1.2.6':
+ resolution: {integrity: sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-effect-event@0.0.5':
+ resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-escape-keydown@1.1.5':
+ resolution: {integrity: sha512-ge3ipobwSXTj4JyVtswQ7qZj0ZHdtbGuOno/LrgAAeSxtsJ6Vs4Gz5IkPH2bmqpjcLUFoqGhA/mueuIf63UXlA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-is-hydrated@0.1.3':
+ resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-layout-effect@1.1.4':
+ resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-previous@1.1.4':
+ resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-rect@1.1.4':
+ resolution: {integrity: sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-use-size@1.1.4':
+ resolution: {integrity: sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-visually-hidden@1.2.11':
+ resolution: {integrity: sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/rect@1.1.3':
+ resolution: {integrity: sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==}
+
+ '@swc/helpers@0.5.23':
+ resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==}
+
+ '@tailwindcss/node@4.3.3':
+ resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
+
+ '@tailwindcss/oxide-android-arm64@4.3.3':
+ resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
+ resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.3.3':
+ resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
+ resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+ resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+ resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+ resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+ resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+ resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+ resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+ resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+ resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.3.3':
+ resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
+ engines: {node: '>= 20'}
+
+ '@tailwindcss/postcss@4.3.3':
+ resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==}
+
+ '@types/node@24.13.6':
+ resolution: {integrity: sha512-SGrw/h3KPFshy3OE6ZL53LMBG5vGQQ8/gIpiqz/kRZhPJ7HgwCEs8LBuNtWLa8dvGZVpSF7+Bf+c11HUrCb/yg==}
+
+ '@types/react-dom@19.3.0':
+ resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==}
+ peerDependencies:
+ '@types/react': ^19.3.0
+
+ '@types/react@19.3.0':
+ resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==}
+
+ '@webgpu/types@0.1.74':
+ resolution: {integrity: sha512-lgiI4hbuLcI9unnm2cL/tvCaQU45dp0xcLWJh5uB/9MBGvIA4F8XIk7nSiBeg+K4xWGYwgZKn80LmERI5CxoTA==}
+
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
+ baseline-browser-mapping@2.11.25:
+ resolution: {integrity: sha512-gMmEShwwq7FJqMwvfRwvCl00v4kN+KOfJqXn+f4nrufak5gNHJOksd/60Dvjuz7sI8Y5WiSFBa8FEYr+zoyqCw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ border-beam@1.4.0:
+ resolution: {integrity: sha512-BsRqN5GQB76V5BlaJd64d8F0lW13HzNt/08cdxzAjlaVMV5/nb9nk0GuZKTF3qLWV2fmfbuUzXxvXisxNnw2TA==}
+ peerDependencies:
+ react: '>=18.0.0'
+ react-dom: '>=18.0.0'
+
+ caniuse-lite@1.0.30001810:
+ resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==}
+
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
+ client-only@0.0.1:
+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ cn@0.4.0:
+ resolution: {integrity: sha512-qOAeUhPwPzBxx6jaeQdo646XIKliKHc2j1ZF7Ngb1o0pJZKH5gq8FkA0aVdUdPFUDXNXyUCXpCtoJISo6dhizg==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ detect-node-es@1.1.0:
+ resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
+ enhanced-resolve@5.25.1:
+ resolution: {integrity: sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==}
+ engines: {node: '>=10.13.0'}
+
+ framer-motion@13.4.0:
+ resolution: {integrity: sha512-HCpqKM9BTu6UYKtj0u6J1QNxojnnirNcghcSDZ+SkpiL3myxvtsgXPS3ZGEELC2eSma7YiA937rAEXtRyydSXQ==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
+ get-nonce@1.0.1:
+ resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+ engines: {node: '>=6'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ gsap@3.15.0:
+ resolution: {integrity: sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==}
+
+ jiti@2.7.0:
+ resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
+ hasBin: true
+
+ lightningcss-android-arm64@1.32.0:
+ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.32.0:
+ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.32.0:
+ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.32.0:
+ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.32.0:
+ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-arm64-musl@1.32.0:
+ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-linux-x64-gnu@1.32.0:
+ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ lightningcss-linux-x64-musl@1.32.0:
+ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ lightningcss-win32-arm64-msvc@1.32.0:
+ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.32.0:
+ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.32.0:
+ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
+ engines: {node: '>= 12.0.0'}
+
+ lucide-react@1.47.0:
+ resolution: {integrity: sha512-o8C23aXpNQypRY73W7fW02EyvWJinEMXgKeGjFoKym0zj3Q73hD97A1IQps1g8C14HTGsOpZL0Am+xjfgFZAbg==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ motion-dom@13.3.0:
+ resolution: {integrity: sha512-AmAnB6pHdZ1vHGzWzuzteG6Q3j1lHKeX/lbST6jGlgm0cjvLUgaCk1xhOuPMOy5SgovN6wnnUdwFrkcsus7Ftg==}
+
+ motion-utils@13.3.0:
+ resolution: {integrity: sha512-sgSschQp7EseHInIlR7hBbMuvet3RA0bs28KPZAXJcGKGdxHGvh1ogpYDilY3bOMtl73EqPNmp75sAKHYPU5sg==}
+
+ motion@13.4.0:
+ resolution: {integrity: sha512-aiNSA29N+vgV5p5cJSB5cFzx8KTuuxB99z8zGtxsaqlwKtBK6sq8YgPRpkVQLkbJMOcLDU0q/ShdT95qpBy/0g==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
+ nanoid@3.3.19:
+ resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ next@16.3.5:
+ resolution: {integrity: sha512-MdtsTgzyfCPRLC6uJ1mN8ao7lyJ4BB0U6Inhnx3gta1UcCIdHK3yxLG0E8OWQteWD8/Q0qb8A5o7wJaL8M9y2w==}
+ engines: {node: '>=20.9.0'}
+ hasBin: true
+ 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
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@playwright/test':
+ optional: true
+ babel-plugin-react-compiler:
+ optional: true
+ sass:
+ optional: true
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ postcss@8.5.23:
+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ postcss@8.5.28:
+ resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ radix-ui@1.6.7:
+ resolution: {integrity: sha512-QBdhh1arIEUvPC0dQ5+nwWAxt7+N+oP/9jPwjJkGFoSk/sqxg32gJtSXGtFh8frAIcS6oC9cx2Q+7KYCQLOAeA==}
+ 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
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ react-dom@19.3.0:
+ resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==}
+ peerDependencies:
+ react: ^19.3.0
+
+ react-remove-scroll-bar@2.3.8:
+ resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-remove-scroll@2.7.2:
+ resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react-style-singleton@2.2.3:
+ resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ react@19.3.0:
+ resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==}
+ engines: {node: '>=0.10.0'}
+
+ scheduler@0.28.0:
+ resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==}
+
+ semver@7.8.5:
+ resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ sharp@0.35.4:
+ resolution: {integrity: sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==}
+ engines: {node: '>=20.9.0'}
+ peerDependencies:
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ styled-jsx@5.1.6:
+ resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ '@babel/core': '*'
+ babel-plugin-macros: '*'
+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ babel-plugin-macros:
+ optional: true
+
+ tailwind-merge@3.7.0:
+ resolution: {integrity: sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA==}
+
+ tailwindcss@4.3.3:
+ resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
+
+ tapable@2.3.3:
+ resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
+ engines: {node: '>=6'}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
+ use-callback-ref@1.3.3:
+ resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ use-sidecar@1.1.3:
+ resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+snapshots:
+
+ '@alloc/quick-lru@5.3.0': {}
+
+ '@emnapi/runtime@1.11.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@floating-ui/core@1.8.0':
+ dependencies:
+ '@floating-ui/utils': 0.2.12
+
+ '@floating-ui/dom@1.8.0':
+ dependencies:
+ '@floating-ui/core': 1.8.0
+ '@floating-ui/utils': 0.2.12
+
+ '@floating-ui/react-dom@2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@floating-ui/dom': 1.8.0
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ '@floating-ui/utils@0.2.12': {}
+
+ '@gsap/react@2.1.2(gsap@3.15.0)(react@19.3.0)':
+ dependencies:
+ gsap: 3.15.0
+ react: 19.3.0
+
+ '@img/colour@1.1.0':
+ optional: true
+
+ '@img/sharp-darwin-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-arm64': 1.3.3
+ optional: true
+
+ '@img/sharp-darwin-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.3.3
+ optional: true
+
+ '@img/sharp-freebsd-wasm32@0.35.4':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.4
+ optional: true
+
+ '@img/sharp-libvips-darwin-arm64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-darwin-x64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-ppc64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-riscv64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-s390x@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linux-x64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.3':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-x64@1.3.3':
+ optional: true
+
+ '@img/sharp-linux-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.3.3
+ optional: true
+
+ '@img/sharp-linux-arm@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.3.3
+ optional: true
+
+ '@img/sharp-linux-ppc64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-ppc64': 1.3.3
+ optional: true
+
+ '@img/sharp-linux-riscv64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-riscv64': 1.3.3
+ optional: true
+
+ '@img/sharp-linux-s390x@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.3.3
+ optional: true
+
+ '@img/sharp-linux-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.3.3
+ optional: true
+
+ '@img/sharp-linuxmusl-arm64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
+ optional: true
+
+ '@img/sharp-linuxmusl-x64@0.35.4':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
+ optional: true
+
+ '@img/sharp-wasm32@0.35.4':
+ dependencies:
+ '@emnapi/runtime': 1.11.3
+ optional: true
+
+ '@img/sharp-webcontainers-wasm32@0.35.4':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.4
+ optional: true
+
+ '@img/sharp-win32-arm64@0.35.4':
+ optional: true
+
+ '@img/sharp-win32-ia32@0.35.4':
+ optional: true
+
+ '@img/sharp-win32-x64@0.35.4':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.6.0
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.6.0': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.6.0
+
+ '@next/env@16.3.5': {}
+
+ '@next/swc-darwin-arm64@16.3.5':
+ optional: true
+
+ '@next/swc-darwin-x64@16.3.5':
+ optional: true
+
+ '@next/swc-linux-arm64-gnu@16.3.5':
+ optional: true
+
+ '@next/swc-linux-arm64-musl@16.3.5':
+ optional: true
+
+ '@next/swc-linux-x64-gnu@16.3.5':
+ optional: true
+
+ '@next/swc-linux-x64-musl@16.3.5':
+ optional: true
+
+ '@next/swc-win32-arm64-msvc@16.3.5':
+ optional: true
+
+ '@next/swc-win32-x64-msvc@16.3.5':
+ optional: true
+
+ '@radix-ui/number@1.1.3': {}
+
+ '@radix-ui/primitive@1.1.7': {}
+
+ '@radix-ui/react-accessible-icon@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-accordion@1.2.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collapsible': 1.1.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-alert-dialog@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-arrow@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-aspect-ratio@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-avatar@1.2.6(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-checkbox@1.3.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-collapsible@1.1.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-collection@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-compose-refs@1.1.5(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-context-menu@2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-context@1.2.2(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-dialog@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ aria-hidden: 1.2.6
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-direction@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-dismissable-layer@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-dropdown-menu@2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-focus-guards@1.1.6(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-focus-scope@1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-form@0.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-label': 2.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-hover-card@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-id@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-label@2.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-menu@2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ aria-hidden: 1.2.6
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-menubar@1.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-navigation-menu@1.2.22(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-previous': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-one-time-password-field@0.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/number': 1.1.3
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-password-toggle-field@0.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-popover@1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ aria-hidden: 1.2.6
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-popper@1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@floating-ui/react-dom': 2.1.9(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-rect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/rect': 1.1.3
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-portal@1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-presence@1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-primitive@2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-progress@1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-radio-group@1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-roving-focus@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-scroll-area@1.2.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/number': 1.1.3
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-select@2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/number': 1.1.3
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-previous': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ aria-hidden: 1.2.6
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ react-remove-scroll: 2.7.2(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-separator@1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-slider@1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/number': 1.1.3
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-previous': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-slot@1.3.3(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-switch@1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-tabs@1.1.21(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-toast@1.2.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-toggle-group@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toggle': 1.1.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-toggle@1.1.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-toolbar@1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-separator': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toggle-group': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-tooltip@1.2.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-escape-keydown@1.1.5(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-previous@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-rect@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/rect': 1.1.3
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-use-size@1.1.4(@types/react@19.3.0)(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ react: 19.3.0
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ '@radix-ui/react-visually-hidden@1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ '@radix-ui/rect@1.1.3': {}
+
+ '@swc/helpers@0.5.23':
+ dependencies:
+ tslib: 2.8.1
+
+ '@tailwindcss/node@4.3.3':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.25.1
+ jiti: 2.7.0
+ lightningcss: 1.32.0
+ magic-string: 0.30.21
+ source-map-js: 1.2.1
+ tailwindcss: 4.3.3
+
+ '@tailwindcss/oxide-android-arm64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+ optional: true
+
+ '@tailwindcss/oxide@4.3.3':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.3.3
+ '@tailwindcss/oxide-darwin-arm64': 4.3.3
+ '@tailwindcss/oxide-darwin-x64': 4.3.3
+ '@tailwindcss/oxide-freebsd-x64': 4.3.3
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
+ '@tailwindcss/oxide-linux-arm64-musl': 4.3.3
+ '@tailwindcss/oxide-linux-x64-gnu': 4.3.3
+ '@tailwindcss/oxide-linux-x64-musl': 4.3.3
+ '@tailwindcss/oxide-wasm32-wasi': 4.3.3
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
+ '@tailwindcss/oxide-win32-x64-msvc': 4.3.3
+
+ '@tailwindcss/postcss@4.3.3':
+ dependencies:
+ '@alloc/quick-lru': 5.3.0
+ '@tailwindcss/node': 4.3.3
+ '@tailwindcss/oxide': 4.3.3
+ postcss: 8.5.28
+ tailwindcss: 4.3.3
+
+ '@types/node@24.13.6':
+ dependencies:
+ undici-types: 7.18.2
+
+ '@types/react-dom@19.3.0(@types/react@19.3.0)':
+ dependencies:
+ '@types/react': 19.3.0
+
+ '@types/react@19.3.0':
+ dependencies:
+ csstype: 3.2.3
+
+ '@webgpu/types@0.1.74': {}
+
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
+ baseline-browser-mapping@2.11.25: {}
+
+ border-beam@1.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ caniuse-lite@1.0.30001810: {}
+
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
+ client-only@0.0.1: {}
+
+ clsx@2.1.1: {}
+
+ cn@0.4.0: {}
+
+ csstype@3.2.3: {}
+
+ detect-libc@2.1.2: {}
+
+ detect-node-es@1.1.0: {}
+
+ enhanced-resolve@5.25.1:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.3.3
+
+ framer-motion@13.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ motion-dom: 13.3.0
+ motion-utils: 13.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ get-nonce@1.0.1: {}
+
+ graceful-fs@4.2.11: {}
+
+ gsap@3.15.0: {}
+
+ jiti@2.7.0: {}
+
+ lightningcss-android-arm64@1.32.0:
+ optional: true
+
+ lightningcss-darwin-arm64@1.32.0:
+ optional: true
+
+ lightningcss-darwin-x64@1.32.0:
+ optional: true
+
+ lightningcss-freebsd-x64@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.32.0:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.32.0:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.32.0:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.32.0:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.32.0:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.32.0:
+ optional: true
+
+ lightningcss@1.32.0:
+ dependencies:
+ detect-libc: 2.1.2
+ 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
+
+ lucide-react@1.47.0(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.6.0
+
+ motion-dom@13.3.0:
+ dependencies:
+ motion-utils: 13.3.0
+
+ motion-utils@13.3.0: {}
+
+ motion@13.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ framer-motion: 13.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+
+ nanoid@3.3.19: {}
+
+ next@16.3.5(@types/node@24.13.6)(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ '@next/env': 16.3.5
+ '@swc/helpers': 0.5.23
+ baseline-browser-mapping: 2.11.25
+ caniuse-lite: 1.0.30001810
+ postcss: 8.5.23
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ styled-jsx: 5.1.6(react@19.3.0)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 16.3.5
+ '@next/swc-darwin-x64': 16.3.5
+ '@next/swc-linux-arm64-gnu': 16.3.5
+ '@next/swc-linux-arm64-musl': 16.3.5
+ '@next/swc-linux-x64-gnu': 16.3.5
+ '@next/swc-linux-x64-musl': 16.3.5
+ '@next/swc-win32-arm64-msvc': 16.3.5
+ '@next/swc-win32-x64-msvc': 16.3.5
+ sharp: 0.35.4(@types/node@24.13.6)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@types/node'
+ - babel-plugin-macros
+
+ picocolors@1.1.1: {}
+
+ postcss@8.5.23:
+ dependencies:
+ nanoid: 3.3.19
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ postcss@8.5.28:
+ dependencies:
+ nanoid: 3.3.19
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ radix-ui@1.6.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
+ dependencies:
+ '@radix-ui/primitive': 1.1.7
+ '@radix-ui/react-accessible-icon': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-accordion': 1.2.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-alert-dialog': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-aspect-ratio': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-avatar': 1.2.6(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-checkbox': 1.3.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-collapsible': 1.1.20(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context': 1.2.2(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-context-menu': 2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-direction': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-dropdown-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-form': 0.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-hover-card': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-label': 2.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-menubar': 1.1.24(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-navigation-menu': 1.2.22(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-one-time-password-field': 0.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-password-toggle-field': 0.1.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-popover': 1.1.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-progress': 1.1.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-radio-group': 1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-scroll-area': 1.2.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-select': 2.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-separator': 1.1.15(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slider': 1.4.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-slot': 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-switch': 1.3.7(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-tabs': 1.1.21(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toast': 1.2.23(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toggle': 1.1.18(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toggle-group': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-toolbar': 1.1.19(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-tooltip': 1.2.16(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-escape-keydown': 1.1.5(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-use-size': 1.1.4(@types/react@19.3.0)(react@19.3.0)
+ '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
+ react: 19.3.0
+ react-dom: 19.3.0(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+ '@types/react-dom': 19.3.0(@types/react@19.3.0)
+
+ react-dom@19.3.0(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ scheduler: 0.28.0
+
+ react-remove-scroll-bar@2.3.8(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.0)
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-remove-scroll@2.7.2(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ react-remove-scroll-bar: 2.3.8(@types/react@19.3.0)(react@19.3.0)
+ react-style-singleton: 2.2.3(@types/react@19.3.0)(react@19.3.0)
+ tslib: 2.8.1
+ use-callback-ref: 1.3.3(@types/react@19.3.0)(react@19.3.0)
+ use-sidecar: 1.1.3(@types/react@19.3.0)(react@19.3.0)
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react-style-singleton@2.2.3(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ get-nonce: 1.0.1
+ react: 19.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ react@19.3.0: {}
+
+ scheduler@0.28.0: {}
+
+ semver@7.8.5:
+ optional: true
+
+ sharp@0.35.4(@types/node@24.13.6):
+ dependencies:
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.5
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.35.4
+ '@img/sharp-darwin-x64': 0.35.4
+ '@img/sharp-freebsd-wasm32': 0.35.4
+ '@img/sharp-libvips-darwin-arm64': 1.3.3
+ '@img/sharp-libvips-darwin-x64': 1.3.3
+ '@img/sharp-libvips-linux-arm': 1.3.3
+ '@img/sharp-libvips-linux-arm64': 1.3.3
+ '@img/sharp-libvips-linux-ppc64': 1.3.3
+ '@img/sharp-libvips-linux-riscv64': 1.3.3
+ '@img/sharp-libvips-linux-s390x': 1.3.3
+ '@img/sharp-libvips-linux-x64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.3
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.3
+ '@img/sharp-linux-arm': 0.35.4
+ '@img/sharp-linux-arm64': 0.35.4
+ '@img/sharp-linux-ppc64': 0.35.4
+ '@img/sharp-linux-riscv64': 0.35.4
+ '@img/sharp-linux-s390x': 0.35.4
+ '@img/sharp-linux-x64': 0.35.4
+ '@img/sharp-linuxmusl-arm64': 0.35.4
+ '@img/sharp-linuxmusl-x64': 0.35.4
+ '@img/sharp-webcontainers-wasm32': 0.35.4
+ '@img/sharp-win32-arm64': 0.35.4
+ '@img/sharp-win32-ia32': 0.35.4
+ '@img/sharp-win32-x64': 0.35.4
+ '@types/node': 24.13.6
+ optional: true
+
+ source-map-js@1.2.1: {}
+
+ styled-jsx@5.1.6(react@19.3.0):
+ dependencies:
+ client-only: 0.0.1
+ react: 19.3.0
+
+ tailwind-merge@3.7.0: {}
+
+ tailwindcss@4.3.3: {}
+
+ tapable@2.3.3: {}
+
+ tslib@2.8.1: {}
+
+ typescript@5.9.3: {}
+
+ undici-types@7.18.2: {}
+
+ use-callback-ref@1.3.3(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ react: 19.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
+
+ use-sidecar@1.1.3(@types/react@19.3.0)(react@19.3.0):
+ dependencies:
+ detect-node-es: 1.1.0
+ react: 19.3.0
+ tslib: 2.8.1
+ optionalDependencies:
+ '@types/react': 19.3.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..27a9fda
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+minimumReleaseAgeExclude:
+ - border-beam@1.4.0
+ - cn@0.4.0
diff --git a/tests/directory.test.mjs b/tests/directory.test.mjs
deleted file mode 100644
index 354d78e..0000000
--- a/tests/directory.test.mjs
+++ /dev/null
@@ -1,48 +0,0 @@
-import assert from "node:assert/strict";
-import { test } from "node:test";
-import { loadTs } from "./load-ts.mjs";
-
-const { libraries, CATEGORIES, STACKS, USE_CASES } = await loadTs("../data/libraries.ts");
-const { firstQuery, filterLibraries, readSaved, nextSaved } = await loadTs("../lib/directory.ts");
-
-test("repeated and missing route queries resolve to one string", () => {
- assert.equal(firstQuery(["react", "vue"]), "react");
- assert.equal(firstQuery([]), "");
- assert.equal(firstQuery(undefined), "");
-});
-
-test("search tokens, intersecting filters, and sorting", () => {
- const matches = filterLibraries(libraries, "react animation", null, [], [], "curated");
- assert.ok(matches.length > 0);
- assert.ok(matches.every((library) => `${library.name} ${library.description} ${library.category} ${library.stacks.join(" ")} ${library.useCases.join(" ")} ${(library.tags ?? []).join(" ")}`.toLowerCase().includes("react")));
- const filtered = filterLibraries(libraries, "", "Animation & Motion", ["React"], ["Micro-interactions"], "name");
- assert.ok(filtered.length > 0);
- assert.ok(filtered.every((library) => library.category === "Animation & Motion" && library.stacks.includes("React") && library.useCases.includes("Micro-interactions")));
- assert.deepEqual(filtered.map(({ name }) => name), filtered.map(({ name }) => name).toSorted());
-});
-
-test("saved slugs ignore malformed and retired entries", () => {
- const valid = new Set(libraries.map(({ slug }) => slug));
- assert.deepEqual([...readSaved('["react-bits","retired",42]', valid)], ["react-bits"]);
- assert.equal(readSaved("broken", valid).size, 0);
- assert.deepEqual([...nextSaved(new Set(), '["react-bits"]', "motion", valid)], ["react-bits", "motion"]);
- assert.deepEqual([...nextSaved(new Set(["react-bits"]), undefined, "motion", valid)], ["react-bits", "motion"]);
-});
-
-test("registry metadata stays unique and within taxonomy", () => {
- const slugs = new Set();
- const names = new Set();
- for (const library of libraries) {
- assert.match(library.slug, /^[a-z0-9]+(?:-[a-z0-9]+)*$/);
- assert.ok(!slugs.has(library.slug) && !names.has(library.name));
- slugs.add(library.slug);
- names.add(library.name);
- assert.ok(library.name.trim() && library.description.trim());
- assert.equal(new URL(library.url).protocol, "https:");
- assert.ok(CATEGORIES.includes(library.category));
- for (const [values, taxonomy] of [[library.stacks, STACKS], [library.useCases, USE_CASES]]) {
- assert.ok(values.length > 0 && values.every((value) => taxonomy.includes(value)));
- assert.equal(new Set(values).size, values.length);
- }
- }
-});
diff --git a/tests/discovery.test.mjs b/tests/discovery.test.mjs
index 642e77a..420178d 100644
--- a/tests/discovery.test.mjs
+++ b/tests/discovery.test.mjs
@@ -1,25 +1,38 @@
import assert from "node:assert/strict";
+import { readFileSync } from "node:fs";
import { test } from "node:test";
-import { loadTs } from "./load-ts.mjs";
+import ts from "typescript";
-const { libraries } = await loadTs("../data/libraries.ts");
-const { siteUrl, staticRoutes } = await loadTs("../lib/site.ts");
-const dataUrl = `data:text/javascript,${encodeURIComponent(`export const libraries = ${JSON.stringify(libraries)}`)}`;
-const { GET } = await loadTs("../app/llms.txt/route.ts", { "@/data/libraries": dataUrl });
-const siteUrlModule = `data:text/javascript,${encodeURIComponent(`export const siteUrl = ${JSON.stringify(siteUrl)}; export const staticRoutes = ${JSON.stringify(staticRoutes)}`)}`;
-const { default: robots } = await loadTs("../app/robots.ts", { "@/lib/site": siteUrlModule });
-const { default: sitemap } = await loadTs("../app/sitemap.ts", { "@/lib/site": siteUrlModule });
+const source = readFileSync(new URL("../data/libraries.ts", import.meta.url), "utf8");
+const moduleSource = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ESNext } }).outputText;
+const { libraries } = await import(`data:text/javascript,${encodeURIComponent(moduleSource)}`);
-test("discovery routes use the registry and route list", async () => {
- assert.deepEqual(robots().rules[0], { userAgent: "*", allow: "/" });
- assert.equal(robots().sitemap, `${siteUrl}/sitemap.xml`);
- assert.deepEqual(sitemap().map(({ url }) => url), staticRoutes.map((route) => new URL(route, siteUrl).toString()));
+const built = (name) => readFileSync(new URL(`../.next/server/app/${name}.body`, import.meta.url), "utf8");
- const response = GET();
- assert.equal(response.headers.get("content-type"), "text/plain; charset=utf-8");
- const body = await response.text();
+test("build emits complete discovery files", () => {
+ const robots = built("robots.txt");
+ const sitemap = built("sitemap.xml");
+ const llms = built("llms.txt");
+
+ for (const crawler of ["*", "GPTBot", "ClaudeBot", "PerplexityBot", "Google-Extended"]) {
+ assert.ok(robots.includes(`User-Agent: ${crawler}`));
+ }
+ assert.ok(robots.includes("Allow: /"));
+ assert.ok(robots.includes("Sitemap: https://collection-of-libs.vercel.app/sitemap.xml"));
+
+ for (const route of ["/", "/libraries", "/docs", "/contributors"]) {
+ assert.ok(sitemap.includes(`https://collection-of-libs.vercel.app${route} `));
+ }
+ assert.equal((sitemap.match(//g) ?? []).length, 4);
+
+ const entries = llms.split("\n## ").slice(1);
+ assert.equal(entries.length, libraries.length);
for (const library of libraries) {
- assert.ok(body.includes(`## ${library.name}\n`));
- assert.ok(body.includes(`- Description: ${library.description}`));
+ const entry = entries.find((item) => item.startsWith(`${library.name}\n`));
+ assert.ok(entry, `Missing ${library.name}`);
+ assert.ok(entry.includes(`- Domain: [${new URL(library.url).hostname.replace(/^www\./, "")}](${library.url})`));
+ assert.ok(entry.includes(`- Description: ${library.description}`));
+ assert.ok(entry.includes(`- Stacks: ${library.stacks.join(", ")}`));
+ assert.ok(entry.includes(`- Use cases: ${library.useCases.join(", ")}`));
}
});
diff --git a/tests/load-ts.mjs b/tests/load-ts.mjs
deleted file mode 100644
index f3c2db1..0000000
--- a/tests/load-ts.mjs
+++ /dev/null
@@ -1,9 +0,0 @@
-import { readFileSync } from "node:fs";
-import ts from "typescript";
-
-export async function loadTs(path, replacements = {}) {
- let source = readFileSync(new URL(path, import.meta.url), "utf8");
- for (const [from, to] of Object.entries(replacements)) source = source.replaceAll(from, to);
- const output = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ESNext, jsx: ts.JsxEmit.ReactJSX } }).outputText;
- return import(`data:text/javascript,${encodeURIComponent(output)}`);
-}
diff --git a/tests/theme.test.mjs b/tests/theme.test.mjs
deleted file mode 100644
index 8d25c5f..0000000
--- a/tests/theme.test.mjs
+++ /dev/null
@@ -1,30 +0,0 @@
-import assert from "node:assert/strict";
-import { readFileSync } from "node:fs";
-import { test } from "node:test";
-import { runInNewContext } from "node:vm";
-
-const layout = readFileSync(new URL("../app/layout.tsx", import.meta.url), "utf8");
-const script = layout.match(/__html: `([^`]*)`/)?.[1];
-assert.ok(script, "Theme initialization script is present");
-
-test("theme initialization uses saved preference or system theme when storage fails", () => {
- for (const [stored, systemLight, expectedLight] of [
- ["light", false, true],
- ["dark", true, false],
- [null, true, true],
- [null, false, false],
- ["blocked", true, true],
- ]) {
- const classes = new Set();
- runInNewContext(script, {
- localStorage: { getItem: () => {
- if (stored === "blocked") throw new Error("Storage blocked");
- return stored;
- } },
- matchMedia: () => ({ matches: systemLight }),
- document: { documentElement: { classList: { toggle: (name, active) => active ? classes.add(name) : classes.delete(name) } } },
- });
- assert.equal(classes.has("light"), expectedLight);
- assert.equal(classes.has("dark"), !expectedLight);
- }
-});