diff --git a/kits/assistant/pageindex-notebooklm/.env.example b/kits/assistant/pageindex-notebooklm/.env.example new file mode 100644 index 00000000..fb79d815 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/.env.example @@ -0,0 +1,12 @@ +# Lamatic Project Settings +# Get these from: studio.lamatic.ai → Settings → API Keys +LAMATIC_API_KEY="YOUR_LAMATIC_API_KEY" +LAMATIC_PROJECT_ID="YOUR_LAMATIC_PROJECT_ID" +LAMATIC_API_URL="YOUR_LAMATIC_API_ENDPOINT" + +# Flow IDs +# Get each Flow ID from: Lamatic Studio → Flow → three-dot menu → Copy ID +FLOW_ID_UPLOAD="YOUR_UPLOAD_FLOW_ID" +FLOW_ID_CHAT="YOUR_CHAT_FLOW_ID" +FLOW_ID_LIST="YOUR_LIST_FLOW_ID" +FLOW_ID_TREE="YOUR_TREE_FLOW_ID" diff --git a/kits/assistant/pageindex-notebooklm/.gitignore b/kits/assistant/pageindex-notebooklm/.gitignore new file mode 100644 index 00000000..2551eb02 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/.gitignore @@ -0,0 +1,49 @@ +# Dependencies +node_modules/ +.pnp +.pnp.js + +# Build outputs +dist/ +build/ +.next/ +out/ + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# OS files +.DS_Store +Thumbs.db + +# IDE / Editor +.vscode/ +.idea/ +*.swp +*.swo + +# TypeScript +*.tsbuildinfo + +# Cache +.cache/ +.parcel-cache/ +.turbo/ + +# Testing +coverage/ + +# Misc +*.pem diff --git a/kits/assistant/pageindex-notebooklm/README.md b/kits/assistant/pageindex-notebooklm/README.md new file mode 100644 index 00000000..7a83dee8 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/README.md @@ -0,0 +1,249 @@ +# PageIndex NotebookLM — AgentKit + +Upload any PDF and chat with it using **vectorless, tree-structured RAG** — powered **end-to-end by Lamatic AI flows**. + +> **No vector database. No external Python server. No custom backend code.** +> Just 4 Lamatic flows + a Next.js frontend that implements the full PageIndex pipeline — from PDF ingestion to tree-navigated question answering — entirely within Lamatic's orchestration layer. + +--- + +## What Makes This Different + +Most RAG implementations require a vector database, an embedding model, a retrieval server, and often a separate Python backend. **This kit eliminates all of that.** + +The entire PageIndex pipeline — TOC detection, tree construction, page indexing, summary generation, tree-navigated search, and LLM answering — is implemented as **4 Lamatic AI flows** with zero external servers or Python code. The Next.js frontend communicates exclusively with Lamatic's flow execution API via the official `lamatic` SDK. + +### Key Highlights + +- **100% Lamatic-powered backend** — all document processing, indexing, retrieval, and answering logic lives inside Lamatic flows +- **No vector DB** — uses a hierarchical tree index (built from the document's table of contents) instead of vector embeddings +- **No external server** — no FastAPI, no Railway, no Python — the Lamatic flows handle everything +- **No chunking** — sections are identified by their structural position in the document, not arbitrary text splits + +--- + +## Architecture + +```text +┌────────────────────────────────────────────────────┐ +│ Next.js Frontend │ +│ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌─────────┐ │ +│ │ Document │ │ Chat │ │ Tree │ │Document │ │ +│ │ Upload │ │ Window │ │ Viewer │ │ List │ │ +│ └────┬─────┘ └────┬─────┘ └───┬────┘ └────┬────┘ │ +│ │ │ │ │ │ +│ ┌────┴─────────────┴───────────┴────────────┴───┐ │ +│ │ Server Actions (orchestrate.ts) │ │ +│ └────────────────────┬──────────────────────────┘ │ +│ │ │ +│ Lamatic SDK (lamatic npm) │ +└───────────────────────┼─────────────────────────────┘ + │ + ┌────────────┴────────────┐ + │ Lamatic AI Platform │ + │ │ + │ Flow 1: Upload + Index │ + │ Flow 2: Chat + Retrieve │ + │ Flow 3: List Documents │ + │ Flow 4: Tree / Delete │ + │ │ + │ ┌──────────────┐ │ + │ │ Supabase │ │ + │ │ (PostgreSQL) │ │ + │ └──────────────┘ │ + └──────────────────────────┘ +``` + +--- + +## How It Works + +### Document Ingestion (Flow 1) + +When a PDF is uploaded, the Lamatic flow runs a multi-stage pipeline: + +1. **TOC Detection** — scans the first pages to locate the table of contents +2. **TOC Extraction** — multi-pass extraction with completion verification +3. **TOC → JSON** — structured flat list with hierarchy identifiers (`1`, `1.1`, `1.2.3`) +4. **Physical Index Assignment** — verifies each section starts on the correct page +5. **Tree Build** — nested tree structure with exact `start_index` + `end_index` per section +6. **Summary Generation** — 1–2 sentence summary per node +7. **Page Verification** — fuzzy-matches node titles against actual page text +8. **Save** — stores the tree + metadata in Supabase + +### Chat & Retrieval (Flow 2) + +At query time, the LLM navigates the tree like a table of contents: +1. Receives the full tree structure with section titles and summaries +2. Selects the most relevant leaf nodes based on the query +3. Fetches verbatim page content using exact `start_index → end_index` ranges +4. Generates an answer grounded in the retrieved content + +The frontend receives the answer, the retrieved nodes with page ranges, and the LLM's tree-navigation reasoning — all displayed in the UI. + +--- + +## Stack + +| Layer | Technology | +|---|---| +| Orchestration & Backend | **Lamatic AI** (4 flows — no external server) | +| Storage | **Supabase** (PostgreSQL) | +| Frontend | **Next.js 15** (App Router, Server Actions) | +| Styling | **CSS custom properties** (dark-mode design system) | +| SDK | **`lamatic`** npm package | + +--- + +## Features + +- **PDF Upload** — drag-and-drop or paste a URL +- **Tree-Structured RAG** — vectorless retrieval using hierarchical document index +- **Multi-Turn Chat** — conversational history maintained across messages +- **Chat Persistence** — conversations saved to `localStorage`, survive page navigations +- **Interactive Tree Viewer** — explore the full document structure, nodes highlight on retrieval +- **Source Panel** — view retrieved sections with page ranges and LLM reasoning +- **Document Management** — list all documents, view trees, delete documents +- **Markdown Rendering** — AI responses rendered with headings, lists, bold, code +- **Responsive Dark UI** — premium design system with animations and micro-interactions + +--- + +## Prerequisites + +- [Lamatic AI](https://lamatic.ai) account (free) +- [Supabase](https://supabase.com) account (free tier) +- Node.js 18+ + +> **That's it.** No Groq account, no Railway, no Python environment needed. + +--- + +## Setup + +### 1. Set Up Supabase + +Run this SQL in Supabase SQL Editor: + +```sql +create table documents ( + id uuid default gen_random_uuid() primary key, + doc_id text unique not null, + file_name text, + file_url text, + tree jsonb, + raw_text text, + tree_node_count integer default 0, + status text default 'completed', + created_at timestamptz default now() +); +alter table documents enable row level security; +-- Only the Supabase service role (used server-side in Lamatic flows) can +-- read and write documents. No direct client-side access is permitted. +create policy "service_role_only" on documents + for all + using (auth.role() = 'service_role') + with check (auth.role() = 'service_role'); +``` + +### 2. Import Lamatic Flows + +Import all 4 flows from the `flows/` folder into Lamatic Studio: + +| Flow | Folder | Purpose | +|---|---|---| +| Upload | `flows/flow-1-upload-pdf-build-tree-save/` | PDF → 7-stage pipeline → tree index → Supabase | +| Chat | `flows/chat-with-pdf/` | Tree search → page fetch → LLM answer | +| List | `flows/flow-list-all-documents/` | List all documents from Supabase | +| Tree | `flows/flow-4-get-tree-structure/` | Return full tree JSON or delete a document | + +Add these secrets in **Lamatic → Settings → Secrets**: + +| Secret | Value | +|---|---| +| `SUPABASE_URL` | `https://xxx.supabase.co` | +| `SUPABASE_ANON_KEY` | From Supabase Settings → API | +| `SUPABASE_SERVICE_ROLE_KEY` | From Supabase Settings → API — **server-side only, never expose client-side** | + +> **Important:** `SUPABASE_SERVICE_ROLE_KEY` bypasses RLS. Store it in Lamatic Secrets only — never in `.env.local` shipped to the browser. + +### 3. Install and Configure + +```bash +cd kits/assistant/pageindex-notebooklm +npm install +cp .env.example .env.local +``` + +Fill in `.env.local`: + +```env +LAMATIC_API_KEY=... # Lamatic → Settings → API Keys +LAMATIC_PROJECT_ID=... # Lamatic → Settings → Project ID +LAMATIC_API_URL=... # Lamatic → Settings → API Docs → Endpoint + +FLOW_ID_UPLOAD=... # Flow 1 → three-dot menu → Copy ID +FLOW_ID_CHAT=... # Flow 2 → three-dot menu → Copy ID +FLOW_ID_LIST=... # Flow 3 → three-dot menu → Copy ID +FLOW_ID_TREE=... # Flow 4 → three-dot menu → Copy ID +``` + +### 4. Run Locally + +```bash +npm run dev +# → http://localhost:3000 +``` + +--- + +## Project Structure + +```text +pageindex-notebooklm/ (TypeScript · Next.js/React) +├── actions/ +│ └── orchestrate.ts # TypeScript — Server actions — all 4 flow calls via Lamatic SDK +├── app/ +│ ├── globals.css # CSS — Design system (custom properties, animations) +│ ├── layout.tsx # TSX/React — Root layout with metadata +│ └── page.tsx # TSX/React — Main page — document list + chat + tree viewer +├── components/ +│ ├── ChatWindow.tsx # TSX/React — Chat UI with markdown, sources, persistence +│ ├── DocumentList.tsx # TSX/React — Document sidebar with search + delete +│ ├── DocumentUpload.tsx # TSX/React — Drag-and-drop / URL upload +│ └── TreeViewer.tsx # TSX/React — Interactive hierarchical tree viewer +├── flows/ +│ ├── flow-1-upload-pdf-build-tree-save/ +│ ├── chat-with-pdf/ +│ ├── flow-list-all-documents/ +│ └── flow-4-get-tree-structure/ +├── lib/ +│ ├── lamatic-client.ts # TypeScript — Lamatic SDK initialization +│ └── types.ts # TypeScript — Shared interfaces and types +├── config.json # Kit metadata +└── .env.example # Environment variable template +``` + +--- + +## Deploying to Vercel + +```bash +git checkout -b feat/pageindex-notebooklm +git add kits/assistant/pageindex-notebooklm/ +git commit -m "feat: PageIndex NotebookLM — end-to-end Lamatic-powered tree RAG" +git push origin feat/pageindex-notebooklm +``` + +Then in Vercel: +1. Import your repo +2. Set **Root Directory** → `kits/assistant/pageindex-notebooklm` +3. Add all 7 env vars from `.env.local` +4. Deploy + +--- + +## Author + +**Saurabh Tiwari** — [st108113@gmail.com](mailto:st108113@gmail.com) +GitHub: [@Skt329](https://github.com/Skt329) diff --git a/kits/assistant/pageindex-notebooklm/actions/orchestrate.ts b/kits/assistant/pageindex-notebooklm/actions/orchestrate.ts new file mode 100644 index 00000000..eaa2be5e --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/actions/orchestrate.ts @@ -0,0 +1,165 @@ +"use server"; + +import { lamaticClient } from "@/lib/lamatic-client"; + +// ── helpers ────────────────────────────────────────────────── +function safeParseJSON(value: unknown, fallback: T): T { + if (typeof value === "string") { + try { + return JSON.parse(value) as T; + } catch { + return fallback; + } + } + if (value !== null && value !== undefined) return value as T; + return fallback; +} + +// ── Flow 1: Upload PDF → build tree → save to Supabase ─────── +// Accepts either a remote file_url OR a local file (base64 + mime_type). +export async function uploadDocument( + file_name: string, + options: { file_url?: string; file_base64?: string; mime_type?: string } +) { + // ── Validate upload contract ────────────────────────────────── + const hasUrl = Boolean(options.file_url); + const hasBase64 = Boolean(options.file_base64); + + if (hasUrl && hasBase64) { + throw new Error( + "uploadDocument: provide either file_url or file_base64, not both." + ); + } + if (!hasUrl && !hasBase64) { + throw new Error( + "uploadDocument: either file_url or file_base64 must be provided." + ); + } + if (hasBase64 && !options.mime_type) { + throw new Error( + "uploadDocument: mime_type is required when file_base64 is provided." + ); + } + + try { + const response = await lamaticClient.executeFlow( + process.env.FLOW_ID_UPLOAD!, + { file_name, ...options } + ); + const data = (response.result ?? response) as Record; + return data; + } catch (error) { + console.error("Upload flow error:", error); + throw new Error("Failed to upload document"); + } +} + +// ── Flow 2: Chat (tree search → page fetch → answer) ───────── +export async function chatWithDocument( + doc_id: string, + query: string, + messages: Array<{ role: string; content: string }> = [] +) { + try { + // removed FLOW_ID_CHAT check as it is checked in lamatic-client.ts + + // Cap history: strip "No answer found." turns (they corrupt LLM context) + // then keep only the last 10 messages to avoid token-limit failures. + const trimmedMessages = messages + .filter(m => !(m.role === "assistant" && m.content === "No answer found.")) + .slice(-10); + + const payload = { + doc_id, + query, + messages: JSON.stringify(trimmedMessages), + }; + + if (process.env.NODE_ENV !== "production") { + console.log("[chatWithDocument] SENDING → Flow Execution Started"); + } + + const response = await lamaticClient.executeFlow( + process.env.FLOW_ID_CHAT!, + payload + ); + + const raw = response as unknown as Record; + const data = (raw.result ?? raw) as Record; + + if (process.env.NODE_ENV !== "production") { + console.log("[chatWithDocument] RECEIVED ← Flow Execution Completed"); + } + + return { + answer: (data.answer as string) ?? "", + messages: data.messages, + retrieved_nodes: safeParseJSON(data.retrieved_nodes, []), + thinking: (data.thinking as string) ?? "", + }; + } catch (error) { + console.error("Chat flow error:", error); + throw new Error("Failed to get answer: " + (error as Error).message); + } +} + +// ── Flow 3: List all documents ──────────────────────────────── +export async function listDocuments() { + try { + const response = await lamaticClient.executeFlow( + process.env.FLOW_ID_LIST!, + {} + ); + const raw = response as unknown as Record; + const data = (raw.result ?? raw) as Record; + + const documents = safeParseJSON(data?.documents, []); + + return { + ...data, + documents, + total: Number(data?.total) || 0, + }; + } catch (error) { + console.error("List flow error:", error); + throw new Error("Failed to list documents"); + } +} + +// ── Flow 4: Get full tree structure (or delete) ──────────────── +export async function getDocumentTree(doc_id: string) { + try { + const response = await lamaticClient.executeFlow( + process.env.FLOW_ID_TREE!, + { doc_id, action: "get_tree" } + ); + const data = (response.result ?? response) as Record; + return { + ...data, + tree: safeParseJSON(data?.tree, []), + tree_node_count: Number(data?.tree_node_count) || 0, + }; + } catch (error) { + console.error("Tree flow error:", error); + throw new Error("Failed to get document tree"); + } +} + +// ── Flow 4 (delete action): Remove a document ─────────────────── +// Note: This demo kit has no authentication layer — deleteDocument is +// intentionally unauthenticated. Production deployments should add JWT +// validation and ownership checks (e.g., verifyJwt(token) + getDocumentOwner) +// before calling the flow. +export async function deleteDocument(doc_id: string) { + try { + const response = await lamaticClient.executeFlow( + process.env.FLOW_ID_TREE!, + { doc_id, action: "delete" } + ); + const data = (response.result ?? response) as Record; + return data as { success: boolean; action: string; message: string; doc_id: string; file_name: string }; + } catch (error) { + console.error("Delete flow error:", error); + throw new Error("Failed to delete document"); + } +} diff --git a/kits/assistant/pageindex-notebooklm/app/globals.css b/kits/assistant/pageindex-notebooklm/app/globals.css new file mode 100644 index 00000000..2142e7af --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/app/globals.css @@ -0,0 +1,212 @@ +@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,400;12..96,500;12..96,600;12..96,700&family=Geist+Mono:wght@300;400;500&display=swap'); +@import "tailwindcss"; + +@layer base { + :root { + /* Core palette — warm charcoal + luminous teal */ + --bg: #0a0b0d; + --bg-alt: #0e1013; + --surface: #111316; + --surface-1: #161a1f; + --surface-2: #1c2128; + --surface-3: #222933; + + /* Borders */ + --border: rgba(255,255,255,0.07); + --border-md: rgba(255,255,255,0.11); + --border-hi: rgba(255,255,255,0.18); + + /* Accent — luminous teal */ + --accent: #2dd4bf; + --accent-2: #14b8a6; + --accent-dim: rgba(45,212,191,0.1); + --accent-glow: rgba(45,212,191,0.18); + + /* Text */ + --text-1: #f0f2f5; + --text-2: #8d97a8; + --text-3: #4a5568; + + /* Status */ + --amber: #f6c90e; + --amber-dim: rgba(246,201,14,0.1); + --green: #34d399; + --red: #f87171; + + /* Typography */ + --font-display: 'Bricolage Grotesque', system-ui, sans-serif; + --font-mono: 'Geist Mono', 'DM Mono', monospace; + + /* Spatial */ + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 16px; + --radius-xl: 22px; + + /* Shadows */ + --shadow-sm: 0 1px 3px rgba(0,0,0,0.4); + --shadow-md: 0 4px 16px rgba(0,0,0,0.5); + --shadow-lg: 0 12px 40px rgba(0,0,0,0.6); + --glow: 0 0 24px rgba(45,212,191,0.15); + + /* Transitions */ + --ease: cubic-bezier(0.25,0.46,0.45,0.94); + --ease-spring: cubic-bezier(0.34,1.56,0.64,1); + } + + * { box-sizing: border-box; } + + html, body { + height: 100%; + margin: 0; + padding: 0; + scroll-behavior: smooth; + } + + body { + background: var(--bg); + color: var(--text-1); + font-family: var(--font-display); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; + line-height: 1.55; + font-size: 15px; + } + + ::selection { + background: var(--accent-dim); + color: var(--accent); + } + + /* Scrollbar */ + * { + scrollbar-width: thin; + scrollbar-color: rgba(255,255,255,0.1) transparent; + } + ::-webkit-scrollbar { width: 3px; height: 3px; } + ::-webkit-scrollbar-track { background: transparent; } + ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; } + ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.18); } + + input, button, textarea { + font-family: inherit; + } +} + +/* ─── Keyframes ─────────────────────────────────────────── */ +@keyframes spin { to { transform: rotate(360deg); } } +@keyframes pulse-dot { 0%,100%{transform:scale(1);opacity:.35} 50%{transform:scale(1.5);opacity:1} } +@keyframes float-in { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} } +@keyframes slide-in-r { from{opacity:0;transform:translateX(12px)} to{opacity:1;transform:translateX(0)} } +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} +@keyframes msg-in-user { from{opacity:0;transform:translateX(20px) scale(.96)} to{opacity:1;transform:translateX(0) scale(1)} } +@keyframes msg-in-ai { from{opacity:0;transform:translateX(-20px) scale(.96)} to{opacity:1;transform:translateX(0) scale(1)} } +@keyframes glow-pulse { 0%,100%{box-shadow:0 0 0 0 var(--accent-glow)} 50%{box-shadow:0 0 20px 4px var(--accent-glow)} } + +/* ─── Utility classes ───────────────────────────────────── */ +.font-mono { font-family: var(--font-mono); } +.text-accent { color: var(--accent); } +.text-muted { color: var(--text-3); } +.text-sub { color: var(--text-2); } + +.surface { background: var(--surface-1); border: 1px solid var(--border); } + +.glow-border { box-shadow: var(--glow); border-color: rgba(45,212,191,0.3) !important; } + +/* Glass panel */ +.glass { + background: rgba(17,19,22,0.7); + backdrop-filter: blur(16px) saturate(160%); + -webkit-backdrop-filter: blur(16px) saturate(160%); + border: 1px solid var(--border); +} + +/* Subtle noise texture overlay via pseudo */ +.noise::before { + content: ''; + position: absolute; inset: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E"); + pointer-events: none; z-index: 0; border-radius: inherit; +} + +/* Gradient accent line (top edge) */ +.accent-line::after { + content: ''; + position: absolute; top: 0; left: 0; right: 0; + height: 1px; + background: linear-gradient(90deg, transparent, var(--accent), transparent); + opacity: 0.6; +} + +@layer components { + /* Pill badge */ + .badge { + @apply inline-flex items-center gap-1 font-mono text-[10px] font-medium tracking-[0.04em] px-2 py-0.5 rounded-[20px] border; + } + .badge-accent { + @apply text-[var(--accent)] bg-[var(--accent-dim)] border-[rgba(45,212,191,0.25)]; + } + .badge-amber { + @apply text-[var(--amber)] bg-[var(--amber-dim)] border-[rgba(246,201,14,0.25)]; + } + .badge-default { + @apply text-[var(--text-2)] bg-[var(--surface-2)] border-[var(--border)]; + } + + /* Button variants */ + .btn { + @apply inline-flex items-center justify-center gap-[7px] px-4 py-2 rounded-[var(--radius-md)] border border-transparent font-[var(--font-display)] text-[13px] font-medium cursor-pointer transition-all duration-150 outline-none whitespace-nowrap shrink-0; + transition-timing-function: var(--ease); + } + .btn:disabled { @apply opacity-40 cursor-not-allowed; } + .btn-ghost { + @apply bg-transparent border-[var(--border)] text-[var(--text-2)]; + } + .btn-ghost:hover:not(:disabled) { + @apply bg-[var(--surface-2)] border-[var(--border-md)] text-[var(--text-1)]; + } + .btn-accent { + @apply bg-[var(--accent)] border-[var(--accent)] text-[#041a17] font-semibold; + } + .btn-accent:hover:not(:disabled) { + @apply bg-[var(--accent-2)] border-[var(--accent-2)]; + box-shadow: var(--glow); + } + .btn-icon { + @apply p-0 w-[36px] h-[36px] rounded-[var(--radius-md)]; + } + + /* Tab pill */ + .tab { + @apply inline-flex items-center gap-[6px] px-[13px] py-[5px] rounded-[var(--radius-md)] text-[13px] font-medium border-none cursor-pointer bg-transparent text-[var(--text-2)] transition-all duration-150; + transition-timing-function: var(--ease); + } + .tab:hover { @apply text-[var(--text-1)]; } + .tab.active { + @apply bg-[var(--surface-2)] text-[var(--text-1)] border-[var(--border-md)] border border-solid shadow-[var(--shadow-sm)]; + } + + /* Input */ + .input { + @apply flex-1 bg-[var(--surface-2)] border border-[var(--border)] rounded-[var(--radius-md)] px-[14px] py-[10px] text-[13.5px] text-[var(--text-1)] outline-none font-[var(--font-display)] transition-colors duration-150; + } + .input::placeholder { @apply text-[var(--text-3)]; } + .input:focus { + @apply border-[rgba(45,212,191,0.4)]; + box-shadow: 0 0 0 3px var(--accent-dim); + } + + /* Section label */ + .section-label { + @apply font-mono text-[10px] font-medium tracking-[0.1em] uppercase text-[var(--text-3)]; + } + + /* Divider */ + .divider { + @apply h-[1px] bg-[var(--border)] shrink-0; + } +} diff --git a/kits/assistant/pageindex-notebooklm/app/layout.tsx b/kits/assistant/pageindex-notebooklm/app/layout.tsx new file mode 100644 index 00000000..a5dad631 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/app/layout.tsx @@ -0,0 +1,28 @@ +import type { Metadata, Viewport } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "PageIndex — Vectorless Document Intelligence", + description: + "Chat with your documents using PageIndex's agentic tree-structured retrieval. No vectors, no chunking — powered by Lamatic and Groq.", +}; + +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + themeColor: "#0a0b0d", +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + + + + {children} + + ); +} diff --git a/kits/assistant/pageindex-notebooklm/app/page.tsx b/kits/assistant/pageindex-notebooklm/app/page.tsx new file mode 100644 index 00000000..1e5d09cd --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/app/page.tsx @@ -0,0 +1,341 @@ +"use client"; + +import { useState, useEffect, useCallback, useRef } from "react"; +import { listDocuments, getDocumentTree } from "@/actions/orchestrate"; +import { Document, TreeNode, RetrievedNode } from "@/lib/types"; +import { BookOpen, AlertCircle, RefreshCw, MessageSquare, List, Loader2 } from "lucide-react"; +import DocumentUpload from "@/components/DocumentUpload"; +import DocumentList from "@/components/DocumentList"; +import ChatWindow from "@/components/ChatWindow"; +import TreeViewer from "@/components/TreeViewer"; + +export default function Page() { + const [documents, setDocuments] = useState([]); + const [selectedDoc, setSelectedDoc] = useState(null); + const [tree, setTree] = useState([]); + const [treeLoading, setTreeLoading] = useState(false); + const [listLoading, setListLoading] = useState(false); + const [highlightedIds, setHighlightedIds] = useState([]); + const [activeTab, setActiveTab] = useState<"chat" | "tree">("chat"); + // Monotonic counter used to cancel stale tree-fetch results + const treeRequestIdRef = useRef(0); + + const fetchDocuments = useCallback(async () => { + setListLoading(true); + try { + const result = await listDocuments(); + if (Array.isArray(result?.documents)) setDocuments(result.documents); + } catch { /* silent */ } finally { setListLoading(false); } + }, []); + + // One-time migration: clear localStorage chat data corrupted by the old + // persist-effect bug (which wrote one doc's messages into another doc's slot). + // Bump CHAT_STORAGE_VERSION whenever a breaking change requires a fresh wipe. + const CHAT_STORAGE_VERSION = "2"; + useEffect(() => { + if (typeof window === "undefined") return; + if (localStorage.getItem("chat_storage_version") !== CHAT_STORAGE_VERSION) { + Object.keys(localStorage) + .filter(k => k.startsWith("chat_")) + .forEach(k => localStorage.removeItem(k)); + localStorage.setItem("chat_storage_version", CHAT_STORAGE_VERSION); + } + }, []); + + useEffect(() => { fetchDocuments(); }, [fetchDocuments]); + + async function handleSelectDoc(doc: Document) { + setSelectedDoc(doc); + setHighlightedIds([]); + setActiveTab("chat"); + setTreeLoading(true); + // Capture this request's id; if the user selects another doc before this + // resolves, requestId will no longer match the ref and we discard the result. + const requestId = ++treeRequestIdRef.current; + try { + const result = await getDocumentTree(doc.doc_id); + if (requestId !== treeRequestIdRef.current) return; // stale — discard + if (Array.isArray(result?.tree)) setTree(result.tree); + } catch { + if (requestId !== treeRequestIdRef.current) return; + setTree([]); + } finally { + if (requestId === treeRequestIdRef.current) setTreeLoading(false); + } + } + + function handleRetrievedNodes(nodes: RetrievedNode[]) { + setHighlightedIds(nodes.map((n) => n.node_id)); + } + + return ( +
+ + {/* ── Header ─────────────────────────────────── */} +
+ {/* Logo mark */} +
+ +
+ +
+

+ PageIndex +

+

+ Document Intelligence +

+
+ +
+ {/* Live indicator */} +
+ + + ONLINE + +
+ +
+ + + Groq · PageIndex + +
+ + {/* Accent line bottom */} +
+
+ + {/* ── Demo notice ── */} +
+ + + Demo project · Document processing is limited to 30–50 pages · Chat history is not stored persistently + +
+ + {/* ── Body ───────────────────────────────────── */} +
+ + {/* ── Sidebar ─── */} + + + {/* ── Main ─── */} +
+ {selectedDoc ? ( +
+ + {/* Tab bar */} +
+ {(["chat", "tree"] as const).map((tab) => ( + + ))} + +
+ + {selectedDoc.file_name} + +
+
+ + {/* Content — both panels stay mounted to preserve state */} +
+ +
+
+
+ {treeLoading ? ( +
+ + + Building tree… + +
+ ) : tree.length > 0 ? ( + + ) : ( +
+ No tree structure available. +
+ )} +
+
+
+ ) : ( + /* Empty state */ +
+
+ {/* Large icon */} +
+ +
+ +

+ Select a document +

+

+ Upload a PDF and pick it from the sidebar to start an AI conversation. +

+ + {/* Info card */} +
+
+

+ How it works +

+ {[ + ["🌳", "Tree Index", "Builds a hierarchical map of your document like a smart table of contents."], + ["🔍", "Agentic Search", "The LLM navigates the tree to find exactly the right section."], + ["📄", "Verbatim Retrieval", "Returns exact page content — no chunking, no hallucination."], + ].map(([icon, title, desc]) => ( +
+ {icon} +
+

{title as string}

+

{desc as string}

+
+
+ ))} +
+
+
+ )} +
+
+
+ ); +} diff --git a/kits/assistant/pageindex-notebooklm/components.json b/kits/assistant/pageindex-notebooklm/components.json new file mode 100644 index 00000000..4ee62ee1 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/kits/assistant/pageindex-notebooklm/components/ChatWindow.tsx b/kits/assistant/pageindex-notebooklm/components/ChatWindow.tsx new file mode 100644 index 00000000..ebe0c7d9 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/ChatWindow.tsx @@ -0,0 +1,401 @@ +"use client"; + +import { useState, useRef, useEffect } from "react"; +import { chatWithDocument } from "@/actions/orchestrate"; +import { ChatResponse, Message, RetrievedNode } from "@/lib/types"; +import { MessageSquare, Bot, Search, ChevronDown, Send } from "lucide-react"; +import DOMPurify from "dompurify"; +import { Card } from "@/components/ui/card"; +import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@/components/ui/collapsible"; + +// Lightweight markdown → HTML (no external deps) +function renderMarkdown(text: string): string { + const html = text + // Headings + .replace(/^### (.+)$/gm, "

$1

") + .replace(/^## (.+)$/gm, "

$1

") + .replace(/^# (.+)$/gm, "

$1

") + // Bold + italic + .replace(/\*\*\*(.+?)\*\*\*/g, "$1") + .replace(/\*\*(.+?)\*\*/g, "$1") + .replace(/\*(.+?)\*/g, "$1") + // Inline code + .replace(/`([^`]+)`/g, "$1") + // Bullet list items (* or -) + .replace(/^[*-] (.+)$/gm, "
  • $1
  • ") + // Numbered list items + .replace(/^\d+\.\s+(.+)$/gm, "
  • $1
  • ") + // Wrap consecutive
  • blocks in
      + .replace(/((?:
    • [\s\S]*?<\/li>\s*)+)/g, (match) => `
        ${match}
      `) + // Horizontal rule + .replace(/^---$/gm, "
      ") + // Paragraphs: double newline →

      break + .replace(/\n{2,}/g, "

      ") + // Single newline →
      + .replace(/\n/g, "
      ") + // Wrap in paragraph + .replace(/^/, "

      ") + .replace(/$/, "

      "); + return DOMPurify.sanitize(html); +} + +interface Props { + docId: string; + docName: string; + onRetrievedNodes?: (nodes: RetrievedNode[]) => void; +} + +export default function ChatWindow({ docId, docName, onRetrievedNodes }: Props) { + const storageKey = `chat_${docId}`; + const historyKey = `chat_history_${docId}`; + + const [messages, setMessages] = useState(() => { + if (typeof window === "undefined") return []; + try { const s = localStorage.getItem(storageKey); return s ? JSON.parse(s) : []; } catch { return []; } + }); + const [input, setInput] = useState(""); + const [loading, setLoading] = useState(false); + const [sourcesOpen, setSourcesOpen] = useState(false); + const [lastNodes, setLastNodes] = useState([]); + const [lastThinking, setLastThinking] = useState(""); + // Raw Lamatic API message history — passed back each turn for multi-turn context + const [lamaticHistory, setLamaticHistory] = useState>(() => { + if (typeof window === "undefined") return []; + try { const s = localStorage.getItem(historyKey); return s ? JSON.parse(s) : []; } catch { return []; } + }); + const bottomRef = useRef(null); + + // Persist messages — only re-run when messages change. + // Intentionally omit storageKey from deps: if included, a doc switch would + // fire this effect (storageKey changed) with the OLD messages, overwriting + // the new doc's slot before the docId-load effect could populate it. + useEffect(() => { + try { localStorage.setItem(`chat_${docId}`, JSON.stringify(messages)); } catch { /* quota exceeded */ } + }, [messages]); // eslint-disable-line react-hooks/exhaustive-deps + + // Persist lamatic history — same reasoning as above. + useEffect(() => { + try { localStorage.setItem(`chat_history_${docId}`, JSON.stringify(lamaticHistory)); } catch { /* quota exceeded */ } + }, [lamaticHistory]); // eslint-disable-line react-hooks/exhaustive-deps + + useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages, loading]); + + // When docId changes, restore from localStorage (lazy init already handles initial mount) + useEffect(() => { + try { + const saved = localStorage.getItem(`chat_${docId}`); + setMessages(saved ? JSON.parse(saved) : []); + const savedHistory = localStorage.getItem(`chat_history_${docId}`); + setLamaticHistory(savedHistory ? JSON.parse(savedHistory) : []); + } catch { + setMessages([]); + setLamaticHistory([]); + } + setLastNodes([]); setLastThinking(""); setSourcesOpen(false); + }, [docId]); + + async function handleSend(e: React.FormEvent) { + e.preventDefault(); + if (!input.trim() || loading) return; + const userMsg: Message = { role: "user", content: input.trim() }; + const newMsgs = [...messages, userMsg]; + setMessages(newMsgs); + setInput(""); + setLoading(true); + try { + const result = await chatWithDocument(docId, userMsg.content, lamaticHistory) as unknown as ChatResponse & { messages: unknown }; + const assistantContent = result.answer || "No answer found."; + setMessages(prev => [...prev, { role: "assistant", content: assistantContent }]); + + // Update Lamatic history for the next turn + // Try to use the flow-returned messages first + let nextHistory: Array<{ role: string; content: string }> | null = null; + if (result.messages) { + const parsed = typeof result.messages === "string" + ? (() => { + try { + return JSON.parse(result.messages as string); + } catch (e) { + console.warn("Failed to parse result.messages:", e, result.messages); + return null; + } + })() + : result.messages; + if (Array.isArray(parsed) && parsed.length) nextHistory = parsed; + } + // Fallback: build history from UI messages if flow didn't return it + if (!nextHistory) { + nextHistory = [...newMsgs, { role: "assistant", content: assistantContent }].map(m => ({ + role: m.role, + content: m.content, + })); + } + setLamaticHistory(nextHistory); + + // Always update retrieval state when the field is present — even if empty, + // so that previous turn's sources/highlights are cleared correctly. + if (Array.isArray(result.retrieved_nodes)) { + setLastNodes(result.retrieved_nodes); + setLastThinking(result.thinking || ""); + onRetrievedNodes?.(result.retrieved_nodes); + } + } catch { + setMessages(prev => [...prev, { role: "assistant", content: "Something went wrong. Please try again." }]); + } finally { setLoading(false); } + } + + return ( + + + {/* ── Chat header ── */} +
      +
      + + {loading ? "Searching tree…" : "READY"} + + + {docName} + +
      + + {/* ── Messages ── */} +
      + + {messages.length === 0 && ( +
      +
      + +
      +
      +

      + Ask anything +

      +

      + The tree index navigates to the right section in{" "} + {docName} +

      +
      + + {/* Suggested prompts */} +
      + {["Summarize this document", "What are the key findings?", "Explain the main argument"].map(q => ( + + ))} +
      +
      + )} + + {messages.map((msg, i) => ( +
      + {msg.role === "assistant" && ( +
      + +
      + )} +
      +
      + ))} + + {loading && ( +
      +
      + +
      +
      + + {[0, 1, 2].map(i => ( + + ))} + + + navigating tree + +
      +
      + )} +
      +
      + + {/* ── Sources panel ── */} + {lastNodes.length > 0 && ( + + + + + + +
      + {lastThinking && ( +
      + + Tree reasoning + +
      + {lastThinking} +
      + )} + {lastNodes.map(node => ( +
      +
      + {node.title} + pp.{node.start_index}–{node.end_index} +
      + {node.summary && ( +

      + {node.summary} +

      + )} +

      + {node.page_content} +

      +
      + ))} +
      +
      +
      + )} + + {/* ── Input ── */} +
      + setInput(e.target.value)} + placeholder="Ask a question about this document…" + disabled={loading} + /> + +
      + + ); +} diff --git a/kits/assistant/pageindex-notebooklm/components/DocumentList.tsx b/kits/assistant/pageindex-notebooklm/components/DocumentList.tsx new file mode 100644 index 00000000..7d48c454 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/DocumentList.tsx @@ -0,0 +1,232 @@ +"use client"; + +import { useState } from "react"; +import { FileText, Loader2, Trash2 } from "lucide-react"; +import { Document } from "@/lib/types"; +import { deleteDocument } from "@/actions/orchestrate"; + +interface Props { + documents: Document[]; + selectedId: string | null; + onSelect: (doc: Document) => void; + onDeleted?: (doc_id: string) => void; +} + +export default function DocumentList({ documents, selectedId, onSelect, onDeleted }: Props) { + const [confirmId, setConfirmId] = useState(null); + const [deletingId, setDeletingId] = useState(null); + + const [deleteError, setDeleteError] = useState(null); + + async function handleDelete(doc_id: string) { + setDeletingId(doc_id); + setConfirmId(null); + setDeleteError(null); + try { + await deleteDocument(doc_id); + onDeleted?.(doc_id); + } catch (err) { + console.error("Failed to delete document:", err); + // Fallback UI error indication + setDeleteError("Delete failed"); + } finally { + setDeletingId(null); + } + } + + if (documents.length === 0) { + return ( +
      + +

      + No documents yet +

      +

      + Upload a PDF to get started +

      +
      + ); + } + + return ( +
        + + + {deleteError && ( +
      • + {deleteError} +
      • + )} + + {documents.map((doc, idx) => { + const active = selectedId === doc.doc_id; + const isConfirming = confirmId === doc.doc_id; + const isDeleting = deletingId === doc.doc_id; + + return ( +
      • + + + {/* ── Delete button ──────────────────────────────────────────────────── + Placed OUTSIDE the row + )} + + {/* Confirm/Cancel strip below the row */} + {isConfirming && ( +
        + + Delete this doc? + + + +
        + )} + +
      • + ); + })} +
      + ); +} diff --git a/kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx b/kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx new file mode 100644 index 00000000..ec7cc91e --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/DocumentUpload.tsx @@ -0,0 +1,168 @@ +"use client"; + +import { useState, useRef, useEffect } from "react"; +import { Loader2, Check, AlertCircle, Upload } from "lucide-react"; +import { uploadDocument } from "@/actions/orchestrate"; +import { UploadResponse } from "@/lib/types"; + +interface Props { onUploaded: () => void; } +type Status = "idle" | "uploading" | "success" | "error"; + +export default function DocumentUpload({ onUploaded }: Props) { + const [status, setStatus] = useState("idle"); + const [message, setMessage] = useState(""); + const [dragging, setDragging] = useState(false); + const inputRef = useRef(null); + const resetTimerRef = useRef(null); + + async function processFile(file: File) { + if (resetTimerRef.current) clearTimeout(resetTimerRef.current); + + // Only PDFs are supported — the upstream flow does not handle Markdown. + const allowedTypes = ["application/pdf"]; + if (!allowedTypes.includes(file.type) && !file.name.toLowerCase().endsWith(".pdf")) { + setStatus("error"); + setMessage("Only PDF files are supported."); + // Schedule reset so the picker can be re-opened (matches success/error paths). + resetTimerRef.current = setTimeout(() => { setStatus("idle"); setMessage(""); }, 3500); + return; + } + setStatus("uploading"); + try { + const dataUrl = await fileToDataUrl(file); + // Split "data:;base64," → { mime_type, file_base64 } + const [meta, file_base64] = dataUrl.split(","); + const mime_type = meta.replace("data:", "").replace(";base64", ""); + const result = (await uploadDocument(file.name, { file_base64, mime_type })) as unknown as UploadResponse; + setStatus("success"); + setMessage(`${result.tree_node_count} nodes indexed`); + onUploaded(); + } catch { + setStatus("error"); setMessage("Upload failed. Check your flow."); + } + resetTimerRef.current = setTimeout(() => { setStatus("idle"); setMessage(""); }, 3500); + } + + useEffect(() => { + return () => { + if (resetTimerRef.current) clearTimeout(resetTimerRef.current); + }; + }, []); + + function fileToDataUrl(file: File): Promise { + return new Promise((res, rej) => { + const r = new FileReader(); + r.onload = () => res(r.result as string); + r.onerror = rej; + r.readAsDataURL(file); + }); + } + + const isIdle = status === "idle"; + + return ( + // tabIndex + role + onKeyDown make the upload zone keyboard-accessible. + // Keyboard users can Tab to it and press Enter or Space to open the picker. +
      isIdle && inputRef.current?.click()} + onKeyDown={(e) => { + if (!isIdle) return; + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + inputRef.current?.click(); + } + }} + onDragOver={(e) => { e.preventDefault(); setDragging(true); }} + onDragLeave={() => setDragging(false)} + onDrop={(e) => { e.preventDefault(); setDragging(false); const f = e.dataTransfer.files[0]; if (f) processFile(f); }} + style={{ + borderRadius: "var(--radius-md)", + padding: "14px 12px", + cursor: isIdle ? "pointer" : "default", + border: `1.5px dashed ${ + dragging ? "var(--accent)" : + status === "success" ? "var(--green)" : + status === "error" ? "var(--red)" : + status === "uploading" ? "rgba(45,212,191,0.3)" : + "var(--border-md)" + }`, + background: dragging + ? "var(--accent-dim)" + : status === "success" + ? "rgba(52,211,153,0.06)" + : status === "error" + ? "rgba(248,113,113,0.06)" + : "var(--surface-2)", + display: "flex", flexDirection: "column", alignItems: "center", gap: "5px", + textAlign: "center", + transition: "all 0.22s var(--ease)", + position: "relative", overflow: "hidden", + boxShadow: dragging ? "var(--glow)" : "none", + }} + > + { const f = e.target.files?.[0]; if (f) processFile(f); e.target.value = ""; }} + /> + + {status === "uploading" && ( + <> + {/* Progress shimmer line */} +
      + +

      Indexing…

      +

      + Building tree structure +

      + + )} + + {status === "success" && ( + <> +
      + +
      +

      Indexed

      +

      {message}

      + + )} + + {status === "error" && ( + <> + +

      Failed

      +

      {message}

      + + )} + + {isIdle && ( + <> +
      + +
      +

      + Upload document +

      +

      + PDF · drop or click +

      + + )} +
      + ); +} diff --git a/kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx b/kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx new file mode 100644 index 00000000..fd9464d4 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/TreeViewer.tsx @@ -0,0 +1,365 @@ +"use client"; + +import { useState, useMemo } from "react"; +import { TreeNode, TreeNodeResolved } from "@/lib/types"; +import { ChevronRight, Circle, Search } from "lucide-react"; + +interface Props { + tree: TreeNode[]; + fileName: string; + highlightedIds: string[]; +} + +/** Build a lookup map and resolve the flat API list into a nested tree. + * Root nodes are those whose node_id appears in the first item's `nodes` + * list OR nodes that are not referenced as children by any other node. + * Tolerates LLM hallucinations by gracefully ignoring duplicate IDs, missing references, DAGs, and cycles. + */ +function buildTree(flat: TreeNode[]): TreeNodeResolved[] { + const map = new Map(); + + // First pass: create resolved nodes with empty children arrays + for (const n of flat) { + if (map.has(n.node_id)) { + console.warn(`buildTree: Duplicate node_id detected: "${n.node_id}". Skipping.`); + continue; + } + map.set(n.node_id, { ...n, nodes: [] }); + } + + // Second pass: populate children + const parentMap = new Map(); + for (const n of flat) { + const resolved = map.get(n.node_id); + if (!resolved) continue; + + for (const childId of n.nodes) { + const child = map.get(childId); + if (!child) { + console.warn(`buildTree: Missing reference for childId "${childId}" requested by parent "${n.node_id}". Skipping.`); + continue; + } + if (parentMap.has(childId)) { + console.warn(`buildTree: Shared child detected. Child "${childId}" is claimed by multiple parents. Skipping.`); + continue; + } + parentMap.set(childId, n.node_id); + resolved.nodes.push(child); + } + } + + // ── Cycle detection ───────────────────────────────────────────── + type VisitState = "unvisited" | "visiting" | "visited"; + const state = new Map(); + map.forEach((_, id) => state.set(id, "unvisited")); + + function dfs(nodeId: string): void { + state.set(nodeId, "visiting"); + const node = map.get(nodeId)!; + + const validChildren = []; + for (const child of node.nodes) { + const childState = state.get(child.node_id); + if (childState === "visiting") { + console.warn(`buildTree: cycle detected — node "${child.node_id}" is its own ancestor. Skipping back-edge.`); + continue; + } + validChildren.push(child); + if (childState === "unvisited") dfs(child.node_id); + } + node.nodes = validChildren; + + state.set(nodeId, "visited"); + } + + for (const [id, s] of state.entries()) { + if (s === "unvisited") dfs(id); + } + // ── End cycle detection ───────────────────────────────────────── + + // Roots = nodes not referenced as a child + return Array.from(map.values()).filter(n => !parentMap.has(n.node_id)); +} + +function TreeNodeRow({ + node, + depth, + highlightedIdSet, +}: { + node: TreeNodeResolved; + depth: number; + highlightedIdSet: Set; +}) { + const [open, setOpen] = useState(depth < 2); + const isHighlighted = highlightedIdSet.has(node.node_id); + const hasChildren = node.nodes.length > 0; + const pageSpan = + node.start_index === node.end_index + ? `p.${node.start_index}` + : `pp.${node.start_index}–${node.end_index}`; + + return ( +
      + {hasChildren ? ( + + ) : ( +
      +
      { if (!isHighlighted) e.currentTarget.style.background = "var(--surface-2)"; }} + onMouseLeave={e => { if (!isHighlighted) e.currentTarget.style.background = "transparent"; }} + > + {/* Chevron / dot */} + + + + + {/* Content */} +
      +
      + + {node.title} + + + {pageSpan} + + {isHighlighted && ( + + retrieved + + )} +
      + {node.summary && ( +

      + {node.summary} +

      + )} +
      +
      +
      + )} + + {/* Children — rendered outside the toggle button */} + {open && hasChildren && ( +
      + {node.nodes.map((child, i) => ( + + ))} +
      + )} +
      + ); +} + +/** Pure recursive helper — hoisted to module level to avoid redefining on every render. */ +function totalNodes(nodes: TreeNodeResolved[]): number { + return nodes.reduce((acc, n) => acc + 1 + totalNodes(n.nodes), 0); +} + +export default function TreeViewer({ tree, fileName, highlightedIds }: Props) { + // Must be declared before any early return to satisfy Rules of Hooks + const highlightedIdSet = useMemo(() => new Set(highlightedIds), [highlightedIds]); + + let resolvedRoots: TreeNodeResolved[]; + try { + resolvedRoots = buildTree(tree); + } catch (err) { + console.error("TreeViewer: buildTree failed —", err); + return ( +
      + Invalid tree structure detected. Please re-upload the document. +
      + ); + } + + return ( +
      + {/* Header */} +
      +
      +

      + Document Tree +

      +

      + {fileName} +

      +
      +
      + {highlightedIdSet.size > 0 && ( + + {highlightedIdSet.size} retrieved + + )} + + {totalNodes(resolvedRoots)} nodes + +
      +
      + + {/* Tree body */} +
      + {resolvedRoots.map((node, i) => ( + + ))} +
      + + {/* Retrieved footer */} + {highlightedIdSet.size > 0 && ( +
      + + + {highlightedIdSet.size} NODE{highlightedIdSet.size !== 1 ? "S" : ""} USED IN LAST ANSWER + +
      + )} +
      + ); +} diff --git a/kits/assistant/pageindex-notebooklm/components/ui/card.tsx b/kits/assistant/pageindex-notebooklm/components/ui/card.tsx new file mode 100644 index 00000000..acf57dc5 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/ui/card.tsx @@ -0,0 +1,92 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Card({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardAction({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
      + ) +} + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +} diff --git a/kits/assistant/pageindex-notebooklm/components/ui/collapsible.tsx b/kits/assistant/pageindex-notebooklm/components/ui/collapsible.tsx new file mode 100644 index 00000000..2f7a4e7f --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/components/ui/collapsible.tsx @@ -0,0 +1,33 @@ +"use client" + +import { Collapsible as CollapsiblePrimitive } from "radix-ui" + +function Collapsible({ + ...props +}: React.ComponentProps) { + return +} + +function CollapsibleTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function CollapsibleContent({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/kits/assistant/pageindex-notebooklm/config.json b/kits/assistant/pageindex-notebooklm/config.json new file mode 100644 index 00000000..9b5a5910 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/config.json @@ -0,0 +1,66 @@ +{ + "name": "PageIndex NotebookLM — Vectorless Tree-Structured RAG", + "description": "Upload any PDF and chat with it using vectorless, tree-structured RAG powered entirely by Lamatic AI flows. No vector database, no external Python server, no chunking — just a hierarchical document index built from the table of contents.", + "tags": [ + "pageindex", + "rag", + "notebooklm", + "tree-structured-rag", + "document-chat", + "pdf", + "lamatic", + "next.js", + "agentkit" + ], + "author": { + "name": "Saurabh Tiwari", + "email": "st108113@gmail.com", + "github": "https://github.com/Skt329" + }, + "steps": [ + { + "id": "flow-1-upload-pdf-build-tree-save", + "type": "mandatory", + "envKey": "FLOW_ID_UPLOAD", + "description": "Upload PDF → build hierarchical tree index → save to Supabase" + }, + { + "id": "chat-with-pdf", + "type": "mandatory", + "envKey": "FLOW_ID_CHAT", + "description": "Tree-navigated search → page content fetch → LLM answer" + }, + { + "id": "flow-list-all-documents", + "type": "mandatory", + "envKey": "FLOW_ID_LIST", + "description": "List all uploaded documents from Supabase" + }, + { + "id": "flow-4-get-tree-structure", + "type": "mandatory", + "envKey": "FLOW_ID_TREE", + "description": "Get full tree JSON for a document or delete a document" + } + ], + "integrations": [ + "lamatic-ai", + "supabase" + ], + "features": [ + "PDF upload with drag-and-drop or URL", + "Vectorless tree-structured RAG (no vector DB)", + "Hierarchical table-of-contents index", + "Multi-turn conversational chat with document", + "Chat history persistence across sessions", + "Interactive tree viewer with node highlighting", + "Source retrieval with page ranges and LLM reasoning", + "Document management (list, view, delete)", + "Markdown-rendered AI responses", + "Responsive dark-mode UI" + ], + "demoUrl": "https://pageindex-notebooklm.vercel.app/", + "githubUrl": "https://github.com/Skt329/AgentKit", + "deployUrl": "https://pageindex-notebooklm.vercel.app/", + "documentationUrl": "https://github.com/Skt329/AgentKit" +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/README.md b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/README.md new file mode 100644 index 00000000..9293d95c --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/README.md @@ -0,0 +1,65 @@ +# Chat with Pdf + +## About This Flow + +This flow automates a workflow with **7 nodes** working together to process and transform data. The flow is designed to streamline operations and can be easily integrated into your existing systems. + +## Flow Components + +This workflow includes the following node types: +- API Request +- Postgres +- Code +- Generate JSON +- Generate Text +- API Response + +## Configuration Requirements + +This flow requires configuration for **3 node(s)** with private inputs (credentials, API keys, model selections, etc.). All required configurations are documented in the `inputs.json` file. + +## Files Included + +- **config.json** - Complete flow structure with nodes and connections +- **inputs.json** - Private inputs requiring configuration +- **meta.json** - Flow metadata and information + +## Next Steps + +### Share with the Community + +Help grow the Lamatic ecosystem by contributing this flow to AgentKit! + +1. **Fork the Repository** + - Visit [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Fork the repository to your GitHub account + +2. **Prepare Your Submission** + - Create a new folder with a descriptive name for your flow + - Add all files from this package (`config.json`, `inputs.json`, `meta.json`) + - Write a comprehensive README.md that includes: + - Clear description of what the flow does + - Use cases and benefits + - Step-by-step setup instructions + - Required credentials and how to obtain them + - Example inputs and expected outputs + - Screenshots or diagrams (optional but recommended) + +3. **Open a Pull Request** + - Commit your changes with a descriptive message + - Push to your forked repository + - Open a PR to [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Add a clear description of your flow in the PR + +Your contribution will help others build amazing automations! 🚀 + +## Support + +For questions or issues with this flow: +- Review the node documentation for specific integrations +- Check the Lamatic documentation at docs.lamatic.ai +- Contact support for assistance + +--- +*Exported from Lamatic Flow Editor* +*Generated on 3/29/2026* diff --git a/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/config.json b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/config.json new file mode 100644 index 00000000..78b940bd --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/config.json @@ -0,0 +1,276 @@ +{ + "nodes": [ + { + "id": "triggerNode_1", + "data": { + "modes": {}, + "nodeId": "graphqlNode", + "values": { + "id": "triggerNode_1", + "nodeName": "API Request", + "responeType": "realtime", + "advance_schema": "{\n \"doc_id\": \"string\",\n \"query\": \"string\",\n \"messages\": \"string\"\n}" + }, + "trigger": true + }, + "type": "triggerNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 0 + }, + "selected": false + }, + { + "id": "postgresNode_817", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "postgresNode", + "values": { + "id": "postgresNode_817", + "query": "SELECT tree, raw_text, file_name FROM documents WHERE doc_id = '{{triggerNode_1.output.doc_id}}' LIMIT 1;", + "action": "runQuery", + "nodeName": "Postgres", + "credentials": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 130 + }, + "selected": false + }, + { + "id": "codeNode_429", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "schema": { + "toc_json": "string", + "node_count": "number" + }, + "values": { + "id": "codeNode_429", + "code": "const tree = {{postgresNode_817.output.queryResult[0].tree}};\n\n// tree.nodes are string IDs, not objects — just pass them as-is\nfunction stripToTOC(nodes, depth = 0) {\n return nodes.map(node => ({\n node_id: node.node_id,\n title: node.title,\n start_index: node.start_index,\n end_index: node.end_index,\n description: node.summary,\n children: node.nodes && node.nodes.length > 0\n ? stripToTOC(node.nodes, depth + 1)\n : []\n }));\n}\n\noutput = {\n toc_json: JSON.stringify(stripToTOC(tree)),\n node_count: tree.length\n};", + "nodeName": "Code" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 260 + }, + "selected": false + }, + { + "id": "InstructorLLMNode_432", + "data": { + "label": "dynamicNode node", + "modes": {}, + "nodeId": "InstructorLLMNode", + "values": { + "id": "InstructorLLMNode_432", + "tools": [], + "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"thinking\": {\n \"type\": \"string\"\n },\n \"node_list\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n}", + "prompts": [ + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7b", + "role": "system", + "content": "You are a document retrieval expert using tree-based reasoning. Your job is to identify which sections of a document tree are most relevant to answer the user's query.\nIMPORTANT RULES:\n- Always prefer LEAF nodes (nodes where \"children\" is an empty array [])\n- Never select root or parent nodes that span many pages\n- Select 2-3 most specific nodes that directly answer the query\n- A good node covers 1-3 pages maximum" + }, + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7d", + "role": "user", + "content": "You are given a query and a document table of contents (TOC).\nNavigate the TOC structure and find which LEAF sections (children: []) likely contain the answer.\nQuery: {{triggerNode_1.output.query}}\nDocument TOC (titles and structure only): {{codeNode_429.output.toc_json}}\nEach node has start_index and end_index showing which pages it covers.\nONLY select nodes where children is [] (leaf nodes, not parent sections).\nReply with:\n- thinking: your reasoning about which specific leaf sections contain the answer\n- node_list: array of 2-3 leaf node_ids most likely to contain the answer" + } + ], + "memories": "[]", + "messages": "{{triggerNode_1.output.messages}}", + "nodeName": "Generate JSON", + "attachments": "", + "generativeModelName": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 390 + }, + "selected": false + }, + { + "id": "codeNode_358", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "schema": { + "context": "string", + "total_chars": "number", + "retrieved_nodes": "array" + }, + "values": { + "id": "codeNode_358", + "code": "const tree = {{postgresNode_817.output.queryResult[0].tree}};\nconst rawTextRaw = {{postgresNode_817.output.queryResult[0].raw_text}};\nconst nodeList = {{InstructorLLMNode_432.output.node_list}};\n\nconst pages = typeof rawTextRaw === \"string\" ? JSON.parse(rawTextRaw) : rawTextRaw;\n\n// ── Detect page offset ────────────────────────────────────────────────────────\n// The tree uses PRINTED page numbers from the TOC.\n// The pages array uses PHYSICAL page indices (0-based).\n// Books with roman-numeral front matter have an offset between the two.\n//\n// Strategy: find the first chapter node in the tree (depth 1, lowest start_index).\n// Search physical pages for that chapter's title text.\n// offset = physical_page_found - tree_start_index\n\nfunction detectOffset(tree, pages) {\n // Get all top-level nodes sorted by start_index\n const topLevel = [...tree].sort((a, b) => (a.start_index || 0) - (b.start_index || 0));\n \n for (const node of topLevel) {\n const printedPage = node.start_index;\n if (!printedPage || !node.title) continue;\n \n const titleLower = node.title.toLowerCase().replace(/chapter-?\\d+[-:\\s]*/i, \"\").trim();\n if (titleLower.length < 3) continue;\n\n // Search physical pages around where we expect to find it\n // Front matter is rarely more than 40 pages\n for (let physIdx = 0; physIdx < Math.min(pages.length, 60); physIdx++) {\n const pageText = (pages[physIdx] || \"\").toLowerCase();\n if (pageText.includes(titleLower)) {\n const offset = physIdx - (printedPage - 1); // physIdx is 0-based, printedPage is 1-based\n if (offset !== 0) {\n console.log(`[offset] \"${node.title}\" TOC page ${printedPage} → physical index ${physIdx} → offset +${offset}`);\n }\n return offset;\n }\n }\n }\n return 0; // no offset detected\n}\n\nconst pageOffset = detectOffset(tree, pages);\n\n// ── Flatten tree recursively ──────────────────────────────────────────────────\nfunction flattenTree(nodes, map = {}) {\n for (const n of nodes) {\n map[n.node_id] = n;\n if (n.nodes && n.nodes.length > 0) flattenTree(n.nodes, map);\n }\n return map;\n}\nconst nodeMap = flattenTree(tree);\nconst selectedNodes = nodeList.map(id => nodeMap[id]).filter(Boolean);\n\nconst MAX_PAGES_PER_NODE = 2;\nconst MAX_CHARS_PER_PAGE = 2000;\n\nconst retrieved = selectedNodes.map(node => {\n // Apply offset: convert printed page number → physical array index (0-based)\n const startPhysIdx = (node.start_index || 1) - 1 + pageOffset;\n const endPhysIdx = (node.end_index || node.start_index || 1) - 1 + pageOffset;\n\n const cappedEnd = Math.min(endPhysIdx, startPhysIdx + MAX_PAGES_PER_NODE - 1, pages.length - 1);\n\n const pageSlices = pages\n .slice(startPhysIdx, cappedEnd + 1)\n .map(p => p && p.length > MAX_CHARS_PER_PAGE ? p.slice(0, MAX_CHARS_PER_PAGE) + \"...\" : (p || \"\"));\n\n const pageContent = pageSlices.join(\"\\n\\n\").trim();\n\n return {\n node_id: node.node_id,\n title: node.title,\n start_index: node.start_index,\n end_index: node.end_index,\n summary: node.summary,\n page_content: pageContent || node.summary,\n };\n});\n\nconst context = retrieved\n .map(n => `[Section: \"${n.title}\" | Pages: ${n.start_index}–${n.end_index}]\\n${n.page_content}`)\n .join(\"\\n\\n---\\n\\n\");\n\noutput = {\n context,\n retrieved_nodes: retrieved,\n total_chars: context.length,\n page_offset_detected: pageOffset,\n};", + "nodeName": "Code" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 520 + }, + "selected": true + }, + { + "id": "LLMNode_392", + "data": { + "label": "dynamicNode node", + "modes": {}, + "nodeId": "LLMNode", + "values": { + "id": "LLMNode_392", + "tools": [], + "prompts": [ + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7b", + "role": "system", + "content": "You are a research assistant. Answer questions based ONLY on the retrieved document sections. Always cite the section title and page number in your answer. If the answer is not found in the provided sections, say so clearly — do not guess." + }, + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7d", + "role": "user", + "content": "Retrieved document sections: {{codeNode_358.output.context}} User question: {{triggerNode_1.output.query}}" + } + ], + "memories": "[]", + "messages": "{{triggerNode_1.output.messages}}", + "nodeName": "Generate Text", + "attachments": "", + "credentials": "", + "generativeModelName": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 650 + }, + "selected": false + }, + { + "id": "responseNode_triggerNode_1", + "data": { + "label": "Response", + "nodeId": "graphqlResponseNode", + "values": { + "id": "responseNode_triggerNode_1", + "headers": "{\"content-type\":\"application/json\"}", + "retries": "0", + "nodeName": "API Response", + "webhookUrl": "", + "retry_delay": "0", + "outputMapping": "{\n \"answer\": \"{{LLMNode_392.output.generatedResponse}}\",\n \"messages\": \"{{LLMNode_392.output.messages}}\",\n \"retrieved_nodes\": \"{{codeNode_358.output.retrieved_nodes}}\",\n \"thinking\": \"{{InstructorLLMNode_432.output.thinking}}\",\n \"doc_id\": \"{{triggerNode_1.output.doc_id}}\"\n}" + }, + "isResponseNode": true + }, + "type": "responseNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 780 + }, + "selected": false + } + ], + "edges": [ + { + "id": "triggerNode_1-postgresNode_817", + "type": "defaultEdge", + "source": "triggerNode_1", + "target": "postgresNode_817", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "InstructorLLMNode_432-codeNode_358", + "type": "defaultEdge", + "source": "InstructorLLMNode_432", + "target": "codeNode_358", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "postgresNode_817-codeNode_429", + "type": "defaultEdge", + "source": "postgresNode_817", + "target": "codeNode_429", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "codeNode_429-InstructorLLMNode_432", + "type": "defaultEdge", + "source": "codeNode_429", + "target": "InstructorLLMNode_432", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "codeNode_358-LLMNode_392", + "type": "defaultEdge", + "source": "codeNode_358", + "target": "LLMNode_392", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "LLMNode_392-responseNode_triggerNode_1", + "type": "defaultEdge", + "source": "LLMNode_392", + "target": "responseNode_triggerNode_1", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "response-trigger_triggerNode_1", + "type": "responseEdge", + "source": "triggerNode_1", + "target": "responseNode_triggerNode_1", + "sourceHandle": "to-response", + "targetHandle": "from-trigger" + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/inputs.json b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/inputs.json new file mode 100644 index 00000000..1a1bb9eb --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/inputs.json @@ -0,0 +1,62 @@ +{ + "postgresNode_817": [ + { + "name": "credentials", + "label": "Credentials", + "description": "Select the credentials for postgres authentication.", + "type": "select", + "isCredential": true, + "required": true, + "defaultValue": "", + "isPrivate": true + } + ], + "InstructorLLMNode_432": [ + { + "name": "generativeModelName", + "label": "Generative Model Name", + "type": "model", + "mode": "instructor", + "description": "Select the model to generate text based on the prompt.", + "modelType": "generator/text", + "required": true, + "isPrivate": true, + "defaultValue": [ + { + "configName": "configA", + "type": "generator/text", + "provider_name": "", + "credential_name": "", + "params": {} + } + ], + "typeOptions": { + "loadOptionsMethod": "listModels" + } + } + ], + "LLMNode_392": [ + { + "name": "generativeModelName", + "label": "Generative Model Name", + "type": "model", + "modelType": "generator/text", + "mode": "chat", + "description": "Select the model to generate text based on the prompt.", + "required": true, + "defaultValue": [ + { + "configName": "configA", + "type": "generator/text", + "provider_name": "", + "credential_name": "", + "params": {} + } + ], + "typeOptions": { + "loadOptionsMethod": "listModels" + }, + "isPrivate": true + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.json b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.json new file mode 100644 index 00000000..f299b139 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/chat-with-pdf/meta.json @@ -0,0 +1,14 @@ +{ + "name": "Chat with Pdf", + "description": "chat-with-pdf using NotebookLM", + "tags": [ + "pdf", + "notebooklm", + "assistant", + "document-search" + ], + "testInput": "{}", + "githubUrl": "https://github.com/Skt329/AgentKit", + "documentationUrl": "https://github.com/Skt329/AgentKit", + "deployUrl": "https://pageindex-notebooklm.vercel.app/" +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/README.md b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/README.md new file mode 100644 index 00000000..47096414 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/README.md @@ -0,0 +1,65 @@ +# Flow 1 Upload PDF Build Tree Save + +## About This Flow + +This flow automates a workflow with **8 nodes** working together to process and transform data. The flow is designed to streamline operations and can be easily integrated into your existing systems. + +## Flow Components + +This workflow includes the following node types: +- API Request +- Code +- Extract from File +- Generate JSON +- Variables +- API Response + +## Configuration Requirements + +This flow requires configuration for **1 node(s)** with private inputs (credentials, API keys, model selections, etc.). All required configurations are documented in the `inputs.json` file. + +## Files Included + +- **config.json** - Complete flow structure with nodes and connections +- **inputs.json** - Private inputs requiring configuration +- **meta.json** - Flow metadata and information + +## Next Steps + +### Share with the Community + +Help grow the Lamatic ecosystem by contributing this flow to AgentKit! + +1. **Fork the Repository** + - Visit [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Fork the repository to your GitHub account + +2. **Prepare Your Submission** + - Create a new folder with a descriptive name for your flow + - Add all files from this package (`config.json`, `inputs.json`, `meta.json`) + - Write a comprehensive README.md that includes: + - Clear description of what the flow does + - Use cases and benefits + - Step-by-step setup instructions + - Required credentials and how to obtain them + - Example inputs and expected outputs + - Screenshots or diagrams (optional but recommended) + +3. **Open a Pull Request** + - Commit your changes with a descriptive message + - Push to your forked repository + - Open a PR to [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Add a clear description of your flow in the PR + +Your contribution will help others build amazing automations! 🚀 + +## Support + +For questions or issues with this flow: +- Review the node documentation for specific integrations +- Check the Lamatic documentation at docs.lamatic.ai +- Contact support for assistance + +--- +*Exported from Lamatic Flow Editor* +*Generated on 3/29/2026* diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json new file mode 100644 index 00000000..77015213 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/config.json @@ -0,0 +1,309 @@ +{ + "nodes": [ + { + "id": "triggerNode_1", + "data": { + "modes": {}, + "nodeId": "graphqlNode", + "schema": { + "sampleOutput": "string" + }, + "values": { + "id": "triggerNode_1", + "nodeName": "API Request", + "responeType": "realtime", + "advance_schema": "{\n \"file_url\": \"string\",\n \"file_name\": \"string\",\n \"file_base64\": \"string\",\n \"mime_type\": \"string\"\n}" + }, + "trigger": true + }, + "type": "triggerNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 0 + }, + "selected": false + }, + { + "id": "codeNode_630", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "schema": { + "file_name": "string", + "resolved_url": "string", + "uploaded_to_storage": "boolean" + }, + "values": { + "id": "codeNode_630", + "code": "// Assign the value you want to return from this code node to `output`. \n// The `output` variable is already declared.\nconst fileBase64 = {{triggerNode_1.output.file_base64}};\nconst fileUrl = {{triggerNode_1.output.file_url}};\nconst fileName = {{triggerNode_1.output.file_name}} || \"document.pdf\";\nconst mimeType = {{triggerNode_1.output.mime_type}} || \"application/pdf\";\n\n// If a URL was provided directly, use it — no storage upload needed\nif (!fileBase64 && fileUrl) {\n output = { resolved_url: fileUrl, file_name: fileName, uploaded_to_storage: false };\n return output;\n}\n\nif (!fileBase64) {\n throw new Error(\"No file_base64 or file_url provided\");\n}\n\n// Upload base64 to Supabase Storage\nconst supabaseUrl = {{secrets.project.SUPABASE_URL}}; // from Lamatic secret\nconst serviceKey = {{secrets.project.SUPABASE_SERVICE_ROLE_KEY}}; // from Lamatic secret\n\n// Convert base64 to binary\n// base64 may arrive as a plain string or as data:mime;base64,... URI\nlet b64 = fileBase64;\nif (b64.includes(\",\")) b64 = b64.split(\",\")[1];\n\nconst binaryStr = atob(b64);\nconst bytes = new Uint8Array(binaryStr.length);\nfor (let i = 0; i < binaryStr.length; i++) {\n bytes[i] = binaryStr.charCodeAt(i);\n}\n\n// Unique storage path\nconst safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\");\nconst storagePath = `${Date.now()}_${safeName}`;\n\nconst uploadResp = await fetch(\n `${supabaseUrl}/storage/v1/object/pdfs/${storagePath}`,\n {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Content-Type\": mimeType,\n \"x-upsert\": \"false\",\n },\n body: bytes,\n }\n);\n\nif (!uploadResp.ok) {\n const errText = await uploadResp.text();\n throw new Error(`Storage upload failed: ${uploadResp.status} — ${errText}`);\n}\n\nconst signResp = await fetch(\n `${supabaseUrl}/storage/v1/object/sign/pdfs/${storagePath}`,\n {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${serviceKey}`,\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify({ expiresIn: 3600 }) // Valid for 1 hour\n }\n);\nif (!signResp.ok) {\n throw new Error(`Signed URL failed: ${signResp.status}`);\n}\nconst signData = await signResp.json();\nconst signedUrl = `${supabaseUrl}/storage/v1${signData.signedURL}`;\nconsole.log(\"Processing complete\");\n\noutput = {\n resolved_url: signedUrl,\n file_name: fileName,\n uploaded_to_storage: true,\n};\n\nconsole.log(\"✅ Code node complete:\", output.resolved_url);", + "nodeName": "Code" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 130 + }, + "selected": true + }, + { + "id": "extractFromFileNode_1", + "data": { + "logic": [], + "modes": {}, + "nodeId": "extractFromFileNode", + "schema": { + "files": "object" + }, + "values": { + "id": "extractFromFileNode_1", + "format": "pdf", + "fileUrl": "{{codeNode_630.output.resolved_url}}", + "nodeName": "Extract PDF", + "joinPages": false, + "operation": "extractFromPDF" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 260 + }, + "selected": false, + "draggable": false + }, + { + "id": "codeNode_format", + "data": { + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "schema": { + "pages": "array", + "raw_text": "string", + "toc_items": "array", + "page_count": "number", + "pages_json": "string", + "has_native_toc": "boolean" + }, + "values": { + "id": "codeNode_format", + "code": "const files = {{extractFromFileNode_1.output.files}};\nconst file = files[0];\nconst pages = file.data; // array of page strings\nconst tocItems = {{extractFromFileNode_1.output.toc_items}} || [];\n\n// Build raw_text with [PAGE N] markers (same format your query flow expects)\nconst rawText = pages\n .map((text, i) => `[PAGE ${i + 1}]\\n${text}`)\n .join(\"\\n\\n\");\n\noutput = {\n raw_text: rawText,\n pages: pages,\n page_count: pages.length,\n toc_items: tocItems,\n has_native_toc: tocItems.length > 0,\n pages_json: JSON.stringify(pages)\n};", + "nodeName": "Format Pages" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 390 + }, + "selected": false, + "draggable": false + }, + { + "id": "InstructorLLMNode_tree", + "data": { + "modes": {}, + "nodeId": "InstructorLLMNode", + "schema": {}, + "values": { + "id": "InstructorLLMNode_tree", + "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"tree\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"node_id\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"start_index\": {\n \"type\": \"number\"\n },\n \"end_index\": {\n \"type\": \"number\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"nodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": true\n }\n },\n \"tree_node_count\": {\n \"type\": \"number\",\n \"description\": \"Total number of nodes in the tree array\"\n }\n }\n}", + "prompts": [ + { + "role": "system", + "content": "Total pages: {{codeNode_format.output.page_count}}\n{{#if codeNode_format.output.has_native_toc}} Native TOC found — use this as the structure basis: {{codeNode_format.output.toc_items}} {{else}} No TOC found — infer structure from these first 3 pages: {{codeNode_format.output.pages_json}} {{/if}}\nBuild a complete PageIndex tree covering all {{codeNode_format.output.page_count}} pages." + }, + { + "role": "user", + "content": "Total pages: {{codeNode_format.output.page_count}}\n{{#if codeNode_format.output.has_native_toc}} Native TOC found — use this as the structure basis: {{codeNode_format.output.toc_items}} {{else}} No TOC found — infer structure from these first 3 pages: {{codeNode_format.output.pages_json}} {{/if}}\nBuild a complete PageIndex tree covering all {{codeNode_format.output.page_count}} pages." + } + ], + "nodeName": "Generate Tree", + "generativeModelName": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 520 + }, + "selected": false, + "draggable": false + }, + { + "id": "variablesNode_617", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "variablesNode", + "schema": {}, + "values": { + "id": "variablesNode_617", + "mapping": "{\n \"file_name\": {\n \"type\": \"string\",\n \"value\": \"{{triggerNode_1.output.file_name}}\"\n },\n \"file_url\": {\n \"type\": \"string\",\n \"value\": \"{{triggerNode_1.output.file_url}}\"\n },\n \"tree\": {\n \"type\": \"string\",\n \"value\": \"{{InstructorLLMNode_tree.output.tree}}\"\n },\n \"raw_data\": {\n \"type\": \"string\",\n \"value\": \"{{extractFromFileNode_1.output.files}}\"\n },\n \"tree_node_count\": {\n \"type\": \"number\",\n \"value\": \"{{InstructorLLMNode_tree.output.tree_node_count}}\"\n }\n}", + "nodeName": "Variables" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 650 + }, + "selected": false + }, + { + "id": "codeNode_save", + "data": { + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "schema": { + "error": "null", + "doc_id": "string", + "status": "string", + "success": "boolean", + "file_name": "string", + "status_code": "number", + "response_text": "string", + "tree_node_count": "number" + }, + "values": { + "id": "codeNode_save", + "code": "const tree = {{InstructorLLMNode_tree.output.tree}};\nconst rawText = {{codeNode_format.output.raw_text}};\nconst fileName = {{triggerNode_1.output.file_name}};\nconst fileUrl = {{codeNode_630.output.resolved_url}};\nconst supabaseUrl = {{secrets.project.SUPABASE_URL}};\nconst supabaseKey = {{secrets.project.SUPABASE_SERVICE_ROLE_KEY}};\n\nfunction sanitize(str) {\n if (typeof str !== \"string\") return str;\n return str.replace(/\\u0000/g, \"\").replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, \"\");\n}\n\nconst sanitizedRawText = sanitize(rawText);\n\nconst docId = \"pi-\" + Math.random().toString(36).slice(2, 18);\n\nconst payload = {\n doc_id: docId,\n file_name: fileName,\n file_url: fileUrl,\n raw_text: rawText,\n tree: tree,\n tree_node_count: tree.length,\n status: \"completed\"\n};\n\nconst response = await fetch(supabaseUrl + \"/rest/v1/documents\", {\n method: \"POST\",\n headers: {\n \"apikey\": supabaseKey,\n \"Authorization\": \"Bearer \" + supabaseKey,\n \"Content-Type\": \"application/json\",\n \"Prefer\": \"return=representation\"\n },\n body: JSON.stringify(payload)\n});\n\nconst result = await response.json();\n\nif (!response.ok) {\n const errorDetail = result?.message || result?.error || result?.hint || response.statusText;\n output = {\n success: false,\n status_code: response.status,\n response_text: response.statusText,\n error: errorDetail,\n doc_id: docId,\n file_name: fileName,\n tree_node_count: tree.length,\n status: \"failed\"\n };\n throw new Error(`Supabase write failed [${response.status}]: ${errorDetail}`);\n}\n\noutput = {\n success: true,\n status_code: response.status,\n response_text: response.statusText,\n error: null,\n doc_id: result[0]?.doc_id || docId,\n file_name: fileName,\n tree_node_count: tree.length,\n status: \"completed\"\n};\n", + "nodeName": "Save to Supabase" + }, + "disabled": false + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 780 + }, + "selected": false, + "draggable": false + }, + { + "id": "responseNode_triggerNode_1", + "data": { + "label": "Response", + "modes": {}, + "nodeId": "graphqlResponseNode", + "schema": {}, + "values": { + "id": "responseNode_triggerNode_1", + "nodeName": "API Response", + "outputMapping": "{\n \"doc_id\": \"{{codeNode_save.output.doc_id}}\",\n \"file_name\": \"{{codeNode_save.output.file_name}}\",\n \"tree_node_count\": \"{{codeNode_save.output.tree_node_count}}\",\n \"status\": \"{{codeNode_save.output.status}}\"\n}" + }, + "disabled": false, + "isResponseNode": true + }, + "type": "responseNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 910 + }, + "selected": false + } + ], + "edges": [ + { + "id": "extractFromFileNode_1-codeNode_format", + "type": "defaultEdge", + "source": "extractFromFileNode_1", + "target": "codeNode_format", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "codeNode_format-InstructorLLMNode_tree", + "type": "defaultEdge", + "source": "codeNode_format", + "target": "InstructorLLMNode_tree", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "codeNode_save-responseNode_triggerNode_1", + "type": "defaultEdge", + "source": "codeNode_save", + "target": "responseNode_triggerNode_1", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "variablesNode_617-codeNode_save", + "type": "defaultEdge", + "source": "variablesNode_617", + "target": "codeNode_save", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "InstructorLLMNode_tree-variablesNode_617", + "type": "defaultEdge", + "source": "InstructorLLMNode_tree", + "target": "variablesNode_617", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "triggerNode_1-codeNode_630", + "type": "defaultEdge", + "source": "triggerNode_1", + "target": "codeNode_630", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "codeNode_630-extractFromFileNode_1", + "type": "defaultEdge", + "source": "codeNode_630", + "target": "extractFromFileNode_1", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "response-responseNode_triggerNode_1", + "type": "responseEdge", + "source": "triggerNode_1", + "target": "responseNode_triggerNode_1", + "sourceHandle": "to-response", + "targetHandle": "from-trigger" + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/inputs.json b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/inputs.json new file mode 100644 index 00000000..a238fe74 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/inputs.json @@ -0,0 +1,26 @@ +{ + "InstructorLLMNode_tree": [ + { + "name": "generativeModelName", + "label": "Generative Model Name", + "type": "model", + "mode": "instructor", + "description": "Select the model to generate text based on the prompt.", + "modelType": "generator/text", + "required": true, + "isPrivate": true, + "defaultValue": [ + { + "configName": "configA", + "type": "generator/text", + "provider_name": "", + "credential_name": "", + "params": {} + } + ], + "typeOptions": { + "loadOptionsMethod": "listModels" + } + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.json b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.json new file mode 100644 index 00000000..464b84e3 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-1-upload-pdf-build-tree-save/meta.json @@ -0,0 +1,14 @@ +{ + "name": "Flow 1 Upload PDF Build Tree Save", + "description": "Upload a PDF, build a tree index, and save to database.", + "tags": [ + "upload", + "pdf", + "pageindex", + "notebooklm" + ], + "testInput": "{}", + "githubUrl": "https://github.com/Skt329/AgentKit", + "documentationUrl": "https://github.com/Skt329/AgentKit", + "deployUrl": "https://pageindex-notebooklm.vercel.app/" +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/README.md b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/README.md new file mode 100644 index 00000000..69b6c2f6 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/README.md @@ -0,0 +1,64 @@ +# Flow 4 Get tree structure + +## About This Flow + +This flow automates a workflow with **6 nodes** working together to process and transform data. The flow is designed to streamline operations and can be easily integrated into your existing systems. + +## Flow Components + +This workflow includes the following node types: +- API Request +- Condition +- Postgres +- Code +- API Response + +## Configuration Requirements + +This flow requires configuration for **2 node(s)** with private inputs (credentials, API keys, model selections, etc.). All required configurations are documented in the `inputs.json` file. + +## Files Included + +- **config.json** - Complete flow structure with nodes and connections +- **inputs.json** - Private inputs requiring configuration +- **meta.json** - Flow metadata and information + +## Next Steps + +### Share with the Community + +Help grow the Lamatic ecosystem by contributing this flow to AgentKit! + +1. **Fork the Repository** + - Visit [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Fork the repository to your GitHub account + +2. **Prepare Your Submission** + - Create a new folder with a descriptive name for your flow + - Add all files from this package (`config.json`, `inputs.json`, `meta.json`) + - Write a comprehensive README.md that includes: + - Clear description of what the flow does + - Use cases and benefits + - Step-by-step setup instructions + - Required credentials and how to obtain them + - Example inputs and expected outputs + - Screenshots or diagrams (optional but recommended) + +3. **Open a Pull Request** + - Commit your changes with a descriptive message + - Push to your forked repository + - Open a PR to [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Add a clear description of your flow in the PR + +Your contribution will help others build amazing automations! 🚀 + +## Support + +For questions or issues with this flow: +- Review the node documentation for specific integrations +- Check the Lamatic documentation at docs.lamatic.ai +- Contact support for assistance + +--- +*Exported from Lamatic Flow Editor* +*Generated on 3/29/2026* diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/config.json b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/config.json new file mode 100644 index 00000000..ed6a1441 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/config.json @@ -0,0 +1,228 @@ +{ + "nodes": [ + { + "id": "triggerNode_1", + "data": { + "modes": {}, + "nodeId": "graphqlNode", + "values": { + "id": "triggerNode_1", + "nodeName": "API Request", + "responeType": "realtime", + "advance_schema": "{\n \"doc_id\": \"string\",\n \"action\": \"string\"\n}" + }, + "trigger": true + }, + "type": "triggerNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 225, + "y": 0 + }, + "selected": true + }, + { + "id": "conditionNode_944", + "data": { + "label": "Condition", + "modes": {}, + "nodeId": "conditionNode", + "values": { + "id": "conditionNode_944", + "nodeName": "Condition", + "conditions": [ + { + "label": "Condition 1", + "value": "conditionNode_944-addNode_581", + "condition": "{\n \"operator\": null,\n \"operands\": [\n {\n \"name\": \"{{triggerNode_1.output.action}}\",\n \"operator\": \"==\",\n \"value\": \"get_tree\"\n }\n ]\n}" + }, + { + "label": "Else", + "value": "conditionNode_944-addNode_226", + "condition": {} + } + ], + "allowMultipleConditionExecution": false + } + }, + "type": "conditionNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 225, + "y": 130 + }, + "selected": false + }, + { + "id": "postgresNode_113", + "data": { + "label": "New", + "logic": [], + "modes": {}, + "nodeId": "postgresNode", + "values": { + "id": "postgresNode_113", + "query": "DELETE FROM documents WHERE doc_id = '{{triggerNode_1.output.doc_id}}' RETURNING doc_id, file_name;", + "action": "runQuery", + "nodeName": "Delete Document", + "credentials": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 450, + "y": 260 + }, + "selected": false + }, + { + "id": "postgresNode_206", + "data": { + "label": "New", + "logic": [], + "modes": {}, + "nodeId": "postgresNode", + "values": { + "id": "postgresNode_206", + "query": "SELECT tree, file_name, tree_node_count, created_at FROM documents WHERE doc_id = '{{triggerNode_1.output.doc_id}}' LIMIT 1;", + "action": "runQuery", + "nodeName": "Get Tree", + "credentials": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 260 + }, + "selected": false + }, + { + "id": "codeNode_merge", + "data": { + "logic": [], + "modes": {}, + "nodeId": "codeNode", + "values": { + "id": "codeNode_merge", + "code": "const action = {{triggerNode_1.output.action}};\n\nif (action === \"get_tree\") {\n const getResult = {{postgresNode_206.output.queryResult}};\n const doc = getResult && getResult[0];\n\n if (!doc) {\n output = {\n success: false,\n action: \"get_tree\",\n message: \"Document not found\",\n doc_id: {{triggerNode_1.output.doc_id}},\n tree: null,\n file_name: null,\n tree_node_count: null,\n created_at: null\n };\n } else {\n output = {\n success: true,\n action: \"get_tree\",\n message: \"Document fetched successfully\",\n doc_id: {{triggerNode_1.output.doc_id}},\n tree: JSON.stringify(doc.tree),\n file_name: doc.file_name,\n tree_node_count: doc.tree_node_count,\n created_at: doc.created_at\n };\n }\n\n} else {\n const deleteResult = {{postgresNode_113.output.queryResult}};\n\n if (!deleteResult || deleteResult.length === 0) {\n output = {\n success: false,\n action: \"delete\",\n message: \"Document not found or already deleted\",\n doc_id: {{triggerNode_1.output.doc_id}},\n tree: null,\n file_name: null,\n tree_node_count: null,\n created_at: null\n };\n } else {\n output = {\n success: true,\n action: \"delete\",\n message: \"Document deleted successfully\",\n doc_id: deleteResult[0].doc_id,\n tree: null,\n file_name: deleteResult[0].file_name,\n tree_node_count: null,\n created_at: null\n };\n }\n}", + "nodeName": "Merge Response" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 225, + "y": 390 + }, + "selected": false, + "draggable": false + }, + { + "id": "responseNode_triggerNode_1", + "data": { + "label": "Response", + "modes": {}, + "nodeId": "graphqlResponseNode", + "values": { + "id": "responseNode_triggerNode_1", + "headers": "{\"content-type\":\"application/json\"}", + "nodeName": "API Response", + "outputMapping": "{\n \"success\": \"{{codeNode_merge.output.success}}\",\n \"action\": \"{{codeNode_merge.output.action}}\",\n \"message\": \"{{codeNode_merge.output.message}}\",\n \"doc_id\": \"{{codeNode_merge.output.doc_id}}\",\n \"tree\": \"{{codeNode_merge.output.tree}}\",\n \"file_name\": \"{{codeNode_merge.output.file_name}}\",\n \"tree_node_count\": \"{{codeNode_merge.output.tree_node_count}}\",\n \"created_at\": \"{{codeNode_merge.output.created_at}}\"\n}" + }, + "isResponseNode": true + }, + "type": "responseNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 225, + "y": 520 + }, + "selected": false + } + ], + "edges": [ + { + "id": "codeNode_merge-responseNode_triggerNode_1", + "type": "defaultEdge", + "source": "codeNode_merge", + "target": "responseNode_triggerNode_1", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "conditionNode_944-postgresNode_206", + "data": { + "condition": "Condition 1" + }, + "type": "conditionEdge", + "source": "conditionNode_944", + "target": "postgresNode_206", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "conditionNode_944-postgresNode_113", + "data": { + "condition": "Else" + }, + "type": "conditionEdge", + "source": "conditionNode_944", + "target": "postgresNode_113", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "postgresNode_206-codeNode_merge", + "type": "defaultEdge", + "source": "postgresNode_206", + "target": "codeNode_merge", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "postgresNode_113-codeNode_merge", + "type": "defaultEdge", + "source": "postgresNode_113", + "target": "codeNode_merge", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "triggerNode_1-conditionNode_944", + "type": "defaultEdge", + "source": "triggerNode_1", + "target": "conditionNode_944", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "response-responseNode_triggerNode_1", + "type": "responseEdge", + "source": "triggerNode_1", + "target": "responseNode_triggerNode_1", + "sourceHandle": "to-response", + "targetHandle": "from-trigger" + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/inputs.json b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/inputs.json new file mode 100644 index 00000000..70de2392 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/inputs.json @@ -0,0 +1,26 @@ +{ + "postgresNode_113": [ + { + "name": "credentials", + "label": "Credentials", + "description": "Select the credentials for postgres authentication.", + "type": "select", + "isCredential": true, + "required": true, + "defaultValue": "", + "isPrivate": true + } + ], + "postgresNode_206": [ + { + "name": "credentials", + "label": "Credentials", + "description": "Select the credentials for postgres authentication.", + "type": "select", + "isCredential": true, + "required": true, + "defaultValue": "", + "isPrivate": true + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.json b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.json new file mode 100644 index 00000000..c5395a3a --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-4-get-tree-structure/meta.json @@ -0,0 +1,10 @@ +{ + "name": "Flow 4 Get Tree Structure", + "description": "Retrieve the full hierarchical tree structure for a document or delete a document and its associated data from Supabase.", + "tags": ["tree", "pageindex", "notebooklm", "document-management", "delete"], + "testInput": "{\"doc_id\": \"example-doc-id\", \"action\": \"get_tree\"}", + "githubUrl": "https://github.com/Skt329/AgentKit", + "documentationUrl": "https://github.com/Skt329/AgentKit", + "deployUrl": "https://pageindex-notebooklm.vercel.app/" +} + \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/README.md b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/README.md new file mode 100644 index 00000000..8e43b3ee --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/README.md @@ -0,0 +1,62 @@ +# flow list all documents + +## About This Flow + +This flow automates a workflow with **3 nodes** working together to process and transform data. The flow is designed to streamline operations and can be easily integrated into your existing systems. + +## Flow Components + +This workflow includes the following node types: +- API Request +- Postgres +- API Response + +## Configuration Requirements + +This flow requires configuration for **1 node(s)** with private inputs (credentials, API keys, model selections, etc.). All required configurations are documented in the `inputs.json` file. + +## Files Included + +- **config.json** - Complete flow structure with nodes and connections +- **inputs.json** - Private inputs requiring configuration +- **meta.json** - Flow metadata and information + +## Next Steps + +### Share with the Community + +Help grow the Lamatic ecosystem by contributing this flow to AgentKit! + +1. **Fork the Repository** + - Visit [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Fork the repository to your GitHub account + +2. **Prepare Your Submission** + - Create a new folder with a descriptive name for your flow + - Add all files from this package (`config.json`, `inputs.json`, `meta.json`) + - Write a comprehensive README.md that includes: + - Clear description of what the flow does + - Use cases and benefits + - Step-by-step setup instructions + - Required credentials and how to obtain them + - Example inputs and expected outputs + - Screenshots or diagrams (optional but recommended) + +3. **Open a Pull Request** + - Commit your changes with a descriptive message + - Push to your forked repository + - Open a PR to [github.com/Lamatic/AgentKit](https://github.com/Lamatic/AgentKit) + - Add a clear description of your flow in the PR + +Your contribution will help others build amazing automations! 🚀 + +## Support + +For questions or issues with this flow: +- Review the node documentation for specific integrations +- Check the Lamatic documentation at docs.lamatic.ai +- Contact support for assistance + +--- +*Exported from Lamatic Flow Editor* +*Generated on 3/29/2026* diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json new file mode 100644 index 00000000..0db47693 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/config.json @@ -0,0 +1,106 @@ +{ + "nodes": [ + { + "id": "triggerNode_1", + "data": { + "modes": {}, + "nodeId": "graphqlNode", + "values": { + "nodeName": "API Request", + "responeType": "realtime", + "advance_schema": "{\"sampleInput\":\"string\"}" + }, + "trigger": true + }, + "type": "triggerNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 0 + }, + "selected": false + }, + { + "id": "postgresNode_831", + "data": { + "label": "dynamicNode node", + "logic": [], + "modes": {}, + "nodeId": "postgresNode", + "values": { + "id": "postgresNode_831", + "query": "SELECT doc_id, file_name, file_url, tree_node_count, status, created_at FROM documents ORDER BY created_at DESC;", + "action": "runQuery", + "nodeName": "Postgres", + "credentials": "" + } + }, + "type": "dynamicNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 130 + }, + "selected": false + }, + { + "id": "responseNode_triggerNode_1", + "data": { + "label": "Response", + "nodeId": "graphqlResponseNode", + "values": { + "id": "responseNode_triggerNode_1", + "headers": "{\"content-type\":\"application/json\"}", + "retries": "0", + "nodeName": "API Response", + "webhookUrl": "", + "retry_delay": "0", + "outputMapping": "{\n \"documents\": \"{{postgresNode_831.output.queryResult}}\",\n \"total\": \"{{postgresNode_831.output.queryResult.length}}\"\n}" + }, + "isResponseNode": true + }, + "type": "responseNode", + "measured": { + "width": 216, + "height": 93 + }, + "position": { + "x": 0, + "y": 260 + }, + "selected": true + } + ], + "edges": [ + { + "id": "triggerNode_1-postgresNode_831", + "type": "defaultEdge", + "source": "triggerNode_1", + "target": "postgresNode_831", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "postgresNode_831-responseNode_triggerNode_1", + "type": "defaultEdge", + "source": "postgresNode_831", + "target": "responseNode_triggerNode_1", + "sourceHandle": "bottom", + "targetHandle": "top" + }, + { + "id": "response-trigger_triggerNode_1", + "type": "responseEdge", + "source": "triggerNode_1", + "target": "responseNode_triggerNode_1", + "sourceHandle": "to-response", + "targetHandle": "from-trigger" + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/inputs.json b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/inputs.json new file mode 100644 index 00000000..4d220daf --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/inputs.json @@ -0,0 +1,14 @@ +{ + "postgresNode_831": [ + { + "name": "credentials", + "label": "Credentials", + "description": "Select the credentials for postgres authentication.", + "type": "select", + "isCredential": true, + "required": true, + "defaultValue": "", + "isPrivate": true + } + ] +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.json b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.json new file mode 100644 index 00000000..fa45fa74 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/flows/flow-list-all-documents/meta.json @@ -0,0 +1,9 @@ +{ + "name": "Flow List All Documents", + "description": "List all uploaded documents stored in Supabase, returning doc_id, file_name, file_url, tree_node_count, status, and created_at for each document.", + "tags": ["list", "documents", "pageindex", "notebooklm", "supabase"], + "testInput": "{}", + "githubUrl": "https://github.com/Skt329/AgentKit", + "documentationUrl": "https://github.com/Skt329/AgentKit", + "deployUrl": "https://pageindex-notebooklm.vercel.app/" +} \ No newline at end of file diff --git a/kits/assistant/pageindex-notebooklm/lib/lamatic-client.ts b/kits/assistant/pageindex-notebooklm/lib/lamatic-client.ts new file mode 100644 index 00000000..50df4435 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/lib/lamatic-client.ts @@ -0,0 +1,28 @@ +import { Lamatic } from "lamatic"; + +if ( + !process.env.FLOW_ID_UPLOAD || + !process.env.FLOW_ID_CHAT || + !process.env.FLOW_ID_LIST || + !process.env.FLOW_ID_TREE +) { + throw new Error( + "One or more Flow IDs are missing. Set FLOW_ID_UPLOAD, FLOW_ID_CHAT, FLOW_ID_LIST, FLOW_ID_TREE in your .env file." + ); +} + +if ( + !process.env.LAMATIC_API_URL || + !process.env.LAMATIC_PROJECT_ID || + !process.env.LAMATIC_API_KEY +) { + throw new Error( + "Lamatic API credentials missing. Set LAMATIC_API_URL, LAMATIC_PROJECT_ID, LAMATIC_API_KEY in your .env file." + ); +} + +export const lamaticClient = new Lamatic({ + endpoint: process.env.LAMATIC_API_URL!, + projectId: process.env.LAMATIC_PROJECT_ID!, + apiKey: process.env.LAMATIC_API_KEY!, +}); diff --git a/kits/assistant/pageindex-notebooklm/lib/types.ts b/kits/assistant/pageindex-notebooklm/lib/types.ts new file mode 100644 index 00000000..4463c3ba --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/lib/types.ts @@ -0,0 +1,81 @@ +export interface Document { + doc_id: string; + file_name: string; + file_url: string; + tree_node_count: number; + status: string; + created_at: string; +} + +// Raw API shape: nodes is a flat array of child IDs +export interface TreeNode { + node_id: string; + title: string; + start_index: number; + end_index: number; + summary: string; + nodes: string[]; // child node_ids +} + +// Resolved shape used internally after building the tree +export interface TreeNodeResolved { + node_id: string; + title: string; + start_index: number; + end_index: number; + summary: string; + nodes: TreeNodeResolved[]; +} + +export interface RetrievedNode { + node_id: string; + title: string; + start_index: number; // exact start page + end_index: number; // exact end page + summary: string; // short description from tree node + page_content: string; // verbatim PDF text fetched from start→end range +} + +export interface Message { + role: "user" | "assistant"; + content: string; +} + +export interface ChatResponse { + answer: string; + retrieved_nodes: RetrievedNode[]; + thinking: string; + /** Raw Lamatic message history returned by the flow for multi-turn context. */ + messages?: unknown; +} + +export interface UploadResponse { + doc_id: string; + file_name: string; + tree_node_count: number; + status: string; +} + +export interface ListResponse { + documents: Document[]; + total: number; +} + +export interface TreeResponse { + success: boolean; + action: string; + message: string; + doc_id: string; + tree: TreeNode[]; + file_name: string; + tree_node_count: number; + created_at: string; +} + +export interface DeleteResponse { + success: boolean; + action: string; + message: string; + doc_id: string; + file_name: string; +} diff --git a/kits/assistant/pageindex-notebooklm/lib/utils.ts b/kits/assistant/pageindex-notebooklm/lib/utils.ts new file mode 100644 index 00000000..bd0c391d --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/kits/assistant/pageindex-notebooklm/next-env.d.ts b/kits/assistant/pageindex-notebooklm/next-env.d.ts new file mode 100644 index 00000000..1b3be084 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/kits/assistant/pageindex-notebooklm/next.config.mjs b/kits/assistant/pageindex-notebooklm/next.config.mjs new file mode 100644 index 00000000..bd341913 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/next.config.mjs @@ -0,0 +1,11 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + typescript: { + ignoreBuildErrors: true, + }, + images: { + unoptimized: true, + }, +}; + +export default nextConfig; diff --git a/kits/assistant/pageindex-notebooklm/package-lock.json b/kits/assistant/pageindex-notebooklm/package-lock.json new file mode 100644 index 00000000..bb0ef997 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/package-lock.json @@ -0,0 +1,3684 @@ +{ + "name": "pageindex-notebooklm", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pageindex-notebooklm", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-slot": "^1.2.4", + "clsx": "^2.1.1", + "dompurify": "3.3.3", + "lamatic": "0.3.2", + "lucide-react": "0.511.0", + "next": "15.3.8", + "radix-ui": "^1.4.3", + "react": "19.0.0", + "react-dom": "19.0.0", + "tailwind-merge": "^3.5.0", + "tailwindcss": "4.1.4" + }, + "devDependencies": { + "@tailwindcss/postcss": "4.2.2", + "@types/dompurify": "3.0.5", + "@types/node": "20.12.7", + "@types/react": "19.0.0", + "@types/react-dom": "19.0.0", + "postcss": "8.5.8", + "typescript": "5.4.5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "15.3.8", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.8.tgz", + "integrity": "sha512-SAfHg0g91MQVMPioeFeDjE+8UPF3j3BvHjs8ZKJAUz1BG7eMPvfCKOAgNWJ6s1MLNeP6O2InKQRTNblxPWuq+Q==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.5.tgz", + "integrity": "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.5.tgz", + "integrity": "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.5.tgz", + "integrity": "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.5.tgz", + "integrity": "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.5.tgz", + "integrity": "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.5.tgz", + "integrity": "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.5.tgz", + "integrity": "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.5.tgz", + "integrity": "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accessible-icon": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.7.tgz", + "integrity": "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-aspect-ratio": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", + "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-form": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.8.tgz", + "integrity": "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-hover-card": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-one-time-password-field": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.1.8.tgz", + "integrity": "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-password-toggle-field": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.1.3.tgz", + "integrity": "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toast": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", + "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toolbar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.11.tgz", + "integrity": "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-toggle-group": "1.1.11" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", + "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.2" + } + }, + "node_modules/@tailwindcss/node/node_modules/tailwindcss": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz", + "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-arm64": "4.2.2", + "@tailwindcss/oxide-darwin-x64": "4.2.2", + "@tailwindcss/oxide-freebsd-x64": "4.2.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", + "@tailwindcss/oxide-linux-x64-musl": "4.2.2", + "@tailwindcss/oxide-wasm32-wasi": "4.2.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz", + "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz", + "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz", + "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz", + "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz", + "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz", + "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz", + "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz", + "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz", + "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz", + "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", + "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz", + "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.2.tgz", + "integrity": "sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.2.2", + "@tailwindcss/oxide": "4.2.2", + "postcss": "^8.5.6", + "tailwindcss": "4.2.2" + } + }, + "node_modules/@tailwindcss/postcss/node_modules/tailwindcss": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.0.tgz", + "integrity": "sha512-MY3oPudxvMYyesqs/kW1Bh8y9VqSmf+tzqw3ae8a9DZW68pUe3zAdHeI1jc6iAysuRdACnVknHP8AhwD4/dxtg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-1KfiQKsH1o00p9m5ag12axHQSb3FOU9H20UTrujVSkNhuCrRHiQWFqgEnTNK5ZNfnzZv8UWrnXVqCmCF9fgY3w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001780", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/dompurify": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/lamatic": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/lamatic/-/lamatic-0.3.2.tgz", + "integrity": "sha512-oOIpnJmjOxlMuViFsmI3LsbEMFxB7unZXplqgzKeu9hy87kqxP1/K1gU6NMQU+98iy1A3XbW7aQSfSLxvYq3sA==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "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" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lucide-react": { + "version": "0.511.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.511.0.tgz", + "integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "15.3.8", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.8.tgz", + "integrity": "sha512-L+4c5Hlr84fuaNADZbB9+ceRX9/CzwxJ+obXIGHupboB/Q1OLbSUapFs4bO8hnS/E6zV/JDX7sG1QpKVR2bguA==", + "license": "MIT", + "dependencies": { + "@next/env": "15.3.8", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.15", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.3.5", + "@next/swc-darwin-x64": "15.3.5", + "@next/swc-linux-arm64-gnu": "15.3.5", + "@next/swc-linux-arm64-musl": "15.3.5", + "@next/swc-linux-x64-gnu": "15.3.5", + "@next/swc-linux-x64-musl": "15.3.5", + "@next/swc-win32-arm64-msvc": "15.3.5", + "@next/swc-win32-x64-msvc": "15.3.5", + "sharp": "^0.34.1" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "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 + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/radix-ui": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz", + "integrity": "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-accessible-icon": "1.1.7", + "@radix-ui/react-accordion": "1.2.12", + "@radix-ui/react-alert-dialog": "1.1.15", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-aspect-ratio": "1.1.7", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-checkbox": "1.3.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-context-menu": "2.2.16", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-form": "0.1.8", + "@radix-ui/react-hover-card": "1.1.15", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-menubar": "1.1.16", + "@radix-ui/react-navigation-menu": "1.2.14", + "@radix-ui/react-one-time-password-field": "0.1.8", + "@radix-ui/react-password-toggle-field": "0.1.3", + "@radix-ui/react-popover": "1.1.15", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-progress": "1.1.7", + "@radix-ui/react-radio-group": "1.3.8", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-scroll-area": "1.2.10", + "@radix-ui/react-select": "2.2.6", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-slider": "1.3.6", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-switch": "1.2.6", + "@radix-ui/react-tabs": "1.1.13", + "@radix-ui/react-toast": "1.2.15", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-toggle-group": "1.1.11", + "@radix-ui/react-toolbar": "1.1.11", + "@radix-ui/react-tooltip": "1.2.8", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-escape-keydown": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/radix-ui/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.25.0" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "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 + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "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 + } + } + }, + "node_modules/scheduler": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "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 + } + } + }, + "node_modules/tailwind-merge": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz", + "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz", + "integrity": "sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "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 + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "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 + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + } + } +} diff --git a/kits/assistant/pageindex-notebooklm/package.json b/kits/assistant/pageindex-notebooklm/package.json new file mode 100644 index 00000000..f36a2c9e --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/package.json @@ -0,0 +1,34 @@ +{ + "name": "pageindex-notebooklm", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-slot": "1.2.4", + "clsx": "2.1.1", + "dompurify": "3.3.3", + "lamatic": "0.3.2", + "lucide-react": "0.511.0", + "next": "15.3.8", + "radix-ui": "1.4.3", + "react": "19.0.0", + "react-dom": "19.0.0", + "tailwind-merge": "3.5.0", + "tailwindcss": "4.1.4" + }, + "devDependencies": { + "@tailwindcss/postcss": "4.2.2", + "@types/dompurify": "3.0.5", + "@types/node": "20.12.7", + "@types/react": "19.0.0", + "@types/react-dom": "19.0.0", + "postcss": "8.5.8", + "typescript": "5.4.5" + } +} diff --git a/kits/assistant/pageindex-notebooklm/postcss.config.mjs b/kits/assistant/pageindex-notebooklm/postcss.config.mjs new file mode 100644 index 00000000..61e36849 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/kits/assistant/pageindex-notebooklm/tsconfig.json b/kits/assistant/pageindex-notebooklm/tsconfig.json new file mode 100644 index 00000000..53b445a0 --- /dev/null +++ b/kits/assistant/pageindex-notebooklm/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2018", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}