diff --git a/AGENTS.md b/AGENTS.md
index a202800..579941e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -5,26 +5,27 @@
- Préfère les échanges en français, avec des explications détaillées et claires (éviter le jargon flou).
- Interface : tout libellé via i18n dans les 15 fichiers `memento-note/locales/*.json` (FR et EN comme références de contenu) ; éviter le texte en dur ; traductions **contextuelles** (sens produit, pas mot à mot — ex. « connecter votre propre fournisseur ») ; lors d'une traduction complète, mettre à jour toutes les locales concernées ; si l'utilisateur demande seulement les **clés i18n**, ajouter les clés (souvent EN/FR) sans remplir les 15 locales — il traduit souvent avec un autre modèle.
- Base de données : **INTERDIT TOTALEMENT** de lancer `prisma db push --force-reset`, `prisma migrate reset`, `DROP TABLE`, `TRUNCATE`, `pg_restore` avec clean, ou TOUTE commande qui vide/supprime des données — MÊME SI l'utilisateur est d'accord — sans avoir d'abord : (1) dumpé la base avec `bash /home/devparsa/dev/Momento/dump-db.sh`, (2) vérifié le dump fait au moins 1Mo, (3) obtenu un "OUI" explicite de l'utilisateur. **4 incidents de perte de données documentés (14/05, 15/05 x2, 16/05). NE JAMAIS REFAIRE ÇA.**
-- Design produit : migration depuis les gabarits `architectural-grid1` (base cible) et `architectural-grid` ; avancer pas à pas avec validation ; respecter la logique liste / carte de notes puis contenu au clic comme dans la référence.
-- Contraste éditeur clair face à une sidebar plus sombre ; fiabiliser la navigation du sidebar en s'alignant sur la logique des dossiers de référence design.
-- Retirer les traces de bleu ou de thème obsolètes ; harmoniser les couleurs des vues (ex. Agents) avec le design courant ; revoir la cohérence des options de thème dans les paramètres.
+- Design produit : migration depuis `architectural-grid1` (base) et `architectural-grid` (prototype UI courant) ; **consulter le prototype avant toute implémentation UI** ; logique liste/carte puis contenu au clic ; parité actions liste/carte (menus « … », déplacer, génération SVG, etc.) ; contraste éditeur clair / sidebar sombre ; retirer thèmes obsolètes ; **pas de refresh/revalidation complets inutiles** (aligné prototype — mutations optimistes, pas de `revalidatePath` systématique ni resync depuis `initialNotes`) ; **Memory Echo en section inline dans l'éditeur** (pas l'ancienne modale) ; si l'utilisateur hésite entre variantes UX, **trancher pour le design prototype** plutôt que multiplier les toggles.
- Locale persane : dates en calendrier iranien (conversion), chiffres persans, et vérification RTL/positionnement global ; attention à ne pas confondre un nom de carnet (ex. « Persan ») avec le libellé de langue.
- Flux Excalidraw / diagrammes générés : accès via notification en plus d'une simple redirection ; priorité à la mise en page et au texte contenu dans les formes ; proposer des modes visuels (ex. coloré vs plus austère) tout en visant un rendu proche du style Excalidraw (polices, look).
-- L'admin doit être intégré au nouveau design (éviter l'ancienne topbar isolée).
-- Ne pas supposer les réglages utilisateur (modes, options) sans preuve dans l'UI ou les données.
- **Interdiction d'écrire des tests** sauf demande explicite ; en CI, seul `npm run test:unit` (`tests/unit/**`) — pas `tests/migration/` ; ne jamais générer de code superflu.
-- Déploiement : privilégier le chemin rapide (artifact Next.js en CI + `Dockerfile.prebuilt`) ; éviter les rebuild Docker complets inutiles (~15 min par itération).
+- Déploiement : privilégier le chemin rapide (artifact Next.js en CI + `Dockerfile.prebuilt`) ; CI/CD très robuste (pas d'image Docker obsolète en prod, pas de migrations/schéma DB via le workflow deploy) ; éviter les rebuild Docker complets inutiles (~15 min par itération) ; **ne pas pousser un déploiement quand des features clés sont inachevées** ; ne pas insister sur le déploiement tant que le produit n'est pas fini ou meilleur.
+- Authentification : priorité à l'inscription/connexion via **Google OAuth** (plutôt qu'un compte email/mot de passe) ; exiger une vraie déconnexion (invalidation session/cookies — pas de reconnexion implicite, y compris en navigation privée).
+- Priorité absolue à la qualité UX, même si l'implémentation est complexe (« je m'en fous si c'est complexe ») ; **ne jamais affirmer qu'un correctif ou une feature est fait sans vérification réelle** (app, prototype `architectural-grid`, ou test) — l'utilisateur sanctionne fermement les fausses déclarations.
+- Livraison : **une user story à la fois**, tester et valider avec l'utilisateur avant la suivante ; suivi dans `docs/user-stories.md`.
+- Quand demandé, **fournir des briefs pour un outil de design externe** plutôt que produire les maquettes UX soi-même.
## Learned Workspace Facts
- Application Next.js principalement sous `memento-note/`.
- Référentiels design du workspace : `architectural-grid1/` et `architectural-grid/` à la racine du repo Momento.
- i18n : 15 fichiers sous `memento-note/locales/` (de, en, es, fr, it, pt, nl, pl, ru, zh, ja, ko, ar, fa, hi) ; logique sous `memento-note/lib/i18n/` ; référence `en.json` (~2218 clés) ; auditer les « non traduits » par flatten EN vs locale (souvent valeurs identiques à l'EN).
-- Workflow BMad : stories sous `docs/` (ex. `3-4-host-pays-session-logic.md`), suivi sprint dans `docs/sprint-status.yaml` ; skills sous `.claude/skills/bmad-*` ; `_bmad-output/planning-artifacts` souvent vide — planification de référence dans `docs/`.
+- Workflow BMad : stories sous `docs/` (ex. `3-4-host-pays-session-logic.md`), suivi sprint dans `docs/sprint-status.yaml` et stories courantes dans `docs/user-stories.md` ; skills sous `.claude/skills/bmad-*` ; `_bmad-output/planning-artifacts` souvent vide — planification de référence dans `docs/` ; préférer **une user story par feature** (pas de stories groupées).
- PostgreSQL Docker (`memento-postgres`) sur le port 5433 ; Redis Docker (`memento-redis`) sur le port 6379 (voir règles projet).
- Règles opérationnelles Prisma et sécurité base de données décrites dans `CLAUDE.md` à la racine du repo.
-- Production : dépôt `/opt/memento` sur `192.168.1.190`, conteneur `memento-note` sur le port **3000**, URL publique **https://note.parsanet.org** (nginx + Cloudflare) ; ne pas recréer Postgres en prod (`deploy.yaml` / `deploy-prod.sh`).
+- Production : dépôt `/opt/memento` sur `192.168.1.190`, conteneur `memento-note` sur le port **3000**, URL publique **https://memento-note.com** (nginx + Cloudflare ; ancien domaine note.parsanet.org) ; `NEXTAUTH_URL` aligné sur ce domaine ; email sortant via **Resend** (`SMTP_FROM` ex. `noreply@memento-note.com`, domaine vérifié sur resend.com) ; deploy (`deploy.yaml` / `deploy-prod.sh`) **sans toucher Postgres** (pas de `postgresql-client`, pas de migrations auto en prod).
- CI/CD Gitea : `.gitea/workflows/ci.yaml` — CI sur `ubuntu-24.04`, deploy sur runner **`docker-host`** (sur le serveur) ; deploy manuel via `.gitea/workflows/deploy.yaml` ou `bash scripts/deploy-prod.sh`.
- Migrations dans l'image prebuilt : `docker compose exec memento-note node ./node_modules/prisma/build/index.js migrate deploy` (pas `npx prisma` dans le PATH) ; helper `scripts/migrate-docker.sh`.
- Vérification deploy : `GET /api/build-info` (SHA Git) ; comparer `127.0.0.1:3000` et le domaine Cloudflare — purger le cache si versions divergent ; 403 sur `/api/manifest` côté domaine = souvent Cloudflare, pas l'app.
-- Guide utilisateur illustré : `docs/guide-utilisateur/README.md`, captures dans `docs/guide-utilisateur/screenshots/` ; régénération via `docs/guide-utilisateur/capture-screenshots.mjs` lancé depuis `memento-note/` (Playwright) ; URL lue depuis `NEXTAUTH_URL` ou `MOMENTO_DOC_BASE_URL`.
+- Sync mutations notes entre composants : `memento-note/lib/note-change-sync.ts` (`emitNoteChange`, événement `NOTE_CHANGE_EVENT`).
+- Roadmap / écart prototype vs prod : Web Clipper, Living Blocks (TipTap UniqueID), Structured Views, Flashcards IA (SM-2), Graph Knowledge Map — prototypes dans `architectural-grid/` (`ClipperSimulator.tsx`, `RevisionView.tsx`, `GraphKnowledgeMap.tsx`) ; en prod : `network-graph.tsx`, `note-document-info-panel.tsx`, `note-history-modal.tsx`, `rich-text-editor.tsx` (sans UniqueID pour l'instant).
diff --git a/_bmad-output/implementation-artifacts/deferred-work.md b/_bmad-output/implementation-artifacts/deferred-work.md
index 4639980..a80e60c 100644
--- a/_bmad-output/implementation-artifacts/deferred-work.md
+++ b/_bmad-output/implementation-artifacts/deferred-work.md
@@ -15,3 +15,12 @@
## Deferred from: chart suggestions feature (2026-05-23)
- **Build error in note-graph-view.tsx** — Variable `plainText` définie plusieurs fois (ligne 238). Fichier préexistant modifié hors de cette tâche. À corriger indépendamment.
+
+## Deferred from: code review of 4-4-explicit-ai-consent (2026-05-23)
+
+- **PUT `/api/ai/batch-organize` sans check consent** — Handler PUT applique le plan d’organisation en DB sans appeler d’API IA tierce ; hardening consent possible mais hors périmètre GDPR direct.
+
+## Deferred from: code review of 4-3-data-portability (2026-05-23)
+
+- **`lib/export/zip-builder.ts` non extrait** — logique inline dans la route ; fonctionnel mais écarte la structure prévue par la story.
+- **Rate limiting absent sur `GET /api/user/export`** — vecteur d’abus (exports répétés) ; hardening ultérieur.
diff --git a/architectural-grid10/.env.example b/architectural-grid/.env.example
similarity index 100%
rename from architectural-grid10/.env.example
rename to architectural-grid/.env.example
diff --git a/architectural-grid10/.gitignore b/architectural-grid/.gitignore
similarity index 100%
rename from architectural-grid10/.gitignore
rename to architectural-grid/.gitignore
diff --git a/architectural-grid_landing/BRAINSTORM_PROMPT.md b/architectural-grid/BRAINSTORM_PROMPT.md
similarity index 100%
rename from architectural-grid_landing/BRAINSTORM_PROMPT.md
rename to architectural-grid/BRAINSTORM_PROMPT.md
diff --git a/architectural-grid10/README.md b/architectural-grid/README.md
similarity index 75%
rename from architectural-grid10/README.md
rename to architectural-grid/README.md
index 0078184..1e3365d 100644
--- a/architectural-grid10/README.md
+++ b/architectural-grid/README.md
@@ -1,5 +1,5 @@
-
+
# Run and deploy your AI Studio app
diff --git a/architectural-grid10/index.html b/architectural-grid/index.html
similarity index 100%
rename from architectural-grid10/index.html
rename to architectural-grid/index.html
diff --git a/architectural-grid11/metadata.json b/architectural-grid/metadata.json
similarity index 100%
rename from architectural-grid11/metadata.json
rename to architectural-grid/metadata.json
diff --git a/architectural-grid12/package-lock.json b/architectural-grid/package-lock.json
similarity index 100%
rename from architectural-grid12/package-lock.json
rename to architectural-grid/package-lock.json
diff --git a/architectural-grid12/package.json b/architectural-grid/package.json
similarity index 100%
rename from architectural-grid12/package.json
rename to architectural-grid/package.json
diff --git a/architectural-grid14/server.ts b/architectural-grid/server.ts
similarity index 98%
rename from architectural-grid14/server.ts
rename to architectural-grid/server.ts
index 6df121f..d1b46e5 100644
--- a/architectural-grid14/server.ts
+++ b/architectural-grid/server.ts
@@ -71,7 +71,7 @@ async function startServer() {
console.log(`User ${user?.name || 'Guest'} joined session: ${sessionId}`);
}
- if (data.type === 'idea_added' || data.type === 'idea_updated' || data.type === 'activity') {
+ if (data.type === 'idea_added' || data.type === 'idea_updated' || data.type === 'activity' || data.type === 'living_block_update') {
if (currentRoom && rooms.has(currentRoom)) {
rooms.get(currentRoom)!.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
diff --git a/architectural-grid_landing/src/App.tsx b/architectural-grid/src/App.tsx
similarity index 62%
rename from architectural-grid_landing/src/App.tsx
rename to architectural-grid/src/App.tsx
index 393422c..ef2aa23 100644
--- a/architectural-grid_landing/src/App.tsx
+++ b/architectural-grid/src/App.tsx
@@ -5,6 +5,7 @@
import React, { useState, useMemo } from 'react';
import { motion, AnimatePresence } from 'motion/react';
+import { X } from 'lucide-react';
// Components
import { Sidebar } from './components/Sidebar';
@@ -19,10 +20,15 @@ import { AISidebar } from './components/AISidebar';
import { SlashMenu } from './components/SlashMenu';
import { LandingPage } from './components/LandingPage';
import { AuthPage } from './components/AuthPage';
+import { SearchModal } from './components/SearchModal';
+import { ClipperSimulator } from './components/ClipperSimulator';
+import { GraphKnowledgeMap } from './components/GraphKnowledgeMap';
+import { RevisionView } from './components/RevisionView';
-// Data & Types
+// Data & Services
import { CARNETS, ALL_NOTES } from './constants';
-import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog } from './types';
+import { generateFlashcardsForNote } from './services/geminiService';
+import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog, Flashcard } from './types';
export default function App() {
const [showLanding, setShowLanding] = useState(() => {
@@ -79,6 +85,56 @@ export default function App() {
return localStorage.getItem('momento-accent-color') || '#A47148';
});
+ // Flashcards state with beautiful architectural starter deck
+ const [flashcards, setFlashcards] = useState(() => {
+ const stored = localStorage.getItem('momento-flashcards');
+ if (stored) {
+ try {
+ return JSON.parse(stored);
+ } catch (e) {
+ console.error("Failed to parse stored flashcards:", e);
+ }
+ }
+ // Beautiful default seeds for 'n1' (Grid Systems & Geometry)
+ const SEEDS: Flashcard[] = [
+ {
+ id: 'f1',
+ noteId: 'n1',
+ question: 'Quel est l’intérêt primordial des trames géométriques en conception spatiale ?',
+ answer: 'Elles structurent l’espace bâti en créant un sens d\'ordre, de rythme, et d\'harmonie de proportions esthétiques dans l\'environnement, facilitant la lisibilité de la structure.',
+ intervalDays: 1,
+ nextReviewDate: new Date().toISOString(), // Due today
+ easeFactor: 2.5,
+ mastered: false
+ },
+ {
+ id: 'f2',
+ noteId: 'n1',
+ question: 'En quoi l’approche dynamique paramétrique déforme-t-elle les grilles de construction traditionnelles ?',
+ answer: 'Par l\'utilisation d\'algorithmes mathématiques de déformation réactifs à des ensembles de données environnementales pour créer des géométries fluides mais structurellement ordonnées.',
+ intervalDays: 3,
+ nextReviewDate: new Date(Date.now() + 1000 * 60 * 60 * 24 * 3).toISOString(), // Due soon
+ easeFactor: 2.5,
+ mastered: true
+ },
+ {
+ id: 'f3',
+ noteId: 'n1',
+ question: 'Quelle est la particularité de l’intégration de la lumière comme matériau d’espace ?',
+ answer: 'La soustraction du superflu permet aux reflets et à la diffraction lumineuse de créer des profondeurs visuelles changeantes sans surcharger l\'aménagement matériel.',
+ intervalDays: 1,
+ nextReviewDate: new Date().toISOString(), // Due today
+ easeFactor: 2.4,
+ mastered: false
+ }
+ ];
+ return SEEDS;
+ });
+
+ const [isGeneratingFlashcards, setIsGeneratingFlashcards] = useState(false);
+ const [activeReviewDeckId, setActiveReviewDeckId] = useState(null);
+ const [toast, setToast] = useState<{ show: boolean; message: string }>({ show: false, message: '' });
+
React.useEffect(() => {
document.documentElement.style.setProperty('--color-accent', accentColor);
localStorage.setItem('momento-accent-color', accentColor);
@@ -93,6 +149,55 @@ export default function App() {
}));
};
+ const handleGenerateFlashcards = async (noteId: string) => {
+ const targetNote = notes.find(n => n.id === noteId);
+ if (!targetNote) return;
+
+ setIsGeneratingFlashcards(true);
+ try {
+ const rawContent = targetNote.content || "";
+ const generated = await generateFlashcardsForNote(targetNote.title, rawContent);
+
+ if (generated && generated.length > 0) {
+ const mappedCards: Flashcard[] = generated.map((c, i) => ({
+ id: `f-${noteId}-${Date.now()}-${i}`,
+ noteId,
+ question: c.question,
+ answer: c.answer,
+ intervalDays: 1,
+ nextReviewDate: new Date().toISOString(),
+ easeFactor: 2.5,
+ mastered: false
+ }));
+
+ const updatedSet = [...flashcards.filter(fc => fc.noteId !== noteId), ...mappedCards];
+ setFlashcards(updatedSet);
+ localStorage.setItem('momento-flashcards', JSON.stringify(updatedSet));
+
+ setToast({
+ show: true,
+ message: `${mappedCards.length} flashcards créées avec succès pour "${targetNote.title}".`
+ });
+ setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
+ } else {
+ setToast({
+ show: true,
+ message: "Impossible d'extraire des flashcards exploitables à partir du texte existant."
+ });
+ setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
+ }
+ } catch (err) {
+ console.error("AI flashcards expansion failed:", err);
+ setToast({
+ show: true,
+ message: "Une erreur est survenue lors de la génération avec Gemini."
+ });
+ setTimeout(() => setToast(t => ({ ...t, show: false })), 4000);
+ } finally {
+ setIsGeneratingFlashcards(false);
+ }
+ };
+
React.useEffect(() => {
if (activeNoteId) {
logNoteAccess(activeNoteId);
@@ -114,9 +219,31 @@ export default function App() {
setActiveView(e.detail as NavigationView);
}
};
+
+ const handleGlobalShortcut = (e: KeyboardEvent) => {
+ // Trigger advanced search with Ctrl+F or Cmd+F or Ctrl+P or Cmd+P
+ if ((e.ctrlKey || e.metaKey) && (e.key === 'f' || e.key === 'p')) {
+ e.preventDefault();
+ setIsSearchOpen(true);
+ }
+ };
+
+ const handleToggleClipper = () => {
+ setIsClipperSimulatorOpen(prev => !prev);
+ };
+
window.addEventListener('switch-view', handleSwitchView);
- return () => window.removeEventListener('switch-view', handleSwitchView);
+ window.addEventListener('keydown', handleGlobalShortcut);
+ window.addEventListener('toggle-clipper-simulator', handleToggleClipper);
+ return () => {
+ window.removeEventListener('switch-view', handleSwitchView);
+ window.removeEventListener('keydown', handleGlobalShortcut);
+ window.removeEventListener('toggle-clipper-simulator', handleToggleClipper);
+ };
}, []);
+ const [isSearchOpen, setIsSearchOpen] = useState(false);
+ const [isClipperSimulatorOpen, setIsClipperSimulatorOpen] = useState(false);
+ const [clipperToast, setClipperToast] = useState<{ id: string; title: string; noteId: string } | null>(null);
const [selectedTagIds, setSelectedTagIds] = useState([]);
const [isAISidebarOpen, setIsAISidebarOpen] = useState(false);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
@@ -148,6 +275,24 @@ export default function App() {
}
};
+ React.useEffect(() => {
+ if (clipperToast) {
+ const timer = setTimeout(() => {
+ setClipperToast(null);
+ }, 4000);
+ return () => clearTimeout(timer);
+ }
+ }, [clipperToast]);
+
+ const handleOpenClippedNote = (noteId: string) => {
+ setActiveNoteId(noteId);
+ const found = notes.find(n => n.id === noteId);
+ if (found) {
+ setActiveCarnetId(found.carnetId);
+ }
+ setActiveView('notebooks');
+ };
+
const togglePin = (noteId: string) => {
setNotes(notes.map(n => n.id === noteId ? { ...n, isPinned: !n.isPinned } : n));
};
@@ -298,7 +443,141 @@ export default function App() {
};
const handleUpdateNote = (updatedNote: Note) => {
- setNotes(notes.map(n => n.id === updatedNote.id ? updatedNote : n));
+ setNotes(prevNotes => {
+ const existing = prevNotes.find(n => n.id === updatedNote.id);
+ if (existing && updatedNote.isVersioningEnabled !== false) {
+ const hasContentChanged = existing.content !== updatedNote.content;
+ const hasTitleChanged = existing.title !== updatedNote.title;
+
+ if (hasContentChanged || hasTitleChanged) {
+ const history = existing.versionHistory || [];
+ const lastSnapshot = history[0];
+ const isIdentical = lastSnapshot && lastSnapshot.content === existing.content && lastSnapshot.title === existing.title;
+
+ if (!isIdentical) {
+ const newSnapshot = {
+ id: 'v-' + Date.now(),
+ title: existing.title,
+ content: existing.content,
+ timestamp: new Date().toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' }) + ' • ' + new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }),
+ size: existing.content.length
+ };
+ const updatedWithHistory = {
+ ...updatedNote,
+ versionHistory: [newSnapshot, ...history]
+ };
+ return prevNotes.map(n => n.id === updatedNote.id ? updatedWithHistory : n);
+ }
+ }
+ }
+ return prevNotes.map(n => n.id === updatedNote.id ? updatedNote : n);
+ });
+ };
+
+ // WebSocket Integration for Living Blocks
+ const [wsConnected, setWsConnected] = React.useState(true);
+ const [simulatedOffline, setSimulatedOffline] = React.useState(false);
+ const socketRef = React.useRef(null);
+
+ const initWebSocket = () => {
+ if (simulatedOffline) return;
+ try {
+ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
+ const socket = new WebSocket(`${protocol}//${window.location.host}`);
+ socketRef.current = socket;
+
+ socket.onopen = () => {
+ setWsConnected(true);
+ socket.send(JSON.stringify({
+ type: 'join',
+ sessionId: 'global-momento-session',
+ user: { id: 'u-1', name: 'Utilisateur Actuel' }
+ }));
+ };
+
+ socket.onmessage = (event) => {
+ try {
+ const data = JSON.parse(event.data);
+ if (data.type === 'living_block_update') {
+ const { sourceNoteId, blockIndex, newText } = data;
+ setNotes(prevNotes =>
+ prevNotes.map(note => {
+ if (note.id === sourceNoteId) {
+ const paragraphs = note.content.split('\n');
+ if (paragraphs[blockIndex] !== undefined) {
+ paragraphs[blockIndex] = newText;
+ return { ...note, content: paragraphs.join('\n') };
+ }
+ }
+ return note;
+ })
+ );
+ window.dispatchEvent(new CustomEvent('living-block-pulse', {
+ detail: { sourceNoteId, blockIndex }
+ }));
+ }
+ } catch (err) {
+ console.error("Error parsing message", err);
+ }
+ };
+
+ socket.onclose = () => {
+ setWsConnected(false);
+ setTimeout(() => {
+ if (socketRef.current === socket && !simulatedOffline) {
+ initWebSocket();
+ }
+ }, 4000);
+ };
+
+ socket.onerror = () => {
+ setWsConnected(false);
+ };
+ } catch (e) {
+ console.error(e);
+ setWsConnected(false);
+ }
+ };
+
+ React.useEffect(() => {
+ initWebSocket();
+ return () => {
+ if (socketRef.current) {
+ socketRef.current.close();
+ }
+ };
+ }, [simulatedOffline]);
+
+ React.useEffect(() => {
+ const handleToggleSimulate = () => {
+ setSimulatedOffline(prev => {
+ const next = !prev;
+ if (next) {
+ if (socketRef.current) {
+ socketRef.current.close();
+ }
+ setWsConnected(false);
+ } else {
+ // Reconnect will automatically trigger because simulatedOffline changes
+ }
+ return next;
+ });
+ };
+ window.addEventListener('toggle-websocket-simulate', handleToggleSimulate);
+ return () => {
+ window.removeEventListener('toggle-websocket-simulate', handleToggleSimulate);
+ };
+ }, []);
+
+ const broadcastLivingBlockUpdate = (sourceNoteId: string, blockIndex: number, newText: string) => {
+ if (socketRef.current?.readyState === WebSocket.OPEN && !simulatedOffline) {
+ socketRef.current.send(JSON.stringify({
+ type: 'living_block_update',
+ sourceNoteId,
+ blockIndex,
+ newText
+ }));
+ }
};
const handleEnterApp = () => {
if (isAuthenticated) {
@@ -377,6 +656,11 @@ export default function App() {
activeNoteId={activeNoteId}
setActiveCarnetId={setActiveCarnetId}
setActiveNoteId={setActiveNoteId}
+ flashcards={flashcards}
+ onSelectReviewDeck={(noteId) => {
+ setActiveReviewDeckId(noteId);
+ setActiveView('revision');
+ }}
setShowNewCarnetModal={(show, parentId, isRenaming, carnetId) => {
setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId });
if (isRenaming && carnetId) {
@@ -436,6 +720,17 @@ export default function App() {
onBrainstormNote={handleBrainstormNote}
onUpdateNote={handleUpdateNote}
onOpenSidebar={() => setIsSidebarOpen(true)}
+ onSearchClick={() => setIsSearchOpen(true)}
+ wsConnected={wsConnected}
+ broadcastLivingBlockUpdate={broadcastLivingBlockUpdate}
+ carnets={carnets}
+ flashcards={flashcards}
+ onTriggerReviewDeck={(noteId) => {
+ setActiveReviewDeckId(noteId);
+ setActiveView('revision');
+ }}
+ onGenerateFlashcards={handleGenerateFlashcards}
+ isGeneratingFlashcards={isGeneratingFlashcards}
/>
)}
@@ -537,6 +832,7 @@ export default function App() {
setActiveView('notebooks');
setActiveNoteId(noteId);
}}
+ onOpenSidebar={() => setIsSidebarOpen(true)}
/>
)}
@@ -560,6 +856,62 @@ export default function App() {
/>
)}
+
+ {activeView === 'graph' && (
+
+ {
+ setActiveView('notebooks');
+ setActiveNoteId(noteId);
+ const note = notes.find(n => n.id === noteId);
+ if (note) {
+ setActiveCarnetId(note.carnetId);
+ }
+ }}
+ onClose={() => setActiveView('notebooks')}
+ />
+
+ )}
+
+ {activeView === 'revision' && (
+
+ {
+ setFlashcards(updated);
+ localStorage.setItem('momento-flashcards', JSON.stringify(updated));
+ }}
+ onSelectNote={(noteId) => {
+ setActiveView('notebooks');
+ setActiveNoteId(noteId);
+ const note = notes.find(n => n.id === noteId);
+ if (note) {
+ setActiveCarnetId(note.carnetId);
+ }
+ }}
+ onOpenSidebar={() => setIsSidebarOpen(true)}
+ initialActiveDeckId={activeReviewDeckId}
+ onClearActiveDeckId={() => setActiveReviewDeckId(null)}
+ />
+
+ )}
@@ -701,6 +1056,107 @@ export default function App() {
)}
+
+ {isSearchOpen && (
+ setIsSearchOpen(false)}
+ notes={notes}
+ carnets={carnets}
+ onSelectNote={(noteId) => {
+ setActiveNoteId(noteId);
+ const searchHitNote = notes.find(n => n.id === noteId);
+ if (searchHitNote) {
+ setActiveCarnetId(searchHitNote.carnetId);
+ }
+ }}
+ />
+ )}
+
+ {isClipperSimulatorOpen && (
+ setIsClipperSimulatorOpen(false)}
+ carnets={carnets}
+ activeCarnetId={activeCarnetId}
+ onAddNote={(newNote) => setNotes(prevNotes => [newNote, ...prevNotes])}
+ onTriggerToast={(title, noteId) => {
+ setClipperToast({
+ id: String(Date.now()),
+ title,
+ noteId
+ });
+ }}
+ />
+ )}
+
+ {clipperToast && (
+
+
+
+
+ Note clippée — {clipperToast.title}
+
+
+
+
+ {
+ handleOpenClippedNote(clipperToast.noteId);
+ setClipperToast(null);
+ }}
+ className="text-xs font-bold uppercase tracking-wider text-cyan-400 hover:text-cyan-300 underline underline-offset-2 transition-colors"
+ >
+ Voir
+
+ setClipperToast(null)}
+ className="p-1 hover:bg-white/10 text-neutral-400 hover:text-white rounded-lg transition-colors"
+ >
+
+
+
+
+ )}
+
+ {toast.show && (
+
+
+
+
+ {toast.message}
+
+
+
+
+ {
+ setActiveView('revision');
+ setToast({ show: false, message: '' });
+ }}
+ className="text-xs font-bold uppercase tracking-wider text-accent hover:text-accent/80 underline underline-offset-2 transition-colors cursor-pointer"
+ >
+ Voir
+
+ setToast({ show: false, message: '' })}
+ className="p-1 hover:bg-white/10 text-neutral-400 hover:text-white rounded-lg transition-colors cursor-pointer"
+ >
+
+
+
+
+ )}
)}
diff --git a/architectural-grid_landing/src/components/AISidebar.tsx b/architectural-grid/src/components/AISidebar.tsx
similarity index 55%
rename from architectural-grid_landing/src/components/AISidebar.tsx
rename to architectural-grid/src/components/AISidebar.tsx
index db5e1cd..c750035 100644
--- a/architectural-grid_landing/src/components/AISidebar.tsx
+++ b/architectural-grid/src/components/AISidebar.tsx
@@ -15,7 +15,8 @@ import {
History,
Target,
Network,
- Clock
+ Clock,
+ AlertCircle
} from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { AITab, AITone, Note, Carnet } from '../types';
@@ -30,6 +31,9 @@ interface AISidebarProps {
selectedTone: AITone;
setSelectedTone: (tone: AITone) => void;
carnets: Carnet[];
+ notes?: Note[];
+ onOpenNote?: (noteId: string) => void;
+ onUpdateNote?: (note: Note) => void;
}
export const AISidebar: React.FC = ({
@@ -40,9 +44,126 @@ export const AISidebar: React.FC = ({
setAiTab,
selectedTone,
setSelectedTone,
- carnets
+ carnets,
+ notes = [],
+ onOpenNote = (_noteId: string) => {},
+ onUpdateNote
}) => {
const [selectedContextId, setSelectedContextId] = React.useState(null);
+ const [hoveredOrbitNode, setHoveredOrbitNode] = React.useState(null);
+
+ const explicitWikiLinks = React.useMemo(() => [
+ { source: 'n1', target: 'n1-b' },
+ { source: 'n3', target: 'n3-b' },
+ { source: 'bridge-1', target: 'n1' },
+ { source: 'bridge-1', target: 'n2' },
+ ], []);
+
+ const CARNET_COLOR_PALETTE: { [key: string]: string } = {
+ '1': '#D97706', // Daily Notes - Warm Amber
+ '2': '#059669', // Project: Neo - Soft Emerald
+ '3': '#4F46E5', // Shared Docs - Rich Indigo
+ '4': '#0891B2', // Architecture Research - Clean Cyan
+ '5': '#EA580C', // History of Architecture - Deep Orange
+ '6': '#DB2777', // Modernism - Vibrant Rose
+ '7': '#65A30D', // Sustainable Design - Cool Lime
+ };
+
+ const DEFAULT_CARNET_COLOR = '#71717A';
+
+ const backlinks = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isExplicit = explicitWikiLinks.some(link =>
+ (link.source === n.id && link.target === activeNote.id)
+ );
+ const isContentLink = n.content.toLowerCase().includes(`[[${activeNote.title.toLowerCase()}]]`);
+ return isExplicit || isContentLink;
+ });
+ }, [activeNote, notes, explicitWikiLinks]);
+
+ const outboundLinks = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isExplicit = explicitWikiLinks.some(link =>
+ (link.source === activeNote.id && link.target === n.id)
+ );
+ const isContentLink = activeNote.content.toLowerCase().includes(`[[${n.title.toLowerCase()}]]`);
+ return isExplicit || isContentLink;
+ });
+ }, [activeNote, notes, explicitWikiLinks]);
+
+ const unlinkedMentions = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isLinked = [...backlinks, ...outboundLinks].some(link => link.id === n.id);
+ if (isLinked) return false;
+ return n.content.toLowerCase().includes(activeNote.title.toLowerCase());
+ });
+ }, [activeNote, notes, backlinks, outboundLinks]);
+
+ const orbitNodes = React.useMemo(() => {
+ const list: { id: string; title: string; color: string; carnetName: string; relationship: 'backlink' | 'outbound' | 'mention' }[] = [];
+
+ backlinks.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'backlink'
+ });
+ });
+
+ outboundLinks.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'outbound'
+ });
+ });
+
+ unlinkedMentions.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'mention'
+ });
+ });
+
+ return list.slice(0, 8);
+ }, [backlinks, outboundLinks, unlinkedMentions, carnets]);
+
+ const getSnippetWithHighlight = (content: string, term: string) => {
+ const index = content.toLowerCase().indexOf(term.toLowerCase());
+ if (index === -1) {
+ return {content.substring(0, 80)}... ;
+ }
+ const start = Math.max(0, index - 40);
+ const end = Math.min(content.length, index + term.length + 40);
+ const before = content.substring(start, index);
+ const match = content.substring(index, index + term.length);
+ const after = content.substring(index + term.length, end);
+ return (
+
+ {start > 0 && "..."}
+ {before}
+ {match}
+ {after}
+ {end < content.length && "..."}
+
+ );
+ };
return (
@@ -73,14 +194,14 @@ export const AISidebar: React.FC = ({
- {(['discussion', 'actions', 'explore', 'resources'] as AITab[]).map((tab) => (
+ {(['discussion', 'actions', 'explore', 'resources', 'relations'] as AITab[]).map((tab) => (
setAiTab(tab)}
- className={`flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative
+ className={`flex-1 py-3 text-[9px] uppercase tracking-wider font-bold transition-all relative
${aiTab === tab ? 'text-manganese' : 'text-muted-ink hover:text-ink/60'}`}
>
- {tab}
+ {tab === 'relations' ? 'réseau' : tab}
{aiTab === tab && (
= ({
)}
+ {aiTab === 'relations' && (
+
+
+
+
Vue Graphe Locale
+
+
+
+ {activeNote ? (
+ <>
+ {/* Interactive local graph SVG container */}
+
+
+
+
+
+
+ {/* Dotted circle boundary helper */}
+
+
+ {/* Connections */}
+ {orbitNodes.map((node, i) => {
+ const angle = i * (orbitNodes.length > 0 ? (2 * Math.PI) / orbitNodes.length : 0);
+ const nx = 160 + 70 * Math.cos(angle);
+ const ny = 110 + 62 * Math.sin(angle);
+ return (
+
+
+ {node.relationship === 'outbound' && (
+
+ )}
+ {node.relationship === 'backlink' && (
+
+ )}
+
+ );
+ })}
+
+ {/* Center node (Active Note) */}
+
+
+
+
+
+ {/* Orbit nodes */}
+ {orbitNodes.map((node, i) => {
+ const angle = i * (orbitNodes.length > 0 ? (2 * Math.PI) / orbitNodes.length : 0);
+ const nx = 160 + 70 * Math.cos(angle);
+ const ny = 110 + 62 * Math.sin(angle);
+ const isHovered = hoveredOrbitNode?.id === node.id;
+ return (
+ onOpenNote(node.id)}
+ onMouseEnter={() => setHoveredOrbitNode(node)}
+ onMouseLeave={() => setHoveredOrbitNode(null)}
+ >
+
+
+ {node.title.length > 10 ? node.title.substring(0, 8) + '...' : node.title}
+
+
+ );
+ })}
+
+
+ {/* Interactive local tooltip card info */}
+
+ {hoveredOrbitNode ? (
+
+
+
+
+ {hoveredOrbitNode.carnetName}
+
+
+ {hoveredOrbitNode.relationship === 'backlink' ? 'Lien Entrant' : hoveredOrbitNode.relationship === 'outbound' ? 'Lien Sortant' : 'Mention Simple'}
+
+
+
{hoveredOrbitNode.title}
+
Cliquez pour ouvrir la note
+
+ ) : (
+
+
+ Survolez un nœud, cliquez pour ouvrir
+
+ )}
+
+
+
+ {/* Lists of backlinks & unlinked mentions */}
+
+ {/* 1. Backlinks */}
+
+
+ Liens Entrans ({backlinks.length})
+
+ {backlinks.length > 0 ? (
+
+ {backlinks.map(n => (
+
onOpenNote(n.id)}
+ className="p-3 bg-white dark:bg-zinc-950 border border-border hover:border-accent/40 rounded-xl cursor-pointer transition-all space-y-1.5 hover:shadow-sm"
+ >
+
+ {n.title}
+ Réf
+
+
+ {getSnippetWithHighlight(n.content, activeNote.title)}
+
+
+ ))}
+
+ ) : (
+
Aucun lien entrant explicite pointant vers cette note.
+ )}
+
+
+ {/* 2. Outbound Links */}
+
+
+ Liens Sortants ({outboundLinks.length})
+
+ {outboundLinks.length > 0 ? (
+
+ {outboundLinks.map(n => (
+
onOpenNote(n.id)}
+ className="p-3 bg-white dark:bg-zinc-950 border border-border hover:border-accent/40 rounded-xl cursor-pointer transition-all space-y-1.5 hover:shadow-sm animate-fadeIn"
+ >
+
+ {n.title}
+ Cible
+
+
+ {getSnippetWithHighlight(activeNote.content, n.title)}
+
+
+ ))}
+
+ ) : (
+
Cette note ne pointe vers aucun lien sortant explicite.
+ )}
+
+
+ {/* 3. Unlinked Mentions */}
+
+
+ Mentions Simples ({unlinkedMentions.length})
+
+ {unlinkedMentions.length > 0 ? (
+
+ {unlinkedMentions.map(n => (
+
onOpenNote(n.id)}
+ className="p-3 bg-white dark:bg-zinc-950 border border-border hover:border-accent/40 rounded-xl cursor-pointer transition-all space-y-1.5 hover:shadow-sm"
+ >
+
+ {n.title}
+ Mention
+
+
+ {getSnippetWithHighlight(n.content, activeNote.title)}
+
+
+ ))}
+
+ ) : (
+
Aucune mention textuelle non-liée trouvée dans vos autres notes.
+ )}
+
+
+ >
+ ) : (
+
+
+
Veuillez sélectionner une note pour explorer son graphe relationnel.
+
+ )}
+
+ )}
+
{aiTab === 'resources' && (
void;
+ currentNote: Note | undefined;
+ allNotes: Note[];
+ carnets: Carnet[];
+ onSelectBlock: (sourceNoteId: string, blockIndex: number) => void;
+ prefilledBlock?: { noteId: string; blockIndex: number } | null;
+}
+
+export const BlockPicker: React.FC = ({
+ isOpen,
+ onClose,
+ currentNote,
+ allNotes,
+ carnets,
+ onSelectBlock,
+ prefilledBlock
+}) => {
+ const [activeTab, setActiveTab] = useState<'suggestions' | 'search'>('suggestions');
+ const [searchQuery, setSearchQuery] = useState('');
+
+ // Extract all paragraphs across notes (exlucing the current note to avoid self-embed)
+ const allBlocks = useMemo(() => {
+ const list: Array<{
+ id: string;
+ noteId: string;
+ noteTitle: string;
+ carnetName: string;
+ blockIndex: number;
+ text: string;
+ snippet: string;
+ }> = [];
+
+ allNotes.forEach(note => {
+ if (currentNote && note.id === currentNote.id) return;
+
+ const paragraphs = note.content.split('\n');
+ paragraphs.forEach((p, idx) => {
+ const text = p.trim();
+ // Skip empty lines, headings, or short snippets
+ if (text.length < 20 || text.startsWith('#') || text.startsWith('[[living-block')) return;
+
+ // Find carnet
+ const carnet = carnets.find(c => c.id === note.carnetId);
+
+ // 30-word snippet
+ const words = text.split(/\s+/);
+ const snippet = words.slice(0, 30).join(' ') + (words.length > 30 ? '...' : '');
+
+ list.push({
+ id: `${note.id}-${idx}`,
+ noteId: note.id,
+ noteTitle: note.title || 'Untitled',
+ carnetName: carnet?.name || 'Général',
+ blockIndex: idx,
+ text,
+ snippet
+ });
+ });
+ });
+
+ return list;
+ }, [allNotes, currentNote, carnets]);
+
+ // Jaccard similarity helper for AI Recommendations
+ const calculateSimilarity = (textA: string, textB: string): number => {
+ const getWords = (str: string) => new Set(str.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()?"']/g,"").split(/\s+/).filter(w => w.length > 3));
+ const wordsA = getWords(textA);
+ const wordsB = getWords(textB);
+
+ if (wordsA.size === 0 || wordsB.size === 0) return 0;
+
+ let intersection = 0;
+ wordsA.forEach(w => {
+ if (wordsB.has(w)) intersection++;
+ });
+
+ const union = wordsA.size + wordsB.size - intersection;
+ return intersection / union;
+ };
+
+ // Compile recommendations
+ const blockSuggestions = useMemo(() => {
+ if (!currentNote) return [];
+
+ return allBlocks.map(block => {
+ const baseSim = calculateSimilarity(currentNote.content + " " + currentNote.title, block.text);
+
+ // Add visual context factors: same carnet gets small boost, matching titles get boost
+ let score = baseSim * 100;
+ if (currentNote.carnetId === allNotes.find(n => n.id === block.noteId)?.carnetId) {
+ score += 15;
+ }
+
+ // Random deterministic variation to keep scores diverse but stable
+ const pseudoRandom = Math.abs(Math.sin(block.blockIndex + block.noteId.charCodeAt(0))) * 12;
+ score = Math.min(94, Math.max(52, score + pseudoRandom));
+
+ return {
+ ...block,
+ score: Math.round(score)
+ };
+ }).sort((a, b) => b.score - a.score);
+ }, [allBlocks, currentNote, allNotes]);
+
+
+ // Compile search results
+ const searchResults = useMemo(() => {
+ if (!searchQuery) return allBlocks;
+ const query = searchQuery.toLowerCase();
+ return allBlocks.filter(block =>
+ block.text.toLowerCase().includes(query) ||
+ block.noteTitle.toLowerCase().includes(query)
+ );
+ }, [allBlocks, searchQuery]);
+
+ if (!isOpen) return null;
+
+ return (
+
+
+ {/* Header */}
+
+
+
+
+
+
+
Living Block Picker
+
Connecter un bloc en temps réel
+
+
+
+
+
+
+
+ {/* Tab Selection */}
+
+ setActiveTab('suggestions')}
+ className={`flex-1 py-3 text-[10px] uppercase tracking-[0.15em] font-extrabold transition-all relative
+ ${activeTab === 'suggestions' ? 'text-blue-600 dark:text-blue-400 font-black' : 'text-concrete hover:text-ink/70'}`}
+ >
+
+
+ Suggestions IA
+
+ {activeTab === 'suggestions' && (
+
+ )}
+
+ setActiveTab('search')}
+ className={`flex-1 py-3 text-[10px] uppercase tracking-[0.15em] font-extrabold transition-all relative
+ ${activeTab === 'search' ? 'text-blue-600 dark:text-blue-400 font-black' : 'text-concrete hover:text-ink/70'}`}
+ >
+
+
+ Rechercher
+
+ {activeTab === 'search' && (
+
+ )}
+
+
+
+ {/* Search Input Box */}
+ {activeTab === 'search' && (
+
+
+
+ setSearchQuery(e.target.value)}
+ placeholder="Rechercher un extrait de note..."
+ className="w-full bg-white dark:bg-zinc-850 border border-[#D5D2CD] dark:border-neutral-800 rounded-xl pl-9 pr-4 py-2 text-xs outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500/20 transition-all font-sans"
+ autoFocus
+ />
+
+
+ )}
+
+ {/* Main List */}
+
+ {activeTab === 'suggestions' ? (
+ blockSuggestions.length > 0 ? (
+ blockSuggestions.map(block => (
+
onSelectBlock(block.noteId, block.blockIndex)}
+ className="w-full text-left p-3 rounded-xl border border-transparent hover:border-black/[0.08] hover:bg-white/70 dark:hover:bg-zinc-800/50 bg-white/30 dark:bg-zinc-800/10 transition-all group relative flex gap-3.5"
+ >
+
+
+ « {block.snippet} »
+
+
+ {block.noteTitle}
+ •
+
+ {block.carnetName}
+
+
+
+
+ {/* Discrete Percentage Circle Score */}
+
+
+ {block.score}% d'affinité
+
+
+
+ ))
+ ) : (
+
+ Aucune note complémentaire disponible pour suggérer un bloc.
+
+ )
+ ) : (
+ searchResults.length > 0 ? (
+ searchResults.map(block => (
+
onSelectBlock(block.noteId, block.blockIndex)}
+ className="w-full text-left p-3 rounded-xl border border-transparent hover:border-black/[0.08] hover:bg-white/70 dark:hover:bg-zinc-800/50 bg-white/30 dark:bg-zinc-800/10 transition-all group flex flex-col gap-1.5"
+ >
+
+ « {block.text} »
+
+
+ Source : {block.noteTitle}
+
+ {block.carnetName}
+
+
+
+ ))
+ ) : (
+
+ Aucun bloc ne correspond à votre recherche.
+
+ )
+ )}
+
+
+
+ );
+};
diff --git a/architectural-grid_landing/src/components/BrainstormView/BrainstormView.tsx b/architectural-grid/src/components/BrainstormView/BrainstormView.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/BrainstormView/BrainstormView.tsx
rename to architectural-grid/src/components/BrainstormView/BrainstormView.tsx
diff --git a/architectural-grid12/src/components/BrainstormView/WaveCanvas.tsx b/architectural-grid/src/components/BrainstormView/WaveCanvas.tsx
similarity index 100%
rename from architectural-grid12/src/components/BrainstormView/WaveCanvas.tsx
rename to architectural-grid/src/components/BrainstormView/WaveCanvas.tsx
diff --git a/architectural-grid/src/components/ClipperSimulator.tsx b/architectural-grid/src/components/ClipperSimulator.tsx
new file mode 100644
index 0000000..4fa68c5
--- /dev/null
+++ b/architectural-grid/src/components/ClipperSimulator.tsx
@@ -0,0 +1,618 @@
+import React, { useState, useEffect, useRef } from 'react';
+import {
+ X,
+ Lock,
+ RefreshCw,
+ Chrome,
+ Check,
+ Loader2,
+ ChevronDown,
+ Sparkles,
+ ArrowUpRight,
+ AlertTriangle,
+ Globe,
+ Scissors,
+ Bookmark
+} from 'lucide-react';
+import { motion, AnimatePresence } from 'motion/react';
+import { Carnet, Note, Tag } from '../types';
+import { v4 as uuidv4 } from 'uuid';
+
+interface ClipperSimulatorProps {
+ isOpen: boolean;
+ onClose: () => void;
+ carnets: Carnet[];
+ activeCarnetId: string;
+ onAddNote: (note: Note) => void;
+ onTriggerToast: (title: string, noteId: string) => void;
+}
+
+interface MockArticle {
+ id: string;
+ title: string;
+ domain: string;
+ url: string;
+ favicon: string;
+ content: string[];
+ suggestedTags: string[];
+ aiGeneratedTitle: string;
+ aiSummary: string;
+}
+
+const MOCK_ARTICLES: MockArticle[] = [
+ {
+ id: 'art-1',
+ title: 'The Bauhaus Theory & Functional Spatial Systems',
+ domain: 'bauhausstudios.org',
+ url: 'https://bauhausstudios.org/theory/functionalism',
+ favicon: 'https://www.google.com/s2/favicons?domain=bauhausstudios.org&sz=64',
+ content: [
+ 'Functionalist design operates on the direct correlation between physical geometry and spatial behavior. At the Bauhaus, teachers like Walter Gropius and Hannes Meyer postulated that an architectural object should serve its function strictly, discarding superfluous details that obscure the purity of its skeleton.',
+ 'The modern grid represents an honest commitment to industrial standardization. By segmenting living and working spaces into predictable, modular blocks, architects can optimize solar gain, human traffic flows, and construction material metrics.',
+ 'Light is the ultimate deconstructive asset within functional systems. When light pierces the rigid geometry of a modernist envelope, it shifts the perceived density of structural grids, transforming cold static steel interfaces into canvas-like elements that respond dynamically to local chronologies.'
+ ],
+ suggestedTags: ['Bauhaus', 'Functionalism', 'Spatial Design', 'German Modernism'],
+ aiGeneratedTitle: 'Bauhaus Functionalism & Rhythmic Grid Logic',
+ aiSummary: 'An exploration of how Walter Gropius and Bauhaus theorists utilized geometric grids and deconstructive light to align architectural materiality with industrial standardization and human behavioral workflows.'
+ },
+ {
+ id: 'art-2',
+ title: 'Sustainable Wood Frameworks & Decarbonized Structures',
+ domain: 'ecotimber.com',
+ url: 'https://ecotimber.com/future/timber',
+ favicon: 'https://www.google.com/s2/favicons?domain=ecotimber.com&sz=64',
+ content: [
+ 'Decarbonizing global real estate requires replacing portland cement and heavy structural steel with cross-laminated timber (CLT). CLT stands as a highly predictable engineered wood structure that sequesters atmospheric carbon dioxide directly inside the load-bearing framework of high-density buildings.',
+ 'Integrating CLT with parametric optimization allows for maximum material efficiency. Architects slice wood beams along precise stress lines generated by finite element analysis solvers, removing empty material volumes while keeping the building safe, functional, and durable.',
+ 'Passive solar energy design matches this structural honesty perfectly. By positioning CLT mass in the interior core, the building acts as a solar battery, absorbing raw passive light energy during peak hours and radiating warmth throughout the cold seasonal nights.'
+ ],
+ suggestedTags: ['Sustainabilty', 'Ecology', 'CLT Material', 'Decarbonization'],
+ aiGeneratedTitle: 'CLT Systems & Carbon-Neutral Frameworks',
+ aiSummary: 'A breakdown of high-density cross-laminated timber (CLT) integration, using parametric simulation to optimize stress distribution and passive thermal retention for modern sustainable spaces.'
+ }
+];
+
+export const ClipperSimulator: React.FC = ({
+ isOpen,
+ onClose,
+ carnets,
+ activeCarnetId,
+ onAddNote,
+ onTriggerToast,
+}) => {
+ const [activeArticleIdx, setActiveArticleIdx] = useState(0);
+ const activeArticle = MOCK_ARTICLES[activeArticleIdx];
+
+ // Clipper Extension Popup States
+ const [selectedCarnetId, setSelectedCarnetId] = useState(activeCarnetId || carnets[0]?.id || '1');
+ const [selectedText, setSelectedText] = useState('');
+ const [clipperState, setClipperState] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
+ const [aiGeneratedTitle, setAiGeneratedTitle] = useState('');
+ const [lastCreatedNoteId, setLastCreatedNoteId] = useState('');
+ const [customError, setCustomError] = useState('');
+
+ // Dropdown UI
+ const [showCarnetDropdown, setShowCarnetDropdown] = useState(false);
+
+ // Monitor text selections in the mock web page content
+ const handleTextSelection = () => {
+ const selection = window.getSelection();
+ if (selection && selection.toString().trim().length > 0) {
+ const text = selection.toString().trim();
+ // Ensure the text belongs to our mock article content
+ setSelectedText(text);
+ }
+ };
+
+ // Clear selections
+ const clearSelection = () => {
+ setSelectedText('');
+ window.getSelection()?.removeAllRanges();
+ };
+
+ // Preset highlights to make it easy to select text without highlighting with mouse
+ const handlePresetHighlight = (paragraph: string) => {
+ setSelectedText(paragraph);
+ };
+
+ // Handle the Clipper Action
+ const handleClip = (type: 'page' | 'selection') => {
+ setClipperState('loading');
+
+ // Simulate AI extraction and processing (summary, tags generation)
+ setTimeout(() => {
+ try {
+ // Occasional simulated error for retry demonstration
+ if (Math.random() < 0.15) {
+ throw new Error("Connexion réseau interrompue. L'extension n'a pas pu joindre les serveurs Momento.");
+ }
+
+ const dateStr = new Date().toLocaleDateString('fr-FR', {
+ day: 'numeric',
+ month: 'short',
+ year: 'numeric'
+ });
+
+ const generatedTags: Tag[] = activeArticle.suggestedTags.map((tagLabel, idx) => ({
+ id: `t-clip-${Date.now()}-${idx}`,
+ label: tagLabel,
+ type: 'ai'
+ }));
+
+ const newNoteId = `n-clip-${Date.now()}`;
+
+ let clipTitle = activeArticle.aiGeneratedTitle;
+ let clipContent = '';
+
+ if (type === 'selection' && selectedText) {
+ clipTitle = `Capture : ${activeArticle.title.substring(0, 30)}...`;
+ clipContent = `**[Sélection capturée]**\n\n> ${selectedText}\n\n---\n\n**Contexte initial :** ${activeArticle.aiSummary}\n\nURL Source : ${activeArticle.url}`;
+ } else {
+ clipContent = `**[Page web complète clippée]**\n\n**Résumé généré par l'IA :**\n${activeArticle.aiSummary}\n\n---\n\n**Contenu de l'article :**\n\n${activeArticle.content.join('\n\n')}\n\nURL Source : ${activeArticle.url}`;
+ }
+
+ const newNote: Note = {
+ id: newNoteId,
+ carnetId: selectedCarnetId,
+ title: clipTitle,
+ content: clipContent,
+ imageUrl: activeArticleIdx === 0
+ ? 'https://images.unsplash.com/photo-1503387762-592dea58ef23?auto=format&fit=crop&q=80&w=800&h=600'
+ : 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=600',
+ date: dateStr,
+ tags: [
+ ...generatedTags,
+ { id: 't-web-source', label: 'Clipped', type: 'user' }
+ ],
+ // Custom clipper details
+ isClipped: true,
+ clipSourceUrl: activeArticle.url,
+ clipFavicon: activeArticle.favicon,
+ clipDate: dateStr
+ };
+
+ setAiGeneratedTitle(clipTitle);
+ setLastCreatedNoteId(newNoteId);
+ setClipperState('success');
+
+ // Add note to Momento Database
+ onAddNote(newNote);
+
+ // Fire real-time notification toast in Momento!
+ onTriggerToast(clipTitle, newNoteId);
+
+ } catch (err: any) {
+ setCustomError(err.message || "Erreur de connexion.");
+ setClipperState('error');
+ }
+ }, 1500);
+ };
+
+ const handleResetClipper = () => {
+ setClipperState('idle');
+ setCustomError('');
+ };
+
+ if (!isOpen) return null;
+
+ return (
+
+
+ {/* Left column: Realistic Mock Browser Page */}
+
+ {/* Mock Browser Header */}
+
+ {/* Window Controls */}
+
+
+ {/* Tabs */}
+
+ {MOCK_ARTICLES.map((art, idx) => (
+
{
+ setActiveArticleIdx(idx);
+ clearSelection();
+ handleResetClipper();
+ }}
+ className={`px-3 py-1.5 text-xs rounded-lg font-medium flex items-center gap-2 max-w-[170px] truncate transition-colors
+ ${activeArticleIdx === idx
+ ? 'bg-slate-100 dark:bg-white/5 text-ink dark:text-dark-ink border border-border'
+ : 'text-concrete hover:bg-slate-50 dark:hover:bg-white/5'}`}
+ >
+ { (e.target as any).src = 'https://www.google.com/s2/favicons?domain=google.com'; }} />
+ {art.title}
+
+ ))}
+
+
+ {/* Live Indicator of Clipper Simulator */}
+
+
+ Simulateur de Capture
+
+
+
+ {/* Browser Address Bar */}
+
+
+
+
+
{ clearSelection(); handleResetClipper(); }} className="p-1 hover:bg-slate-100 dark:hover:bg-white/5 rounded">
+
+
+
+
+ https://
+ {activeArticle.domain}
+ {activeArticle.url.slice(activeArticle.url.indexOf(activeArticle.domain) + activeArticle.domain.length)}
+
+
+ {/* Web Extension active badge */}
+
+
+
+ Extension active sur cette page
+
+
+
+
+ {/* Web Viewport */}
+
+
+
+
+ Publié sur {activeArticle.domain}
+
+
+
+ {activeArticle.title}
+
+
+
+ Date : Capture Temps Réel
+ Sélectionnez du texte ci-dessous pour le clipper
+
+
+ {/* Tips */}
+
+
+
+ Piste d'évaluation :
+
+
+ Survolez et surlignez n'importe quel texte à la souris dans l'article ci-dessous pour activer instantanément l'état Sélection active dans l'extension ! Vous pouvez aussi cliquer sur un paragraphe pour le simuler :
+
+
+
+ {/* Main Content paragraphs */}
+
+ {activeArticle.content.map((p, index) => {
+ const isParaSelected = selectedText === p;
+ return (
+
handlePresetHighlight(p)}
+ className={`cursor-pointer transition-all duration-300 p-2.5 rounded-lg border
+ ${isParaSelected
+ ? 'bg-accent/10 border-accent text-neutral-900 dark:text-white font-medium scale-[1.01] shadow-sm'
+ : 'border-transparent hover:bg-neutral-50 dark:hover:bg-neutral-900'}`}
+ title="Cliquer pour sélectionner ce paragraphe"
+ >
+ {p}
+
+ );
+ })}
+
+
+ {selectedText && (
+
+
+
+ Sélection enregistrée ({selectedText.split(' ').length} mots)
+
+
+ Effacer la sélection
+
+
+ )}
+
+
+
+
+ {/* Right column: Simulated Browser Extension Popup Screen (Exactly 400x520px envelope styled elegantly) */}
+
+
+
+
+
+ {/* Explicitly designed container mimicking browser overlay/extension dropdown at 400x520px target size */}
+
+
+
+
+ );
+};
diff --git a/architectural-grid/src/components/GraphKnowledgeMap.tsx b/architectural-grid/src/components/GraphKnowledgeMap.tsx
new file mode 100644
index 0000000..1fba097
--- /dev/null
+++ b/architectural-grid/src/components/GraphKnowledgeMap.tsx
@@ -0,0 +1,874 @@
+import React, { useEffect, useRef, useState, useMemo } from 'react';
+import * as d3 from 'd3';
+import { motion, AnimatePresence } from 'motion/react';
+import { Note, Carnet, Tag } from '../types';
+import {
+ Network,
+ Search,
+ Sliders,
+ HelpCircle,
+ X,
+ Filter,
+ Compass,
+ BookOpen,
+ Eye,
+ Sparkles,
+ RefreshCw,
+ Plus,
+ Minus,
+ Maximize2,
+ ChevronLeft,
+ Calendar,
+ Layers,
+ FileText
+} from 'lucide-react';
+
+interface GraphKnowledgeMapProps {
+ notes: Note[];
+ carnets: Carnet[];
+ onOpenNote: (noteId: string) => void;
+ onClose?: () => void;
+}
+
+// 7 Gorgeous colors corresponding to the carnets palette
+const CARNET_COLOR_PALETTE: { [key: string]: string } = {
+ '1': '#D97706', // Daily Notes - Warm Amber
+ '2': '#059669', // Project: Neo - Soft Emerald
+ '3': '#4F46E5', // Shared Docs - Rich Indigo
+ '4': '#0891B2', // Architecture Research - Clean Cyan
+ '5': '#EA580C', // History of Architecture - Deep Orange
+ '6': '#DB2777', // Modernism - Vibrant Rose
+ '7': '#65A30D', // Sustainable Design - Cool Lime
+};
+
+const DEFAULT_CARNET_COLOR = '#71717A'; // Zinc
+
+interface D3Node extends d3.SimulationNodeDatum {
+ id: string;
+ title: string;
+ carnetId: string;
+ carnetName: string;
+ color: string;
+ date: string;
+ snippet: string;
+ tags: Tag[];
+ degree: number;
+}
+
+interface D3Link extends d3.SimulationLinkDatum {
+ source: string | D3Node;
+ target: string | D3Node;
+ type: 'wikilink' | 'semantic';
+ strength: number;
+}
+
+export const GraphKnowledgeMap: React.FC = ({
+ notes,
+ carnets,
+ onOpenNote,
+ onClose
+}) => {
+ const containerRef = useRef(null);
+ const svgRef = useRef(null);
+
+ // Settings & Toggles
+ const [showSemanticLinks, setShowSemanticLinks] = useState(true);
+ const [minSemanticStrength, setMinSemanticStrength] = useState(0.40); // threshold
+ const [selectedCarnetIds, setSelectedCarnetIds] = useState([]);
+
+ // Interaction States
+ const [searchQuery, setSearchQuery] = useState('');
+ const [hoveredNode, setHoveredNode] = useState(null);
+ const [activeLocalNode, setActiveLocalNode] = useState(null);
+ const [nodeConnections, setNodeConnections] = useState>(new Set());
+
+ // D3 Zoom controller ref to trigger programmatically
+ const d3ZoomRef = useRef | null>(null);
+
+ // Initialize carnet filters with all carnets on mount
+ useEffect(() => {
+ setSelectedCarnetIds(carnets.map(c => c.id));
+ }, [carnets]);
+
+ // Static list of explicit links (Wikilinks)
+ const explicitWikiLinks = useMemo(() => {
+ return [
+ { source: 'n1', target: 'n1-b' },
+ { source: 'n3', target: 'n3-b' },
+ { source: 'bridge-1', target: 'n1' },
+ { source: 'bridge-1', target: 'n2' },
+ ];
+ }, []);
+
+ // Filter and process notes and carnets
+ const filteredNotes = useMemo(() => {
+ return notes.filter(n => {
+ // Exclude trashed/deleted notes
+ if (n.isDeleted) return false;
+ // Filter by selected carnets
+ return selectedCarnetIds.includes(n.carnetId);
+ });
+ }, [notes, selectedCarnetIds]);
+
+ // Compute all links based on state (Wikilinks + Semantic if enabled)
+ const graphData = useMemo(() => {
+ const noteMap = new Map();
+ filteredNotes.forEach(n => noteMap.set(n.id, n));
+
+ const nodes: D3Node[] = filteredNotes.map(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ return {
+ id: n.id,
+ title: n.title,
+ carnetId: n.carnetId,
+ carnetName: carnet?.name || 'Carnet Inconnu',
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ date: n.date,
+ snippet: n.content.split('.').slice(0, 3).join('.') + '.',
+ tags: n.tags || [],
+ degree: 0, // calculated below
+ x: undefined,
+ y: undefined
+ };
+ });
+
+ const links: D3Link[] = [];
+
+ // 1. Add Explicit Wikilinks if both target and source are inside filtered list
+ explicitWikiLinks.forEach(link => {
+ if (noteMap.has(link.source) && noteMap.has(link.target)) {
+ links.push({
+ source: link.source,
+ target: link.target,
+ type: 'wikilink',
+ strength: 1.0
+ });
+ }
+ });
+
+ // 2. Add Semantic Connections (Memory Echo) based on embedding similarities
+ if (showSemanticLinks) {
+ for (let i = 0; i < filteredNotes.length; i++) {
+ for (let j = i + 1; j < filteredNotes.length; j++) {
+ const ni = filteredNotes[i];
+ const nj = filteredNotes[j];
+
+ if (ni.embedding && nj.embedding) {
+ // Cosine vector similarity approximation / Euclidean inverse mapping
+ const dist = Math.sqrt(
+ Math.pow(ni.embedding[0] - nj.embedding[0], 2) +
+ Math.pow(ni.embedding[1] - nj.embedding[1], 2)
+ );
+ // Translate distance into similarity standard (0.0 - 1.0)
+ const similarity = Math.max(0, 1 - dist * 0.7);
+
+ if (similarity >= minSemanticStrength) {
+ // Avoid duplicate links with explicit ones to keep display clean
+ const hasExplicit = explicitWikiLinks.some(
+ ex => (ex.source === ni.id && ex.target === nj.id) || (ex.source === nj.id && ex.target === ni.id)
+ );
+
+ if (!hasExplicit) {
+ links.push({
+ source: ni.id,
+ target: nj.id,
+ type: 'semantic',
+ strength: similarity
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Calculate node connectivity degrees
+ nodes.forEach(node => {
+ const connectionsCount = links.filter(l =>
+ l.source === node.id || l.target === node.id ||
+ (typeof l.source === 'object' && (l.source as any).id === node.id) ||
+ (typeof l.target === 'object' && (l.target as any).id === node.id)
+ ).length;
+ node.degree = connectionsCount;
+ });
+
+ return { nodes, links };
+ }, [filteredNotes, carnets, showSemanticLinks, minSemanticStrength, selectedCarnetIds, explicitWikiLinks]);
+
+ // Handle Note connection highlights during hover
+ useEffect(() => {
+ if (!hoveredNode) {
+ setNodeConnections(new Set());
+ return;
+ }
+
+ const connected = new Set();
+ connected.add(hoveredNode.id);
+
+ graphData.links.forEach((l: any) => {
+ const srcId = typeof l.source === 'object' ? l.source.id : l.source;
+ const tgtId = typeof l.target === 'object' ? l.target.id : l.target;
+
+ if (srcId === hoveredNode.id) {
+ connected.add(tgtId);
+ } else if (tgtId === hoveredNode.id) {
+ connected.add(srcId);
+ }
+ });
+
+ setNodeConnections(connected);
+ }, [hoveredNode, graphData.links]);
+
+ // Main D3 force layout rendering loop
+ useEffect(() => {
+ if (!svgRef.current || !containerRef.current) return;
+
+ const width = containerRef.current.clientWidth;
+ const height = containerRef.current.clientHeight;
+
+ const svg = d3.select(svgRef.current);
+ svg.selectAll("*").remove();
+
+ // Base containment group
+ const mainGroup = svg.append("g");
+
+ // Configure zooming behaviors
+ const zoomBehavior = d3.zoom()
+ .scaleExtent([0.15, 5])
+ .on("zoom", (event) => {
+ mainGroup.attr("transform", event.transform);
+ });
+
+ d3ZoomRef.current = zoomBehavior;
+ svg.call(zoomBehavior);
+
+ // D3 nodes and links references mapped to copyable arrays
+ const simulationNodes = JSON.parse(JSON.stringify(graphData.nodes)) as D3Node[];
+ const simulationLinks = graphData.links.map(l => ({
+ source: l.source,
+ target: l.target,
+ type: l.type,
+ strength: l.strength
+ })) as D3Link[];
+
+ // Build the force simulation
+ const simulation = d3.forceSimulation(simulationNodes)
+ .force("link", d3.forceLink(simulationLinks)
+ .id(d => d.id)
+ .distance(d => d.type === 'wikilink' ? 100 : 140)
+ )
+ .force("charge", d3.forceManyBody().strength(-240))
+ .force("center", d3.forceCenter(width / 2, height / 2))
+ .force("collision", d3.forceCollide().radius(d => {
+ // Size proportional to connections: min 8px, max 20px
+ const rad = 8 + Math.min(d.degree * 2.5, 12);
+ return rad + 24;
+ }));
+
+ // Draw Links
+ const linkGroup = mainGroup.append("g")
+ .attr("class", "links-layer");
+
+ const link = linkGroup.selectAll("line")
+ .data(simulationLinks)
+ .enter()
+ .append("line")
+ .attr("stroke", d => d.type === 'semantic' ? '#4f46e5' : '#18181b')
+ .attr("stroke-opacity", d => d.type === 'semantic' ? 0.35 : 0.18)
+ .attr("stroke-width", d => d.type === 'semantic' ? 1.2 : 1.5)
+ .attr("stroke-dasharray", d => d.type === 'semantic' ? '4,4' : 'none');
+
+ // Draw Nodes
+ const nodeGroup = mainGroup.append("g")
+ .attr("class", "nodes-layer");
+
+ const node = nodeGroup.selectAll(".node")
+ .data(simulationNodes)
+ .enter()
+ .append("g")
+ .attr("class", "node cursor-pointer")
+ .on("click", (event, d) => {
+ event.stopPropagation();
+ handleSelectNode(d);
+ })
+ .on("mouseenter", (event, d) => {
+ setHoveredNode(d);
+ })
+ .on("mouseleave", () => {
+ setHoveredNode(null);
+ })
+ .call(d3.drag()
+ .on("start", dragStarted)
+ .on("drag", dragged)
+ .on("end", dragEnded) as any);
+
+ // Create central circles
+ node.append("circle")
+ .attr("r", d => 6 + Math.min(d.degree * 1.5, 9))
+ .attr("fill", d => d.color)
+ .attr("stroke", "rgba(255,255,255,0.95)")
+ .attr("stroke-width", 2)
+ .attr("class", "transition-all duration-300 dark:stroke-zinc-950")
+ .style("filter", "drop-shadow(0 2px 4px rgba(0,0,0,0.1))");
+
+ // Text labels overlay
+ node.append("text")
+ .attr("dy", d => 14 + Math.min(d.degree * 1.5, 9) + 4)
+ .attr("text-anchor", "middle")
+ .attr("class", "text-[10px] sm:text-[11px] font-sans font-semibold tracking-tight fill-zinc-850 dark:fill-zinc-300 select-none pointer-events-none")
+ .text(d => d.title.length > 22 ? d.title.substring(0, 20) + "..." : d.title)
+ .style("opacity", d => (d.degree > 2 || d.title.toLowerCase().includes(searchQuery.toLowerCase()) && searchQuery) ? 1 : 0.65);
+
+ // Search query search highlight ring
+ if (searchQuery) {
+ node.filter(d => d.title.toLowerCase().includes(searchQuery.toLowerCase()))
+ .append("circle")
+ .attr("r", d => 14 + Math.min(d.degree * 1.5, 9))
+ .attr("fill", "none")
+ .attr("stroke", "#06b6d4")
+ .attr("stroke-width", 2)
+ .attr("stroke-dasharray", "3,1")
+ .attr("class", "animate-[spin_20s_linear_infinite]");
+ }
+
+ // Node active local neighbor rings
+ if (activeLocalNode) {
+ const activeConns = getLocalNodeNeighbors(activeLocalNode.id);
+
+ node.style("opacity", d => {
+ return activeConns.has(d.id) ? 1.0 : 0.15;
+ });
+
+ link.style("stroke-opacity", (l: any) => {
+ const srcId = l.source.id;
+ const tgtId = l.target.id;
+ return (activeConns.has(srcId) && activeConns.has(tgtId)) ? 0.75 : 0.05;
+ });
+
+ // Highlight the focused local hub node with a neat accent circle
+ node.filter(d => d.id === activeLocalNode.id)
+ .append("circle")
+ .attr("r", d => 16 + Math.min(d.degree * 1.5, 9))
+ .attr("fill", "none")
+ .attr("stroke", "rgba(79, 70, 229, 0.4)")
+ .attr("stroke-width", 1.5)
+ .attr("stroke-opacity", 0.9);
+ }
+ // Node hover lighting state
+ else if (hoveredNode) {
+ const hoveredConns = new Set();
+ hoveredConns.add(hoveredNode.id);
+
+ graphData.links.forEach((l: any) => {
+ const srcId = typeof l.source === 'object' ? l.source.id : l.source;
+ const tgtId = typeof l.target === 'object' ? l.target.id : l.target;
+
+ if (srcId === hoveredNode.id) {
+ hoveredConns.add(tgtId);
+ } else if (tgtId === hoveredNode.id) {
+ hoveredConns.add(srcId);
+ }
+ });
+
+ // Subdue unconnected elements to 20% opacity
+ node.style("opacity", d => hoveredConns.has(d.id) ? 1.0 : 0.20);
+ link.style("stroke-opacity", (l: any) => {
+ const srcId = l.source.id;
+ const tgtId = l.target.id;
+ return (srcId === hoveredNode.id || tgtId === hoveredNode.id) ? 0.8 : 0.05;
+ });
+
+ // Hover scale update for primary
+ node.filter(d => d.id === hoveredNode.id)
+ .select("circle")
+ .attr("transform", "scale(1.3)");
+ }
+ // Normal / Base state
+ else {
+ node.style("opacity", 1.0);
+ link.style("stroke-opacity", d => d.type === 'semantic' ? 0.35 : 0.18);
+ }
+
+ // Run ticks
+ simulation.on("tick", () => {
+ link
+ .attr("x1", d => (d.source as any).x)
+ .attr("y1", d => (d.source as any).y)
+ .attr("x2", d => (d.target as any).x)
+ .attr("y2", d => (d.target as any).y);
+
+ node
+ .attr("transform", d => `translate(${d.x},${d.y})`);
+ });
+
+ // Zoom on local node view trigger
+ if (activeLocalNode && width && height) {
+ const targetNodeCopy = simulationNodes.find(n => n.id === activeLocalNode.id);
+ if (targetNodeCopy) {
+ // Step ticker synchronously to finalize force state layout
+ for (let i = 0; i < 40; ++i) simulation.tick();
+
+ const x = targetNodeCopy.x || width / 2;
+ const y = targetNodeCopy.y || height / 2;
+
+ svg.transition()
+ .duration(850)
+ .ease(d3.easeCubicOut)
+ .call(
+ zoomBehavior.transform,
+ d3.zoomIdentity.translate(width / 2, height / 2).scale(1.65).translate(-x, -y)
+ );
+ }
+ } else {
+ // Re-center whole graph
+ svg.transition()
+ .duration(800)
+ .ease(d3.easeCubicOut)
+ .call(zoomBehavior.transform, d3.zoomIdentity);
+ }
+
+ function dragStarted(event: any, d: any) {
+ if (!event.active) simulation.alphaTarget(0.25).restart();
+ d.fx = d.x;
+ d.fy = d.y;
+ }
+
+ function dragged(event: any, d: any) {
+ d.fx = event.x;
+ d.fy = event.y;
+ }
+
+ function dragEnded(event: any, d: any) {
+ if (!event.active) simulation.alphaTarget(0);
+ d.fx = null;
+ d.fy = null;
+ }
+
+ return () => {
+ simulation.stop();
+ };
+ }, [graphData, showSemanticLinks, minSemanticStrength, searchQuery, activeLocalNode, hoveredNode]);
+
+ // Compute local neighbors
+ const getLocalNodeNeighbors = (nodeId: string): Set => {
+ const list = new Set();
+ list.add(nodeId);
+ graphData.links.forEach(l => {
+ if (l.source === nodeId) {
+ list.add(typeof l.target === 'object' ? (l.target as any).id : l.target);
+ } else if (l.target === nodeId) {
+ list.add(typeof l.source === 'object' ? (l.source as any).id : l.source);
+ }
+ });
+ return list;
+ };
+
+ const handleSelectNode = (node: D3Node) => {
+ setActiveLocalNode(node);
+ };
+
+ const handleResetLocalView = () => {
+ setActiveLocalNode(null);
+ };
+
+ const handleZoom = (direction: 'in' | 'out' | 'fit') => {
+ if (!svgRef.current || !d3ZoomRef.current) return;
+ const svg = d3.select(svgRef.current);
+
+ if (direction === 'fit') {
+ svg.transition().duration(500).call(d3ZoomRef.current.transform, d3.zoomIdentity);
+ } else {
+ const factor = direction === 'in' ? 1.3 : 1 / 1.3;
+ svg.transition().duration(400).call(d3ZoomRef.current.scaleBy, factor);
+ }
+ };
+
+ const toggleCarnetSelector = (carnetId: string) => {
+ setSelectedCarnetIds(prev =>
+ prev.includes(carnetId)
+ ? prev.filter(id => id !== carnetId)
+ : [...prev, carnetId]
+ );
+ };
+
+ const selectAllCarnets = () => {
+ setSelectedCarnetIds(carnets.map(c => c.id));
+ };
+
+ const clearAllCarnets = () => {
+ setSelectedCarnetIds([]);
+ };
+
+ return (
+
+
+ {/* Dynamic Header Overlay */}
+
+ {activeLocalNode ? (
+
+
+ Graphe Global
+
+ ) : onClose ? (
+
+
+ Retour Notes
+
+ ) : (
+
+
+ Carte Sémantique
+
+ )}
+
+
+ {graphData.nodes.length} Nœuds
+ |
+ {graphData.links.length} Relations
+
+
+
+ {/* Global Hub Search Bar */}
+
+
+ setSearchQuery(e.target.value)}
+ placeholder="Chercher une note dans le graphe sémantique..."
+ className="w-full text-xs pl-9 pr-8 py-2.5 rounded-2xl border border-neutral-200 dark:border-neutral-800 bg-white/95 dark:bg-zinc-950/95 placeholder-concrete/60 shadow-lg outline-none focus:border-accent focus:ring-1 focus:ring-accent/10 transition-all text-ink dark:text-dark-ink font-medium"
+ />
+
+
+ {searchQuery && (
+ setSearchQuery('')}
+ className="absolute right-3 top-1/2 -translate-y-1/2 p-0.5 text-concrete hover:text-ink hover:bg-black/5 dark:hover:bg-white/5 rounded-full"
+ >
+
+
+ )}
+
+
+
+ {/* Zoom controls (bottom right) */}
+
+
handleZoom('in')}
+ className="p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg text-concrete hover:text-ink transition-colors"
+ title="Zoomer (+)"
+ >
+
+
+
+
handleZoom('out')}
+ className="p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg text-concrete hover:text-ink transition-colors"
+ title="Dézoomer (-)"
+ >
+
+
+
+
+
+
handleZoom('fit')}
+ className="p-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg text-concrete hover:text-accent transition-colors"
+ title="Ajuster la vue"
+ >
+
+
+
+
+ {/* Floating Controls Panel (top right) */}
+
+
+
+
+
+ Paramètres du Graphe
+
+ {
+ setShowSemanticLinks(true);
+ setMinSemanticStrength(0.40);
+ selectAllCarnets();
+ }}
+ className="text-[9px] font-bold uppercase text-accent hover:text-accent/80 transition-colors"
+ title="Rétablir par défaut"
+ >
+ Reset
+
+
+
+
+ {/* Semantic Link Toggle Details */}
+
+
+
+
+ Liens sémantiques
+
+ setShowSemanticLinks(e.target.checked)}
+ className="w-4 h-4 text-accent border-gray-300 rounded focus:ring-accent"
+ />
+
+
+ Visualiser la couche d'affinité IA générée par embeddings sémantiques (Memory Echo).
+
+
+
+ {/* Slider for semantic filtering threshold - Displayed only if activated */}
+ {showSemanticLinks && (
+
+
+ Force minimum sémantique
+
+ {(minSemanticStrength * 100).toFixed(0)}%
+
+
+
+
+ 0.2
+ setMinSemanticStrength(parseFloat(e.target.value))}
+ className="w-full h-1.5 bg-neutral-200 dark:bg-neutral-800 rounded-lg appearance-none cursor-pointer accent-indigo-600"
+ />
+ 0.85
+
+
+ )}
+
+ {/* Filter by Carnets with Checkboxes */}
+
+
+
+
+ Filtrer par Carnet ({selectedCarnetIds.length})
+
+
+ Tous
+ •
+ Aucun
+
+
+
+
+ {carnets.map(c => {
+ const isChecked = selectedCarnetIds.includes(c.id);
+ const carnetColor = CARNET_COLOR_PALETTE[c.id] || DEFAULT_CARNET_COLOR;
+ return (
+
+
+
+ {c.name}
+
+
+ toggleCarnetSelector(c.id)}
+ className="w-3.5 h-3.5 text-accent border-gray-300 rounded focus:ring-accent"
+ />
+
+ );
+ })}
+
+
+
+
+
+
+ {/* Dynamic Tooltip Hover UI Card (In case of node hovering) */}
+
+ {hoveredNode && !activeLocalNode && (
+
+
+
+
+ {hoveredNode.carnetName}
+
+
+
+ Modifié le : {hoveredNode.date}
+
+
+
+
+ {hoveredNode.title}
+
+
+
+ {/* Micro Metrics stats */}
+
+
+
Connexions
+
{hoveredNode.degree}
+
+
+
+
Tags détectés
+
{hoveredNode.tags.length || 0}
+
+
+
+
+ Cliquez pour isoler / modifier
+
+
+ )}
+
+
+ {/* SVG Core Render canvas */}
+
+
+
+ {/* State D: Note focus right panel slider (280px width) */}
+
+ {activeLocalNode && (
+
+ {/* Panel header and close button */}
+
+
+
+
+ Aperçu de Note
+
+
+
+ Fermer
+
+
+
+ {/* Note details */}
+
+
+
+ {activeLocalNode.carnetName}
+
+
+
+ {activeLocalNode.title}
+
+
+
+
+ Dernier update : {activeLocalNode.date}
+
+
+
+
+ {/* Snippet body content */}
+
+
+
Résumé / Extrait
+
+ "{activeLocalNode.snippet}"
+
+
+
+ {/* Relationship listing */}
+
+
+ Éléments connectés ({getLocalNodeNeighbors(activeLocalNode.id).size - 1})
+
+
+
+ {notes
+ .filter(n => n.id !== activeLocalNode.id && getLocalNodeNeighbors(activeLocalNode.id).has(n.id))
+ .map(neighbor => {
+ return (
+
{
+ const foundNode = graphData.nodes.find(v => v.id === neighbor.id);
+ if (foundNode) handleSelectNode(foundNode);
+ }}
+ className="flex items-center justify-between text-[10px] p-2 bg-neutral-50 dark:bg-neutral-900/60 rounded-xl hover:bg-neutral-100 cursor-pointer border border-transparent hover:border-border transition-colors group"
+ >
+
+
+ {neighbor.title}
+
+
+ Séléctionner
+
+
+ );
+ })}
+
+
+
+ {/* Tags panel detail */}
+ {activeLocalNode.tags && activeLocalNode.tags.length > 0 && (
+
+
Index de tags
+
+ {activeLocalNode.tags.map((t, idx) => (
+
+ {t.label}
+
+ ))}
+
+
+ )}
+
+
+ {/* CTA action bottom block */}
+
+ onOpenNote(activeLocalNode.id)}
+ className="w-full py-3.5 bg-ink text-paper dark:bg-neutral-50 dark:text-zinc-950 rounded-xl text-xs font-bold uppercase tracking-widest hover:opacity-95 transition-all text-center flex items-center justify-center gap-1.5 shadow-xl shadow-black/10 scale-100 active:scale-95"
+ >
+
+ Ouvrir la note
+
+
+
+ )}
+
+
+ );
+};
diff --git a/architectural-grid_landing/src/components/HierarchicalCarnetSelector.tsx b/architectural-grid/src/components/HierarchicalCarnetSelector.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/HierarchicalCarnetSelector.tsx
rename to architectural-grid/src/components/HierarchicalCarnetSelector.tsx
diff --git a/architectural-grid/src/components/InsightsView.tsx b/architectural-grid/src/components/InsightsView.tsx
new file mode 100644
index 0000000..fd76491
--- /dev/null
+++ b/architectural-grid/src/components/InsightsView.tsx
@@ -0,0 +1,482 @@
+import React, { useState, useEffect, useMemo } from 'react';
+import { motion, AnimatePresence } from 'motion/react';
+import {
+ Network,
+ Lightbulb,
+ Layers,
+ Sparkles,
+ ArrowRight,
+ RefreshCw,
+ Trophy,
+ Zap,
+ Tag,
+ Link as LinkIcon,
+ Menu,
+ FileText,
+ AlertCircle,
+ Clock,
+ ChevronRight,
+ TrendingUp,
+ Sliders,
+ CheckCircle2,
+ Lock
+} from 'lucide-react';
+import { Note, NoteCluster, BridgeNote, ConnectionSuggestion } from '../types';
+import { runClustering, detectBridges, calculateCentroid, getMostCentralNoteTitles } from '../services/clusteringService';
+import { nameCluster, suggestBridgeIdeas } from '../services/geminiService';
+import { NetworkGraph } from './NetworkGraph';
+
+interface InsightsViewProps {
+ notes: Note[];
+ onUpdateNotes: (updatedNotes: Note[]) => void;
+ onNoteSelect: (noteId: string) => void;
+ onOpenSidebar?: () => void;
+}
+
+export const InsightsView: React.FC = ({
+ notes,
+ onUpdateNotes,
+ onNoteSelect,
+ onOpenSidebar
+}) => {
+ const [isCalculating, setIsCalculating] = useState(false);
+ const [clusters, setClusters] = useState([]);
+ const [bridgeNotes, setBridgeNotes] = useState([]);
+ const [suggestions, setSuggestions] = useState([]);
+ const [selectedClusterId, setSelectedClusterId] = useState(null);
+
+ // Mobile responsive view selector
+ const [viewMode, setViewMode] = useState<'graph' | 'dashboard'>('dashboard');
+
+ // Interactive automatic recalculation parameters simulator / status
+ const [lastSyncTime, setLastSyncTime] = useState(() => {
+ return new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
+ });
+
+ // Track changes to notes since last calculation to show a conditions indicator
+ const [notesModifiedCount, setNotesModifiedCount] = useState(0);
+
+ // Monitor edits to emulate the state "Recalcul quotidien planifié" or condition (>10 notes modified)
+ useEffect(() => {
+ // Whenever notes length or contents change, we simulate a tally
+ setNotesModifiedCount(prev => Math.min(prev + 1, 12));
+ }, [notes.length]);
+
+ const performAnalysis = async () => {
+ setIsCalculating(true);
+ try {
+ // 1. Run clustering (DBSCAN acting on density with outlier filtering, label -1 is outlier)
+ const { clusters: newClusters } = runClustering(notes);
+
+ // 2. Name clusters (find the 5 notes closest to each cluster's centroid vector)
+ const namedClusters = await Promise.all(newClusters.map(async (c) => {
+ const centroid = calculateCentroid(c.noteIds, notes);
+ // Find the 5 most central notes (closest to the cluster centroid by cosine similarity)
+ const clusterNoteSummaries = getMostCentralNoteTitles(c.noteIds, centroid, notes, 5);
+
+ const name = await nameCluster(clusterNoteSummaries);
+
+ return { ...c, name, centroid };
+ }));
+
+ // 3. Update notes with cluster IDs
+ const updatedNotes = notes.map(n => {
+ const cluster = namedClusters.find(c => c.noteIds.includes(n.id));
+ return { ...n, clusterId: cluster?.id };
+ });
+ onUpdateNotes(updatedNotes);
+
+ // 4. Detect bridges (notes exhibiting similarity > 0.5 to >= 2 clusters)
+ const bridges = detectBridges(updatedNotes, namedClusters);
+
+ // 5. Build suggestions for unconnected cluster pairs
+ // A pair is unconnected if there are no existing bridge notes linking them
+ const newSuggestions: ConnectionSuggestion[] = [];
+ if (namedClusters.length >= 2) {
+ const unconnectedPairs: { cA: NoteCluster; cB: NoteCluster }[] = [];
+
+ for (let i = 0; i < namedClusters.length; i++) {
+ for (let j = i + 1; j < namedClusters.length; j++) {
+ const cA = namedClusters[i];
+ const cB = namedClusters[j];
+
+ // Check if any bridge note connects these two clusters
+ const hasBridge = bridges.some(b =>
+ b.connectedClusterIds.includes(cA.id) && b.connectedClusterIds.includes(cB.id)
+ );
+
+ if (!hasBridge) {
+ unconnectedPairs.push({ cA, cB });
+ }
+ }
+ }
+
+ // Generate bridge suggestions for the top 3 unconnected pairs
+ for (let k = 0; k < Math.min(unconnectedPairs.length, 3); k++) {
+ const { cA, cB } = unconnectedPairs[k];
+ const cA_notes = updatedNotes.filter(n => cA.noteIds.includes(n.id)).map(n => n.title).slice(0, 3).join(', ');
+ const cB_notes = updatedNotes.filter(n => cB.noteIds.includes(n.id)).map(n => n.title).slice(0, 3).join(', ');
+
+ const bridgeIdeas = await suggestBridgeIdeas(cA.name, cB.name, cA_notes, cB_notes);
+ bridgeIdeas.forEach((idea, idx) => {
+ newSuggestions.push({
+ id: `suggestion-${cA.id}-${cB.id}-${idx}`,
+ ...idea,
+ clusterAId: cA.id,
+ clusterBId: cB.id
+ });
+ });
+ }
+ }
+
+ setClusters(namedClusters);
+ setBridgeNotes(bridges);
+ setSuggestions(newSuggestions);
+ setLastSyncTime(new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }));
+ setNotesModifiedCount(0); // Reset modified counter upon successful clustering recalculation
+ } catch (error) {
+ console.error("Analysis failed:", error);
+ } finally {
+ setIsCalculating(false);
+ }
+ };
+
+ useEffect(() => {
+ if (notes.some(n => n.embedding) && clusters.length === 0) {
+ performAnalysis();
+ }
+ }, [notes]);
+
+ const bridgeList = useMemo(() => {
+ return bridgeNotes.map(b => {
+ const note = notes.find(n => n.id === b.noteId);
+ return { ...b, title: note?.title || 'Note de passage' };
+ });
+ }, [bridgeNotes, notes]);
+
+ // Compute isolated clusters (ones with no bridge notes spanning to them)
+ const isolatedClusters = useMemo(() => {
+ const networkedClusterIds = new Set(bridgeNotes.flatMap(b => b.connectedClusterIds));
+ return clusters.filter(c => !networkedClusterIds.has(c.id));
+ }, [clusters, bridgeNotes]);
+
+ // Find currently selected cluster info for the zoom drilldown list
+ const selectedCluster = useMemo(() => {
+ return clusters.find(c => c.id === selectedClusterId);
+ }, [clusters, selectedClusterId]);
+
+ const selectedClusterNotes = useMemo(() => {
+ if (!selectedCluster) return [];
+ return notes.filter(n => selectedCluster.noteIds.includes(n.id));
+ }, [notes, selectedCluster]);
+
+ return (
+
+ {/* Header with Mobile Drawer Trigger & Responsiveness Tab controls */}
+
+
+ {onOpenSidebar && (
+
+
+
+ )}
+
+
+
+
+
+
Analyses & Cartographie
+
+
Modèles sémantiques & clusters de connaissances
+
+
+
+
+ {/* Mobile Tab Switcher */}
+
+ setViewMode('graph')}
+ className={`px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider rounded-lg transition-all ${viewMode === 'graph' ? 'bg-white dark:bg-black text-ink shadow-sm' : 'text-concrete'}`}
+ >
+ Réseau Graphique
+
+ setViewMode('dashboard')}
+ className={`px-3 py-1.5 text-[10px] font-bold uppercase tracking-wider rounded-lg transition-all ${viewMode === 'dashboard' ? 'bg-white dark:bg-black text-ink shadow-sm' : 'text-concrete'}`}
+ >
+ Analyses & Ponts
+
+
+
+
+ {isCalculating ? : }
+ {isCalculating ? 'Calcul...' : 'Re-analyser'}
+
+
+
+
+
+ {/* Left: Interactive Canvas Network Graph View */}
+
+
+
+
+ {/* Right: Insight Dashboard Column */}
+
+
+
+ {/* Active Cluster Inspection Drawer / Side Card */}
+
+ {selectedCluster && (
+
+
+
+
+ Focus Cluster Activé
+
{selectedCluster.name}
+
+
setSelectedClusterId(null)}
+ className="p-1 px-2.5 bg-black/5 dark:bg-white/5 hover:bg-black/10 text-xs font-bold rounded-lg uppercase tracking-wider transition-colors"
+ >
+ Fermer
+
+
+
+
+
Cet ensemble thématique réunit {selectedClusterNotes.length} notes complémentaires. Cliquez sur une note pour y accéder directement :
+
+ {selectedClusterNotes.map(note => (
+ onNoteSelect(note.id)}
+ className="w-full text-left p-2.5 rounded-lg bg-black/5 hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10 text-xs font-medium text-ink dark:text-dark-ink flex items-center justify-between gap-3 group transition-all"
+ >
+ {note.title || 'Note sans titre'}
+
+
+ ))}
+
+
+
+ )}
+
+
+ {/* Stats Highlights Header */}
+
+
+
+
+ Clusters Actifs
+
+
+
{clusters.length}
+
Détectés sans à priori
+
+
+
+
+
+ Notes-Ponts
+
+
+
{bridgeNotes.length}
+
Passerelles d'idées
+
+
+
+
+ {/* NEW SECTION: Auto Recalculator Control Dashboard Section */}
+
+
+
+
+
Système de Recalcul
+
+
+ Synchronisé
+
+
+
+
+
+
CRON PLANIFIÉ
+
+ Quotidien (04:00)
+
+
+
+
DERNIÈRE SYNCHRONISATION
+
+ Aujourd'hui, {lastSyncTime}
+
+
+
+
+ {/* Recalcul Trigger Metrics */}
+
+
+
+ Notes éditées depuis recul :
+ {notesModifiedCount} / 10 modifs
+
+
+
+
+
Le recalcul incrémental se déclenche automatiquement si modification de {'>'} 10 notes ou variation d'embeddings {'>'} 5%.
+
+
+
+
+ {/* Isolated Clusters List */}
+
+
+
+
+
Clusters Isolés ({isolatedClusters.length})
+
+
Sans points d'accroche
+
+
+ {isolatedClusters.map(c => (
+
setSelectedClusterId(c.id)}
+ className="p-3.5 rounded-xl bg-white dark:bg-zinc-800 border border-border/30 hover:border-black/10 flex items-center justify-between cursor-pointer"
+ >
+
+
+ Non connecté
+
+
+ ))}
+ {isolatedClusters.length === 0 && (
+
+ Tous les clusters thématiques sont liés par au moins un point de passage sémantique !
+
+ )}
+
+
+
+ {/* Bridge Notes Section */}
+
+
+
+
Notes-Ponts Influentes
+
+
+ {bridgeList.map(bridge => (
+
onNoteSelect(bridge.noteId)}
+ className="p-4 rounded-xl bg-white dark:bg-zinc-800 border border-border/30 hover:border-ochre/40 hover:shadow-sm transition-all cursor-pointer group"
+ >
+
+
{bridge.title}
+
+ Lien : {(bridge.bridgeScore * 100).toFixed(0)}%
+
+
+
+ {bridge.connectedClusterIds.map(cid => {
+ const c = clusters.find(cl => cl.id === cid);
+ return (
+
{
+ e.stopPropagation();
+ setSelectedClusterId(cid);
+ }}
+ className="flex items-center gap-1.5 px-2 py-0.5 bg-black/[0.02] dark:bg-white/[0.02] border border-border/30 rounded-md hover:border-concrete/40 transition-colors"
+ >
+
+
{c?.name}
+
+ );
+ })}
+
+
+ ))}
+ {bridgeList.length === 0 && !isCalculating && (
+
+ Aucune note-pont significative n'a été détectée. Créez des notes transversales pour forger de nouveaux liens créatifs.
+
+ )}
+
+
+
+ {/* Connection Suggestions */}
+
+
+
+
Opportunités de Connexion (Ponts Suggérés)
+
+
+ {suggestions.map((s) => (
+
+
+
+
+ Relier {clusters.find(c => c.id === s.clusterAId)?.name} & {clusters.find(c => c.id === s.clusterBId)?.name}
+
+
+
{s.title}
+
{s.description}
+
+
+ {s.reasoning}
+
+
+ ))}
+ {isCalculating && (
+
+ {[1, 2].map(i => (
+
+ ))}
+
+ )}
+ {!isCalculating && suggestions.length === 0 && (
+
+ Toutes vos thématiques clés sont déjà formidablement interconnectées !
+
+ )}
+
+
+
+
+
+
+ );
+};
diff --git a/architectural-grid_landing/src/components/LandingPage.tsx b/architectural-grid/src/components/LandingPage.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/LandingPage.tsx
rename to architectural-grid/src/components/LandingPage.tsx
diff --git a/architectural-grid/src/components/LivingBlock.tsx b/architectural-grid/src/components/LivingBlock.tsx
new file mode 100644
index 0000000..51b0c07
--- /dev/null
+++ b/architectural-grid/src/components/LivingBlock.tsx
@@ -0,0 +1,194 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { motion, AnimatePresence } from 'motion/react';
+import { Zap, HelpCircle, ArrowRight, RefreshCw, Unlink, AlertCircle } from 'lucide-react';
+import { Note } from '../types';
+
+interface LivingBlockProps {
+ sourceNoteId: string;
+ blockIndex: number;
+ allNotes: Note[];
+ hostNote: Note;
+ onUpdateNote: (updatedNote: Note) => void;
+ onOpenNote: (noteId: string) => void;
+ wsConnected: boolean;
+ broadcastLivingBlockUpdate?: (sourceNoteId: string, blockIndex: number, newText: string) => void;
+}
+
+export const LivingBlock: React.FC = ({
+ sourceNoteId,
+ blockIndex,
+ allNotes,
+ hostNote,
+ onUpdateNote,
+ onOpenNote,
+ wsConnected,
+ broadcastLivingBlockUpdate
+}) => {
+ const [pulse, setPulse] = useState(false);
+ const pulseRef = useRef(null);
+
+ // Locate source note and actual paragraph text
+ const sourceNote = allNotes.find(n => n.id === sourceNoteId);
+ const paragraphs = sourceNote?.content.split('\n') || [];
+ const rawText = paragraphs[blockIndex];
+
+ // Store a local cache in standard state to support the "Source Deleted Snapshot" or local typing lag minimization
+ const [localText, setLocalText] = useState(rawText || "Contenu de l'extrait sémantique.");
+ const [isDeleted, setIsDeleted] = useState(!sourceNote || rawText === undefined);
+
+ // Sync state if source note or text updates from outside
+ useEffect(() => {
+ const isSourceMissing = !sourceNote || rawText === undefined;
+ setIsDeleted(isSourceMissing);
+
+ if (!isSourceMissing && rawText !== localText) {
+ setLocalText(rawText);
+ }
+ }, [rawText, sourceNote]);
+
+ // Handle pulse notification when custom update event is received from socket
+ useEffect(() => {
+ const handlePulseEvent = (e: any) => {
+ if (e.detail && e.detail.sourceNoteId === sourceNoteId && e.detail.blockIndex === blockIndex) {
+ setPulse(true);
+ if (pulseRef.current) clearTimeout(pulseRef.current);
+ pulseRef.current = setTimeout(() => {
+ setPulse(false);
+ }, 1000);
+ }
+ };
+
+ window.addEventListener('living-block-pulse', handlePulseEvent);
+ return () => {
+ window.removeEventListener('living-block-pulse', handlePulseEvent);
+ if (pulseRef.current) clearTimeout(pulseRef.current);
+ };
+ }, [sourceNoteId, blockIndex]);
+
+ // Edit body text and stream to central note and websockets
+ const handleBodyTextChange = (e: React.ChangeEvent) => {
+ const newText = e.target.value;
+ setLocalText(newText);
+
+ if (sourceNote && !isDeleted) {
+ const updatedParagraphs = [...paragraphs];
+ updatedParagraphs[blockIndex] = newText;
+ const updatedSourceNote = {
+ ...sourceNote,
+ content: updatedParagraphs.join('\n')
+ };
+ // 1. Update state
+ onUpdateNote(updatedSourceNote);
+
+ // 2. Broadcast via WS connection to other terminals
+ if (broadcastLivingBlockUpdate) {
+ broadcastLivingBlockUpdate(sourceNoteId, blockIndex, newText);
+ }
+ }
+ };
+
+ // Convert Living Block to normal local text paragraph
+ const handleConvertLocalText = () => {
+ const hostParagraphs = hostNote.content.split('\n');
+ // Find matching shortcode index
+ const codeToSearch = `[[living-block:${sourceNoteId}:${blockIndex}]]`;
+ const targetIdx = hostParagraphs.findIndex(line => line.trim() === codeToSearch);
+
+ if (targetIdx !== -1) {
+ hostParagraphs[targetIdx] = localText; // Replace code with snapped plain text
+ const updatedHostNote = {
+ ...hostNote,
+ content: hostParagraphs.join('\n')
+ };
+ onUpdateNote(updatedHostNote);
+ }
+ };
+
+ // Styling helpers
+ const borderStyle = isDeleted
+ ? 'border-rose-500/60 dark:border-red-900/60 bg-rose-50/20 dark:bg-rose-950/5'
+ : !wsConnected
+ ? 'border-amber-500 dark:border-amber-700 bg-amber-50/10 dark:bg-amber-950/5'
+ : pulse
+ ? 'border-blue-500 shadow-md shadow-blue-500/15 bg-blue-50/20 dark:bg-blue-950/10'
+ : 'border-blue-500/80 bg-blue-50/5 dark:bg-blue-950/5';
+
+ return (
+
+
+ {/* Header (20px) */}
+
+
+ {isDeleted ? (
+
+ ) : (
+
+ )}
+
+ {isDeleted ? "Source déconnectée" : sourceNote?.title || "Note connectée"}
+
+
+ {/* Live syncing status badge */}
+ {isDeleted ? (
+
+ DÉCONNECTÉ
+
+ ) : wsConnected ? (
+
+ LIVE
+
+ ) : (
+
+ HORS-LIGNE
+
+ )}
+
+
+
+ {isDeleted ? (
+
+
+ Décharger le lien
+
+ ) : (
+ <>
+ {!wsConnected && (
+
+ Synchro suspendue
+
+ )}
+
onOpenNote(sourceNoteId)}
+ className="opacity-0 group-hover/block:opacity-100 flex items-center gap-1 text-[9.5px] font-extrabold text-blue-600 dark:text-blue-400 hover:underline transition-all"
+ >
+ Ouvrir
+
+ >
+ )}
+
+
+
+ {/* Body content editable block */}
+
+
+
+
+
+ );
+};
diff --git a/architectural-grid14/src/components/NetworkGraph.tsx b/architectural-grid/src/components/NetworkGraph.tsx
similarity index 54%
rename from architectural-grid14/src/components/NetworkGraph.tsx
rename to architectural-grid/src/components/NetworkGraph.tsx
index aa83e68..a49b8d4 100644
--- a/architectural-grid14/src/components/NetworkGraph.tsx
+++ b/architectural-grid/src/components/NetworkGraph.tsx
@@ -8,13 +8,17 @@ interface NetworkGraphProps {
clusters: NoteCluster[];
bridgeNotes: BridgeNote[];
onNoteSelect: (id: string) => void;
+ selectedClusterId: string | null;
+ onClusterSelect: (id: string | null) => void;
}
export const NetworkGraph: React.FC = ({
notes,
clusters,
bridgeNotes,
- onNoteSelect
+ onNoteSelect,
+ selectedClusterId,
+ onClusterSelect
}) => {
const svgRef = useRef(null);
const containerRef = useRef(null);
@@ -67,7 +71,7 @@ export const NetworkGraph: React.FC = ({
clusterId: n.clusterId!,
color: cluster?.color || '#cbd5e1',
isBridge,
- radius: isBridge ? 12 : 8
+ radius: isBridge ? 13 : 8
};
});
@@ -85,10 +89,10 @@ export const NetworkGraph: React.FC = ({
}
const simulation = d3.forceSimulation(nodes)
- .force("link", d3.forceLink(links).id(d => d.id).distance(100))
- .force("charge", d3.forceManyBody().strength(-200))
+ .force("link", d3.forceLink(links).id(d => d.id).distance(110))
+ .force("charge", d3.forceManyBody().strength(-220))
.force("center", d3.forceCenter(width / 2, height / 2))
- .force("collision", d3.forceCollide().radius(d => d.radius + 10));
+ .force("collision", d3.forceCollide().radius(d => d.radius + 12));
// Links
const link = g.append("g")
@@ -97,7 +101,14 @@ export const NetworkGraph: React.FC = ({
.enter()
.append("line")
.attr("stroke", "#e2e8f0")
- .attr("stroke-opacity", 0.6)
+ .attr("stroke-opacity", (d: any) => {
+ if (!selectedClusterId) return 0.6;
+ const sId = typeof d.source === 'string' ? d.source : (d.source as any).id;
+ const tId = typeof d.target === 'string' ? d.target : (d.target as any).id;
+ const sourceNote = nodes.find(n => n.id === sId);
+ const targetNote = nodes.find(n => n.id === tId);
+ return (sourceNote?.clusterId === selectedClusterId && targetNote?.clusterId === selectedClusterId) ? 0.8 : 0.05;
+ })
.attr("stroke-width", 1);
// Nodes
@@ -113,12 +124,18 @@ export const NetworkGraph: React.FC = ({
.on("drag", dragged)
.on("end", dragended) as any);
+ // Node opacities based on focus
+ node.attr("opacity", d => {
+ if (!selectedClusterId) return 1;
+ return d.clusterId === selectedClusterId ? 1 : 0.15;
+ });
+
node.append("circle")
.attr("r", d => d.radius)
.attr("fill", d => d.color)
.attr("stroke", d => d.isBridge ? "#D4AF37" : "#fff")
- .attr("stroke-width", d => d.isBridge ? 3 : 2)
- .style("filter", d => d.isBridge ? "drop-shadow(0 0 4px rgba(212, 175, 55, 0.4))" : "none");
+ .attr("stroke-width", d => d.isBridge ? 3.5 : 2)
+ .style("filter", d => d.isBridge ? "drop-shadow(0 0 6px rgba(212, 175, 55, 0.6))" : "none");
node.append("text")
.attr("dy", d => d.radius + 14)
@@ -137,6 +154,34 @@ export const NetworkGraph: React.FC = ({
.attr("transform", d => `translate(${d.x},${d.y})`);
});
+ // Zoom transition on cluster highlight
+ if (selectedClusterId && width && height) {
+ const clusterNodes = nodes.filter(n => n.clusterId === selectedClusterId);
+ if (clusterNodes.length > 0) {
+ // Run a small tick count synchronously to find coordinates quickly if layout is starting
+ for (let i = 0; i < 50; ++i) simulation.tick();
+
+ const xCoords = clusterNodes.map(cn => cn.x).filter((x): x is number => x !== undefined);
+ const yCoords = clusterNodes.map(cn => cn.y).filter((y): y is number => y !== undefined);
+
+ if (xCoords.length > 0 && yCoords.length > 0) {
+ const avgX = d3.mean(xCoords) || width / 2;
+ const avgY = d3.mean(yCoords) || height / 2;
+
+ svg.transition()
+ .duration(800)
+ .call(
+ zoom.transform,
+ d3.zoomIdentity.translate(width / 2, height / 2).scale(1.4).translate(-avgX, -avgY)
+ );
+ }
+ }
+ } else {
+ svg.transition()
+ .duration(800)
+ .call(zoom.transform, d3.zoomIdentity);
+ }
+
function dragstarted(event: any, d: D3Node) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
@@ -155,17 +200,36 @@ export const NetworkGraph: React.FC = ({
}
return () => simulation.stop();
- }, [notes, clusters, bridgeNotes, onNoteSelect]);
+ }, [notes, clusters, bridgeNotes, onNoteSelect, selectedClusterId]);
return (
-
- {clusters.map(c => (
-
- ))}
+
+ {clusters.map(c => {
+ const isSelected = selectedClusterId === c.id;
+ return (
+
onClusterSelect?.(isSelected ? null : c.id)}
+ className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border shadow-sm transition-all text-[9px] font-bold uppercase tracking-wider
+ ${isSelected
+ ? 'bg-ink text-white dark:bg-white dark:text-black border-ink dark:border-white scale-105 shadow-md'
+ : 'bg-white/90 dark:bg-black/80 text-concrete hover:text-ink hover:border-concrete/40 border-border'
+ }`}
+ >
+
+ {c.name}
+
+ );
+ })}
+ {selectedClusterId && (
+
onClusterSelect?.(null)}
+ className="px-3 py-1.5 rounded-full border border-rose-200 bg-rose-50 dark:bg-rose-950/20 dark:border-rose-900/40 text-rose-500 text-[9px] font-bold uppercase tracking-wider hover:bg-rose-100 transition-all shadow-sm"
+ >
+ Réinitialiser focus
+
+ )}
diff --git a/architectural-grid/src/components/NotebookInfoSidebar.tsx b/architectural-grid/src/components/NotebookInfoSidebar.tsx
new file mode 100644
index 0000000..e821c31
--- /dev/null
+++ b/architectural-grid/src/components/NotebookInfoSidebar.tsx
@@ -0,0 +1,769 @@
+import React from 'react';
+import {
+ X,
+ Clock,
+ Folder,
+ Calendar,
+ FileText,
+ Hash,
+ Network,
+ CheckCircle2,
+ AlertCircle,
+ Copy,
+ Check,
+ History,
+ Info,
+ ChevronRight
+} from 'lucide-react';
+import { motion, AnimatePresence } from 'motion/react';
+import { Note, Carnet } from '../types';
+
+interface NotebookInfoSidebarProps {
+ isOpen: boolean;
+ onClose: () => void;
+ activeNote: Note | undefined;
+ notes: Note[];
+ carnets: Carnet[];
+ onOpenNote: (id: string) => void;
+ onUpdateNote?: (note: Note) => void;
+}
+
+export const NotebookInfoSidebar: React.FC
= ({
+ isOpen,
+ onClose,
+ activeNote,
+ notes = [],
+ carnets,
+ onOpenNote,
+ onUpdateNote
+}) => {
+ const [activeTab, setActiveTab] = React.useState<'infos' | 'versions' | 'relations'>('infos');
+ const [copiedId, setCopiedId] = React.useState(false);
+ const [hoveredOrbitNode, setHoveredOrbitNode] = React.useState(null);
+
+ // For ID copy action
+ const handleCopyId = (id: string) => {
+ navigator.clipboard.writeText(id).then(() => {
+ setCopiedId(true);
+ setTimeout(() => setCopiedId(false), 2000);
+ });
+ };
+
+ // Explicit links for Network
+ const explicitWikiLinks = React.useMemo(() => [
+ { source: 'n1', target: 'n1-b' },
+ { source: 'n3', target: 'n3-b' },
+ { source: 'bridge-1', target: 'n1' },
+ { source: 'bridge-1', target: 'n2' },
+ ], []);
+
+ const CARNET_COLOR_PALETTE: { [key: string]: string } = {
+ '1': '#D97706', // Daily Notes - Warm Amber
+ '2': '#059669', // Project: Neo - Soft Emerald
+ '3': '#4F46E5', // Shared Docs - Rich Indigo
+ '4': '#0891B2', // Architecture Research - Clean Cyan
+ '5': '#EA580C', // History of Architecture - Deep Orange
+ '6': '#DB2777', // Modernism - Vibrant Rose
+ '7': '#65A30D', // Sustainable Design - Cool Lime
+ };
+
+ const DEFAULT_CARNET_COLOR = '#71717A';
+
+ // Network calculation values
+ const backlinks = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isExplicit = explicitWikiLinks.some(link =>
+ (link.source === n.id && link.target === activeNote.id)
+ );
+ const isContentLink = n.content.toLowerCase().includes(`[[${activeNote.title.toLowerCase()}]]`);
+ return isExplicit || isContentLink;
+ });
+ }, [activeNote, notes, explicitWikiLinks]);
+
+ const outboundLinks = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isExplicit = explicitWikiLinks.some(link =>
+ (link.source === activeNote.id && link.target === n.id)
+ );
+ const isContentLink = activeNote.content.toLowerCase().includes(`[[${n.title.toLowerCase()}]]`);
+ return isExplicit || isContentLink;
+ });
+ }, [activeNote, notes, explicitWikiLinks]);
+
+ const unlinkedMentions = React.useMemo(() => {
+ if (!activeNote || !notes) return [];
+ return notes.filter(n => {
+ if (n.id === activeNote.id || n.isDeleted) return false;
+ const isLinked = [...backlinks, ...outboundLinks].some(link => link.id === n.id);
+ if (isLinked) return false;
+ return n.content.toLowerCase().includes(activeNote.title.toLowerCase());
+ });
+ }, [activeNote, notes, backlinks, outboundLinks]);
+
+ const orbitNodes = React.useMemo(() => {
+ const list: { id: string; title: string; color: string; carnetName: string; relationship: 'backlink' | 'outbound' | 'mention' }[] = [];
+
+ backlinks.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'backlink'
+ });
+ });
+
+ outboundLinks.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'outbound'
+ });
+ });
+
+ unlinkedMentions.forEach(n => {
+ const carnet = carnets.find(c => c.id === n.carnetId);
+ list.push({
+ id: n.id,
+ title: n.title,
+ color: CARNET_COLOR_PALETTE[n.carnetId] || DEFAULT_CARNET_COLOR,
+ carnetName: carnet?.name || 'Carnet',
+ relationship: 'mention'
+ });
+ });
+
+ return list.slice(0, 8);
+ }, [backlinks, outboundLinks, unlinkedMentions, carnets]);
+
+ const getSnippetWithHighlight = (content: string, term: string) => {
+ const index = content.toLowerCase().indexOf(term.toLowerCase());
+ if (index === -1) {
+ return {content.substring(0, 80)}... ;
+ }
+ const start = Math.max(0, index - 40);
+ const end = Math.min(content.length, index + term.length + 40);
+ const before = content.substring(start, index);
+ const match = content.substring(index, index + term.length);
+ const after = content.substring(index + term.length, end);
+ return (
+
+ {start > 0 && "..."}
+ {before}
+ {match}
+ {after}
+ {end < content.length && "..."}
+
+ );
+ };
+
+ // Safe time calculation helper (mocked cleanly to match image's 'il y a 12 jours' or standard dynamic calculations)
+ const getRelativeCreatedStr = (dateStr: string) => {
+ if (dateStr.includes('12 mai 2026')) return 'il y a 12 jours';
+ if (dateStr.includes('Oct 26')) return 'il y a 2h';
+ if (dateStr.includes('Oct 27')) return 'il y a 1j';
+ if (dateStr.includes('Oct 24')) return 'il y a 3j';
+ if (dateStr.includes('Oct 25')) return 'il y a 2j';
+ if (dateStr.includes('Oct 22')) return 'il y a 5j';
+ if (dateStr.includes('Oct 23')) return 'il y a 4j';
+ if (dateStr.includes('Oct 28')) return 'il y a 10 min';
+ return 'il y a quelques jours';
+ };
+
+ return (
+
+ {isOpen && (
+
+ {/* Header tabs row matching image style */}
+
+
+ {/* Infos tab */}
+ setActiveTab('infos')}
+ className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-full text-xs font-bold tracking-wide transition-all duration-200 cursor-pointer
+ ${activeTab === 'infos'
+ ? 'bg-ink text-paper dark:bg-white dark:text-ink shadow-sm'
+ : 'text-concrete hover:text-ink hover:bg-black/[0.03] dark:hover:bg-white/5'}`}
+ >
+
+ Infos
+
+
+ {/* Versions tab */}
+ setActiveTab('versions')}
+ className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-full text-xs font-bold tracking-wide transition-all duration-200 cursor-pointer
+ ${activeTab === 'versions'
+ ? 'bg-ink text-paper dark:bg-white dark:text-ink shadow-sm'
+ : 'text-concrete hover:text-ink hover:bg-black/[0.03] dark:hover:bg-white/5'}`}
+ >
+
+ Versions
+
+
+ {/* Network / Relations tab */}
+ setActiveTab('relations')}
+ className={`flex items-center gap-1.5 px-3.5 py-1.5 rounded-full text-xs font-bold tracking-wide transition-all duration-200 cursor-pointer
+ ${activeTab === 'relations'
+ ? 'bg-ink text-paper dark:bg-white dark:text-ink shadow-sm'
+ : 'text-concrete hover:text-ink hover:bg-black/[0.03] dark:hover:bg-white/5'}`}
+ >
+
+ Réseau
+
+
+
+
+
+
+
+
+ {/* Core scrollable content area */}
+
+
+ {/* TABS - INFOS */}
+ {activeTab === 'infos' && (
+
+ {activeNote ? (
+
+ {/* Calculated Stats */}
+ {(() => {
+ const wordCount = activeNote.content.trim() ? activeNote.content.trim().split(/\s+/).filter(Boolean).length : 0;
+ const charCount = activeNote.content.length;
+ const lineCount = activeNote.content.trim() ? activeNote.content.split('\n').length : 0;
+
+ // Count math equations
+ const matchesBigMath = (activeNote.content.match(/\$\$[\s\S]*?\$\$/g) || []).length;
+ const matchesInlineMath = (activeNote.content.match(/\$[^\$\n]+?\$/g) || []).length;
+ const equationCount = matchesBigMath + matchesInlineMath;
+
+ // Count graph relations or internal visual blocks
+ const matchesLivingBlocks = (activeNote.content.match(/\[\[living-block:.*?\]\]/g) || []).length;
+ const graphCount = orbitNodes.length + matchesLivingBlocks;
+
+ // Count images
+ const matchesMarkdownImages = (activeNote.content.match(/!\[.*?\]\(.*?\)/g) || []).length;
+ const matchesHtmlImages = (activeNote.content.match(/
+ {/* Grid Stats */}
+
+
+
+ {wordCount}
+
+ Mots
+
+
+
+ {charCount}
+
+ Caractères
+
+
+
+ {/* Secondary Detailed Counts Widget */}
+
+
+ {lineCount}
+ Lignes
+
+
+ {equationCount}
+ Équations
+
+
+ {graphCount}
+ Graphes
+
+
+ {imageCount}
+ Images
+
+
+ >
+ );
+ })()}
+
+ {/* Attribute Detail rows styled to 100% exact layout matching the attached image */}
+
+ {/* Carnet attribute */}
+
+
+
+
+
+ Carnet
+
+ {carnets.find(c => c.id === activeNote.carnetId)?.name || "Général"}
+
+
+
+
+ {/* Type attribute */}
+
+
+
+
+
+ Type
+
+ {activeNote.isClipped ? 'Source Web' : 'Texte enrichi'}
+
+
+
+
+ {/* Créé le attribute */}
+
+
+
+
+
+ Créée le
+
+ {activeNote.date || "12 mai 2026"}
+
+
+ {getRelativeCreatedStr(activeNote.date || "12 mai 2026")}
+
+
+
+
+ {/* Modifiée attribute */}
+
+
+
+
+
+ Modifiée
+
+ {activeNote.date || "12 mai 2026"} • 15:58
+
+
+ {getRelativeCreatedStr(activeNote.date || "12 mai 2026")}
+
+
+
+
+ {/* ID attribute */}
+
+
+
+
+
+
ID
+
+
+ {activeNote.id}
+
+ handleCopyId(activeNote.id)}
+ className="p-1 hover:bg-slate-100 dark:hover:bg-neutral-800 rounded text-concrete shrink-0 transition-all cursor-pointer"
+ title="Copier l'ID de la note"
+ >
+ {copiedId ? : }
+
+
+
+
+
+
+ {/* Snapshots Toggle */}
+
+
+
+
+
+
+
Snapshots Actifs
+
Suivi d'historique automatique
+
+
+
+ {
+ onUpdateNote?.({
+ ...activeNote,
+ isVersioningEnabled: activeNote.isVersioningEnabled === false ? true : false
+ });
+ }}
+ />
+
+
+
+
+ ) : (
+
+
+
Veuillez sélectionner une note pour inspecter ses informations.
+
+ )}
+
+ )}
+
+ {/* TABS - VERSIONS */}
+ {activeTab === 'versions' && (
+
+
+
Snapshots & Versions
+
+ {(activeNote?.versionHistory || []).length} Snapshots
+
+
+
+ {activeNote ? (
+
+ {activeNote.isVersioningEnabled !== false ? (
+ <>
+ {/* Banner to snap manual version */}
+
+
+
Garnir l'historique
+
Figer manuellement l'état actuel de la note.
+
+
{
+ const newSnapshot = {
+ id: 'v-' + Date.now(),
+ title: activeNote.title,
+ content: activeNote.content,
+ timestamp: new Date().toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' }) + ' • ' + new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }),
+ size: activeNote.content.length
+ };
+ onUpdateNote?.({
+ ...activeNote,
+ versionHistory: [newSnapshot, ...(activeNote.versionHistory || [])]
+ });
+ }}
+ className="w-full text-center py-2 bg-ink dark:bg-white hover:opacity-90 text-paper dark:text-ink text-[10px] uppercase tracking-widest font-bold rounded-lg transition-all shadow-sm cursor-pointer"
+ >
+ Figer un instant
+
+
+
+ {/* Snapshot list */}
+
+ {(activeNote.versionHistory || []).length > 0 ? (
+
+ {(activeNote.versionHistory || []).map((v) => (
+
+
+
+
+ {v.title}
+
+ {v.timestamp}
+
+
+ {v.size >= 1024 ? (v.size / 1024).toFixed(1) + ' KB' : v.size + ' B'}
+
+
+
+
+ {
+ alert(`Aperçu de la version "${v.title}" :\n\n${v.content || "Note vide"}`);
+ }}
+ className="text-muted-ink hover:text-ink transition-colors font-semibold"
+ >
+ Aperçu
+
+ {
+ if (window.confirm("Êtes-vous sûr de vouloir restaurer cette version ? Le contenu actuel sera archivé comme nouvelle version.")) {
+ const backupSnapshot = {
+ id: 'v-' + Date.now(),
+ title: activeNote.title,
+ content: activeNote.content,
+ timestamp: new Date().toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' }) + ' • ' + new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }),
+ size: activeNote.content.length
+ };
+ onUpdateNote?.({
+ ...activeNote,
+ title: v.title,
+ content: v.content,
+ versionHistory: [backupSnapshot, ...(activeNote.versionHistory || []).filter(h => h.id !== v.id)]
+ });
+ }
+ }}
+ className="text-ochre dark:text-ochre font-bold hover:underline"
+ >
+ Restaurer
+
+
+
+ ))}
+
+ ) : (
+
+
+
Aucun snapshot enregistré pour le moment. Modifiez la note pour démarrer le suivi ou figez-en un manuellement.
+
+ )}
+
+ >
+ ) : (
+
+
+
Suivi d'historique inactif
+
L'historique des versions est actuellement désactivé pour cette note spécifique. Pour l'activer, cochez l'option dans l'onglet "Infos".
+
+ )}
+
+ ) : (
+
+
+
Veuillez sélectionner une note pour voir son historique de versions.
+
+ )}
+
+ )}
+
+ {/* TABS - RELATIONS (RESEAU) */}
+ {activeTab === 'relations' && (
+
+
+
+
Vue Graphe Locale
+
+
+
+ {activeNote ? (
+ <>
+ {/* Interactive Local Graph representation */}
+
+
+
+
+
+
+ {/* Dotted boundary */}
+
+
+ {/* Links */}
+ {orbitNodes.map((node, i) => {
+ const angle = i * (orbitNodes.length > 0 ? (2 * Math.PI) / orbitNodes.length : 0);
+ const nx = 160 + 70 * Math.cos(angle);
+ const ny = 110 + 62 * Math.sin(angle);
+ return (
+
+
+ {node.relationship === 'outbound' && (
+
+ )}
+ {node.relationship === 'backlink' && (
+
+ )}
+
+ );
+ })}
+
+ {/* Center Node: Active Note */}
+
+
+
+
+
+ {/* Orbit nodes */}
+ {orbitNodes.map((node, i) => {
+ const angle = i * (orbitNodes.length > 0 ? (2 * Math.PI) / orbitNodes.length : 0);
+ const nx = 160 + 70 * Math.cos(angle);
+ const ny = 110 + 62 * Math.sin(angle);
+ const isHovered = hoveredOrbitNode?.id === node.id;
+ return (
+ onOpenNote(node.id)}
+ onMouseEnter={() => setHoveredOrbitNode(node)}
+ onMouseLeave={() => setHoveredOrbitNode(null)}
+ >
+
+
+ {node.title.substring(0, 10)}
+
+
+ );
+ })}
+
+
+
+ {hoveredOrbitNode ? (
+
+
+ {hoveredOrbitNode.carnetName}
+
+ {hoveredOrbitNode.relationship === 'backlink' ? 'Lien Entrant' : hoveredOrbitNode.relationship === 'outbound' ? 'Lien Sortant' : 'Mention Simple'}
+
+
+
{hoveredOrbitNode.title}
+
Cliquez pour ouvrir la note
+
+ ) : (
+
+
+ Survolez un nœud, cliquez pour ouvrir
+
+ )}
+
+
+
+ {/* Explicit links listings with highlighting */}
+
+ {/* 1. Backlinks */}
+
+
+ Liens Entrants ({backlinks.length})
+
+ {backlinks.length > 0 ? (
+
+ {backlinks.map(n => (
+
onOpenNote(n.id)}
+ className="p-3 bg-white dark:bg-zinc-950 border border-border hover:border-accent/40 rounded-xl cursor-pointer transition-all space-y-1.5 hover:shadow-sm"
+ >
+
+ {n.title}
+ Réf
+
+
+ {getSnippetWithHighlight(n.content, activeNote.title)}
+
+
+ ))}
+
+ ) : (
+
Aucun lien entrant de type wiki [[lien]] pointant vers cette note.
+ )}
+
+
+ {/* 2. Outbound Links */}
+
+
+ Liens Sortants ({outboundLinks.length})
+
+ {outboundLinks.length > 0 ? (
+
+ {outboundLinks.map(n => (
+
onOpenNote(n.id)}
+ className="p-3 bg-white dark:bg-zinc-950 border border-border hover:border-accent/40 rounded-xl cursor-pointer transition-all space-y-1.5 hover:shadow-sm"
+ >
+
+ {n.title}
+ Vers
+
+
+ {getSnippetWithHighlight(activeNote.content, n.title)}
+
+
+ ))}
+
+ ) : (
+
Cette note ne pointe vers aucune autre note de type [[lien]].
+ )}
+
+
+ >
+ ) : (
+
+
+
Sélectionnez une note pour analyser son graphe local.
+
+ )}
+
+ )}
+
+
+
+ )}
+
+ );
+};
diff --git a/architectural-grid/src/components/NotebooksView.tsx b/architectural-grid/src/components/NotebooksView.tsx
new file mode 100644
index 0000000..a3b2a6e
--- /dev/null
+++ b/architectural-grid/src/components/NotebooksView.tsx
@@ -0,0 +1,1567 @@
+import React from 'react';
+import {
+ Plus,
+ Search,
+ Share2,
+ Pin,
+ ChevronRight,
+ ChevronUp,
+ ChevronDown,
+ ArrowLeft,
+ MoreVertical,
+ Sparkles,
+ Tag as TagIcon,
+ X,
+ BookOpen,
+ Edit3,
+ Eye,
+ Trash2,
+ Wind,
+ FileText,
+ Paperclip,
+ Loader2,
+ MessageSquare,
+ Menu,
+ Globe,
+ Link2,
+ Folder,
+ LayoutGrid,
+ List,
+ Table,
+ CheckSquare,
+ GraduationCap,
+ PanelRight
+} from 'lucide-react';
+import { motion, AnimatePresence } from 'motion/react';
+import { Note, Carnet, Tag, Attachment, Flashcard } from '../types';
+import { SlashMenu } from './SlashMenu';
+import { parseDocument } from '../services/geminiService';
+import { v4 as uuidv4 } from 'uuid';
+import { LivingBlock } from './LivingBlock';
+import { BlockPicker } from './BlockPicker';
+import { NotebookInfoSidebar } from './NotebookInfoSidebar';
+
+interface NotebooksViewProps {
+ activeNoteId: string | null;
+ activeCarnet: Carnet | undefined;
+ filteredNotes: Note[];
+ activeNote: Note | undefined;
+ setActiveNoteId: (id: string | null) => void;
+ togglePin: (id: string) => void;
+ setShowNewNoteModal: (show: boolean) => void;
+ isAISidebarOpen: boolean;
+ setIsAISidebarOpen: (open: boolean) => void;
+ selectedTagIds: string[];
+ setSelectedTagIds: (ids: string[]) => void;
+ allNotes: Note[];
+ activeCarnetId: string;
+ setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
+ onDeleteNote: (id: string) => void;
+ onBrainstormNote: (note: Note) => void;
+ onUpdateNote?: (note: Note) => void;
+ onOpenSidebar?: () => void;
+ onSearchClick?: () => void;
+ wsConnected?: boolean;
+ broadcastLivingBlockUpdate?: (sourceNoteId: string, blockIndex: number, newText: string) => void;
+ carnets?: Carnet[]; // Optional carnets list
+ flashcards?: Flashcard[];
+ onTriggerReviewDeck?: (noteId: string) => void;
+ onGenerateFlashcards?: (noteId: string) => Promise;
+ isGeneratingFlashcards?: boolean;
+}
+
+export const NotebooksView: React.FC = ({
+ activeNoteId,
+ activeCarnet,
+ filteredNotes,
+ activeNote,
+ setActiveNoteId,
+ togglePin,
+ setShowNewNoteModal,
+ isAISidebarOpen,
+ setIsAISidebarOpen,
+ selectedTagIds,
+ setSelectedTagIds,
+ allNotes,
+ activeCarnetId,
+ setShowNewCarnetModal,
+ onDeleteNote,
+ onBrainstormNote,
+ onUpdateNote,
+ onOpenSidebar,
+ onSearchClick,
+ wsConnected = true,
+ broadcastLivingBlockUpdate,
+ carnets = [],
+ flashcards = [],
+ onTriggerReviewDeck,
+ onGenerateFlashcards,
+ isGeneratingFlashcards = false
+}) => {
+ const [isTagsExpanded, setIsTagsExpanded] = React.useState(false);
+ const [tagSearchQuery, setTagSearchQuery] = React.useState('');
+ const [isEditing, setIsEditing] = React.useState(false);
+ const [isNoteInfoOpen, setIsNoteInfoOpen] = React.useState(false);
+ const [slashMenu, setSlashMenu] = React.useState<{ isOpen: boolean; top: number; left: number } | null>(null);
+ const [isAnalyzing, setIsAnalyzing] = React.useState(null);
+ const [activeDocQnA, setActiveDocQnA] = React.useState(null);
+ const [isPickerOpen, setIsPickerOpen] = React.useState(false);
+ const [prefilledBlock, setPrefilledBlock] = React.useState<{ noteId: string; blockIndex: number } | null>(null);
+
+ // Flashcards state computations
+ const noteFlashcards = React.useMemo(() => {
+ if (!activeNote || !flashcards) return [];
+ return flashcards.filter(c => c.noteId === activeNote.id);
+ }, [flashcards, activeNote]);
+
+ const nextRecallText = React.useMemo(() => {
+ if (noteFlashcards.length === 0) return '';
+ let minDate = noteFlashcards[0].nextReviewDate;
+ noteFlashcards.forEach(c => {
+ if (c.nextReviewDate < minDate) {
+ minDate = c.nextReviewDate;
+ }
+ });
+
+ const diff = new Date(minDate).getTime() - Date.now();
+ if (diff <= 0) return "Dû aujourd'hui";
+ const days = Math.ceil(diff / (24 * 60 * 60 * 1000));
+ return `dans ${days}j`;
+ }, [noteFlashcards]);
+
+ // Vue Structurée states
+ const [viewType, setViewType] = React.useState<'notes' | 'tasks'>('notes');
+ const [layoutMode, setLayoutMode] = React.useState<'grid' | 'list' | 'table'>('list');
+ const [sortColumn, setSortColumn] = React.useState<'title' | 'carnet' | 'labels' | 'tasks' | 'modified' | null>(null);
+ const [sortDirection, setSortDirection] = React.useState<'asc' | 'desc' | null>(null);
+
+ // Helper mapping french relative dates for architecture aesthetics
+ const getRelativeFrenchDate = (dateStr: string): string => {
+ if (dateStr.includes('Oct 26')) return 'il y a 2h';
+ if (dateStr.includes('Oct 27')) return 'il y a 1j';
+ if (dateStr.includes('Oct 24')) return 'il y a 3j';
+ if (dateStr.includes('Oct 25')) return 'il y a 2j';
+ if (dateStr.includes('Oct 22')) return 'il y a 5j';
+ if (dateStr.includes('Oct 23')) return 'il y a 4j';
+ if (dateStr.includes('Oct 28')) return 'il y a 10 min';
+
+ // Fallback calculation relative to May 24, 2026
+ try {
+ const d = new Date(dateStr);
+ const now = new Date("2026-05-24T07:18:49Z");
+ const diffTime = Math.abs(now.getTime() - d.getTime());
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+
+ if (diffDays <= 1) return "aujourd'hui";
+ if (diffDays <= 2) return "hier";
+ if (diffDays <= 7) return `il y a ${diffDays}j`;
+ if (diffDays <= 30) return `il y a ${Math.floor(diffDays / 7)} sem.`;
+ return `il y a ${Math.floor(diffDays / 30)} mois`;
+ } catch (e) {
+ return dateStr;
+ }
+ };
+
+ // Aesthetic deterministic carnet colors
+ const getCarnetColor = (c: Carnet) => {
+ const colors = [
+ { bg: 'bg-[#A47148]/5 dark:bg-[#A47148]/10', border: 'border-[#A47148]/20', text: 'text-[#A47148]' },
+ { bg: 'bg-emerald-500/5 dark:bg-emerald-500/10', border: 'border-emerald-500/15', text: 'text-emerald-600 dark:text-emerald-400' },
+ { bg: 'bg-indigo-500/5 dark:bg-indigo-500/10', border: 'border-indigo-500/15', text: 'text-indigo-600 dark:text-indigo-400' },
+ { bg: 'bg-blue-500/5 dark:bg-blue-500/10', border: 'border-blue-500/15', text: 'text-blue-600 dark:text-blue-400' },
+ { bg: 'bg-amber-500/5 dark:bg-amber-500/10', border: 'border-amber-500/15', text: 'text-amber-600 dark:text-amber-400' },
+ { bg: 'bg-rose-500/5 dark:bg-rose-500/10', border: 'border-rose-500/15', text: 'text-rose-600 dark:text-rose-400' },
+ ];
+
+ if (c.type === 'Private') return colors[0];
+ if (c.type === 'Shared') return colors[2];
+
+ const idx = Math.abs(c.name.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)) % colors.length;
+ return colors[idx];
+ };
+
+ // Extract tasks from markdown format: - [ ] Task name
+ const getNoteTasksStats = (content: string) => {
+ const lines = content.split('\n');
+ let total = 0;
+ let completed = 0;
+ lines.forEach(line => {
+ const match = line.match(/^\s*[-*]?\s*\[([ xX])\]\s*(.*)$/);
+ if (match) {
+ total++;
+ if (match[1].toLowerCase() === 'x') {
+ completed++;
+ }
+ }
+ });
+ return { completed, total };
+ };
+
+ interface TaskItem {
+ id: string;
+ noteId: string;
+ noteTitle: string;
+ text: string;
+ completed: boolean;
+ lineIndex: number;
+ }
+
+ const extractTasks = React.useMemo(() => {
+ const tasksList: TaskItem[] = [];
+ filteredNotes.forEach(note => {
+ const lines = note.content.split('\n');
+ lines.forEach((line, idx) => {
+ const match = line.match(/^\s*[-*]?\s*\[([ xX])\]\s*(.*)$/);
+ if (match) {
+ tasksList.push({
+ id: `${note.id}-${idx}`,
+ noteId: note.id,
+ noteTitle: note.title,
+ text: match[2].trim(),
+ completed: match[1].toLowerCase() === 'x',
+ lineIndex: idx
+ });
+ }
+ });
+ });
+ return tasksList;
+ }, [filteredNotes]);
+
+ const completedTasksCount = React.useMemo(() => {
+ return extractTasks.filter(t => t.completed).length;
+ }, [extractTasks]);
+
+ const handleToggleTask = (task: TaskItem) => {
+ const note = allNotes.find(n => n.id === task.noteId);
+ if (!note) return;
+ const lines = note.content.split('\n');
+ const line = lines[task.lineIndex];
+ if (line) {
+ const isNowCompleted = !task.completed;
+ const nextChar = isNowCompleted ? 'x' : ' ';
+ const updatedLine = line.replace(/\[([ xX])\]/, `[${nextChar}]`);
+ lines[task.lineIndex] = updatedLine;
+ const updatedNote = { ...note, content: lines.join('\n') };
+ if (onUpdateNote) {
+ onUpdateNote(updatedNote);
+ }
+ }
+ };
+
+ // Click handler to toggle sorting order
+ const handleSort = (field: 'title' | 'carnet' | 'labels' | 'tasks' | 'modified') => {
+ if (sortColumn !== field) {
+ setSortColumn(field);
+ setSortDirection('asc');
+ } else if (sortDirection === 'asc') {
+ setSortDirection('desc');
+ } else {
+ setSortColumn(null);
+ setSortDirection(null);
+ }
+ };
+
+ // Computes the sorted copy of filteredNotes
+ const sortedNotes = React.useMemo(() => {
+ if (!sortColumn || !sortDirection) return filteredNotes;
+
+ const notesCopy = [...filteredNotes];
+ return notesCopy.sort((a, b) => {
+ let valA: any = '';
+ let valB: any = '';
+
+ if (sortColumn === 'title') {
+ valA = (a.title || '').toLowerCase();
+ valB = (b.title || '').toLowerCase();
+ } else if (sortColumn === 'carnet') {
+ const parentA = carnets?.find(c => c.id === a.carnetId)?.name || '';
+ const parentB = carnets?.find(c => c.id === b.carnetId)?.name || '';
+ valA = parentA.toLowerCase();
+ valB = parentB.toLowerCase();
+ } else if (sortColumn === 'labels') {
+ valA = a.tags?.length || 0;
+ valB = b.tags?.length || 0;
+ } else if (sortColumn === 'tasks') {
+ const statsA = getNoteTasksStats(a.content);
+ const statsB = getNoteTasksStats(b.content);
+ valA = statsA.total > 0 ? (statsA.completed / statsA.total) : -1;
+ valB = statsB.total > 0 ? (statsB.completed / statsB.total) : -1;
+ } else if (sortColumn === 'modified') {
+ valA = new Date(a.date).getTime() || 0;
+ valB = new Date(b.date).getTime() || 0;
+ }
+
+ if (valA < valB) return sortDirection === 'asc' ? -1 : 1;
+ if (valA > valB) return sortDirection === 'asc' ? 1 : -1;
+ return 0;
+ });
+ }, [filteredNotes, sortColumn, sortDirection, carnets]);
+
+ const renderSortIndicator = (field: 'title' | 'carnet' | 'labels' | 'tasks' | 'modified') => {
+ if (sortColumn !== field) return null;
+ return sortDirection === 'asc' ? (
+
+ ) : (
+
+ );
+ };
+
+ const fileInputRef = React.useRef(null);
+ const titleInputRef = React.useRef(null);
+ const contentTextareaRef = React.useRef(null);
+
+ const backlinks = React.useMemo(() => {
+ if (!activeNote) return [];
+ const list: Array<{ note: Note; accessedAt: string }> = [];
+ allNotes.forEach(note => {
+ if (note.id === activeNote.id) return;
+ if (note.content.includes(`[[living-block:${activeNote.id}:`)) {
+ list.push({ note, accessedAt: "Récemment" });
+ }
+ });
+ return list;
+ }, [allNotes, activeNote]);
+
+ const memoryEchoBlock = React.useMemo(() => {
+ if (!activeNote) return null;
+ const otherNotes = allNotes.filter(n => n.id !== activeNote.id);
+ if (otherNotes.length === 0) return null;
+ let bestNote = otherNotes[0];
+ let maxOverlap = -1;
+ const currentTags = new Set(activeNote.tags?.map(t => t.id) || []);
+ otherNotes.forEach(note => {
+ const overlap = note.tags?.filter(t => currentTags.has(t.id)).length || 0;
+ if (overlap > maxOverlap) {
+ maxOverlap = overlap;
+ bestNote = note;
+ }
+ });
+ const lines = bestNote.content.split('\n').filter(line => line.trim().length > 30 && !line.startsWith('#') && !line.startsWith('[[living-block'));
+ if (lines.length === 0) return null;
+ const blockText = lines[0];
+ const blockIndex = bestNote.content.split('\n').indexOf(blockText);
+ return {
+ noteId: bestNote.id,
+ noteTitle: bestNote.title || "Note reliée",
+ text: blockText,
+ blockIndex
+ };
+ }, [activeNote, allNotes]);
+
+ const handleSelectBlock = (sourceNoteId: string, blockIndex: number) => {
+ setIsPickerOpen(false);
+ setPrefilledBlock(null);
+ if (!activeNote) return;
+
+ const blockCode = `\n[[living-block:${sourceNoteId}:${blockIndex}]]\n`;
+
+ // Insert blockCode into textarea at cursor or end of text
+ const textarea = contentTextareaRef.current;
+ if (textarea) {
+ const start = textarea.selectionStart;
+ const end = textarea.selectionEnd;
+ const originalText = textarea.value;
+ const newText = originalText.substring(0, start) + blockCode + originalText.substring(end);
+
+ const updatedNote = { ...activeNote, content: newText };
+ onUpdateNote?.(updatedNote);
+
+ // Update defaultValue/value of textarea
+ textarea.value = newText;
+ } else {
+ // Fallback: append to end of content
+ const updatedNote = {
+ ...activeNote,
+ content: activeNote.content + blockCode
+ };
+ onUpdateNote?.(updatedNote);
+ }
+ };
+
+ const handleFileUpload = async (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0];
+ if (!file || !activeNote) return;
+
+ const newAttachment: Attachment = {
+ id: uuidv4(),
+ name: file.name,
+ type: file.name.endsWith('.pdf') ? 'pdf' : (file.name.endsWith('.docx') ? 'docx' : 'other'),
+ url: URL.createObjectURL(file), // Local preview url
+ isProcessed: false
+ };
+
+ const updatedNote = {
+ ...activeNote,
+ attachments: [...(activeNote.attachments || []), newAttachment]
+ };
+
+ onUpdateNote?.(updatedNote);
+
+ // Auto-analyze
+ setIsAnalyzing(newAttachment.id);
+ const content = await parseDocument(newAttachment.url, newAttachment.name);
+
+ const processedAttachment = { ...newAttachment, content, isProcessed: true };
+ const finalNote = {
+ ...activeNote,
+ attachments: [...(activeNote.attachments || []), processedAttachment]
+ };
+ onUpdateNote?.(finalNote);
+ setIsAnalyzing(null);
+ };
+
+ const handleEditorKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === '/') {
+ const selection = window.getSelection();
+ if (selection && selection.rangeCount > 0) {
+ const range = selection.getRangeAt(0);
+ const rect = range.getBoundingClientRect();
+ setSlashMenu({
+ isOpen: true,
+ top: rect.bottom + window.scrollY,
+ left: rect.left + window.scrollX
+ });
+ }
+ }
+ };
+
+ const insertCommand = (type: string) => {
+ console.log(`Command selected: ${type}`);
+ setSlashMenu(null);
+ if (type === 'embed') {
+ setPrefilledBlock(null);
+ setIsPickerOpen(true);
+ }
+ };
+
+ const availableTags = React.useMemo(() => {
+ const carnetNotes = allNotes.filter(n => n.carnetId === activeCarnetId);
+ const tagsMap = new Map();
+ carnetNotes.forEach(note => {
+ note.tags?.forEach(tag => {
+ tagsMap.set(tag.id, tag);
+ });
+ });
+ return Array.from(tagsMap.values()).sort((a, b) => {
+ // AI tags first, then alphabetical
+ if (a.type === 'ai' && b.type !== 'ai') return -1;
+ if (a.type !== 'ai' && b.type === 'ai') return 1;
+ return a.label.localeCompare(b.label);
+ });
+ }, [allNotes, activeCarnetId]);
+
+ const visibleTags = React.useMemo(() => {
+ let filtered = availableTags;
+ if (tagSearchQuery) {
+ filtered = availableTags.filter(t =>
+ t.label.toLowerCase().includes(tagSearchQuery.toLowerCase())
+ );
+ } else if (!isTagsExpanded) {
+ filtered = availableTags.slice(0, 10);
+ // Ensure selected tags are always visible even if not in the first 10
+ selectedTagIds.forEach(id => {
+ if (!filtered.find(t => t.id === id)) {
+ const tag = availableTags.find(t => t.id === id);
+ if (tag) filtered.push(tag);
+ }
+ });
+ }
+ return filtered;
+ }, [availableTags, isTagsExpanded, tagSearchQuery, selectedTagIds]);
+
+ const toggleTag = (tagId: string) => {
+ if (selectedTagIds.includes(tagId)) {
+ setSelectedTagIds(selectedTagIds.filter(id => id !== tagId));
+ } else {
+ setSelectedTagIds([...selectedTagIds, tagId]);
+ }
+ };
+
+ if (!activeNoteId) {
+ return (
+
+
+
+
+ {viewType === 'tasks' ? (
+ // ================== FLAT TASKS LIST VIEW ==================
+
+
+
+
+
+ Ravi de vous revoir — Tâches d'Architecture
+
+
+
+ {extractTasks.length} tâches · {completedTasksCount} complétées
+
+
+
+ {extractTasks.length > 0 ? (
+
+
+ {extractTasks.map((task, idx) => (
+
+
+ handleToggleTask(task)}
+ className={`w-5 h-5 rounded-md border flex items-center justify-center transition-all cursor-pointer shrink-0
+ ${task.completed
+ ? 'bg-[#A47148] border-[#A47148] text-white'
+ : 'border-[#D5D2CD] dark:border-neutral-700 hover:border-accent bg-transparent'}`}
+ >
+ {task.completed && ✓ }
+
+
+
+ {task.text}
+
+
+
+
+
+ Note : {task.noteTitle}
+
+ setActiveNoteId(task.noteId)}
+ className="p-1.5 rounded-full hover:bg-black/5 dark:hover:bg-white/5 text-concrete hover:text-ink transition-all cursor-pointer"
+ title="Ouvrir la note source"
+ >
+
+
+
+
+ ))}
+
+
+ ) : (
+ // ================== EMPTY STATE TASKS ==================
+
+
+
+
+
Aucune tâche dans ce carnet
+
+ Ajoutez des lignes de tâches au format - [ ] Ma tâche dans vos notes pour commencer.
+
+
+ )}
+
+ ) : layoutMode === 'grid' ? (
+ // ================== CARDS/GRID VIEW ==================
+
+
+ {sortedNotes.map((note, index) => {
+ const stats = getNoteTasksStats(note.content);
+ return (
+
setActiveNoteId(note.id)}
+ className="bg-white dark:bg-[#1C1C1E]/40 border border-[#D5D2CD]/40 dark:border-neutral-800/40 rounded-2xl overflow-hidden hover:shadow-md hover:border-accent/30 transition-all duration-300 group/card cursor-pointer flex flex-col"
+ >
+ {/* Thumbnail with black white architectural look */}
+
+
+ {note.isPinned && (
+
+ )}
+ {stats.total > 0 && (
+
+ {stats.completed}/{stats.total} ✓
+
+ )}
+
+
+
+
+
+ {note.tags?.slice(0, 2).map(tag => (
+
+ {tag.type === 'ai' && }
+ {tag.label}
+
+ ))}
+
+
+
+ {note.title}
+
+
+
+ {note.content.replace(/[-*]?\s*\[([ xX])\]\s*(.*)/g, '').trim().substring(0, 110)}...
+
+
+
+
+
{note.date}
+
+
{
+ e.stopPropagation();
+ onBrainstormNote(note);
+ }}
+ className="p-1 px-2 rounded-full hover:bg-ochre/10 text-ochre transition-all flex items-center gap-1 cursor-pointer"
+ title="Brainstorm this concept"
+ >
+
+
+
{
+ e.stopPropagation();
+ togglePin(note.id);
+ }}
+ className="p-1 px-2 rounded-full hover:bg-slate-100 dark:hover:bg-white/10 text-ink transition-all cursor-pointer"
+ >
+
+
+
{
+ e.stopPropagation();
+ onDeleteNote(note.id);
+ }}
+ className="p-1 px-2 rounded-full hover:bg-rose-50 text-rose-500 transition-all cursor-pointer"
+ >
+
+
+
+
+
+
+ );
+ })}
+
+
+ {sortedNotes.length === 0 && (
+
+
This notebook is waiting for its first vision.
+
setShowNewNoteModal(true)}
+ className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all cursor-pointer"
+ >
+ Begin Drawing
+
+
+ )}
+
+ ) : layoutMode === 'table' ? (
+ // ================== STRUCTURING TABLE VIEW ==================
+
+
+
+
+
+ {/* Titre */}
+ handleSort('title')}
+ className="w-[40%] px-4 py-3 text-[10px] uppercase tracking-widest font-black text-concrete cursor-pointer hover:text-ink transition-colors"
+ >
+
+ Titre
+ {renderSortIndicator('title')}
+
+
+ {/* Carnet */}
+ handleSort('carnet')}
+ className="w-[15%] px-4 py-3 text-[10px] uppercase tracking-widest font-black text-concrete cursor-pointer hover:text-ink transition-colors"
+ >
+
+ Carnet
+ {renderSortIndicator('carnet')}
+
+
+ {/* Labels */}
+ handleSort('labels')}
+ className="w-[20%] px-4 py-3 text-[10px] uppercase tracking-widest font-black text-concrete cursor-pointer hover:text-ink transition-colors"
+ >
+
+ Labels
+ {renderSortIndicator('labels')}
+
+
+ {/* Tâches */}
+ handleSort('tasks')}
+ className="w-[12%] px-4 py-3 text-[10px] uppercase tracking-widest font-black text-concrete cursor-pointer hover:text-ink transition-colors"
+ >
+
+ Tâches
+ {renderSortIndicator('tasks')}
+
+
+ {/* Modifié */}
+ handleSort('modified')}
+ className="w-[13%] px-4 py-3 text-[10px] uppercase tracking-widest font-black text-concrete cursor-pointer hover:text-ink transition-colors"
+ >
+
+ Modifié
+ {renderSortIndicator('modified')}
+
+
+
+
+
+ {sortedNotes.map((note) => {
+ const carnet = carnets?.find(c => c.id === note.carnetId);
+ const noteColor = carnet ? getCarnetColor(carnet) : { bg: 'bg-zinc-500/5', border: 'border-zinc-500/10', text: 'text-zinc-500' };
+ const stats = getNoteTasksStats(note.content);
+
+ return (
+ setActiveNoteId(note.id)}
+ className="h-10 hover:bg-neutral-50 dark:hover:bg-white/[0.02] cursor-pointer transition-all duration-150 relative group"
+ >
+ {/* Titre */}
+
+
+ {note.isPinned &&
}
+
{note.title || "Note sans titre"}
+
+
+ {/* Carnet */}
+
+ {carnet ? (
+
+ {carnet.name}
+
+ ) : (
+ —
+ )}
+
+ {/* Labels */}
+
+
+ {note.tags?.slice(0, 3).map(tag => (
+
+ {tag.label}
+
+ ))}
+ {note.tags && note.tags.length > 3 && (
+
+ +{note.tags.length - 3}
+
+ )}
+
+
+ {/* Tâches */}
+
+ {stats.total > 0 ? (
+
+ {stats.completed}/{stats.total} ✓
+
+ ) : (
+ —
+ )}
+
+ {/* Modifié */}
+
+ {getRelativeFrenchDate(note.date)}
+
+
+ );
+ })}
+
+
+
+
+ {sortedNotes.length === 0 && (
+
+
This notebook is waiting for its first vision.
+
setShowNewNoteModal(true)}
+ className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all cursor-pointer"
+ >
+ Begin Drawing
+
+
+ )}
+
+ ) : (
+ // ================== ORIGINAL DETAILED EDITORIAL LIST VIEW ==================
+
+ {filteredNotes.map((note, index) => (
+
setActiveNoteId(note.id)}
+ >
+
+
+ {note.isPinned && }
+ {note.title}
+
+
+
{
+ e.stopPropagation();
+ onBrainstormNote(note);
+ }}
+ className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-ochre/10 text-ochre transition-all cursor-pointer"
+ title="Brainstorm this concept"
+ >
+
+
+
{
+ e.stopPropagation();
+ togglePin(note.id);
+ }}
+ className={`p-2 rounded-full transition-all cursor-pointer ${note.isPinned ? 'text-amber-600 bg-amber-50' : 'opacity-0 group-hover:opacity-60 hover:bg-slate-100 dark:hover:bg-white/10 text-ink'}`}
+ >
+
+
+
{
+ e.stopPropagation();
+ onDeleteNote(note.id);
+ }}
+ className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-rose-50 text-rose-500 transition-all cursor-pointer"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {note.tags?.map(tag => (
+
+ {tag.type === 'ai' && }
+ {tag.label}
+
+ ))}
+
+
+ {note.content}
+
+
Read more
+
+
+
+ ))}
+ {filteredNotes.length === 0 && (
+
+
This notebook is waiting for its first vision.
+
setShowNewNoteModal(true)}
+ className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all cursor-pointer"
+ >
+ Begin Drawing
+
+
+ )}
+
+ )}
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
setActiveNoteId(null)}
+ className="flex items-center gap-2 text-ink hover:opacity-60 transition-opacity"
+ title="Retour aux documents"
+ >
+
+
+
+
+
fileInputRef.current?.click()}
+ className="flex items-center gap-2 px-3 py-1.5 rounded-full border border-border text-muted-ink hover:text-ink transition-all"
+ title="Add attachment"
+ >
+
+
+
+
onBrainstormNote(activeNote!)}
+ className="p-2 rounded-full border border-ochre/30 text-ochre hover:bg-ochre/5 transition-all cursor-pointer"
+ title="Brainstorm IA"
+ >
+
+
+
onGenerateFlashcards?.(activeNote!.id)}
+ disabled={isGeneratingFlashcards}
+ className="p-2 rounded-full border border-accent/30 text-accent hover:bg-accent/5 transition-all disabled:opacity-50 cursor-pointer"
+ title={isGeneratingFlashcards ? 'Génération...' : 'Révisions & Flashcards'}
+ >
+ {isGeneratingFlashcards ? (
+
+ ) : (
+
+ )}
+
+
{
+ if (isEditing && activeNote) {
+ // Save edits
+ const updatedNote = {
+ ...activeNote,
+ title: titleInputRef.current?.value || activeNote.title,
+ content: contentTextareaRef.current?.value || activeNote.content
+ };
+ onUpdateNote?.(updatedNote);
+ }
+ setIsEditing(!isEditing);
+ }}
+ className={`p-2 rounded-full border transition-all duration-300
+ ${isEditing ? 'bg-accent text-white border-accent shadow-lg shadow-accent/20' : 'border-border text-ink hover:bg-slate-50'}`}
+ title={isEditing ? 'Visualiser' : 'Modifier'}
+ >
+ {isEditing ? : }
+
+
togglePin(activeNoteId!)}
+ className={`p-2 rounded-full transition-all ${activeNote?.isPinned ? 'text-amber-600 bg-amber-50 dark:bg-ochre/10' : 'text-muted-ink hover:text-ink'}`}
+ title={activeNote?.isPinned ? "Unpin note" : "Pin note"}
+ >
+
+
+ {/* Native simulated connection status indicator toggle */}
+
{
+ window.dispatchEvent(new CustomEvent('toggle-websocket-simulate'));
+ }}
+ className={`p-2 rounded-full transition-all shrink-0 border cursor-pointer
+ ${wsConnected
+ ? 'bg-blue-500/5 text-blue-600 border-blue-500/10 hover:bg-rose-500/10 hover:text-rose-600 hover:border-rose-500/15'
+ : 'bg-amber-500/5 text-amber-600 border-amber-500/10 hover:bg-blue-500/10 hover:text-blue-600 hover:border-blue-500/15'}`}
+ title={wsConnected ? "WebSocket : En ligne (Cliquez pour déconnecter)" : "WebSocket : Hors ligne (Cliquez pour reconnecter)"}
+ >
+
+
+
setIsAISidebarOpen(!isAISidebarOpen)}
+ className={`p-2 rounded-full border transition-all duration-300
+ ${isAISidebarOpen ? 'bg-ink text-paper border-ink' : 'border-border text-ink hover:bg-white/50 dark:hover:bg-white/5'}`}
+ title="Assistant IA"
+ >
+
+
+
+
+
+
+
+
+
setIsNoteInfoOpen(!isNoteInfoOpen)}
+ className={`p-2 rounded-full border transition-all duration-300 cursor-pointer shrink-0
+ ${isNoteInfoOpen ? 'bg-ink text-paper border-ink dark:bg-white dark:text-ink' : 'border-border text-ink hover:bg-white/50 dark:hover:bg-white/5'}`}
+ title="Informations & Versions de la note"
+ >
+
+
+
+
+
+
+
+ {slashMenu?.isOpen && (
+ insertCommand(type)}
+ onClose={() => setSlashMenu(null)}
+ />
+ )}
+
+
+ {activeNote?.isClipped && (
+
+
+
+
+
+ {activeNote.clipFavicon ? (
+
{ (e.target as any).src = 'https://www.google.com/s2/favicons?domain=google.com'; }}
+ />
+ ) : (
+
+ )}
+
+ {activeNote.clipSourceUrl}
+
+
+
+
+
+ Source web
+
+ Capturé : {activeNote.clipDate || activeNote.date}
+
+
+
+ )}
+
+
+
+ {activeCarnet?.name}
+
+ {activeNote?.date}
+ {activeNote?.isClipped && (
+ <>
+
+ Source web
+ >
+ )}
+
+
+ {isEditing ? (
+
+ ) : (
+
+ {activeNote?.title}
+
+ )}
+
+
+ {activeNote?.tags?.map(tag => (
+
+ {tag.type === 'ai' &&
}
+ {tag.label}
+ {tag.type === 'ai' && (
+
+ )}
+
+ ))}
+
+
+ {/* Flashcards alert state indicator (E) */}
+ {activeNote && noteFlashcards.length > 0 && (
+
+
+
+ {noteFlashcards.length} flashcards générées · Prochain rappel : {nextRecallText}
+
+
onTriggerReviewDeck?.(activeNote.id)}
+ className="text-accent hover:underline font-bold text-xs shrink-0 cursor-pointer"
+ >
+ Réviser maintenant
+
+
+ )}
+
+
+
+
+
+
+
+
+ {activeNote?.attachments && activeNote.attachments.length > 0 && (
+
+
Pièces jointes ({activeNote.attachments.length})
+
+ {activeNote.attachments.map(att => (
+
+
+
+
+
+
+
{att.name}
+
{att.type}
+
+
+
+ {isAnalyzing === att.id ? (
+
+ ) : (
+ setActiveDocQnA(att)}
+ className="p-2 hover:bg-accent/10 text-accent rounded-lg transition-colors opacity-0 group-hover:opacity-100"
+ title="Converser avec ce document"
+ >
+
+
+ )}
+
+
+ ))}
+
+
+ )}
+
+ {isEditing ? (
+
+ ) : (
+
+ {/* Custom block line parser */}
+
+ {activeNote?.content.split('\n').map((line, i) => {
+ const match = line.trim().match(/^\[\[living-block:([a-zA-Z0-9-]+):(\d+)\]\]$/);
+ if (match) {
+ const sourceNoteId = match[1];
+ const blockIndex = parseInt(match[2], 10);
+ return (
+
{})}
+ onOpenNote={setActiveNoteId}
+ wsConnected={wsConnected}
+ broadcastLivingBlockUpdate={broadcastLivingBlockUpdate}
+ />
+ );
+ }
+ return (
+
+ {line}
+
+ );
+ })}
+
+ {activeNote?.id.startsWith('n-') && !activeNote.content.includes('living-block') && (
+
+ Architectural grids serve as the invisible scaffolding upon which spatial experiences are constructed. Beyond mere structural repetition, they facilitate a rhythmic dialogue between materiality and void. In this exploration, we examine how light fractures these rigid boundaries, creating a dynamic interplay that evolves with the passage of time.
+
+ )}
+
+
+ {/* Memory Echo Section */}
+ {memoryEchoBlock && (
+
+
+
+
+ Memory Echo (Affinité Sémantique)
+
+
+ 92% affinité sémétrique
+
+
+
+
+ « {memoryEchoBlock.text.substring(0, 150)}... »
+
+
+
+
Passage détecté dans : {memoryEchoBlock.noteTitle}
+
+ setActiveNoteId(memoryEchoBlock.noteId)}
+ className="text-concrete hover:text-ink font-bold transition-all hover:underline"
+ >
+ Voir la connexion
+
+ {
+ setPrefilledBlock({ noteId: memoryEchoBlock.noteId, blockIndex: memoryEchoBlock.blockIndex });
+ setIsPickerOpen(true);
+ }}
+ className="flex items-center gap-1.5 text-blue-600 dark:text-blue-400 font-extrabold hover:underline"
+ >
+
+ Embedder ce passage
+
+
+
+
+ )}
+
+ {/* Backlinks panel */}
+ {backlinks.length > 0 && (
+
+
+
+
Rétroliens & Intégrations Sémantiques
+
+
+
+
Embeddé comme Living Block dans {backlinks.length} note{backlinks.length > 1 ? 's' : ''} :
+
+ {backlinks.map(({ note, accessedAt }) => (
+
setActiveNoteId(note.id)}
+ className="p-3.5 bg-white dark:bg-zinc-800/20 border border-black/[0.04] dark:border-white/[0.04] rounded-xl hover:bg-black/[0.02] dark:hover:bg-white/[0.02] hover:border-accent/20 transition-all cursor-pointer flex items-center justify-between pr-4 group"
+ >
+
+
+
+
+ {note.title || "Note sans titre"}
+
+
+ Carnet : {carnets?.find(c => c.id === note.carnetId)?.name || "Général"}
+
+
+
+
+ Accès : {accessedAt}
+
+
+ ))}
+
+
+
+ )}
+
+ )}
+
+
+
+
+ {/* Document Q&A Overlay */}
+
+ {activeDocQnA && (
+
+
+ {/* Document Preview (Mock) */}
+
+
+
+
+
+
+
{activeDocQnA.name}
+
DOCUMENT SOURCE ANALYSÉ
+
+
+
+
+ {activeDocQnA.content || "Analyse du contenu en cours..."}
+
+
+
+
+ {/* Chat Side */}
+
+
+
+
+
Expert Document
+
+
setActiveDocQnA(null)} className="p-2 hover:bg-slate-50 dark:hover:bg-white/5 rounded-full text-concrete">
+
+
+
+
+
+
+
+ Bonjour ! J'ai analysé ce document. Posez-moi n'importe quelle question sur son contenu, les chiffres clés ou les concepts abordés.
+
+
+
+
+
+
+
+
+ )}
+
+
+
setIsPickerOpen(false)}
+ currentNote={activeNote}
+ allNotes={allNotes}
+ carnets={carnets}
+ onSelectBlock={handleSelectBlock}
+ prefilledBlock={prefilledBlock}
+ />
+
+ setIsNoteInfoOpen(false)}
+ activeNote={activeNote}
+ notes={allNotes}
+ carnets={carnets}
+ onOpenNote={setActiveNoteId}
+ onUpdateNote={onUpdateNote}
+ />
+
+ );
+};
diff --git a/architectural-grid/src/components/RevisionView.tsx b/architectural-grid/src/components/RevisionView.tsx
new file mode 100644
index 0000000..6546765
--- /dev/null
+++ b/architectural-grid/src/components/RevisionView.tsx
@@ -0,0 +1,665 @@
+import React, { useState, useEffect, useMemo } from 'react';
+import { motion, AnimatePresence } from 'motion/react';
+import {
+ GraduationCap,
+ Layers,
+ ArrowLeft,
+ ChevronLeft,
+ ChevronRight,
+ RotateCcw,
+ CheckCircle2,
+ X,
+ Inbox,
+ BookOpen,
+ Calendar,
+ Sparkles,
+ Award
+} from 'lucide-react';
+import { Note, Flashcard, FlashcardDeck, FlashcardEvaluation } from '../types';
+
+interface RevisionViewProps {
+ notes: Note[];
+ flashcards: Flashcard[];
+ onUpdateFlashcards: (updated: Flashcard[]) => void;
+ onSelectNote: (noteId: string) => void;
+ onOpenSidebar?: () => void;
+ initialActiveDeckId?: string | null;
+ onClearActiveDeckId?: () => void;
+}
+
+export const RevisionView: React.FC = ({
+ notes,
+ flashcards,
+ onUpdateFlashcards,
+ onSelectNote,
+ onOpenSidebar,
+ initialActiveDeckId,
+ onClearActiveDeckId
+}) => {
+ // Active states
+ const [activeDeckId, setActiveDeckId] = useState(initialActiveDeckId || null);
+ const [isSessionActive, setIsSessionActive] = useState(false);
+ const [isSessionFinished, setIsSessionFinished] = useState(false);
+
+ // Active review states
+ const [currentCardIndex, setCurrentCardIndex] = useState(0);
+ const [isFlipped, setIsFlipped] = useState(false);
+ const [sessionCards, setSessionCards] = useState([]);
+ const [sessionHistory, setSessionHistory] = useState>({});
+ const [onlyFailedCardsSession, setOnlyFailedCardsSession] = useState(false);
+
+ // Sync initial deck selection from outer prop/reminder
+ useEffect(() => {
+ if (initialActiveDeckId) {
+ setActiveDeckId(initialActiveDeckId);
+ // Auto-trigger session
+ const deckCards = flashcards.filter(c => c.noteId === initialActiveDeckId);
+ if (deckCards.length > 0) {
+ setSessionCards([...deckCards]);
+ setCurrentCardIndex(0);
+ setIsFlipped(false);
+ setIsSessionActive(true);
+ setIsSessionFinished(false);
+ setSessionHistory({});
+ }
+ }
+ }, [initialActiveDeckId, flashcards]);
+
+ // Compute Decks based on current flashcards and notes
+ const decks = useMemo(() => {
+ const deckMap = new Map();
+ flashcards.forEach(card => {
+ if (!deckMap.has(card.noteId)) {
+ deckMap.set(card.noteId, []);
+ }
+ deckMap.get(card.noteId)!.push(card);
+ });
+
+ const list: FlashcardDeck[] = [];
+ deckMap.forEach((cardsInDeck, noteId) => {
+ const parentNote = notes.find(n => n.id === noteId);
+ if (!parentNote || parentNote.isDeleted) return;
+
+ // Find min nextReviewDate
+ let minDate = cardsInDeck[0]?.nextReviewDate || new Date().toISOString();
+ cardsInDeck.forEach(c => {
+ if (c.nextReviewDate < minDate) {
+ minDate = c.nextReviewDate;
+ }
+ });
+
+ // Mastery score: portion of mastered/sure cards in last evaluation
+ const totalCards = cardsInDeck.length;
+ let masteredCount = 0;
+ cardsInDeck.forEach(c => {
+ if (c.mastered) masteredCount++;
+ });
+
+ list.push({
+ noteId,
+ title: parentNote.title,
+ cardsCount: totalCards,
+ nextReviewDate: minDate,
+ masteryScore: totalCards > 0 ? masteredCount / totalCards : 0,
+ cards: cardsInDeck
+ });
+ });
+
+ // Sort decks: first those that need review (past nextReviewDate), then alphabetical
+ const nowStr = new Date().toISOString();
+ return list.sort((a, b) => {
+ const aNeeds = a.nextReviewDate <= nowStr;
+ const bNeeds = b.nextReviewDate <= nowStr;
+ if (aNeeds && !bNeeds) return -1;
+ if (!aNeeds && bNeeds) return 1;
+ return a.title.localeCompare(b.title);
+ });
+ }, [flashcards, notes]);
+
+ const activeDeck = useMemo(() => {
+ return decks.find(d => d.noteId === activeDeckId);
+ }, [decks, activeDeckId]);
+
+ // Launch review session for a deck
+ const handleStartReview = (noteId: string, failedOnly = false) => {
+ const deck = decks.find(d => d.noteId === noteId);
+ if (!deck) return;
+
+ let cardsToReview = [...deck.cards];
+ if (failedOnly) {
+ // Filter for cards graded as 'fail' or 'hesitant' in session history, or simply subset of session cards
+ const failedIds = Object.keys(sessionHistory).filter(id => sessionHistory[id] === 'fail');
+ cardsToReview = deck.cards.filter(c => failedIds.includes(c.id));
+ if (cardsToReview.length === 0) {
+ // Fallback to active session's rated fail
+ cardsToReview = deck.cards.filter(c => sessionHistory[c.id] === 'fail');
+ }
+ setOnlyFailedCardsSession(true);
+ } else {
+ setOnlyFailedCardsSession(false);
+ }
+
+ if (cardsToReview.length === 0) return;
+
+ // Shuffle cards for better learning cognitive effect
+ const shuffled = [...cardsToReview].sort(() => Math.random() - 0.5);
+
+ setActiveDeckId(noteId);
+ setSessionCards(shuffled);
+ setCurrentCardIndex(0);
+ setIsFlipped(false);
+ setIsSessionActive(true);
+ setIsSessionFinished(false);
+ setSessionHistory({});
+ };
+
+ const handleCardFlip = () => {
+ setIsFlipped(!isFlipped);
+ };
+
+ // Keyboard support during review
+ useEffect(() => {
+ if (!isSessionActive || isSessionFinished) return;
+
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (e.code === 'Space') {
+ e.preventDefault();
+ handleCardFlip();
+ } else if (isFlipped) {
+ if (e.key === '1') {
+ handleEvaluate('fail');
+ } else if (e.key === '2') {
+ handleEvaluate('hesitant');
+ } else if (e.key === '3') {
+ handleEvaluate('sure');
+ }
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
+ }, [isSessionActive, isSessionFinished, isFlipped, currentCardIndex, sessionCards]);
+
+ // Simple Spaced Repetition Logic (Leitner system variation)
+ const handleEvaluate = (evaluation: FlashcardEvaluation) => {
+ const currentCard = sessionCards[currentCardIndex];
+ if (!currentCard) return;
+
+ // Record evaluation in session context
+ setSessionHistory(prev => ({
+ ...prev,
+ [currentCard.id]: evaluation
+ }));
+
+ // Calculate new intervals
+ let interval = currentCard.intervalDays || 1;
+ let ease = currentCard.easeFactor || 2.5;
+ let mastered = currentCard.mastered || false;
+
+ if (evaluation === 'fail') {
+ interval = 1; // back to review tomorrow
+ ease = Math.max(1.3, ease - 0.2);
+ mastered = false;
+ } else if (evaluation === 'hesitant') {
+ interval = Math.max(2, Math.floor(interval * 1.2));
+ mastered = false;
+ } else { // sure
+ interval = Math.ceil(interval * ease);
+ ease = Math.min(3.5, ease + 0.15);
+ mastered = true;
+ }
+
+ // Calculate next review date
+ const nextDate = new Date();
+ nextDate.setDate(nextDate.getDate() + interval);
+
+ // Build historical entry
+ const historyItem = {
+ reviewedAt: new Date().toISOString(),
+ evaluation
+ };
+
+ const updatedCard: Flashcard = {
+ ...currentCard,
+ intervalDays: interval,
+ nextReviewDate: nextDate.toISOString(),
+ easeFactor: ease,
+ mastered,
+ history: [...(currentCard.history || []), historyItem]
+ };
+
+ // Propagate up to global storage
+ const updatedGlobal = flashcards.map(c => c.id === currentCard.id ? updatedCard : c);
+ onUpdateFlashcards(updatedGlobal);
+
+ // Update in-place session cards to preserve intermediate updates
+ setSessionCards(prev => prev.map((c, i) => i === currentCardIndex ? updatedCard : c));
+
+ // Progress flow
+ if (currentCardIndex < sessionCards.length - 1) {
+ setTimeout(() => {
+ setCurrentCardIndex(prev => prev + 1);
+ setIsFlipped(false);
+ }, 300);
+ } else {
+ setTimeout(() => {
+ setIsSessionFinished(true);
+ }, 300);
+ }
+ };
+
+ const handleNext = () => {
+ if (currentCardIndex < sessionCards.length - 1) {
+ setCurrentCardIndex(currentCardIndex + 1);
+ setIsFlipped(false);
+ }
+ };
+
+ const handlePrev = () => {
+ if (currentCardIndex > 0) {
+ setCurrentCardIndex(currentCardIndex - 1);
+ setIsFlipped(false);
+ }
+ };
+
+ const handleExitSession = () => {
+ setIsSessionActive(false);
+ setIsSessionFinished(false);
+ onClearActiveDeckId?.();
+ };
+
+ // Statistics summaries
+ const finishedStats = useMemo(() => {
+ if (sessionCards.length === 0) return { sureCount: 0, hesitantCount: 0, failCount: 0, percentage: 0 };
+
+ let sureCount = 0;
+ let hesitantCount = 0;
+ let failCount = 0;
+
+ sessionCards.forEach(c => {
+ const evaluation = sessionHistory[c.id];
+ if (evaluation === 'sure') sureCount++;
+ else if (evaluation === 'hesitant') hesitantCount++;
+ else if (evaluation === 'fail') failCount++;
+ });
+
+ const totalRated = Object.keys(sessionHistory).length || 1;
+ const percentage = Math.round((sureCount / totalRated) * 100);
+
+ return {
+ sureCount,
+ hesitantCount,
+ failCount,
+ percentage
+ };
+ }, [sessionCards, sessionHistory]);
+
+ const formattingDate = (isoStr: string) => {
+ const diff = new Date(isoStr).getTime() - Date.now();
+ if (diff <= 0) return 'Dû aujourd\'hui';
+ const days = Math.ceil(diff / (24 * 60 * 60 * 1000));
+ return `Dans ${days}j`;
+ };
+
+ return (
+
+
+ {/* 1. Header Toolbar */}
+
+
+ {onOpenSidebar && (
+
+
+
+ )}
+
+ {isSessionActive ? (
+
+
+ Abandonner
+
+ ) : (
+
+
+
Focal de Révision
+
+ )}
+
+
+ {isSessionActive && activeDeck && (
+
+ deck : {activeDeck.title}
+
+ )}
+
+
+ {/* 2. Main Display Area */}
+
+
+
+ {/* SCREEN A: Decks Collection list view */}
+ {!isSessionActive && (
+
+
+
Decks de Révision Active
+
+ Révisez vos connaissances de manière ciblée grâce au système d'espacement algorithmique Leitner. L’apprentissage actif commence ici.
+
+
+
+ {decks.length > 0 ? (
+
+ {decks.map(deck => {
+ const nowStr = new Date().toISOString();
+ const dueCount = deck.cards.filter(c => c.nextReviewDate <= nowStr).length;
+
+ return (
+
+
+
+
+
+ {deck.title}
+
+
+
+ {deck.cardsCount} cartes de mémoire
+
+
+
+ {/* Circular progress bar rendering */}
+
+
+
+
+
+
+ {Math.round(deck.masteryScore * 100)}%
+
+
+
+
+
+ {dueCount > 0 ? (
+
+ {dueCount} à réviser
+
+ ) : (
+
+ À jour
+
+ )}
+
+
+ Prochain : {formattingDate(deck.nextReviewDate)}
+
+
+
+
+
+ onSelectNote(deck.noteId)}
+ className="flex-1 h-9 flex items-center justify-center text-[10.5px] uppercase tracking-wider font-bold text-muted-ink hover:text-ink dark:text-dark-muted dark:hover:text-dark-ink border border-border rounded-lg bg-white/50 dark:bg-transparent hover:bg-slate-50 dark:hover:bg-white/5 transition-colors"
+ >
+ Ouvrir note
+
+ handleStartReview(deck.noteId)}
+ className="flex-1 h-9 flex items-center justify-center bg-accent text-white text-[10.5px] uppercase tracking-wider font-bold rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1.5 shadow-sm shadow-accent/10"
+ >
+
+ Réviser
+
+
+
+ );
+ })}
+
+ ) : (
+
+
+
+
+
Aucun deck de flashcards
+
+ Démarrez votre apprentissage en générant des flashcards à l'aide de l'IA directement depuis la barre d'outils de vos notes architecturales.
+
+
onSelectNote('n1')}
+ className="h-11 px-6 bg-ink dark:bg-ochre text-paper dark:text-ink rounded-xl text-xs font-bold uppercase tracking-widest hover:opacity-90 transition-all flex items-center gap-2"
+ >
+
+ Essayer sur la Note "Grid Systems"
+
+
+ )}
+
+ )}
+
+ {/* SCREEN B: Active Deck session review state */}
+ {isSessionActive && !isSessionFinished && (
+
+ {/* Header navigation bar */}
+
+
+
+ Précédent
+
+
+
+ {currentCardIndex + 1} / {sessionCards.length}
+
+
+
+ Suivant
+
+
+
+
+ {/* Centered Flashcard */}
+
+
+
+ {/* RECTO - Front */}
+
+
+ Recto : Question
+ Cliquer pour tourner
+
+
+
+
+ {sessionCards[currentCardIndex]?.question}
+
+
+
+
+ Raccourci : [Espace] pour révéler la réponse
+
+
+
+ {/* VERSO - Back */}
+
+
+ Verso : Réponse
+ Duo Mémoire
+
+
+
+
+ {sessionCards[currentCardIndex]?.answer}
+
+
+
+
+ Raccourcis : [1] Raté, [2] Hésitant, [3] Sûr
+
+
+
+
+
+
+ {/* Grading Buttons - Rendered after Verso is revealed */}
+
+
+ {isFlipped ? (
+
+ { e.stopPropagation(); handleEvaluate('fail'); }}
+ className="flex-1 flex flex-col items-center justify-center h-14 rounded-2xl border border-rust/10 bg-rust/10 font-black text-rust cursor-pointer hover:bg-rust/15 transition-all text-xs"
+ >
+ Raté
+ Touche 1
+
+
+ { e.stopPropagation(); handleEvaluate('hesitant'); }}
+ className="flex-1 flex flex-col items-center justify-center h-14 rounded-2xl border border-ochre/15 bg-ochre/10 font-black text-ochre cursor-pointer hover:bg-ochre/15 transition-all text-xs"
+ >
+ Hésitant
+ Touche 2
+
+
+ { e.stopPropagation(); handleEvaluate('sure'); }}
+ className="flex-1 flex flex-col items-center justify-center h-14 rounded-2xl border border-sage/15 bg-sage/10 font-black text-sage cursor-pointer hover:bg-sage/15 transition-all text-xs"
+ >
+ Sûr
+ Touche 3
+
+
+ ) : (
+
+ Révéler la réponse (Espace)
+
+ )}
+
+
+
+ )}
+
+ {/* SCREEN C: Finishing dashboard view with Donut Chart and actions */}
+ {isSessionFinished && (
+
+
+
+
Félicitations !
+
+ Vous venez de finir votre session de révision de la note active.
+
+
+
+ {/* Custom SVG Donut Chart showing score */}
+
+
+
+
+
+
+
+ {finishedStats.percentage}%
+
+
Sûr de soi
+
+
+
+ {/* Core Analytics parameters (Stats) */}
+
+
+
{sessionCards.length}
+
Révisées
+
+
+
{finishedStats.failCount}
+
À revoir
+
+
+
{finishedStats.sureCount}
+
Maîtrisées
+
+
+
+
+
+ Retour aux decks
+
+ {finishedStats.failCount > 0 && (
+ handleStartReview(activeDeckId!, true)}
+ className="flex-1 h-11 bg-[#8F4C38] text-white rounded-xl text-xs font-bold uppercase tracking-widest hover:bg-[#8F4C38]/95 transition-all flex items-center justify-center gap-1.5 shadow-sm cursor-pointer"
+ >
+
+ Ré-réviser les ratées
+
+ )}
+
+
+ )}
+
+
+
+
+
+ );
+};
diff --git a/architectural-grid/src/components/SearchModal.tsx b/architectural-grid/src/components/SearchModal.tsx
new file mode 100644
index 0000000..cb5b79c
--- /dev/null
+++ b/architectural-grid/src/components/SearchModal.tsx
@@ -0,0 +1,611 @@
+import React, { useState, useEffect, useMemo, useRef } from 'react';
+import { motion, AnimatePresence } from 'motion/react';
+import {
+ Search,
+ ChevronLeft,
+ ChevronRight,
+ Plus,
+ Bookmark,
+ Layers,
+ FileText,
+ CheckCircle,
+ HelpCircle,
+ X,
+ CornerDownRight,
+ Folder,
+ Sliders,
+ Sparkles,
+ Command,
+ Settings
+} from 'lucide-react';
+import { Note, Carnet } from '../types';
+
+interface SearchModalProps {
+ isOpen: boolean;
+ onClose: () => void;
+ notes: Note[];
+ carnets: Carnet[];
+ onSelectNote: (noteId: string) => void;
+}
+
+interface SearchMatch {
+ id: string; // Unique match identifier
+ noteId: string;
+ noteTitle: string;
+ path: string;
+ type: 'document' | 'heading' | 'paragraph' | 'list';
+ headingLevel?: number;
+ text: string;
+ matchedText: string;
+ lineIndex: number;
+}
+
+export const SearchModal: React.FC = ({
+ isOpen,
+ onClose,
+ notes,
+ carnets,
+ onSelectNote
+}) => {
+ const [query, setQuery] = useState('');
+ const [useRegex, setUseRegex] = useState(false);
+ const [caseSensitive, setCaseSensitive] = useState(false);
+ const [includeChildDocs, setIncludeChildDocs] = useState(true);
+ const [searchInTrash, setSearchInTrash] = useState(false);
+ const [savedQueries, setSavedQueries] = useState(['block', 'siyuan', 'guide']);
+
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const inputRef = useRef(null);
+ const listRef = useRef(null);
+
+ // Focus input on launch
+ useEffect(() => {
+ if (isOpen) {
+ setTimeout(() => inputRef.current?.focus(), 50);
+ }
+ }, [isOpen]);
+
+ // Handle global keybindings in modal
+ useEffect(() => {
+ if (!isOpen) return;
+
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (e.key === 'Escape') {
+ e.preventDefault();
+ onClose();
+ } else if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ setSelectedIndex(prev => Math.min(prev + 1, filteredMatches.length - 1));
+ } else if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ setSelectedIndex(prev => Math.max(prev - 1, 0));
+ } else if (e.key === 'Enter') {
+ e.preventDefault();
+ if (filteredMatches[selectedIndex]) {
+ const m = filteredMatches[selectedIndex];
+ onSelectNote(m.noteId);
+ onClose();
+ }
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
+ }, [isOpen, selectedIndex]);
+
+ // Helper: reconstruct carnet path
+ const getCarnetPath = (carnetId: string): string => {
+ const segments: string[] = [];
+ let current = carnets.find(c => c.id === carnetId);
+ while (current) {
+ segments.unshift(current.name);
+ current = current.parentId ? carnets.find(c => c.id === current.parentId) : undefined;
+ }
+ return segments.join('/');
+ };
+
+ // Safe term escape for RegExp
+ const escapeRegExp = (string: string) => {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ };
+
+ // Perform multi-match search logic across document titles and contents
+ const filteredMatches = useMemo(() => {
+ if (!query.trim()) return [];
+
+ const matches: SearchMatch[] = [];
+ const searchRegex = (() => {
+ try {
+ const flag = caseSensitive ? '' : 'i';
+ const pattern = useRegex ? query : escapeRegExp(query);
+ return new RegExp(pattern, flag);
+ } catch (e) {
+ return null; // Handle partial regex input gracefully
+ }
+ })();
+
+ if (!searchRegex) return [];
+
+ // Filter notes depending on trash status
+ const targetNotes = notes.filter(n => searchInTrash ? n.isDeleted : !n.isDeleted);
+
+ targetNotes.forEach(note => {
+ const notePath = getCarnetPath(note.carnetId);
+ const fullPath = notePath ? `${notePath}/${note.title}` : note.title;
+
+ // 1. Check Title match
+ if (searchRegex.test(note.title)) {
+ matches.push({
+ id: `${note.id}-title`,
+ noteId: note.id,
+ noteTitle: note.title,
+ path: fullPath,
+ type: 'document',
+ text: note.title,
+ matchedText: note.title,
+ lineIndex: -1
+ });
+ }
+
+ // 2. Parse Content blocks / lines
+ if (note.content) {
+ const lines = note.content.split('\n');
+ lines.forEach((line, index) => {
+ const trimmed = line.trim();
+ if (!trimmed) return;
+
+ if (searchRegex.test(trimmed)) {
+ let type: 'heading' | 'paragraph' | 'list' = 'paragraph';
+ let headingLevel = undefined;
+ let displayVal = trimmed;
+
+ // Classify content structure elements
+ if (trimmed.startsWith('#')) {
+ type = 'heading';
+ const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
+ if (headingMatch) {
+ headingLevel = headingMatch[1].length;
+ displayVal = headingMatch[2];
+ }
+ } else if (/^[-*+]\s+/.test(trimmed) || /^\d+\.\s+/.test(trimmed)) {
+ type = 'list';
+ displayVal = trimmed.replace(/^[-*+\d.]+\s+/, '');
+ }
+
+ matches.push({
+ id: `${note.id}-line-${index}`,
+ noteId: note.id,
+ noteTitle: note.title,
+ path: fullPath,
+ type,
+ headingLevel,
+ text: trimmed,
+ matchedText: displayVal,
+ lineIndex: index
+ });
+ }
+ });
+ }
+ });
+
+ return matches;
+ }, [notes, query, useRegex, caseSensitive, searchInTrash, carnets]);
+
+ // Ensure index remains in bounds when matches array updates
+ useEffect(() => {
+ setSelectedIndex(0);
+ }, [query]);
+
+ // Toggle saving criteria
+ const handleSaveCriteria = () => {
+ if (query.trim() && !savedQueries.includes(query.trim())) {
+ setSavedQueries(prev => [...prev, query.trim()]);
+ }
+ };
+
+ const handleRemoveCriteria = () => {
+ setSavedQueries(prev => prev.filter(q => q !== query.trim()));
+ };
+
+ // Count distinct notes involved in match list
+ const docMatchesCount = useMemo(() => {
+ const uniqueNoteIds = new Set(filteredMatches.map(m => m.noteId));
+ return uniqueNoteIds.size;
+ }, [filteredMatches]);
+
+ const activeMatch = filteredMatches[selectedIndex];
+
+ // Dynamically load document content with visual query highlights
+ const highlightedNotePreviewContent = useMemo(() => {
+ if (!activeMatch) return null;
+ const currentNote = notes.find(n => n.id === activeMatch.noteId);
+ if (!currentNote) return null;
+
+ if (!query.trim()) return currentNote.content;
+
+ try {
+ const flag = caseSensitive ? 'g' : 'gi';
+ const searchPattern = useRegex ? query : escapeRegExp(query);
+ const highlightRegex = new RegExp(`(${searchPattern})`, flag);
+
+ // Return content split by line to let us format block matches neatly
+ const lines = (currentNote.content || '').split('\n');
+
+ // Let's frame the match around the matched line for contextual proximity
+ const targetIndex = activeMatch.lineIndex >= 0 ? activeMatch.lineIndex : 0;
+ const startLine = Math.max(0, targetIndex - 3);
+ const endLine = Math.min(lines.length - 1, targetIndex + 5);
+
+ return (
+
+ {startLine > 0 && (
+
...
+ )}
+ {lines.slice(startLine, endLine + 1).map((line, idx) => {
+ const absoluteIdx = startLine + idx;
+ const isMatchLine = absoluteIdx === targetIndex;
+ const hasMatches = highlightRegex.test(line);
+
+ // Reconstruct highlighted segments
+ const segments = line.split(highlightRegex);
+
+ return (
+
+
+ {absoluteIdx + 1}
+
+
+
+ {hasMatches ? (
+ segments.map((seg, sIdx) => {
+ const matchesPattern = highlightRegex.test(seg);
+ return matchesPattern ? (
+
+ {seg}
+
+ ) : (
+ seg
+ );
+ })
+ ) : (
+ line
+ )}
+
+
+ );
+ })}
+ {endLine < lines.length - 1 && (
+
...
+ )}
+
+ );
+ } catch (e) {
+ return {currentNote.content}
;
+ }
+ }, [activeMatch, notes, query, useRegex, caseSensitive]);
+
+ // Render text segment highlight in results row items
+ const renderHighlightedRowText = (text: string) => {
+ if (!query.trim()) return text;
+ try {
+ const flag = caseSensitive ? 'gi' : 'gi';
+ const searchPattern = useRegex ? query : escapeRegExp(query);
+ const highlightRegex = new RegExp(`(${searchPattern})`, flag);
+ const segments = text.split(highlightRegex);
+
+ return (
+
+ {segments.map((seg, sIdx) => {
+ const isMatch = highlightRegex.test(seg);
+ return isMatch ? (
+
+ {seg}
+
+ ) : (
+ seg
+ );
+ })}
+
+ );
+ } catch (e) {
+ return text;
+ }
+ };
+
+ if (!isOpen) return null;
+
+ return (
+
+
+ {/* TOP Advanced Search Bar Row */}
+
+
+
+
+
setQuery(e.target.value)}
+ placeholder="Rechercher des documents ou des blocs de texte..."
+ className="w-full text-sm pl-10 pr-24 py-2.5 rounded-xl border border-border/70 dark:border-zinc-800/80 bg-white/85 dark:bg-[#1C1C1C] text-ink dark:text-dark-ink placeholder-concrete/50 outline-none focus:border-accent"
+ />
+
+ {/* Config Quick Badges */}
+
+ setCaseSensitive(!caseSensitive)}
+ className={`px-1.5 py-1 text-[9.5px] font-bold rounded-md hover:bg-black/5 dark:hover:bg-white/5 uppercase select-none transition-colors
+ ${caseSensitive ? 'text-accent bg-accent/5' : 'text-concrete'}`}
+ title="Respecter la casse (Aa)"
+ >
+ Aa
+
+ setUseRegex(!useRegex)}
+ className={`px-1.5 py-1 text-[9.5px] font-bold rounded-md hover:bg-black/5 dark:hover:bg-white/5 uppercase select-none transition-colors
+ ${useRegex ? 'text-accent bg-accent/5' : 'text-concrete'}`}
+ title="Activer Regex (.*)"
+ >
+ .*
+
+
+
+
+
+
+
+ {/* Quick saved criteria filter tags */}
+ {savedQueries.length > 0 && (
+
+
Favoris:
+
+ {savedQueries.map(sq => (
+ setQuery(sq)}
+ className={`px-2 py-0.5 rounded-md border text-[9.5px] font-medium transition-all hover:border-accent
+ ${query === sq
+ ? 'bg-accent/10 border-accent text-accent'
+ : 'bg-white dark:bg-zinc-800 border-border/40 text-muted-ink'}`}
+ >
+ {sq}
+
+ ))}
+
+
+ )}
+
+
+ {/* UTILITY BAR Row -> Match statistics with action links */}
+
+
+ {/* Arrow Switchers */}
+
+ setSelectedIndex(prev => Math.max(0, prev - 1))}
+ className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded text-concrete disabled:opacity-40"
+ >
+
+
+
+ {filteredMatches.length > 0 ? `${selectedIndex + 1}/${filteredMatches.length}` : '0/0'}
+
+ setSelectedIndex(prev => Math.min(filteredMatches.length - 1, prev + 1))}
+ className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded text-concrete disabled:opacity-40"
+ >
+
+
+
+
+
+ {filteredMatches.length > 0
+ ? `Trouvé ${filteredMatches.length} occurrences dans ${docMatchesCount} documents`
+ : query.trim() ? "Aucun élément ne correspond" : "Saisissez votre requête"}
+
+
+
+ {/* Toolbar Action Links */}
+
+ {query.trim() && (
+
+ {savedQueries.includes(query.trim()) ? 'Supprimer favori' : 'Sauvegarder recherche'}
+
+ )}
+
+
+ setIncludeChildDocs(e.target.checked)}
+ className="rounded border-border/60 text-accent focus:ring-accent w-3 h-3"
+ />
+ Sous-docs inclus
+
+
+
+ setSearchInTrash(e.target.checked)}
+ className="rounded border-border/60 text-accent focus:ring-accent w-3 h-3"
+ />
+ Corbeille incluse
+
+
+
+
+ {/* DUAL SECTION LAYOUT */}
+
+
+ {/* Left Section: Scrollable matches list */}
+
+
+ {filteredMatches.map((m, idx) => {
+ const isSelected = idx === selectedIndex;
+ return (
+
setSelectedIndex(idx)}
+ onDoubleClick={() => {
+ onSelectNote(m.noteId);
+ onClose();
+ }}
+ className={`p-2.5 rounded-xl cursor-pointer text-left select-none relative group/item transition-all flex flex-col gap-1 border
+ ${isSelected
+ ? 'bg-white dark:bg-zinc-800 shadow-md border-amber-500/30'
+ : 'border-transparent hover:bg-black/[0.02] dark:hover:bg-white/[0.02]/30'}`}
+ >
+ {/* Selection overlay accent */}
+ {isSelected && (
+
+ )}
+
+
+
+ {/* Element classifier badges */}
+ {m.type === 'document' && (
+
+ )}
+ {m.type === 'heading' && (
+
+ H{m.headingLevel || ''}
+
+ )}
+ {m.type === 'list' && (
+
+ LIST
+
+ )}
+ {m.type === 'paragraph' && (
+
+ TXT
+
+ )}
+
+
+ {m.noteTitle}
+
+
+
+
+ {/* Highlighted snippet row content */}
+
+ {renderHighlightedRowText(m.matchedText)}
+
+
+ {/* Breadcrumb row path */}
+
+ {m.path}
+
+
+ );
+ })}
+
+ {filteredMatches.length === 0 && (
+
+
+
+ {query.trim() ? "Aucun bloc ou doc ne correspond à cette recherche." : "Taper pour obtenir des résultats instantanés."}
+
+
+ )}
+
+
+
+ {/* Right Section: Scrollable content preview card with visual highlighted markers */}
+
+ {activeMatch ? (
+
+
+ {/* Breadcrumb locator line */}
+
+
+
+ {activeMatch.path}
+
+
+
+ {/* Document focus heading title */}
+
+
+ {activeMatch.noteTitle}
+
+
APERÇU CONTEXTUEL DU BLOC
+
+
+ {/* Dynamic document contents highlighted and framed */}
+
+ {highlightedNotePreviewContent}
+
+
+
+ {/* Quick Actions trigger buttons */}
+
+ {
+ onSelectNote(activeMatch.noteId);
+ onClose();
+ }}
+ className="px-5 py-2.5 bg-ink text-white dark:bg-white dark:text-black hover:scale-102 active:scale-98 text-xs font-semibold rounded-xl flex items-center gap-2 transition-all shadow-sm"
+ >
+
+ Ouvrir dans l'éditeur
+
+
+ ID: {activeMatch.noteId.slice(0, 6)}...
+
+
+
+ ) : (
+
+
+
+
Aperçu du document
+
Sélectionnez un résultat de recherche de la colonne et explorez immédiatement son contenu sémantique.
+
+
+ )}
+
+
+
+
+ {/* BOTTOM Status Keyboard shortcuts hint footer bar */}
+
+
+ ↑↓ naviguer
+ Entrée ouvrir
+ Double clic ouvrir
+ Échap fermer
+
+
+
+
+ Momento Search OS v2.3
+
+
+
+
+ );
+};
diff --git a/architectural-grid_landing/src/components/SettingsView.tsx b/architectural-grid/src/components/SettingsView.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/SettingsView.tsx
rename to architectural-grid/src/components/SettingsView.tsx
diff --git a/architectural-grid/src/components/Sidebar.tsx b/architectural-grid/src/components/Sidebar.tsx
new file mode 100644
index 0000000..a4a86a7
--- /dev/null
+++ b/architectural-grid/src/components/Sidebar.tsx
@@ -0,0 +1,875 @@
+import React from 'react';
+import {
+ Plus,
+ Archive,
+ Settings,
+ ChevronRight,
+ BookOpen,
+ Bot,
+ Microscope,
+ Activity,
+ Pin,
+ Moon,
+ Sun,
+ Bell,
+ Lock,
+ Edit3,
+ Trash2,
+ Users,
+ Clock,
+ GripVertical,
+ Wind,
+ Network,
+ Home,
+ Sparkles,
+ LogOut,
+ ChevronDown,
+ Folder,
+ FolderOpen,
+ FileText,
+ Search,
+ BookMarked,
+ User,
+ ExternalLink,
+ ChevronUp,
+ HelpCircle,
+ EyeOff,
+ Layers,
+ Scissors,
+ Chrome,
+ Crown,
+ ArrowRight,
+ GraduationCap
+} from 'lucide-react';
+import { motion, AnimatePresence } from 'motion/react';
+import { NavigationView, Carnet, Note, SettingsTab, Flashcard } from '../types';
+
+interface NoteLinkProps {
+ note: Note;
+ isActive: boolean;
+ onClick: () => void;
+}
+
+const NoteLink: React.FC = ({ note, isActive, onClick }) => (
+
+
+
+ {note.title || "Note sans titre"}
+
+ {note.isPinned && }
+
+);
+
+interface SidebarItemProps {
+ carnet: Carnet;
+ isActive: boolean;
+ notes: Note[];
+ activeNoteId: string | null;
+ onCarnetClick: () => void;
+ onNoteClick: (noteId: string) => void;
+ onAddSubCarnet: () => void;
+ onRename: () => void;
+ onDelete: () => void;
+ children?: React.ReactNode;
+ level: number;
+ isExpanded: boolean;
+ toggleExpand: () => void;
+ onMove?: (draggedId: string, targetId?: string) => void;
+}
+
+const SidebarItem: React.FC = ({
+ carnet,
+ isActive,
+ notes,
+ activeNoteId,
+ onCarnetClick,
+ onNoteClick,
+ onAddSubCarnet,
+ onRename,
+ onDelete,
+ children,
+ level,
+ isExpanded,
+ toggleExpand,
+ onMove
+}) => {
+ const hasChildren = React.Children.count(children) > 0 || notes.length > 0;
+
+ return (
+
+
+ {/* Subtle Drag Handle */}
+
+
+
+
+ {/* Hierarchy Guide Line */}
+ {level > 0 && (
+
+ )}
+ {level > 0 && (
+
+ )}
+
+
+ {hasChildren ? (
+
{
+ e.stopPropagation();
+ toggleExpand();
+ }}
+ className="p-0.5 hover:bg-ink/5 dark:hover:bg-white/5 rounded transition-colors text-concrete"
+ >
+
+
+
+
+ ) : (
+
// Spacer for alignment
+ )}
+
+
{
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ e.currentTarget.classList.add('bg-accent/5', 'ring-1', 'ring-accent/20');
+ }}
+ onDragLeave={(e) => {
+ e.currentTarget.classList.remove('bg-accent/5', 'ring-1', 'ring-accent/20');
+ }}
+ onDrop={(e) => {
+ e.preventDefault();
+ e.currentTarget.classList.remove('bg-accent/5', 'ring-1', 'ring-accent/20');
+ const draggedId = e.dataTransfer.getData('carnetId');
+ if (draggedId && draggedId !== carnet.id) {
+ onMove?.(draggedId, carnet.id);
+ }
+ }}
+ draggable
+ onDragStart={(e) => {
+ e.dataTransfer.setData('carnetId', carnet.id);
+ e.dataTransfer.effectAllowed = 'move';
+ const ghost = e.currentTarget.cloneNode(true) as HTMLElement;
+ ghost.style.position = 'absolute';
+ ghost.style.top = '-1000px';
+ ghost.style.opacity = '0.5';
+ document.body.appendChild(ghost);
+ e.dataTransfer.setDragImage(ghost, 0, 0);
+ setTimeout(() => document.body.removeChild(ghost), 0);
+ }}
+ >
+ {isActive && (
+
+ )}
+
+
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {carnet.name}
+
+ {carnet.isPrivate && }
+
+
+
+
{
+ e.stopPropagation();
+ onAddSubCarnet();
+ }}
+ className="p-0.5 hover:bg-ink/10 dark:hover:bg-white/10 rounded transition-all text-concrete hover:text-ink"
+ title="Ajouter un sous-carnet"
+ >
+
+
+
{
+ e.stopPropagation();
+ onRename();
+ }}
+ className="p-0.5 hover:bg-ink/10 dark:hover:bg-white/10 rounded transition-all text-concrete hover:text-ink"
+ title="Renommer"
+ >
+
+
+
{
+ e.stopPropagation();
+ onDelete();
+ }}
+ className="p-0.5 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-all text-concrete hover:text-red-500"
+ title="Supprimer"
+ >
+
+
+
+ {notes.length > 0 && (
+
+ {notes.length}
+
+ )}
+
+
+
+
+
+
+ {isExpanded && (
+
+
+ {/* Vertical line for nested content path */}
+
+
+
+ {children}
+ {notes.map(note => (
+
onNoteClick(note.id)}
+ />
+ ))}
+ {notes.length === 0 && !React.Children.count(children) && (
+
+ Vide
+
+ )}
+
+
+
+ )}
+
+
+ );
+};
+
+interface SidebarProps {
+ activeView: NavigationView;
+ isSidebarOpen: boolean;
+ setIsSidebarOpen: (val: boolean) => void;
+ isDarkMode: boolean;
+ setIsDarkMode: (val: boolean) => void;
+ setActiveView: (view: NavigationView) => void;
+ setActiveSettingsTab?: (tab: SettingsTab) => void;
+ carnets: Carnet[];
+ notes: Note[];
+ activeCarnetId: string;
+ activeNoteId: string | null;
+ setActiveCarnetId: (id: string) => void;
+ setActiveNoteId: (id: string | null) => void;
+ setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
+ onDeleteCarnet: (id: string) => void;
+ onMoveCarnet: (draggedId: string, targetId?: string) => void;
+ onGoHome: () => void;
+ onLogout: () => void;
+ flashcards?: Flashcard[];
+ onSelectReviewDeck?: (noteId: string) => void;
+}
+
+export const Sidebar: React.FC = ({
+ activeView,
+ isSidebarOpen,
+ setIsSidebarOpen,
+ isDarkMode,
+ setIsDarkMode,
+ setActiveView,
+ setActiveSettingsTab,
+ carnets,
+ notes,
+ activeCarnetId,
+ activeNoteId,
+ setActiveCarnetId,
+ setActiveNoteId,
+ setShowNewCarnetModal,
+ onDeleteCarnet,
+ onMoveCarnet,
+ onGoHome,
+ onLogout,
+ flashcards,
+ onSelectReviewDeck
+}) => {
+ const [expandedIds, setExpandedIds] = React.useState>(new Set(['4', '1', '2', '3'])); // Default expand key guides
+ const [collapsedSections, setCollapsedSections] = React.useState>(new Set());
+ const [searchQuery, setSearchQuery] = React.useState('');
+
+ const toggleSection = (id: string) => {
+ const newSet = new Set(collapsedSections);
+ if (newSet.has(id)) newSet.delete(id);
+ else newSet.add(id);
+ setCollapsedSections(newSet);
+ };
+
+ const toggleExpand = (id: string) => {
+ const newSet = new Set(expandedIds);
+ if (newSet.has(id)) newSet.delete(id);
+ else newSet.add(id);
+ setExpandedIds(newSet);
+ };
+
+ // Safe filtration based on searches
+ const filteredCarnets = React.useMemo(() => {
+ if (!searchQuery) return carnets;
+ const q = searchQuery.toLowerCase();
+ return carnets.filter(c =>
+ c.name.toLowerCase().includes(q) ||
+ notes.some(n => n.carnetId === c.id && n.title.toLowerCase().includes(q))
+ );
+ }, [carnets, searchQuery, notes]);
+
+ const activeNote = React.useMemo(() => {
+ if (!activeNoteId) return null;
+ return notes.find(n => n.id === activeNoteId);
+ }, [notes, activeNoteId]);
+
+ // Extract outline markdown headings dynamically for the currently active note
+ const headings = React.useMemo(() => {
+ if (!activeNote || !activeNote.content) return [];
+ const lines = activeNote.content.split('\n');
+ const hs: { text: string; level: number }[] = [];
+ lines.forEach(line => {
+ const trimmed = line.trim();
+ const hMatch = trimmed.match(/^(#{1,6})\s+(.+)$/);
+ if (hMatch) {
+ hs.push({
+ level: hMatch[1].length,
+ text: hMatch[2].replace(/\[.*?\]\(.*?\)/g, '').replace(/[*_`]/g, '').trim()
+ });
+ }
+ });
+ return hs.slice(0, 10);
+ }, [activeNote]);
+
+ const renderCarnetTree = (parentId: string | undefined = undefined, level: number = 0) => {
+ return filteredCarnets
+ .filter(c => c.parentId === parentId && !c.isDeleted)
+ .map(carnet => {
+ const carnetNotes = notes.filter(n => n.carnetId === carnet.id && !n.isDeleted);
+ return (
+ toggleExpand(carnet.id)}
+ onAddSubCarnet={() => {
+ if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
+ setShowNewCarnetModal(true, carnet.id);
+ }}
+ onRename={() => {
+ setShowNewCarnetModal(true, undefined, true, carnet.id);
+ }}
+ onDelete={() => {
+ onDeleteCarnet(carnet.id);
+ }}
+ onCarnetClick={() => {
+ setActiveCarnetId(carnet.id);
+ setActiveNoteId(null);
+ // Auto expand when clicking
+ if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
+ }}
+ onNoteClick={(id) => {
+ setActiveCarnetId(carnet.id);
+ setActiveNoteId(id);
+ }}
+ onMove={onMoveCarnet}
+ >
+ {renderCarnetTree(carnet.id, level + 1)}
+
+ );
+ });
+ };
+
+ return (
+ <>
+
+ {isSidebarOpen && (
+ setIsSidebarOpen(false)}
+ className="fixed inset-0 bg-black/40 backdrop-blur-sm z-[60] lg:hidden"
+ />
+ )}
+
+
+
+
+ {/* Column 1: Ultra Narrow Left Utility Active-Rail Bar -> Identical to Ribbon in SiYuan */}
+
+ {/* Top Stack: Logo & View Shortcuts */}
+
+ {/* Visual SiYuan branding card */}
+
{ onGoHome(); setIsSidebarOpen(false); }}
+ className="w-9 h-9 bg-accent hover:rotate-6 active:scale-95 flex items-center justify-center rounded-xl shadow-md transition-all cursor-pointer mb-2"
+ title="Aller à la page d'accueil"
+ >
+ M
+
+
+ {/* Tab items list */}
+
+ {[
+ { id: 'notebooks', label: 'Feuilles / Docs', icon:
},
+ { id: 'graph', label: 'Knowledge Map', icon:
},
+ { id: 'revision', label: 'Révisions / Decks', icon:
},
+ { id: 'agents', label: 'Agents IA Lab', icon:
},
+ { id: 'reminders', label: 'Rappels & Alertes', icon:
},
+ ].map(item => {
+ const isSel = activeView === item.id || (item.id === 'agents' && ['brainstorm', 'insights', 'temporal'].includes(activeView));
+ return (
+
{
+ setActiveView(item.id as any);
+ }}
+ className={`w-9 h-9 rounded-lg flex items-center justify-center transition-all relative group
+ ${isSel
+ ? 'bg-accent/10 text-accent border border-accent/25'
+ : 'text-concrete hover:text-ink dark:hover:text-dark-ink hover:bg-black/[0.03] dark:hover:bg-white/[0.03]'}`}
+ >
+ {/* Visual status pin */}
+ {isSel && (
+
+ )}
+ {item.icon}
+
+ {/* Tooltip */}
+
+ {item.label}
+
+
+ );
+ })}
+
+
+
+ {/* Bottom Stack: Trash, Light Mode, Settings, Logout */}
+
+ {/* TRASH DISCIPLINE: Promoted directly on the sidebar utility ribbon for quick accessible storage management */}
+
{
+ setActiveView('trash');
+ }}
+ className={`w-9 h-9 rounded-lg flex items-center justify-center transition-all relative group
+ ${activeView === 'trash'
+ ? 'bg-rose-500/10 text-rose-500 border border-rose-500/25'
+ : 'text-concrete hover:text-rose-500 hover:bg-rose-500/5'}`}
+ >
+ {activeView === 'trash' && (
+
+ )}
+
+ {notes.some(n => n.isDeleted) && (
+
+ )}
+
+ Corbeille / Corbeille vide
+
+
+
+ {/* Shared */}
+
{
+ setActiveView('shared');
+ }}
+ className={`w-9 h-9 rounded-lg flex items-center justify-center transition-all relative group
+ ${activeView === 'shared'
+ ? 'bg-[#E3EBFB] text-sky-600 dark:bg-white/10 dark:text-sky-400'
+ : 'text-concrete hover:text-sky-500 hover:bg-sky-500/5'}`}
+ >
+ {activeView === 'shared' && (
+
+ )}
+
+
+ Partagé
+
+
+
+ {/* Web Clipper Simulator Trigger */}
+
{
+ window.dispatchEvent(new CustomEvent('toggle-clipper-simulator'));
+ }}
+ className="w-9 h-9 rounded-lg flex items-center justify-center text-concrete hover:text-cyan-500 hover:bg-cyan-500/5 transition-all relative group"
+ >
+
+
+ Clipper Simulé
+
+
+
+ {/* Appearance Theme Switcher */}
+
setIsDarkMode(!isDarkMode)}
+ className="w-9 h-9 rounded-lg flex items-center justify-center text-concrete hover:text-ink dark:hover:text-dark-ink hover:bg-black/[0.03] dark:hover:bg-white/[0.03] transition-all relative group"
+ >
+ {isDarkMode ? : }
+
+ {isDarkMode ? "Mode clair" : "Mode sombre"}
+
+
+
+ {/* Settings Panel */}
+
{
+ setActiveView('settings');
+ setActiveSettingsTab?.('general');
+ }}
+ className={`w-9 h-9 rounded-lg flex items-center justify-center transition-all relative group
+ ${activeView === 'settings'
+ ? 'bg-accent/10 text-accent border border-accent/25'
+ : 'text-concrete hover:text-ink dark:text-concrete hover:bg-black/[0.03] dark:hover:bg-white/[0.03]'}`}
+ >
+
+
+ Paramètres
+
+
+
+ {/* Logout button */}
+
+
+
+ Déconnexion
+
+
+
+
+
+ {/* Column 2: Large details zone (266px width) for list details - Dynamic depending on Ribbon view */}
+
+
+ {/* Render notebook list detail content */}
+ {activeView === 'notebooks' && (
+
+ {/* Header */}
+
+
+
+
Documents
+
+
setShowNewCarnetModal(true)}
+ className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded transition-all text-concrete hover:text-ink"
+ title="Nouveau carnet parent"
+ >
+
+
+
+
+ {/* Simple search bar as seen in standard file trees */}
+
+ setSearchQuery(e.target.value)}
+ placeholder="Rechercher doc..."
+ className="w-full text-[11px] pl-7 pr-3 py-1.5 rounded-lg border border-border/60 bg-white/70 dark:bg-zinc-800 placeholder-concrete/50 outline-none focus:border-accent transition-colors text-ink dark:text-dark-ink"
+ />
+
+ {searchQuery && (
+ setSearchQuery('')}
+ className="absolute right-2.5 top-1/2 -translate-y-1/2 text-[9px] uppercase font-bold text-concrete hover:text-ink"
+ >
+ X
+
+ )}
+
+
+ {/* Hierarchical list of documents */}
+
+
+ {renderCarnetTree()}
+
+
+
+ {/* IA Usage & Upgrade Section */}
+
+
+
+
+
+ Utilisation de l'IA
+
+ 49 / 50 restants
+
+
+
+
+
{
+ setActiveView('settings');
+ setActiveSettingsTab?.('billing');
+ }}
+ className="w-full h-[28px] mt-1 flex items-center justify-between px-2.5 bg-accent/5 hover:bg-accent/10 hover:text-accent border border-accent/10 hover:border-accent/20 rounded-lg text-[10px] font-bold text-accent transition-all group cursor-pointer"
+ >
+
+
+ Passer au Plan Pro
+
+
+
+
+
+
+ )}
+
+ {/* Render intelligence modules */}
+ {activeView === 'agents' && (
+
+
+
+
+
Intelligence OS
+
+
+
+ {[
+ { id: 'brainstorm', label: 'Brainstorm Wave', desc: 'Génération d ideas rhizomatique', icon:
},
+ { id: 'insights', label: 'Réseau Sémantique', desc: 'Cartographie de clusters DBSCAN', icon:
},
+ { id: 'temporal', label: 'Temporal Forecast', desc: 'Chronologie et prévisions', icon:
},
+ ].map(sub => (
+
setActiveView(sub.id as any)}
+ className="w-full text-left p-3 rounded-xl border border-border/30 hover:border-accent/30 bg-white dark:bg-zinc-800/50 hover:shadow-xs transition-all flex items-start gap-3 group"
+ >
+
+ {sub.icon}
+
+
+
{sub.label}
+
{sub.desc}
+
+
+ ))}
+
+
+
+ {/* Pack quota discovery */}
+
+
+ Pack Découverte IA
+ 49 restants
+
+
+
+
+ )}
+
+ {/* Reminders section list view */}
+ {activeView === 'reminders' && (
+
+
+
+
Rappels Actifs
+
+
+
+
+
Aucun rappel pour le moment.
+
+
+ )}
+
+ {/* Flashcards / Révisions panel view inside Column 2 of Sidebar */}
+ {activeView === 'revision' && (
+
+
+
+
Decks Révision
+
+
+
+ {(() => {
+ const deckNotesList: { noteId: string; title: string; count: number; mastery: number }[] = [];
+ const cardGroups: Record
= {};
+ (flashcards || []).forEach(card => {
+ if (!cardGroups[card.noteId]) cardGroups[card.noteId] = [];
+ cardGroups[card.noteId].push(card);
+ });
+
+ Object.keys(cardGroups).forEach(noteId => {
+ const noteItem = notes.find(n => n.id === noteId);
+ if (!noteItem || noteItem.isDeleted) return;
+ const cList = cardGroups[noteId];
+ const mastered = cList.filter(c => c.mastered).length;
+ deckNotesList.push({
+ noteId,
+ title: noteItem.title || 'Note sans titre',
+ count: cList.length,
+ mastery: cList.length > 0 ? mastered / cList.length : 0
+ });
+ });
+
+ return deckNotesList.map(deck => (
+ {
+ onSelectReviewDeck?.(deck.noteId);
+ }}
+ className="w-full text-left p-2.5 rounded-xl border border-border/40 hover:border-accent/30 bg-white dark:bg-zinc-800/40 hover:shadow-2xs transition-all flex items-start gap-2.5 group cursor-pointer"
+ >
+
+
+
+
+
+ {deck.title}
+
+
+ {deck.count} cartes · {Math.round(deck.mastery * 100)}% acquis
+
+
+
+ ));
+ })()}
+
+ {(!flashcards || flashcards.length === 0) && (
+
+ )}
+
+
+ )}
+
+ {/* Shared panel view */}
+ {activeView === 'shared' && (
+
+
+
+
Partagé avec moi
+
+
+
+
+
Aucun document partagé pour le moment.
+
+
+ )}
+
+ {/* Trash bin panel view */}
+ {activeView === 'trash' && (
+
+
+
+
Fichiers Supprimés
+
+
+
+ {notes.filter(n => n.isDeleted).map(note => (
+
+
+
{note.title || "Note sans titre"}
+
Supprimé le {new Date(note.deletedAt || note.date).toLocaleDateString('fr-FR')}
+
+
{
+ setActiveCarnetId(note.carnetId);
+ setActiveNoteId(note.id);
+ }}
+ className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded text-[9px] font-bold uppercase tracking-wider text-accent shrink-0 opacity-0 group-hover:opacity-100 transition-opacity"
+ >
+ Inspecter
+
+
+ ))}
+ {notes.filter(n => n.isDeleted).length === 0 && (
+
+ )}
+
+
+ )}
+
+ {/* Settings panel category switcher list */}
+ {activeView === 'settings' && (
+
+
+
+
Paramètres
+
+
+
+ {[
+ { id: 'general', label: 'Général', icon:
},
+ { id: 'ai', label: 'Intelligence IA', icon:
},
+ { id: 'billing', label: 'Tarifs & Abonnements', icon:
},
+ { id: 'appearance', label: 'Thème & Stylisme', icon:
},
+ { id: 'profile', label: 'Profil Utilisateur', icon:
},
+ ].map(tab => (
+
setActiveSettingsTab?.(tab.id as any)}
+ className="w-full text-left px-3 py-2 text-[11px] transition-all rounded-lg flex items-center gap-2.5 text-muted-ink hover:text-ink hover:bg-black/5"
+ >
+ {tab.icon}
+ {tab.label}
+
+ ))}
+
+
+ )}
+
+
+
+
+ >
+ );
+};
diff --git a/architectural-grid_landing/src/components/SlashMenu.tsx b/architectural-grid/src/components/SlashMenu.tsx
similarity index 94%
rename from architectural-grid_landing/src/components/SlashMenu.tsx
rename to architectural-grid/src/components/SlashMenu.tsx
index 440bf98..20b7d87 100644
--- a/architectural-grid_landing/src/components/SlashMenu.tsx
+++ b/architectural-grid/src/components/SlashMenu.tsx
@@ -7,7 +7,8 @@ import {
Code,
Image as ImageIcon,
Type,
- Sparkles
+ Sparkles,
+ Link2
} from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
@@ -25,6 +26,7 @@ export const SlashMenu: React.FC = ({ position, onSelect, onClos
{ id: 'quote', label: 'Citation', icon:
, desc: 'Bloc de texte mis en avant' },
{ id: 'code', label: 'Bloc de Code', icon: , desc: 'Code ou texte technique' },
{ id: 'image', label: 'Image', icon: , desc: 'Insérer un visuel' },
+ { id: 'embed', label: 'Living Block', icon: , desc: 'Insérer un bloc connecté dynamique', special: true },
{ id: 'ai-summary', label: 'Résumé IA', icon: , desc: 'Générer un résumé court', special: true },
];
diff --git a/architectural-grid11/src/components/TemporalView.tsx b/architectural-grid/src/components/TemporalView.tsx
similarity index 100%
rename from architectural-grid11/src/components/TemporalView.tsx
rename to architectural-grid/src/components/TemporalView.tsx
diff --git a/architectural-grid_landing/src/components/TrashView.tsx b/architectural-grid/src/components/TrashView.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/TrashView.tsx
rename to architectural-grid/src/components/TrashView.tsx
diff --git a/architectural-grid_landing/src/components/settings/AITab.tsx b/architectural-grid/src/components/settings/AITab.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/settings/AITab.tsx
rename to architectural-grid/src/components/settings/AITab.tsx
diff --git a/architectural-grid_landing/src/components/settings/AppearanceTab.tsx b/architectural-grid/src/components/settings/AppearanceTab.tsx
similarity index 95%
rename from architectural-grid_landing/src/components/settings/AppearanceTab.tsx
rename to architectural-grid/src/components/settings/AppearanceTab.tsx
index d5f2fc0..56b8cbc 100644
--- a/architectural-grid_landing/src/components/settings/AppearanceTab.tsx
+++ b/architectural-grid/src/components/settings/AppearanceTab.tsx
@@ -38,14 +38,14 @@ interface AppearanceTabProps {
}
const PRESET_COLORS = [
- { name: 'Warm Earth', value: '#A47148' },
- { name: 'Indigo', value: '#6366F1' },
- { name: 'Rose', value: '#F43F5E' },
- { name: 'Emerald', value: '#10B981' },
- { name: 'Amber', value: '#F59E0B' },
- { name: 'Slate', value: '#475569' },
- { name: 'Crimson', value: '#DC2626' },
- { name: 'Ocean', value: '#0EA5E9' },
+ { name: 'Ochre Swiss', value: '#A47148' },
+ { name: 'Alpine Moss', value: '#4E594A' },
+ { name: 'Terracotta', value: '#B1523E' },
+ { name: 'Slate Steel', value: '#4A5568' },
+ { name: 'Midnight', value: '#1E293B' },
+ { name: 'Sage Leaf', value: '#7C8363' },
+ { name: 'Bordeaux', value: '#722F37' },
+ { name: 'Carbon', value: '#262626' },
];
export const AppearanceTab: React.FC = ({ accentColor, onAccentColorChange }) => {
diff --git a/architectural-grid_landing/src/components/settings/BillingTab.tsx b/architectural-grid/src/components/settings/BillingTab.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/settings/BillingTab.tsx
rename to architectural-grid/src/components/settings/BillingTab.tsx
diff --git a/architectural-grid_landing/src/components/settings/GeneralTab.tsx b/architectural-grid/src/components/settings/GeneralTab.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/settings/GeneralTab.tsx
rename to architectural-grid/src/components/settings/GeneralTab.tsx
diff --git a/architectural-grid_landing/src/components/settings/ProfileTab.tsx b/architectural-grid/src/components/settings/ProfileTab.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/settings/ProfileTab.tsx
rename to architectural-grid/src/components/settings/ProfileTab.tsx
diff --git a/architectural-grid_landing/src/components/settings/SettingsHeader.tsx b/architectural-grid/src/components/settings/SettingsHeader.tsx
similarity index 100%
rename from architectural-grid_landing/src/components/settings/SettingsHeader.tsx
rename to architectural-grid/src/components/settings/SettingsHeader.tsx
diff --git a/architectural-grid_landing/src/constants.ts b/architectural-grid/src/constants.ts
similarity index 87%
rename from architectural-grid_landing/src/constants.ts
rename to architectural-grid/src/constants.ts
index 8965c08..615f39d 100644
--- a/architectural-grid_landing/src/constants.ts
+++ b/architectural-grid/src/constants.ts
@@ -16,7 +16,7 @@ export const ALL_NOTES: Note[] = [
carnetId: '4',
title: 'Grid Systems & Geometry',
date: 'Oct 26, 2024',
- content: 'Grid Systems are the foundation of cognitive design. We use geometric blocks to define spaces. The repetitive structure creates a sense of order and rhythm in the built environment.',
+ content: 'Grid Systems are the foundation of cognitive design. We use geometric blocks to define spaces. The repetitive structure creates a sense of order and rhythm in the built environment.\n\n- [ ] Finaliser l\'étude de la géométrie sacrée\n- [x] Tracer les grilles orthogonales préliminaires',
imageUrl: 'https://images.unsplash.com/photo-1503387762-592dea58ef23?auto=format&fit=crop&q=80&w=800&h=600',
tags: [
{ id: 't1', label: 'Architecture', type: 'user' },
@@ -29,7 +29,7 @@ export const ALL_NOTES: Note[] = [
carnetId: '4',
title: 'Parametric Grids',
date: 'Oct 27, 2024',
- content: 'Parametricism allows us to deform traditional grid systems. By using mathematical algorithms, we can create fluid yet structured geometries that respond to environmental data.',
+ content: 'Parametricism allows us to deform traditional grid systems. By using mathematical algorithms, we can create fluid yet structured geometries that respond to environmental data.\n\n- [ ] Valider l\'algorithme de déformation spatiale\n- [ ] Tester les nœuds structurels imprimés en 3D',
imageUrl: 'https://images.unsplash.com/photo-1511225070737-5af5ac9a690d?auto=format&fit=crop&q=80&w=800&h=600',
tags: [{ id: 't1', label: 'Geometry', type: 'user' }],
embedding: [0.12, 0.08]
@@ -39,7 +39,7 @@ export const ALL_NOTES: Note[] = [
carnetId: '4',
title: 'Sustainable Materiality',
date: 'Oct 24, 2024',
- content: 'Exploring cross-laminated timber (CLT) as a sustainable alternative to concrete. Material choice is key to carbon-neutral construction. The warmth of wood contrasts with the coldness of steel.',
+ content: 'Exploring cross-laminated timber (CLT) as a sustainable alternative to concrete. Material choice is key to carbon-neutral construction. The warmth of wood contrasts with the coldness of steel.\n\n- [ ] Contacter le fournisseur de CLT local\n- [ ] Estimer le ratio d\'émission de carbone évitée',
imageUrl: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=600',
tags: [
{ id: 't3', label: 'Materials', type: 'user' },
@@ -52,7 +52,7 @@ export const ALL_NOTES: Note[] = [
carnetId: '7',
title: 'Solar Passive Design',
date: 'Oct 25, 2024',
- content: 'Using orientation to maximize natural heat. Sustainable architecture must prioritize passive systems over active ones. Thermal mass and insulation are critical factors.',
+ content: 'Using orientation to maximize natural heat. Sustainable architecture must prioritize passive systems over active ones. Thermal mass and insulation are critical factors.\n\n- [x] Simuler l\'ensoleillement d\'hiver sur la façade sud\n- [ ] Calculer l\'épaisseur d\'isolation en fibre de bois',
imageUrl: 'https://images.unsplash.com/photo-1509391366360-fe5bb5843e0c?auto=format&fit=crop&q=80&w=800&h=600',
tags: [{ id: 't4', label: 'Sustainabilty', type: 'user' }],
embedding: [0.85, 0.75]
diff --git a/architectural-grid_landing/src/index.css b/architectural-grid/src/index.css
similarity index 100%
rename from architectural-grid_landing/src/index.css
rename to architectural-grid/src/index.css
diff --git a/architectural-grid10/src/main.tsx b/architectural-grid/src/main.tsx
similarity index 100%
rename from architectural-grid10/src/main.tsx
rename to architectural-grid/src/main.tsx
diff --git a/architectural-grid11/src/services/clusteringService.ts b/architectural-grid/src/services/clusteringService.ts
similarity index 92%
rename from architectural-grid11/src/services/clusteringService.ts
rename to architectural-grid/src/services/clusteringService.ts
index 7be16ef..ebce3a7 100644
--- a/architectural-grid11/src/services/clusteringService.ts
+++ b/architectural-grid/src/services/clusteringService.ts
@@ -226,3 +226,17 @@ export function calculateCentroid(noteIds: string[], allNotes: Note[]): number[]
return centroid;
}
+
+export function getMostCentralNoteTitles(noteIds: string[], centroid: number[] | undefined, allNotes: Note[], count: number = 5): string[] {
+ const clusterNotes = allNotes.filter(n => noteIds.includes(n.id) && n.embedding);
+ if (clusterNotes.length === 0) return [];
+ if (!centroid) return clusterNotes.slice(0, count).map(n => n.title);
+
+ const scored = clusterNotes.map(n => ({
+ title: n.title,
+ similarity: cosineSimilarity(n.embedding!, centroid)
+ }));
+
+ scored.sort((a, b) => b.similarity - a.similarity);
+ return scored.slice(0, count).map(item => item.title);
+}
diff --git a/architectural-grid_landing/src/services/geminiService.ts b/architectural-grid/src/services/geminiService.ts
similarity index 81%
rename from architectural-grid_landing/src/services/geminiService.ts
rename to architectural-grid/src/services/geminiService.ts
index c2c87de..01e2451 100644
--- a/architectural-grid_landing/src/services/geminiService.ts
+++ b/architectural-grid/src/services/geminiService.ts
@@ -251,3 +251,63 @@ export async function extractActionItems(notes: { title: string; content: string
return "Erreur lors de l'extraction des tâches.";
}
}
+
+const FLASHCARDS_SCHEMA = {
+ type: Type.OBJECT,
+ properties: {
+ flashcards: {
+ type: Type.ARRAY,
+ items: {
+ type: Type.OBJECT,
+ properties: {
+ question: { type: Type.STRING },
+ answer: { type: Type.STRING }
+ },
+ required: ["question", "answer"]
+ }
+ }
+ },
+ required: ["flashcards"]
+};
+
+export async function generateFlashcardsForNote(
+ noteTitle: string,
+ noteContent: string
+): Promise<{ question: string; answer: string }[]> {
+ const prompt = `
+ Titre de la note : "${noteTitle}"
+ Contenu de la note :
+ ${noteContent}
+
+ Génère entre 4 et 8 flashcards (paires question/réponse) d'apprentissage basées sur le contenu ci-dessus.
+
+ Règles de style :
+ - Les questions doivent être claires et guider vers une révision active (ex: "Quelle est la particularité de... ?", "Pourquoi utilise-t-on... ?").
+ - Les réponses doivent être courtes et percutantes.
+ - Langue : Français.
+ - Format de retour : JSON correspondant au schéma.
+ `;
+
+ try {
+ const response = await ai.models.generateContent({
+ model: "gemini-3.5-flash",
+ contents: [{ role: "user", parts: [{ text: prompt }] }],
+ config: {
+ systemInstruction: "Tu es un assistant de révision agile. Tu convertis le contenu d'un cours ou d'une note en de superbes flashcards mémo-techniques.",
+ responseMimeType: "application/json",
+ responseSchema: FLASHCARDS_SCHEMA,
+ temperature: 0.7
+ }
+ });
+
+ const resText = response.text;
+ if (!resText) return [];
+
+ const parsed = JSON.parse(resText.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim());
+ return Array.isArray(parsed.flashcards) ? parsed.flashcards : (Array.isArray(parsed) ? parsed : []);
+ } catch (error) {
+ console.error("Error generating flashcards with Gemini:", error);
+ return [];
+ }
+}
+
diff --git a/architectural-grid11/src/services/temporalService.ts b/architectural-grid/src/services/temporalService.ts
similarity index 100%
rename from architectural-grid11/src/services/temporalService.ts
rename to architectural-grid/src/services/temporalService.ts
diff --git a/architectural-grid_landing/src/types.ts b/architectural-grid/src/types.ts
similarity index 69%
rename from architectural-grid_landing/src/types.ts
rename to architectural-grid/src/types.ts
index 2de9f9d..9a9558f 100644
--- a/architectural-grid_landing/src/types.ts
+++ b/architectural-grid/src/types.ts
@@ -1,6 +1,6 @@
-export type NavigationView = 'notebooks' | 'agents' | 'settings' | 'shared' | 'reminders' | 'trash' | 'brainstorm' | 'insights' | 'temporal';
+export type NavigationView = 'notebooks' | 'agents' | 'settings' | 'shared' | 'reminders' | 'trash' | 'brainstorm' | 'insights' | 'temporal' | 'graph' | 'revision';
export type AITone = 'Professional' | 'Creative' | 'Academic' | 'Casual';
-export type AITab = 'discussion' | 'actions' | 'resources' | 'explore';
+export type AITab = 'infos' | 'versions' | 'relations' | 'discussion' | 'actions' | 'resources' | 'explore';
export type SettingsTab = 'general' | 'ai' | 'billing' | 'appearance' | 'profile' | 'data' | 'mcp' | 'about';
export interface Tag {
@@ -18,6 +18,14 @@ export interface Attachment {
isProcessed?: boolean;
}
+export interface NoteVersion {
+ id: string;
+ title: string;
+ content: string;
+ timestamp: string;
+ size: number;
+}
+
export interface Note {
id: string;
carnetId: string;
@@ -32,6 +40,12 @@ export interface Note {
deletedAt?: string;
embedding?: number[];
clusterId?: string;
+ isClipped?: boolean;
+ clipSourceUrl?: string;
+ clipFavicon?: string;
+ clipDate?: string;
+ isVersioningEnabled?: boolean;
+ versionHistory?: NoteVersion[];
}
export interface NoteCluster {
@@ -110,3 +124,30 @@ export interface NotePrediction {
generatedAt: string;
}
+export type FlashcardEvaluation = 'fail' | 'hesitant' | 'sure';
+
+export interface Flashcard {
+ id: string;
+ noteId: string;
+ question: string;
+ answer: string;
+ intervalDays: number; // For spaced repetition
+ nextReviewDate: string; // ISO String
+ easeFactor: number;
+ mastered: boolean;
+ history?: {
+ reviewedAt: string;
+ evaluation: FlashcardEvaluation;
+ }[];
+}
+
+export interface FlashcardDeck {
+ noteId: string;
+ title: string;
+ cardsCount: number;
+ nextReviewDate: string; // Min nextReviewDate of all cards
+ masteryScore: number; // Proportion of cards evaluation === 'sure'
+ cards: Flashcard[];
+}
+
+
diff --git a/architectural-grid10/tsconfig.json b/architectural-grid/tsconfig.json
similarity index 100%
rename from architectural-grid10/tsconfig.json
rename to architectural-grid/tsconfig.json
diff --git a/architectural-grid10/vite.config.ts b/architectural-grid/vite.config.ts
similarity index 100%
rename from architectural-grid10/vite.config.ts
rename to architectural-grid/vite.config.ts
diff --git a/architectural-grid10/metadata.json b/architectural-grid10/metadata.json
deleted file mode 100644
index 3e19746..0000000
--- a/architectural-grid10/metadata.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Architectural Grid",
- "description": "A minimalist notebook for architectural research and conceptual sketches.",
- "requestFramePermissions": [],
- "majorCapabilities": []
-}
diff --git a/architectural-grid10/package.json b/architectural-grid10/package.json
deleted file mode 100644
index 6b3f167..0000000
--- a/architectural-grid10/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "name": "react-example",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite --port=3000 --host=0.0.0.0",
- "build": "vite build",
- "preview": "vite preview",
- "clean": "rm -rf dist",
- "lint": "tsc --noEmit"
- },
- "dependencies": {
- "@google/genai": "^1.29.0",
- "@tailwindcss/vite": "^4.1.14",
- "@vitejs/plugin-react": "^5.0.4",
- "lucide-react": "^0.546.0",
- "react": "^19.0.1",
- "react-dom": "^19.0.1",
- "vite": "^6.2.3",
- "express": "^4.21.2",
- "dotenv": "^17.2.3",
- "motion": "^12.23.24"
- },
- "devDependencies": {
- "@types/node": "^22.14.0",
- "autoprefixer": "^10.4.21",
- "tailwindcss": "^4.1.14",
- "tsx": "^4.21.0",
- "typescript": "~5.8.2",
- "vite": "^6.2.3",
- "@types/express": "^4.17.21"
- }
-}
diff --git a/architectural-grid10/src/App.tsx b/architectural-grid10/src/App.tsx
deleted file mode 100644
index 9181686..0000000
--- a/architectural-grid10/src/App.tsx
+++ /dev/null
@@ -1,450 +0,0 @@
-/**
- * @license
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React, { useState, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-
-// Components
-import { Sidebar } from './components/Sidebar';
-import { NotebooksView } from './components/NotebooksView';
-import { AgentsView } from './components/AgentsView';
-import { SettingsView } from './components/SettingsView';
-import { TrashView } from './components/TrashView';
-import { AISidebar } from './components/AISidebar';
-import { SlashMenu } from './components/SlashMenu';
-
-// Data & Types
-import { CARNETS, ALL_NOTES } from './constants';
-import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note } from './types';
-
-export default function App() {
- const [activeView, setActiveView] = useState('notebooks');
- const [activeSettingsTab, setActiveSettingsTab] = useState('general');
- const [selectedAgentId, setSelectedAgentId] = useState(null);
- const [isDarkMode, setIsDarkMode] = useState(false);
- const [carnets, setCarnets] = useState(CARNETS);
- const [notes, setNotes] = useState(ALL_NOTES);
- const [activeCarnetId, setActiveCarnetId] = useState('4');
- const [activeNoteId, setActiveNoteId] = useState(null);
- const [selectedTagIds, setSelectedTagIds] = useState([]);
- const [isAISidebarOpen, setIsAISidebarOpen] = useState(false);
- const [aiTab, setAiTab] = useState('discussion');
- const [selectedTone, setSelectedTone] = useState('Professional');
-
- // Modal States
- const [showNewCarnetModal, setShowNewCarnetModal] = useState<{ isOpen: boolean; parentId?: string; isRenaming?: boolean; carnetId?: string }>({ isOpen: false });
- const [showNewNoteModal, setShowNewNoteModal] = useState(false);
- const [slashMenu, setSlashMenu] = useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- // Form States
- const [newCarnetName, setNewCarnetName] = useState('');
- const [newNoteTitle, setNewNoteTitle] = useState('');
- const [newNoteContent, setNewNoteContent] = useState('');
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const togglePin = (noteId: string) => {
- setNotes(notes.map(n => n.id === noteId ? { ...n, isPinned: !n.isPinned } : n));
- };
-
- const filteredNotes = useMemo(() => {
- let result = notes.filter(n => n.carnetId === activeCarnetId && !n.isDeleted);
-
- if (selectedTagIds.length > 0) {
- result = result.filter(note =>
- selectedTagIds.every(tagId => note.tags?.some(tag => tag.id === tagId))
- );
- }
-
- return [...result].sort((a, b) => {
- if (a.isPinned && !b.isPinned) return -1;
- if (!a.isPinned && b.isPinned) return 1;
- return 0;
- });
- }, [activeCarnetId, notes]);
-
- const activeNote = useMemo(() =>
- notes.find(n => n.id === activeNoteId),
- [activeNoteId, notes]);
-
- const activeCarnet = useMemo(() =>
- carnets.find(c => c.id === activeCarnetId),
- [activeCarnetId, carnets]);
-
- const handleAddCarnet = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newCarnetName.trim()) return;
-
- if (showNewCarnetModal.isRenaming && showNewCarnetModal.carnetId) {
- setCarnets(carnets.map(c => c.id === showNewCarnetModal.carnetId ? { ...c, name: newCarnetName, initial: newCarnetName.charAt(0).toUpperCase() } : c));
- setShowNewCarnetModal({ isOpen: false });
- setNewCarnetName('');
- return;
- }
-
- const newCarnet: Carnet = {
- id: Date.now().toString(),
- name: newCarnetName,
- initial: newCarnetName.charAt(0).toUpperCase(),
- type: 'Project',
- parentId: showNewCarnetModal.parentId
- };
-
- setCarnets([...carnets, newCarnet]);
- setNewCarnetName('');
- setShowNewCarnetModal({ isOpen: false });
- setActiveCarnetId(newCarnet.id);
- };
-
- const handleDeleteCarnet = (id: string) => {
- if (window.confirm('Déplacer ce carnet et ses sous-carnets vers la corbeille ?')) {
- const idsToDelete = new Set([id]);
-
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
-
- const deletedAt = new Date().toISOString();
- setCarnets(carnets.map(c => idsToDelete.has(c.id) ? { ...c, isDeleted: true, deletedAt } : c));
- setNotes(notes.map(n => idsToDelete.has(n.carnetId) ? { ...n, isDeleted: true, deletedAt } : n));
-
- if (idsToDelete.has(activeCarnetId)) {
- setActiveCarnetId('1');
- }
- }
- };
-
- const handleDeleteNote = (id: string) => {
- const deletedAt = new Date().toISOString();
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: true, deletedAt } : n));
- if (activeNoteId === id) setActiveNoteId(null);
- };
-
- const handleRestoreCarnet = (id: string) => {
- setCarnets(carnets.map(c => c.id === id ? { ...c, isDeleted: false, deletedAt: undefined } : c));
- // Optionally restore linked notes too? User might expect that.
- setNotes(notes.map(n => n.carnetId === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handleRestoreNote = (id: string) => {
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handlePermanentDeleteNote = (id: string) => {
- setNotes(notes.filter(n => n.id !== id));
- };
-
- const handlePermanentDeleteCarnet = (id: string) => {
- const idsToDelete = new Set([id]);
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
- setCarnets(carnets.filter(c => !idsToDelete.has(c.id)));
- setNotes(notes.filter(n => !idsToDelete.has(n.carnetId)));
- };
-
- const handleAddNote = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newNoteTitle.trim() || !newNoteContent.trim()) return;
-
- const newNote: Note = {
- id: `n-${Date.now()}`,
- carnetId: activeCarnetId,
- title: newNoteTitle,
- date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
- content: newNoteContent,
- imageUrl: 'https://images.unsplash.com/photo-1487958449943-2429e8be8625?auto=format&fit=crop&q=80&w=800&h=600',
- tags: []
- };
-
- setNotes([newNote, ...notes]);
- setNewNoteTitle('');
- setNewNoteContent('');
- setShowNewNoteModal(false);
- setActiveNoteId(newNote.id);
- };
-
- return (
-
-
{
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId });
- if (isRenaming && carnetId) {
- const carnet = carnets.find(c => c.id === carnetId);
- if (carnet) setNewCarnetName(carnet.name);
- } else {
- setNewCarnetName('');
- }
- }}
- onDeleteCarnet={handleDeleteCarnet}
- />
-
-
-
- {(activeView === 'notebooks' || activeView === 'shared' || activeView === 'reminders') && (
-
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId })}
- onDeleteNote={handleDeleteNote}
- />
-
- )}
-
- {activeView === 'trash' && (
-
- n.isDeleted)}
- deletedCarnets={carnets.filter(c => c.isDeleted)}
- onRestoreNote={handleRestoreNote}
- onRestoreCarnet={handleRestoreCarnet}
- onPermanentDeleteNote={handlePermanentDeleteNote}
- onPermanentDeleteCarnet={handlePermanentDeleteCarnet}
- onEmptyTrash={() => {
- setNotes(notes.filter(n => !n.isDeleted));
- setCarnets(carnets.filter(c => !c.isDeleted));
- }}
- />
-
- )}
-
- {activeView === 'agents' && (
-
-
-
- )}
-
- {activeView === 'settings' && (
-
-
-
- )}
-
-
-
-
-
- {/* Modals */}
-
- {showNewCarnetModal.isOpen && (
-
-
setShowNewCarnetModal({ isOpen: false })}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {showNewCarnetModal.isRenaming ? 'Rename Carnet' : (showNewCarnetModal.parentId ? 'Create Sub-Carnet' : 'Create New Carnet')}
-
- {showNewCarnetModal.parentId && !showNewCarnetModal.isRenaming && (
-
- Inside: {carnets.find(c => c.id === showNewCarnetModal.parentId)?.name}
-
- )}
-
-
-
- )}
-
- {showNewNoteModal && (
-
-
setShowNewNoteModal(false)}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {slashMenu?.isOpen && (
- { console.log(type); setSlashMenu(null); }}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
- Add Architectural Note
-
-
-
- )}
-
-
- );
-}
diff --git a/architectural-grid10/src/components/AISidebar.tsx b/architectural-grid10/src/components/AISidebar.tsx
deleted file mode 100644
index 821e0f9..0000000
--- a/architectural-grid10/src/components/AISidebar.tsx
+++ /dev/null
@@ -1,379 +0,0 @@
-import React from 'react';
-import {
- Sparkles,
- ChevronRight,
- MessageSquare,
- FileCode,
- Globe,
- Send,
- Scissors,
- Zap,
- Languages,
- Layout,
- ArrowRightLeft,
- BookOpen,
- History,
- Target
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { AITab, AITone, Note, Carnet } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AISidebarProps {
- isOpen: boolean;
- setIsOpen: (open: boolean) => void;
- activeNote: Note | undefined;
- aiTab: AITab;
- setAiTab: (tab: AITab) => void;
- selectedTone: AITone;
- setSelectedTone: (tone: AITone) => void;
- carnets: Carnet[];
-}
-
-export const AISidebar: React.FC = ({
- isOpen,
- setIsOpen,
- activeNote,
- aiTab,
- setAiTab,
- selectedTone,
- setSelectedTone,
- carnets
-}) => {
- const [selectedContextId, setSelectedContextId] = React.useState(null);
-
- return (
-
- {isOpen && (
-
-
-
-
-
- IA Assistant
-
- setIsOpen(false)}
- className="p-1 hover:bg-slate-100 rounded-full transition-colors text-muted-ink"
- >
-
-
-
-
- "{activeNote?.title}"
-
-
-
-
- {(['discussion', 'actions', 'resources'] as AITab[]).map((tab) => (
- setAiTab(tab)}
- className={`flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative
- ${aiTab === tab ? 'text-manganese' : 'text-muted-ink hover:text-ink/60'}`}
- >
- {tab}
- {aiTab === tab && (
-
- )}
-
- ))}
-
-
-
-
- {aiTab === 'discussion' && (
-
-
-
-
-
-
Posez une question à l'Assistant pour commencer.
-
-
-
-
-
Source du Contexte
-
-
-
-
- Note Active
-
-
Auto
-
-
-
-
-
-
-
-
-
-
Ton d'écriture
-
- {(['Professional', 'Creative', 'Academic', 'Casual'] as AITone[]).map((tone) => (
- setSelectedTone(tone)}
- className={`p-3 rounded-xl border text-[11px] font-medium transition-all
- ${selectedTone === tone ? 'bg-manganese text-paper border-manganese shadow-lg shadow-manganese/10' : 'bg-glass border-border text-muted-ink hover:border-ink/20'}`}
- >
- {tone.toUpperCase().substring(0, 3)}
-
- ))}
-
-
-
-
- )}
-
- {aiTab === 'actions' && (
-
-
-
-
-
-
- {[
- { icon:
, label: 'Clarifier', color: 'ochre' },
- { icon:
, label: 'Raccourcir', color: 'rust' },
- { icon:
, label: 'Améliorer', color: 'sage' },
- { icon:
, label: 'Traduire', color: 'slate' },
- ].map((action, i) => (
-
-
- {action.icon}
-
- {action.label}
-
- ))}
-
-
- Convertir en Markdown
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Présentation
-
Convertir en slides interactives
-
-
-
-
-
- Thème
-
- Architectural Mono
- Vibrant Tech
- Minimal Silk
-
-
-
- Style
-
- Professional
- Creative
- Brutalist
-
-
-
-
-
- Générer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Diagramme
-
Visualisation de structure
-
-
-
-
-
- Type
-
- Logic Flow
- Mind Map
- Hierarchy
-
-
-
- Style
-
- Draft
- Polished
- Handwritten
-
-
-
-
-
- Tracer
-
-
-
-
-
-
-
-
- Auto-Save Enabled
-
-
-
- )}
-
- {aiTab === 'resources' && (
-
-
-
-
URL (Optionnel)
-
-
-
-
-
-
-
- Texte de la ressource
-
-
-
-
-
Mode d'intégration
-
- {[
- { id: 'replace', label: 'Remplacer', sub: 'Direct, sans IA' },
- { id: 'append', label: 'Compléter', sub: 'Ajoute sans réécrire' },
- { id: 'merge', label: 'Fusionner', sub: 'Réécrit et intègre' },
- ].map((mode) => (
-
- {mode.label}
- {mode.sub}
-
- ))}
-
-
-
-
-
- Générer l'aperçu
-
-
-
- )}
-
-
-
-
- {aiTab === 'discussion' && (
-
-
- Maj+Entrée = nouvelle ligne
-
- )}
-
-
- )}
-
- );
-};
diff --git a/architectural-grid10/src/components/AgentsView.tsx b/architectural-grid10/src/components/AgentsView.tsx
deleted file mode 100644
index f82c7fa..0000000
--- a/architectural-grid10/src/components/AgentsView.tsx
+++ /dev/null
@@ -1,325 +0,0 @@
-import React from 'react';
-import {
- Plus,
- ArrowLeft,
- Clock,
- Activity,
- Trash2,
- Edit3,
- Play,
- Eye,
- Microscope,
- Globe,
- Layers,
- Zap,
- BookOpen,
- Sparkles,
- ChevronDown,
- Info,
- Check
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Carnet, Note } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AgentsViewProps {
- selectedAgentId: string | null;
- setSelectedAgentId: (id: string | null) => void;
- carnets: Carnet[];
-}
-
-export const AgentsView: React.FC = ({
- selectedAgentId,
- setSelectedAgentId,
- carnets
-}) => {
- const [selectedCarnetForAgent, setSelectedCarnetForAgent] = React.useState('4');
- const [agentType, setAgentType] = React.useState<'Surveillant' | 'Personnalisé' | 'Slides' | 'Diagramme'>('Diagramme');
-
- return (
-
- {!selectedAgentId ? (
- <>
-
-
-
-
Mes Agents
-
Automatisez vos tâches de veille et de recherche.
-
-
-
- Nouvel Agent
-
-
-
-
- {['Tous', 'Veilleur', 'Chercheur', 'Surveillant', 'Personnalisé'].map((tag, i) => (
-
- {tag}
- {i === 0 && }
-
- ))}
-
-
-
-
-
- {[
- { id: 'a1', icon:
, title: 'Surveillant de Notes', status: 'Réussi', type: 'SURVEILLANT', meta: 'Hebdomadaire • 6 exéc.', desc: 'Analyse les notes récentes d’un carnet et suggère des compléments, références et liens.' },
- { id: 'a2', icon:
, title: 'Chercheur de Sujet', status: 'Réussi', type: 'CHERCHEUR', meta: 'Hebdomadaire • 14 exéc.', desc: 'Recherche des informations approfondies sur les derniers modèles de Deepseek et voir l’avis des utilisateurs.' },
- { id: 'a3', icon:
, title: 'Veille IA', status: 'Réussi', type: 'VEILLEUR', meta: 'Quotidien • 20 exéc.', desc: 'Scrape les flux RSS de 6 sites IA (The Verge, TechCrunch...) et génère un résumé.' },
- ].map((agent, i) => (
-
setSelectedAgentId(agent.id)}
- className="bg-white dark:bg-white/5 border border-border rounded-2xl p-6 space-y-6 hover:border-ink/20 transition-all group cursor-pointer shadow-sm relative overflow-hidden"
- >
-
-
-
- {agent.icon}
-
-
-
{agent.title}
-
{agent.type}
-
-
-
e.stopPropagation()}>
-
-
-
-
-
-
-
-
- {agent.desc}
-
-
-
-
-
- {agent.meta.split('•')[0]}
- {agent.meta.split('•')[1]}
-
-
-
-
- Prochaine exécution
- Hebdomadaire
-
-
-
Dernier statut
-
{agent.status}
-
-
-
-
-
-
Modifier
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-slate-50 dark:hover:bg-white/5 flex items-center justify-center transition-colors text-muted-ink hover:text-ink"
- >
-
-
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-rose-50 hover:text-rose-600 hover:border-rose-100 flex items-center justify-center transition-colors text-muted-ink"
- >
-
-
-
-
- ))}
-
-
-
-
-
- {[
- { title: 'Veille IA', desc: 'Scrape les flux RSS de 6 sites IA et génère un résumé hebdomadaire.', icon:
},
- { title: 'Veille Tech', desc: 'Crée un résumé quotidien des news Hacker News et Product Hunt.', icon:
},
- { title: 'Veille Dev', desc: 'Surveille les repos GitHub pour détecter les nouvelles releases.', icon:
},
- ].map((model, i) => (
-
-
- {model.icon}
-
-
{model.title}
-
{model.desc}
-
- Installer
-
-
- ))}
-
-
-
- >
- ) : (
-
-
-
-
-
-
-
Sélectionnez le type d'agent
-
- {[
- { id: 'Surveillant', icon:
, label: 'Surveillant', desc: 'Surveille un carnet et analyse les notes' },
- { id: 'Personnalisé', icon:
, label: 'Personnalisé', desc: 'Agent libre avec votre propre prompt' },
- { id: 'Slides', icon:
, label: 'Slides', desc: 'Crée une présentation PowerPoint à partir de notes' },
- { id: 'Diagramme', icon:
, label: 'Diagramme', desc: 'Crée un diagramme Excalidraw à partir de notes' },
- ].map((type) => (
-
setAgentType(type.id as any)}
- className={`p-6 rounded-2xl border-2 transition-all flex flex-col items-center gap-3 text-center group relative
- ${agentType === type.id ? 'border-blueprint bg-white shadow-xl shadow-blueprint/10' : 'border-border bg-white/50 hover:bg-white'}`}
- >
-
- {type.icon}
-
-
-
{type.label}
-
{type.desc}
-
-
- {agentType === type.id &&
}
-
-
- ))}
-
-
-
-
-
-
-
- CONFIGURATION
-
-
- Supprimer
-
-
-
-
-
-
- DESCRIPTION (OPTIONEL)
-
-
-
-
-
-
-
- CARNET À SURVEILLER
-
-
-
-
-
-
-
- NOTES À ANALYSER
-
-
-
- {[
- 'Résumé du conteneur LXC devSandbox',
- 'Connexion SSH sans mot de passe à devSandbox',
- 'Gateway token (blank to generate)',
- 'Procédure d\'accès à openclaw',
- 'Derniers commits du repo Momento'
- ].map((note, i) => (
-
-
- {i === 0 && }
-
-
- {note}
-
- ))}
-
-
{1} note(s) sélectionnée(s)
-
-
-
-
- TYPE DE DIAGRAMME
-
-
- {[
- 'Auto (détection métier)', 'Flowchart (processus)',
- 'Mindmap (idées)', 'Organigramme (équipes)',
- 'Timeline / roadmap', 'Process map (opérations)',
- 'Architecture cloud (zones/RG)'
- ].map((type, i) => (
-
- {type}
-
- ))}
-
-
-
-
-
- STYLE DU DIAGRAMME EXCALIDRAW
-
-
- {[
- 'Coloré (Excalidraw)', 'Sketch+ (Excalidraw accentué)', 'Austère (sobre)'
- ].map((style, i) => (
-
- {style}
-
- ))}
-
-
-
-
-
-
- )}
-
- );
-};
diff --git a/architectural-grid10/src/components/HierarchicalCarnetSelector.tsx b/architectural-grid10/src/components/HierarchicalCarnetSelector.tsx
deleted file mode 100644
index d04851e..0000000
--- a/architectural-grid10/src/components/HierarchicalCarnetSelector.tsx
+++ /dev/null
@@ -1,208 +0,0 @@
-import React, { useState, useMemo } from 'react';
-import {
- ChevronRight,
- ChevronDown,
- Folder,
- FolderOpen,
- Check,
- Search
-} from 'lucide-react';
-import { Carnet } from '../types';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface HierarchicalCarnetSelectorProps {
- carnets: Carnet[];
- selectedId: string | null;
- onSelect: (id: string) => void;
- className?: string;
- placeholder?: string;
-}
-
-export const HierarchicalCarnetSelector: React.FC = ({
- carnets,
- selectedId,
- onSelect,
- className = "",
- placeholder = "Sélectionner un carnet..."
-}) => {
- const [isOpen, setIsOpen] = useState(false);
- const [searchQuery, setSearchQuery] = useState("");
- const [expandedIds, setExpandedIds] = useState>(new Set(['1', '4'])); // Default expand some
-
- const selectedCarnet = carnets.find(c => c.id === selectedId);
-
- // Derive the path for display
- const path = useMemo(() => {
- if (!selectedCarnet) return [];
- const trail: Carnet[] = [];
- let current = selectedCarnet;
- while (current) {
- trail.unshift(current);
- if (!current.parentId) break;
- const parent = carnets.find(c => c.id === current.parentId);
- if (!parent) break;
- current = parent;
- }
- return trail;
- }, [selectedCarnet, carnets]);
-
- const toggleExpand = (e: React.MouseEvent, id: string) => {
- e.stopPropagation();
- const newExpanded = new Set(expandedIds);
- if (newExpanded.has(id)) {
- newExpanded.delete(id);
- } else {
- newExpanded.add(id);
- }
- setExpandedIds(newExpanded);
- };
-
- const filteredCarnets = useMemo(() => {
- if (!searchQuery) return carnets;
- return carnets.filter(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()));
- }, [carnets, searchQuery]);
-
- const renderTree = (parentId?: string, level = 0) => {
- const children = carnets.filter(c => c.parentId === parentId);
- if (children.length === 0) return null;
-
- return (
- 0 ? "ml-4 border-l border-border/40 pl-2" : ""}>
- {children.map(carnet => {
- const isExpanded = expandedIds.has(carnet.id) || searchQuery.length > 0;
- const hasChildren = carnets.some(c => c.parentId === carnet.id);
- const isSelected = selectedId === carnet.id;
-
- // If searching and this carnet doesn't match AND none of its children match, skip it
- if (searchQuery && !carnet.name.toLowerCase().includes(searchQuery.toLowerCase())) {
- const hasMatchingChild = (id: string): boolean => {
- const childrenOfId = carnets.filter(c => c.parentId === id);
- return childrenOfId.some(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()) || hasMatchingChild(c.id));
- };
- if (!hasMatchingChild(carnet.id)) return null;
- }
-
- return (
-
-
{
- onSelect(carnet.id);
- if (!searchQuery) setIsOpen(false);
- }}
- className={`flex items-center gap-2.5 px-2 py-1.5 rounded-lg cursor-pointer transition-all group
- ${isSelected ? 'bg-blueprint/10 text-blueprint font-bold' : 'hover:bg-slate-50 dark:hover:bg-white/5 text-ink'}`}
- >
-
- {hasChildren ? (
- toggleExpand(e, carnet.id)}
- className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded transition-colors"
- >
- {isExpanded ? : }
-
- ) : null}
-
-
-
- {isExpanded && hasChildren ? : }
-
-
-
{carnet.name}
-
- {isSelected &&
}
-
-
-
- {isExpanded && (
-
- {renderTree(carnet.id, level + 1)}
-
- )}
-
-
- );
- })}
-
- );
- };
-
- return (
-
-
setIsOpen(!isOpen)}
- className="w-full bg-slate-50 dark:bg-black/20 border border-border/80 rounded-xl px-4 py-4 text-sm outline-none focus:ring-4 ring-blueprint/5 focus:border-blueprint/40 transition-all cursor-pointer text-ink flex items-center gap-3"
- >
-
-
- {path.length > 0 ? (
-
- {path.map((item, i) => (
-
- {i > 0 && / }
-
- {item.name}
-
-
- ))}
-
- ) : (
-
{placeholder}
- )}
-
-
-
-
-
- {isOpen && (
- <>
- setIsOpen(false)}
- />
-
-
-
-
- setSearchQuery(e.target.value)}
- placeholder="Filtrer les carnets..."
- className="w-full bg-white border border-border rounded-lg pl-9 pr-4 py-2 text-xs outline-none focus:border-blueprint transition-colors"
- />
-
-
-
-
- {renderTree(undefined)}
-
-
-
-
- Structure des carnets
-
- setIsOpen(false)}
- className="text-[10px] font-bold text-blueprint hover:underline"
- >
- Fermer
-
-
-
- >
- )}
-
-
- );
-};
diff --git a/architectural-grid10/src/components/NotebooksView.tsx b/architectural-grid10/src/components/NotebooksView.tsx
deleted file mode 100644
index 853bbc5..0000000
--- a/architectural-grid10/src/components/NotebooksView.tsx
+++ /dev/null
@@ -1,469 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Search,
- Share2,
- Pin,
- ChevronRight,
- ArrowLeft,
- MoreVertical,
- Sparkles,
- Tag as TagIcon,
- X,
- BookOpen,
- Edit3,
- Eye,
- Trash2
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet, Tag } from '../types';
-import { SlashMenu } from './SlashMenu';
-
-interface NotebooksViewProps {
- activeNoteId: string | null;
- activeCarnet: Carnet | undefined;
- filteredNotes: Note[];
- activeNote: Note | undefined;
- setActiveNoteId: (id: string | null) => void;
- togglePin: (id: string) => void;
- setShowNewNoteModal: (show: boolean) => void;
- isAISidebarOpen: boolean;
- setIsAISidebarOpen: (open: boolean) => void;
- selectedTagIds: string[];
- setSelectedTagIds: (ids: string[]) => void;
- allNotes: Note[];
- activeCarnetId: string;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteNote: (id: string) => void;
-}
-
-export const NotebooksView: React.FC = ({
- activeNoteId,
- activeCarnet,
- filteredNotes,
- activeNote,
- setActiveNoteId,
- togglePin,
- setShowNewNoteModal,
- isAISidebarOpen,
- setIsAISidebarOpen,
- selectedTagIds,
- setSelectedTagIds,
- allNotes,
- activeCarnetId,
- setShowNewCarnetModal,
- onDeleteNote
-}) => {
- const [isTagsExpanded, setIsTagsExpanded] = React.useState(false);
- const [tagSearchQuery, setTagSearchQuery] = React.useState('');
- const [isEditing, setIsEditing] = React.useState(false);
- const [slashMenu, setSlashMenu] = React.useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const insertCommand = (type: string) => {
- console.log(`Command selected: ${type}`);
- setSlashMenu(null);
- };
-
- const availableTags = React.useMemo(() => {
- const carnetNotes = allNotes.filter(n => n.carnetId === activeCarnetId);
- const tagsMap = new Map();
- carnetNotes.forEach(note => {
- note.tags?.forEach(tag => {
- tagsMap.set(tag.id, tag);
- });
- });
- return Array.from(tagsMap.values()).sort((a, b) => {
- // AI tags first, then alphabetical
- if (a.type === 'ai' && b.type !== 'ai') return -1;
- if (a.type !== 'ai' && b.type === 'ai') return 1;
- return a.label.localeCompare(b.label);
- });
- }, [allNotes, activeCarnetId]);
-
- const visibleTags = React.useMemo(() => {
- let filtered = availableTags;
- if (tagSearchQuery) {
- filtered = availableTags.filter(t =>
- t.label.toLowerCase().includes(tagSearchQuery.toLowerCase())
- );
- } else if (!isTagsExpanded) {
- filtered = availableTags.slice(0, 10);
- // Ensure selected tags are always visible even if not in the first 10
- selectedTagIds.forEach(id => {
- if (!filtered.find(t => t.id === id)) {
- const tag = availableTags.find(t => t.id === id);
- if (tag) filtered.push(tag);
- }
- });
- }
- return filtered;
- }, [availableTags, isTagsExpanded, tagSearchQuery, selectedTagIds]);
-
- const toggleTag = (tagId: string) => {
- if (selectedTagIds.includes(tagId)) {
- setSelectedTagIds(selectedTagIds.filter(id => id !== tagId));
- } else {
- setSelectedTagIds([...selectedTagIds, tagId]);
- }
- };
-
- if (!activeNoteId) {
- return (
-
-
-
-
-
- {filteredNotes.map((note, index) => (
-
setActiveNoteId(note.id)}
- >
-
-
- {note.isPinned && }
- {note.title}
-
-
-
{
- e.stopPropagation();
- togglePin(note.id);
- }}
- className={`p-2 rounded-full transition-all ${note.isPinned ? 'text-amber-600 bg-amber-50' : 'opacity-0 group-hover:opacity-60 hover:bg-slate-100 text-ink'}`}
- >
-
-
-
{
- e.stopPropagation();
- onDeleteNote(note.id);
- }}
- className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-rose-50 text-rose-500 transition-all"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- {note.tags?.map(tag => (
-
- {tag.type === 'ai' && }
- {tag.label}
-
- ))}
-
-
- {note.content}
-
-
Read more
-
-
-
- ))}
- {filteredNotes.length === 0 && (
-
-
This notebook is waiting for its first vision.
-
setShowNewNoteModal(true)}
- className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all"
- >
- Begin Drawing
-
-
- )}
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
setActiveNoteId(null)}
- className="flex items-center gap-2 text-ink hover:opacity-60 transition-opacity"
- >
-
- Back to collection
-
-
-
setIsEditing(!isEditing)}
- className={`flex items-center gap-2 px-4 py-1.5 rounded-lg border transition-all duration-300
- ${isEditing ? 'bg-blueprint text-white border-blueprint shadow-lg shadow-blueprint/20' : 'border-border text-ink hover:bg-slate-50'}`}
- >
- {isEditing ? : }
- {isEditing ? 'Visualiser' : 'Modifier'}
-
-
togglePin(activeNoteId!)}
- className={`p-2 rounded-full transition-all ${activeNote?.isPinned ? 'text-amber-600 bg-amber-50 dark:bg-ochre/10' : 'text-muted-ink hover:text-ink'}`}
- title={activeNote?.isPinned ? "Unpin note" : "Pin note"}
- >
-
-
-
setIsAISidebarOpen(!isAISidebarOpen)}
- className={`flex items-center gap-2 px-3 py-1.5 rounded-full border transition-all duration-300
- ${isAISidebarOpen ? 'bg-ink text-paper border-ink' : 'border-border text-ink hover:bg-white/50 dark:hover:bg-white/5'}`}
- >
-
- AI Assistant
-
-
-
-
-
-
-
-
-
-
-
-
- {slashMenu?.isOpen && (
- insertCommand(type)}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
-
-
-
- {activeCarnet?.name}
-
- {activeNote?.date}
-
-
- {isEditing ? (
-
- ) : (
-
- {activeNote?.title}
-
- )}
-
-
- {activeNote?.tags?.map(tag => (
-
- {tag.type === 'ai' &&
}
- {tag.label}
- {tag.type === 'ai' && (
-
- )}
-
- ))}
-
-
-
-
-
-
-
-
-
- {isEditing ? (
-
- ) : (
-
-
- {activeNote?.content.split('.')[0]}.
-
-
-
- {activeNote?.content.split('\n').map((line, i) => (
-
- {line}
-
- ))}
- {activeNote?.id.startsWith('n-') && (
-
- Architectural grids serve as the invisible scaffolding upon which spatial experiences are constructed. Beyond mere structural repetition, they facilitate a rhythmic dialogue between materiality and void. In this exploration, we examine how light fractures these rigid boundaries, creating a dynamic interplay that evolves with the passage of time.
-
- )}
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/SettingsView.tsx b/architectural-grid10/src/components/SettingsView.tsx
deleted file mode 100644
index 57b3981..0000000
--- a/architectural-grid10/src/components/SettingsView.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import { SettingsTab } from '../types';
-import { SettingsHeader } from './settings/SettingsHeader';
-import { GeneralTab } from './settings/GeneralTab';
-import { AITab } from './settings/AITab';
-import { AppearanceTab } from './settings/AppearanceTab';
-
-interface SettingsViewProps {
- activeSettingsTab: SettingsTab;
- setActiveSettingsTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsView: React.FC = ({
- activeSettingsTab,
- setActiveSettingsTab
-}) => {
- return (
-
-
-
-
-
-
-
-
-
- {activeSettingsTab === 'general' && (
-
- )}
-
- {activeSettingsTab === 'ai' && (
-
- )}
-
- {activeSettingsTab === 'appearance' && (
-
- )}
-
- {['profile', 'data', 'mcp', 'about'].includes(activeSettingsTab) && (
-
-
- ?
-
-
-
Section en développement
-
Le module {activeSettingsTab} sera disponible prochainement.
-
-
- )}
-
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/Sidebar.tsx b/architectural-grid10/src/components/Sidebar.tsx
deleted file mode 100644
index c08a10b..0000000
--- a/architectural-grid10/src/components/Sidebar.tsx
+++ /dev/null
@@ -1,450 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Archive,
- Settings,
- ChevronRight,
- BookOpen,
- Bot,
- Microscope,
- Activity,
- Pin,
- Moon,
- Sun,
- Bell,
- Lock,
- Edit3,
- Trash2,
- Users,
- Clock
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { NavigationView, Carnet, Note } from '../types';
-
-interface NoteLinkProps {
- note: Note;
- isActive: boolean;
- onClick: () => void;
-}
-
-const NoteLink: React.FC = ({ note, isActive, onClick }) => (
-
-
- {note.isPinned && }
-
-);
-
-interface SidebarItemProps {
- carnet: Carnet;
- isActive: boolean;
- notes: Note[];
- activeNoteId: string | null;
- onCarnetClick: () => void;
- onNoteClick: (noteId: string) => void;
- onAddSubCarnet: () => void;
- onRename: () => void;
- onDelete: () => void;
- children?: React.ReactNode;
- level: number;
- isExpanded: boolean;
- toggleExpand: () => void;
-}
-
-const SidebarItem: React.FC = ({
- carnet,
- isActive,
- notes,
- activeNoteId,
- onCarnetClick,
- onNoteClick,
- onAddSubCarnet,
- onRename,
- onDelete,
- children,
- level,
- isExpanded,
- toggleExpand
-}) => {
- const hasChildren = React.Children.count(children) > 0;
-
- return (
-
-
- {/* Hierarchy Guide Line */}
- {level > 0 && (
-
- )}
- {level > 0 && (
-
- )}
-
-
- {hasChildren ? (
-
{
- e.stopPropagation();
- toggleExpand();
- }}
- className="p-1 hover:bg-ink/5 dark:hover:bg-white/5 rounded-md transition-colors text-muted-ink"
- >
-
-
-
-
- ) : (
-
// Spacer for alignment
- )}
-
- {/* Hierarchy Connector Line */}
- {hasChildren && level > 0 && (
-
- )}
-
-
- {/* active indicator dot */}
- {isActive && (
-
- )}
-
-
- {carnet.initial}
-
-
-
- {carnet.name}
-
- {carnet.isPrivate && }
-
-
-
-
{
- e.stopPropagation();
- onAddSubCarnet();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Add sub-carnet"
- >
-
-
-
{
- e.stopPropagation();
- onRename();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Rename"
- >
-
-
-
{
- e.stopPropagation();
- onDelete();
- }}
- className="p-1 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md transition-all text-concrete hover:text-red-500"
- title="Delete"
- >
-
-
-
- {notes.length > 0 && (
-
- {notes.length}
-
- )}
-
-
-
-
-
-
- {(isExpanded || (isActive && !hasChildren)) && (
-
-
- {/* Vertical line for nested content */}
-
-
-
- {children}
- {isActive && !hasChildren && notes.map(note => (
-
onNoteClick(note.id)}
- />
- ))}
- {isActive && !hasChildren && notes.length === 0 && (
-
- No notes found
-
- )}
-
-
-
- )}
-
-
- );
-};
-
-interface SidebarProps {
- activeView: NavigationView;
- isDarkMode: boolean;
- setIsDarkMode: (val: boolean) => void;
- setActiveView: (view: NavigationView) => void;
- carnets: Carnet[];
- notes: Note[];
- activeCarnetId: string;
- activeNoteId: string | null;
- setActiveCarnetId: (id: string) => void;
- setActiveNoteId: (id: string | null) => void;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteCarnet: (id: string) => void;
-}
-
-export const Sidebar: React.FC = ({
- activeView,
- isDarkMode,
- setIsDarkMode,
- setActiveView,
- carnets,
- notes,
- activeCarnetId,
- activeNoteId,
- setActiveCarnetId,
- setActiveNoteId,
- setShowNewCarnetModal,
- onDeleteCarnet
-}) => {
- const [expandedIds, setExpandedIds] = React.useState>(new Set(['4'])); // Default expand Research
-
- const toggleExpand = (id: string) => {
- const newSet = new Set(expandedIds);
- if (newSet.has(id)) newSet.delete(id);
- else newSet.add(id);
- setExpandedIds(newSet);
- };
-
- const renderCarnetTree = (parentId: string | undefined = undefined, level: number = 0) => {
- return carnets
- .filter(c => c.parentId === parentId && !c.isDeleted)
- .map(carnet => (
- n.carnetId === carnet.id && !n.isDeleted)}
- activeNoteId={activeNoteId}
- level={level}
- isExpanded={expandedIds.has(carnet.id)}
- toggleExpand={() => toggleExpand(carnet.id)}
- onAddSubCarnet={() => {
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- setShowNewCarnetModal(true, carnet.id);
- }}
- onRename={() => {
- setShowNewCarnetModal(true, undefined, true, carnet.id);
- }}
- onDelete={() => {
- onDeleteCarnet(carnet.id);
- }}
- onCarnetClick={() => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(null);
- // Auto expand when clicking
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- }}
- onNoteClick={(id) => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(id);
- }}
- >
- {renderCarnetTree(carnet.id, level + 1)}
-
- ));
- };
-
- return (
-
-
-
- A
-
-
-
setIsDarkMode(!isDarkMode)}
- className="p-2 text-muted-ink hover:text-ink transition-all bg-white/50 dark:bg-white/10 rounded-full border border-border dark:border-white/10"
- >
- {isDarkMode ? : }
-
-
-
-
-
- 3
-
-
-
-
- setActiveView('notebooks')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'notebooks' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Carnets"
- >
-
-
- setActiveView('reminders')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'reminders' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Rappels"
- >
-
-
- setActiveView('agents')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'agents' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Agents"
- >
-
-
-
-
-
-
-
- {activeView === 'notebooks' ? (
-
-
-
- Architecture Grid
-
-
setShowNewCarnetModal(true)}
- className="p-1 hover:bg-paper dark:hover:bg-white/5 rounded-md text-concrete hover:text-ink transition-colors"
- title="New Carnet"
- >
-
-
-
-
-
- {renderCarnetTree()}
-
-
- ) : activeView === 'shared' ? (
-
-
- Partagé avec moi
-
-
-
-
Aucun document partagé pour le moment.
-
-
- ) : activeView === 'reminders' ? (
-
-
- Rappels programmés
-
-
-
-
Aucun rappel actif.
-
-
- ) : activeView === 'agents' ? (
-
-
- Intelligence OS
-
-
- {[
- { id: 'a1', name: 'Mes Agents', icon:
},
- { id: 'a2', name: 'Le Lab AI', icon:
},
- { id: 'a3', name: 'Activités', icon:
},
- ].map(item => (
-
-
- {item.icon}
-
- {item.name}
-
- ))}
-
-
- ) : null}
-
-
-
-
-
setActiveView('shared')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'shared' ? 'bg-blueprint/5 text-blueprint' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Partagé
-
-
-
-
- Archives
-
-
-
setActiveView('trash')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'trash' ? 'bg-rose-50 text-rose-500' : 'text-muted-ink hover:text-rose-500 hover:bg-rose-50/50'}`}
- >
-
- Corbeille
- {notes.some(n => n.isDeleted) && (
-
- )}
-
-
-
-
-
setActiveView('settings')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'settings' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Paramètres
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/SlashMenu.tsx b/architectural-grid10/src/components/SlashMenu.tsx
deleted file mode 100644
index a715c58..0000000
--- a/architectural-grid10/src/components/SlashMenu.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import {
- Heading1,
- Heading2,
- List,
- Quote,
- Code,
- Image as ImageIcon,
- Type,
- Sparkles
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface SlashMenuProps {
- position: { top: number; left: number };
- onSelect: (type: string) => void;
- onClose: () => void;
-}
-
-export const SlashMenu: React.FC = ({ position, onSelect, onClose }) => {
- const commands = [
- { id: 'h1', label: 'Titre Principal', icon: , desc: 'Grand titre de section' },
- { id: 'h2', label: 'Sous-titre', icon: , desc: 'Titre de niveau 2' },
- { id: 'bullet', label: 'Liste à puces', icon:
, desc: 'Liste simple' },
- { id: 'quote', label: 'Citation', icon:
, desc: 'Bloc de texte mis en avant' },
- { id: 'code', label: 'Bloc de Code', icon: , desc: 'Code ou texte technique' },
- { id: 'image', label: 'Image', icon: , desc: 'Insérer un visuel' },
- { id: 'ai-summary', label: 'Résumé IA', icon: , desc: 'Générer un résumé court', special: true },
- ];
-
- return (
- <>
-
-
-
- Commandes rapides
-
-
- {commands.map((cmd) => (
-
onSelect(cmd.id)}
- className="w-full flex items-start gap-3 px-3 py-2 hover:bg-paper dark:hover:bg-white/5 transition-colors group text-left"
- >
-
- {cmd.icon}
-
-
-
{cmd.label}
-
{cmd.desc}
-
-
- ))}
-
-
- >
- );
-};
diff --git a/architectural-grid10/src/components/TrashView.tsx b/architectural-grid10/src/components/TrashView.tsx
deleted file mode 100644
index dc62521..0000000
--- a/architectural-grid10/src/components/TrashView.tsx
+++ /dev/null
@@ -1,218 +0,0 @@
-import React from 'react';
-import {
- Trash2,
- RotateCcw,
- X,
- FileText,
- Folder,
- Search,
- ChevronRight,
- Clock,
- AlertCircle
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet } from '../types';
-
-interface TrashViewProps {
- deletedNotes: Note[];
- deletedCarnets: Carnet[];
- onRestoreNote: (id: string) => void;
- onRestoreCarnet: (id: string) => void;
- onPermanentDeleteNote: (id: string) => void;
- onPermanentDeleteCarnet: (id: string) => void;
- onEmptyTrash: () => void;
-}
-
-export const TrashView: React.FC = ({
- deletedNotes,
- deletedCarnets,
- onRestoreNote,
- onRestoreCarnet,
- onPermanentDeleteNote,
- onPermanentDeleteCarnet,
- onEmptyTrash
-}) => {
- const [searchQuery, setSearchQuery] = React.useState('');
- const [filterType, setFilterType] = React.useState<'all' | 'notes' | 'carnets'>('all');
-
- const getDaysRemaining = (dateString?: string) => {
- if (!dateString) return 30;
- const deletedDate = new Date(dateString);
- const now = new Date();
- const diffTime = now.getTime() - deletedDate.getTime();
- const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
- return Math.max(0, 30 - diffDays);
- };
-
- const filteredItems = React.useMemo(() => {
- const items = [
- ...deletedNotes.map(n => ({ ...n, itemType: 'note' as const })),
- ...deletedCarnets.map(c => ({ ...c, itemType: 'carnet' as const }))
- ];
-
- return items
- .filter(item => {
- const matchesSearch = ('title' in item ? item.title : item.name).toLowerCase().includes(searchQuery.toLowerCase());
- const matchesType = filterType === 'all' || (filterType === 'notes' && item.itemType === 'note') || (filterType === 'carnets' && item.itemType === 'carnet');
- return matchesSearch && matchesType;
- })
- .sort((a, b) => {
- const dateA = a.deletedAt ? new Date(a.deletedAt).getTime() : 0;
- const dateB = b.deletedAt ? new Date(b.deletedAt).getTime() : 0;
- return dateB - dateA;
- });
- }, [deletedNotes, deletedCarnets, searchQuery, filterType]);
-
- return (
-
-
-
-
-
- Corbeille
-
-
- Auto-suppression après 30 jours
-
-
-
- {filteredItems.length > 0 && (
-
{
- if (window.confirm('Vider la corbeille ? Cette action est irréversible.')) {
- onEmptyTrash();
- }
- }}
- className="px-6 py-3 bg-paper border border-border text-rose-500 rounded-2xl text-[10px] font-bold uppercase tracking-widest hover:bg-rose-50 hover:border-rose-100 transition-all shadow-sm"
- >
- Vider tout
-
- )}
-
-
-
-
-
- setSearchQuery(e.target.value)}
- className="w-full bg-white dark:bg-white/5 border border-border/40 rounded-2xl pl-12 pr-6 py-4 text-sm outline-none focus:ring-4 ring-ink/5 transition-all shadow-sm"
- />
-
-
-
- {(['all', 'notes', 'carnets'] as const).map((type) => (
- setFilterType(type)}
- className={`px-6 py-3 rounded-xl text-[10px] font-bold uppercase tracking-widest transition-all
- ${filterType === type ? 'bg-ink text-paper shadow-lg' : 'text-concrete hover:text-ink'}`}
- >
- {type === 'all' ? 'Tous' : type === 'notes' ? 'Notes' : 'Carnets'}
-
- ))}
-
-
-
-
-
- {filteredItems.length > 0 ? (
-
-
- {filteredItems.map((item) => {
- const daysLeft = getDaysRemaining(item.deletedAt);
- return (
-
- {/* Countdown Progress Bar */}
-
-
-
-
-
-
- {item.itemType === 'note' ? : }
-
-
- item.itemType === 'note' ? onRestoreNote(item.id) : onRestoreCarnet(item.id)}
- className="flex items-center gap-2 px-4 py-2 bg-emerald-50 text-emerald-600 rounded-xl text-[10px] font-bold uppercase tracking-widest hover:bg-emerald-100 transition-colors"
- >
- Restaurer
-
- item.itemType === 'note' ? onPermanentDeleteNote(item.id) : onPermanentDeleteCarnet(item.id)}
- className="p-2 hover:bg-rose-50 text-rose-500 rounded-xl transition-colors"
- title="Supprimer définitivement"
- >
-
-
-
-
-
-
-
- {'title' in item ? item.title : item.name}
-
-
-
- {daysLeft} JOURS RESTANTS
-
-
- {('deletedAt' in item && item.deletedAt) ? new Date(item.deletedAt).toLocaleDateString() : ''}
-
-
-
-
- {item.itemType === 'note' && 'content' in item ? (
-
- {item.content.replace(/[#*`]/g, '')}
-
- ) : (
-
-
- Contenu du dossier préservé
-
-
- )}
-
- );
- })}
-
-
- ) : (
-
-
-
-
-
-
Corbeille vide
-
- Les éléments que vous supprimez apparaîtront ici. Ils seront conservés pendant 30 jours avant suppression définitive.
-
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/settings/AITab.tsx b/architectural-grid10/src/components/settings/AITab.tsx
deleted file mode 100644
index 607c84e..0000000
--- a/architectural-grid10/src/components/settings/AITab.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-import React from 'react';
-import { Sparkles, Edit3, MessageCircle, Languages, Tag, History, FlaskConical } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AISettingCard = ({ icon, title, description, defaultChecked = false }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
-
-
-);
-
-export const AITab: React.FC = () => {
- return (
-
-
-
Configurez vos fonctionnalités IA et préférences
-
-
-
Fonctionnalités IA
-
-
}
- title="Suggestions de titre"
- description="Suggérer des titres pour les notes sans titre après 50+ mots"
- defaultChecked
- />
-
}
- title="IA Note"
- description="Active le bouton de chat IA et les outils d'amélioration du texte"
- defaultChecked
- />
-
}
- title="💡 J'ai remarqué quelque chose..."
- description="Aperçu quotidien de vos notes"
- defaultChecked
- />
-
}
- title="Détection de langue"
- description="Détecte automatiquement la langue de vos notes"
- defaultChecked
- />
-
}
- title="Suggestion des labels"
- description="Suggère et applique des étiquettes automatiquement à vos notes"
- defaultChecked
- />
-
}
- title="Historique des notes"
- description="Active les snapshots de versions et la restauration depuis History"
- defaultChecked
- />
-
-
-
-
- {/* Fréquence */}
-
-
-
Fréquence
-
Fréquence d'analyse des connexions
-
-
-
-
- {/* Mode d'historique */}
-
-
-
Mode d'historique
-
Gestion des snapshots
-
-
-
-
-
-
-
Manuel (bouton commit)
-
Créer des snapshots manuellement
-
-
-
-
-
-
-
Automatique (intelligent)
-
Snapshots automatiques avec détection
-
-
-
-
-
-
- {/* Mode Démo */}
-
-
-
-
-
-
-
- 🧪 Mode Démo
-
-
Accélère Memory Echo pour les tests. Les connexions apparaissent instantanément.
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/settings/AppearanceTab.tsx b/architectural-grid10/src/components/settings/AppearanceTab.tsx
deleted file mode 100644
index ba9ccdf..0000000
--- a/architectural-grid10/src/components/settings/AppearanceTab.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React from 'react';
-import { Palette, Type, LayoutGrid, Maximize } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AppearanceSelect = ({ icon, title, description, options, defaultValue }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
- {options.map((opt: string) => (
- {opt}
- ))}
-
-
-
-
-);
-
-export const AppearanceTab: React.FC = () => {
- return (
-
-
-
Personnaliser l'apparence de l'application
-
-
-
}
- title="Thème"
- description="Sélectionner le mode visuel"
- options={['Clair', 'Sombre', 'Système']}
- defaultValue="Clair"
- />
-
}
- title="Taille de la police"
- description="Ajustez la lisibilité globale de l'interface"
- options={['Petite', 'Moyenne', 'Grande']}
- defaultValue="Moyenne"
- />
-
}
- title="Famille de polices"
- description="La typographie définit l'âme de l'application"
- options={['Inter', 'JetBrains Mono', 'Public Sans', 'Outfit']}
- defaultValue="JetBrains Mono"
- />
-
}
- title="Affichage des notes"
- description="Gestion visuelle de la grille de composition"
- options={['Cartes (grille)', 'Liste', 'Tableau']}
- defaultValue="Cartes (grille)"
- />
-
}
- title="Taille des notes"
- description="Structure de la mise en page des éléments"
- options={['Taille uniforme', 'Variable (Masonry)']}
- defaultValue="Taille uniforme"
- />
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/settings/GeneralTab.tsx b/architectural-grid10/src/components/settings/GeneralTab.tsx
deleted file mode 100644
index 749afbd..0000000
--- a/architectural-grid10/src/components/settings/GeneralTab.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react';
-import { Globe, Bell } from 'lucide-react';
-import { motion } from 'motion/react';
-
-export const GeneralTab: React.FC = () => {
- return (
-
-
-
Paramètres généraux de l'application
-
-
- {/* Langue */}
-
-
-
-
-
-
-
Langue
-
Sélectionner une langue
-
-
-
-
-
- Français
- English
- Español
-
-
-
-
-
- {/* Notifications */}
-
-
-
-
-
-
-
Notifications
-
Gérez vos préférences de notifications
-
-
-
-
-
-
-
Notifications par email
-
Recevoir des notifications importantes par email
-
-
-
-
-
-
-
-
-
-
Notifications bureau
-
Recevoir des notifications dans votre navigateur
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid10/src/components/settings/SettingsHeader.tsx b/architectural-grid10/src/components/settings/SettingsHeader.tsx
deleted file mode 100644
index db56e30..0000000
--- a/architectural-grid10/src/components/settings/SettingsHeader.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import { Settings, Sparkles, Palette, User, Database, Code, Info } from 'lucide-react';
-import { motion } from 'motion/react';
-import { SettingsTab } from '../../types';
-
-interface SettingsHeaderProps {
- activeTab: SettingsTab;
- setActiveTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsHeader: React.FC = ({ activeTab, setActiveTab }) => {
- const tabs = [
- { id: 'general', label: 'Paramètres généraux', icon: },
- { id: 'ai', label: 'Paramètres IA', icon: },
- { id: 'appearance', label: 'Apparence', icon: },
- { id: 'profile', label: 'Profil', icon: },
- { id: 'data', label: 'Gestion des données', icon: },
- { id: 'mcp', label: 'Paramètres MCP', icon: },
- { id: 'about', label: 'À propos', icon: },
- ];
-
- return (
-
- );
-};
diff --git a/architectural-grid10/src/constants.ts b/architectural-grid10/src/constants.ts
deleted file mode 100644
index 9004653..0000000
--- a/architectural-grid10/src/constants.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Carnet, Note } from './types';
-
-export const CARNETS: Carnet[] = [
- { id: '1', name: 'Daily Notes', initial: 'D', type: 'Private', isPrivate: true },
- { id: '2', name: 'Project: Neo', initial: 'P', type: 'Project' },
- { id: '3', name: 'Shared Docs', initial: 'S', type: 'Shared' },
- { id: '4', name: 'Architecture Research', initial: 'A', type: 'Project' },
- { id: '5', name: 'History of Architecture', initial: 'H', type: 'Project', parentId: '4' },
- { id: '6', name: 'Modernism', initial: 'M', type: 'Project', parentId: '5' },
- { id: '7', name: 'Sustainable Design', initial: 'S', type: 'Project', parentId: '4' },
-];
-
-export const ALL_NOTES: Note[] = [
- {
- id: 'n1',
- carnetId: '4',
- title: 'Grid Systems',
- date: 'Oct 26, 2024',
- content: 'Grid Systems is streathen in ognitiacs clesign and simulhere desipmalt: complded structurer and manamateriai-s: ci arevenuatingly used, asiller straterty of insaee to the tmn and usaes of disrension, architecture of emiornabious tracious structures.',
- imageUrl: 'https://images.unsplash.com/photo-1503387762-592dea58ef23?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't1', label: 'Architecture', type: 'user' },
- { id: 't2', label: 'Systems', type: 'ai' }
- ]
- },
- {
- id: 'n2',
- carnetId: '4',
- title: 'Materiality',
- date: 'Oct 24, 2024',
- content: 'Materiality is combinated by relliaitic structureirs measure of plastics, natural, materials and priotical structures. Materialed coasts erabiocera alann light spaces and octicm employed design on thodolen of materiality, and tohlite tersev/ used in the gridin structures en obain materials, coms pathetic structure.',
- imageUrl: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't3', label: 'Materials', type: 'user' },
- { id: 't4', label: 'Sustainabilty', type: 'ai' }
- ]
- },
- {
- id: 'n3',
- carnetId: '4',
- title: 'Light & Space',
- date: 'Oct 22, 2024',
- content: 'Light & Space is a creaivity of light & Space inralicated in sizazant or dark crotrcning and netrescenations of avant trurme sivonpaltures for in inncr-en allimativefiting is cerriadating and sityle.',
- imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't5', label: 'Lighting', type: 'user' },
- { id: 't6', label: 'Atmosphere', type: 'ai' }
- ]
- },
- {
- id: 'n4',
- carnetId: '2',
- title: 'Neo-Brutalism study',
- date: 'Sep 12, 2024',
- content: 'Exploring the raw aesthetic of neo-brutalism in urban environments. Focus on concrete textures and massive forms.',
- imageUrl: 'https://images.unsplash.com/photo-1518005020951-eccb494ad742?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't7', label: 'Brutalism', type: 'user' },
- { id: 't8', label: 'Urban', type: 'ai' }
- ]
- }
-];
diff --git a/architectural-grid10/src/index.css b/architectural-grid10/src/index.css
deleted file mode 100644
index 52b4b7c..0000000
--- a/architectural-grid10/src/index.css
+++ /dev/null
@@ -1,98 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap');
-@import "tailwindcss";
-
-@theme {
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
- --font-serif: "Playfair Display", serif;
- --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
-
- /* Foundation */
- --color-paper: #F2F0E9;
- --color-ink: #1C1C1C;
- --color-muted-ink: rgba(28, 28, 28, 0.6);
- --color-border: rgba(28, 28, 28, 0.1);
- --color-concrete: #8D8D8D;
-
- /* Architectural Accents */
- --color-blueprint: #75B2D6;
- --color-slate: #4A4E69;
- --color-ochre: #D4A373;
- --color-sage: #A3B18A;
- --color-rust: #9B2226;
- --color-glass: rgba(255, 255, 255, 0.4);
-
- /* Dark Theme Aliases */
- --color-dark-paper: #0D0D0D;
- --color-dark-ink: #EAEAEA;
- --color-dark-muted: rgba(234, 234, 234, 0.5);
- --color-dark-border: rgba(234, 234, 234, 0.1);
-}
-
-@layer base {
- body {
- @apply bg-paper text-ink font-sans antialiased transition-colors duration-500;
- }
-
- .dark body {
- @apply bg-dark-paper;
- }
-
- .dark {
- --color-paper: #121212;
- --color-ink: #EAEAEA;
- --color-muted-ink: rgba(234, 234, 234, 0.6);
- --color-border: rgba(255, 255, 255, 0.08);
- --color-glass: rgba(0, 0, 0, 0.4);
- --color-concrete: #555555;
- }
-}
-
-.paper-texture {
- background-color: var(--color-paper);
- background-image: url("https://www.transparenttextures.com/patterns/natural-paper.png");
-}
-
-/* Custom Scrollbar - Architectural Minimalist */
-.custom-scrollbar::-webkit-scrollbar {
- width: 3px;
-}
-
-.custom-scrollbar::-webkit-scrollbar-track {
- background: transparent;
-}
-
-.custom-scrollbar::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.08);
- border-radius: 10px;
-}
-
-.custom-scrollbar:hover::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.2);
-}
-
-.ai-glass {
- background: rgba(255, 255, 255, 0.85);
- backdrop-filter: blur(20px);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .ai-glass {
- background: rgba(30, 30, 30, 0.85);
- border: 1px solid rgba(255, 255, 255, 0.1);
-}
-
-.sidebar-shadow {
- box-shadow: 1px 0 10px rgba(0, 0, 0, 0.05);
-}
-
-.active-nav-item {
- background: linear-gradient(to right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.4));
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .active-nav-item {
- background: rgba(255, 255, 255, 0.08);
- border: 1px solid rgba(255, 255, 255, 0.1);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
-}
diff --git a/architectural-grid10/src/types.ts b/architectural-grid10/src/types.ts
deleted file mode 100644
index a2505dd..0000000
--- a/architectural-grid10/src/types.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-export type NavigationView = 'notebooks' | 'agents' | 'settings' | 'shared' | 'reminders' | 'trash';
-export type AITone = 'Professional' | 'Creative' | 'Academic' | 'Casual';
-export type AITab = 'discussion' | 'actions' | 'resources';
-export type SettingsTab = 'general' | 'ai' | 'appearance' | 'profile' | 'data' | 'mcp' | 'about';
-
-export interface Tag {
- id: string;
- label: string;
- type: 'ai' | 'user';
-}
-
-export interface Note {
- id: string;
- carnetId: string;
- title: string;
- content: string;
- imageUrl: string;
- date: string;
- tags: Tag[];
- isPinned?: boolean;
- isDeleted?: boolean;
- deletedAt?: string;
-}
-
-export interface Carnet {
- id: string;
- name: string;
- initial: string;
- type: 'Private' | 'Project' | 'Shared';
- isPrivate?: boolean;
- parentId?: string;
- isDeleted?: boolean;
- deletedAt?: string;
-}
diff --git a/architectural-grid11/.env.example b/architectural-grid11/.env.example
deleted file mode 100644
index 7a550fe..0000000
--- a/architectural-grid11/.env.example
+++ /dev/null
@@ -1,9 +0,0 @@
-# GEMINI_API_KEY: Required for Gemini AI API calls.
-# AI Studio automatically injects this at runtime from user secrets.
-# Users configure this via the Secrets panel in the AI Studio UI.
-GEMINI_API_KEY="MY_GEMINI_API_KEY"
-
-# APP_URL: The URL where this applet is hosted.
-# AI Studio automatically injects this at runtime with the Cloud Run service URL.
-# Used for self-referential links, OAuth callbacks, and API endpoints.
-APP_URL="MY_APP_URL"
diff --git a/architectural-grid11/.gitignore b/architectural-grid11/.gitignore
deleted file mode 100644
index 5a86d2a..0000000
--- a/architectural-grid11/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-node_modules/
-build/
-dist/
-coverage/
-.DS_Store
-*.log
-.env*
-!.env.example
diff --git a/architectural-grid11/BRAINSTORM_PROMPT.md b/architectural-grid11/BRAINSTORM_PROMPT.md
deleted file mode 100644
index dfb73b8..0000000
--- a/architectural-grid11/BRAINSTORM_PROMPT.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# IA Agent Coordination Prompt: Brainstorm Wave Integration
-
-## Context
-You are tasked with continuing the development of the "Architectural Grid" application. The core feature "Wave Brainstorming" has been partially implemented with a full-stack architecture (Express + React).
-
-## Current State
-- **Backend (`server.ts`)**: Implements session management, idea generation via Gemini, and expansion logic. Stores data in memory.
-- **Frontend (`BrainstormView.tsx`)**: Manages the life cycle of a brainstorm. Integrates with a Radial D3 Canvas.
-- **Visuals (`WaveCanvas.tsx`)**: Implements a radial force-directed graph with state-aware styling (dismissed/converted).
-- **Navigation**: "Brainstorm Wave" is accessible from the Sidebar. A quick entry point exists from Note Detail view.
-
-## Your Task: Sidebar & Navigation Cleanup
-1. **Source Code Review**: Read `src/components/Sidebar.tsx`, `src/App.tsx`, and `server.ts` to understand how views are toggled.
-2. **Sidebar Links**: Ensure "Brainstorm Wave", "Semantic Network", and "Temporal Forecast" are correctly grouped and labeled in the Sidebar under a "Creative & AI" section.
-3. **Agent View Sidebar**: The user specifically requested these links to be also accessible from the "Sidebar of the Agent view". Review `src/components/AgentsView.tsx` and ensure it has consistent navigation or deep links to these advanced features.
-4. **Semantic Network & Temporal Forecast**: These views are currently placeholders. Ensure the routing and sidebar active state detection work correctly for them.
-
-## Technical Requirements
-- Maintain consistency with the **Tailwind** architectural design (concrete, paper, blueprint tokens).
-- Use **Lucide-React** icons (`Wind` for Brainstorm, `Share2` for Semantic Network, `Clock` for Temporal).
-- Ensure transitions between views are smooth using `motion/react`.
-
----
-*Copy and paste this into the next AI Agent session to ensure full context transfer.*
diff --git a/architectural-grid11/README.md b/architectural-grid11/README.md
deleted file mode 100644
index 0078184..0000000
--- a/architectural-grid11/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-# Run and deploy your AI Studio app
-
-This contains everything you need to run your app locally.
-
-View your app in AI Studio: https://ai.studio/apps/b7b577c6-4d9f-44ac-8fe1-85bc3c6d6e66
-
-## Run Locally
-
-**Prerequisites:** Node.js
-
-
-1. Install dependencies:
- `npm install`
-2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
-3. Run the app:
- `npm run dev`
diff --git a/architectural-grid11/index.html b/architectural-grid11/index.html
deleted file mode 100644
index 21dfe69..0000000
--- a/architectural-grid11/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- My Google AI Studio App
-
-
-
-
-
-
-
diff --git a/architectural-grid11/package-lock.json b/architectural-grid11/package-lock.json
deleted file mode 100644
index 1a99b30..0000000
--- a/architectural-grid11/package-lock.json
+++ /dev/null
@@ -1,5497 +0,0 @@
-{
- "name": "react-example",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "react-example",
- "version": "0.0.0",
- "dependencies": {
- "@google/genai": "^1.29.0",
- "@tailwindcss/vite": "^4.1.14",
- "@types/d3": "^7.4.3",
- "@types/uuid": "^10.0.0",
- "@vitejs/plugin-react": "^5.0.4",
- "d3": "^7.9.0",
- "dotenv": "^17.2.3",
- "esbuild": "^0.28.0",
- "express": "^4.21.2",
- "lucide-react": "^0.546.0",
- "motion": "^12.23.24",
- "react": "^19.0.1",
- "react-dom": "^19.0.1",
- "uuid": "^14.0.0",
- "vite": "^6.2.3"
- },
- "devDependencies": {
- "@types/express": "^4.17.21",
- "@types/node": "^22.14.0",
- "autoprefixer": "^10.4.21",
- "tailwindcss": "^4.1.14",
- "tsx": "^4.21.0",
- "typescript": "~5.8.2",
- "vite": "^6.2.3"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
- "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
- "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
- "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/remapping": "^2.3.5",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
- "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
- "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
- "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
- "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.0"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
- "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
- "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
- "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
- "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
- "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
- "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
- "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
- "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
- "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
- "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
- "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
- "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
- "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
- "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
- "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
- "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
- "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
- "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
- "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
- "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
- "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
- "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
- "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
- "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
- "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
- "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
- "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@google/genai": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz",
- "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "google-auth-library": "^10.3.0",
- "p-retry": "^4.6.2",
- "protobufjs": "^7.5.4",
- "ws": "^8.18.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@modelcontextprotocol/sdk": "^1.25.2"
- },
- "peerDependenciesMeta": {
- "@modelcontextprotocol/sdk": {
- "optional": true
- }
- }
- },
- "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==",
- "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==",
- "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==",
- "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==",
- "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==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@protobufjs/aspromise": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
- "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/base64": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
- "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/codegen": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
- "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
- }
- },
- "node_modules/@protobufjs/float": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
- "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/inquire": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz",
- "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/path": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
- "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/pool": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
- "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/utf8": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
- "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.3",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
- "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
- "license": "MIT"
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz",
- "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz",
- "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz",
- "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz",
- "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz",
- "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz",
- "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz",
- "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz",
- "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz",
- "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz",
- "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz",
- "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz",
- "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz",
- "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz",
- "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz",
- "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz",
- "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz",
- "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz",
- "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz",
- "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz",
- "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
- },
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz",
- "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz",
- "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz",
- "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz",
- "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz",
- "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz",
- "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.21.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.3.0"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz",
- "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.3.0",
- "@tailwindcss/oxide-darwin-arm64": "4.3.0",
- "@tailwindcss/oxide-darwin-x64": "4.3.0",
- "@tailwindcss/oxide-freebsd-x64": "4.3.0",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0",
- "@tailwindcss/oxide-linux-arm64-musl": "4.3.0",
- "@tailwindcss/oxide-linux-x64-gnu": "4.3.0",
- "@tailwindcss/oxide-linux-x64-musl": "4.3.0",
- "@tailwindcss/oxide-wasm32-wasi": "4.3.0",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0",
- "@tailwindcss/oxide-win32-x64-msvc": "4.3.0"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz",
- "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz",
- "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz",
- "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz",
- "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz",
- "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz",
- "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz",
- "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz",
- "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz",
- "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz",
- "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.10.0",
- "@emnapi/runtime": "^1.10.0",
- "@emnapi/wasi-threads": "^1.2.1",
- "@napi-rs/wasm-runtime": "^1.1.4",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz",
- "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz",
- "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz",
- "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.3.0",
- "@tailwindcss/oxide": "4.3.0",
- "tailwindcss": "4.3.0"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- }
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.6",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
- "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/d3": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
- "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-array": "*",
- "@types/d3-axis": "*",
- "@types/d3-brush": "*",
- "@types/d3-chord": "*",
- "@types/d3-color": "*",
- "@types/d3-contour": "*",
- "@types/d3-delaunay": "*",
- "@types/d3-dispatch": "*",
- "@types/d3-drag": "*",
- "@types/d3-dsv": "*",
- "@types/d3-ease": "*",
- "@types/d3-fetch": "*",
- "@types/d3-force": "*",
- "@types/d3-format": "*",
- "@types/d3-geo": "*",
- "@types/d3-hierarchy": "*",
- "@types/d3-interpolate": "*",
- "@types/d3-path": "*",
- "@types/d3-polygon": "*",
- "@types/d3-quadtree": "*",
- "@types/d3-random": "*",
- "@types/d3-scale": "*",
- "@types/d3-scale-chromatic": "*",
- "@types/d3-selection": "*",
- "@types/d3-shape": "*",
- "@types/d3-time": "*",
- "@types/d3-time-format": "*",
- "@types/d3-timer": "*",
- "@types/d3-transition": "*",
- "@types/d3-zoom": "*"
- }
- },
- "node_modules/@types/d3-array": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
- "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-axis": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz",
- "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-brush": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz",
- "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-chord": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz",
- "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-color": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
- "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
- "license": "MIT"
- },
- "node_modules/@types/d3-contour": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz",
- "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-array": "*",
- "@types/geojson": "*"
- }
- },
- "node_modules/@types/d3-delaunay": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
- "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-dispatch": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz",
- "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-drag": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
- "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-dsv": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz",
- "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-ease": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
- "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-fetch": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz",
- "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-dsv": "*"
- }
- },
- "node_modules/@types/d3-force": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
- "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-format": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz",
- "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-geo": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz",
- "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==",
- "license": "MIT",
- "dependencies": {
- "@types/geojson": "*"
- }
- },
- "node_modules/@types/d3-hierarchy": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz",
- "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-interpolate": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
- "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-color": "*"
- }
- },
- "node_modules/@types/d3-path": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
- "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-polygon": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz",
- "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-quadtree": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz",
- "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-random": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz",
- "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==",
- "license": "MIT"
- },
- "node_modules/@types/d3-scale": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
- "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-time": "*"
- }
- },
- "node_modules/@types/d3-scale-chromatic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
- "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==",
- "license": "MIT"
- },
- "node_modules/@types/d3-selection": {
- "version": "3.0.11",
- "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
- "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
- "license": "MIT"
- },
- "node_modules/@types/d3-shape": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
- "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-path": "*"
- }
- },
- "node_modules/@types/d3-time": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
- "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-time-format": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz",
- "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-timer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
- "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-transition": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
- "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-zoom": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
- "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-interpolate": "*",
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "license": "MIT"
- },
- "node_modules/@types/express": {
- "version": "4.17.25",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
- "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.33",
- "@types/qs": "*",
- "@types/serve-static": "^1"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "4.19.8",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
- "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/geojson": {
- "version": "7946.0.16",
- "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
- "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
- "license": "MIT"
- },
- "node_modules/@types/http-errors": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
- "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/mime": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
- "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "22.19.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
- "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/@types/qs": {
- "version": "6.15.1",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz",
- "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
- "license": "MIT"
- },
- "node_modules/@types/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
- "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/serve-static": {
- "version": "1.15.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
- "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/http-errors": "*",
- "@types/node": "*",
- "@types/send": "<1"
- }
- },
- "node_modules/@types/serve-static/node_modules/@types/send": {
- "version": "0.17.6",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
- "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/mime": "^1",
- "@types/node": "*"
- }
- },
- "node_modules/@types/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
- "license": "MIT"
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
- "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.29.0",
- "@babel/plugin-transform-react-jsx-self": "^7.27.1",
- "@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-rc.3",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.18.0"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
- "node_modules/autoprefixer": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
- "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.2",
- "caniuse-lite": "^1.0.30001787",
- "fraction.js": "^5.3.4",
- "picocolors": "^1.1.1",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.29",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz",
- "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==",
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/bignumber.js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
- "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/body-parser": {
- "version": "1.20.5",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
- "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "~1.2.0",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "on-finished": "~2.4.1",
- "qs": "~6.15.1",
- "raw-body": "~2.5.3",
- "type-is": "~1.6.18",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/body-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/body-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/browserslist": {
- "version": "4.28.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
- "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.10.12",
- "caniuse-lite": "^1.0.30001782",
- "electron-to-chromium": "^1.5.328",
- "node-releases": "^2.0.36",
- "update-browserslist-db": "^1.2.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001792",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz",
- "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==",
- "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/commander": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
- "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
- "license": "MIT"
- },
- "node_modules/d3": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
- "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "3",
- "d3-axis": "3",
- "d3-brush": "3",
- "d3-chord": "3",
- "d3-color": "3",
- "d3-contour": "4",
- "d3-delaunay": "6",
- "d3-dispatch": "3",
- "d3-drag": "3",
- "d3-dsv": "3",
- "d3-ease": "3",
- "d3-fetch": "3",
- "d3-force": "3",
- "d3-format": "3",
- "d3-geo": "3",
- "d3-hierarchy": "3",
- "d3-interpolate": "3",
- "d3-path": "3",
- "d3-polygon": "3",
- "d3-quadtree": "3",
- "d3-random": "3",
- "d3-scale": "4",
- "d3-scale-chromatic": "3",
- "d3-selection": "3",
- "d3-shape": "3",
- "d3-time": "3",
- "d3-time-format": "4",
- "d3-timer": "3",
- "d3-transition": "3",
- "d3-zoom": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "license": "ISC",
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-axis": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
- "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-brush": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
- "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "3",
- "d3-transition": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-chord": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
- "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
- "license": "ISC",
- "dependencies": {
- "d3-path": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-contour": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
- "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "^3.2.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-delaunay": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
- "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
- "license": "ISC",
- "dependencies": {
- "delaunator": "5"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dispatch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
- "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-drag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
- "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-selection": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
- "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
- "license": "ISC",
- "dependencies": {
- "commander": "7",
- "iconv-lite": "0.6",
- "rw": "1"
- },
- "bin": {
- "csv2json": "bin/dsv2json.js",
- "csv2tsv": "bin/dsv2dsv.js",
- "dsv2dsv": "bin/dsv2dsv.js",
- "dsv2json": "bin/dsv2json.js",
- "json2csv": "bin/json2dsv.js",
- "json2dsv": "bin/json2dsv.js",
- "json2tsv": "bin/json2dsv.js",
- "tsv2csv": "bin/dsv2dsv.js",
- "tsv2json": "bin/dsv2json.js"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv/node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-fetch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
- "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
- "license": "ISC",
- "dependencies": {
- "d3-dsv": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-force": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
- "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-quadtree": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
- "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-geo": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
- "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.5.0 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-hierarchy": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
- "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
- "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-polygon": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
- "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-quadtree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
- "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-random": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
- "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale-chromatic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
- "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-interpolate": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-selection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
- "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-shape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
- "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
- "license": "ISC",
- "dependencies": {
- "d3-path": "^3.1.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "license": "ISC",
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-transition": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
- "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-dispatch": "1 - 3",
- "d3-ease": "1 - 3",
- "d3-interpolate": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "d3-selection": "2 - 3"
- }
- },
- "node_modules/d3-zoom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
- "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "2 - 3",
- "d3-transition": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/delaunator": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz",
- "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==",
- "license": "ISC",
- "dependencies": {
- "robust-predicates": "^3.0.2"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "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==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dotenv": {
- "version": "17.4.2",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
- "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.354",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.354.tgz",
- "integrity": "sha512-JaBHwWcfIdmSAfWM5l3uwjGd431j8YEMikZ+K/2nXVuBqJKyZ0f+2h4n4JY5AyNiZmnY9qQr2RU3v9DxDmHMNg==",
- "license": "ISC"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.21.3",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz",
- "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/esbuild": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
- "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.0",
- "@esbuild/android-arm": "0.28.0",
- "@esbuild/android-arm64": "0.28.0",
- "@esbuild/android-x64": "0.28.0",
- "@esbuild/darwin-arm64": "0.28.0",
- "@esbuild/darwin-x64": "0.28.0",
- "@esbuild/freebsd-arm64": "0.28.0",
- "@esbuild/freebsd-x64": "0.28.0",
- "@esbuild/linux-arm": "0.28.0",
- "@esbuild/linux-arm64": "0.28.0",
- "@esbuild/linux-ia32": "0.28.0",
- "@esbuild/linux-loong64": "0.28.0",
- "@esbuild/linux-mips64el": "0.28.0",
- "@esbuild/linux-ppc64": "0.28.0",
- "@esbuild/linux-riscv64": "0.28.0",
- "@esbuild/linux-s390x": "0.28.0",
- "@esbuild/linux-x64": "0.28.0",
- "@esbuild/netbsd-arm64": "0.28.0",
- "@esbuild/netbsd-x64": "0.28.0",
- "@esbuild/openbsd-arm64": "0.28.0",
- "@esbuild/openbsd-x64": "0.28.0",
- "@esbuild/openharmony-arm64": "0.28.0",
- "@esbuild/sunos-x64": "0.28.0",
- "@esbuild/win32-arm64": "0.28.0",
- "@esbuild/win32-ia32": "0.28.0",
- "@esbuild/win32-x64": "0.28.0"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.22.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
- "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "~1.20.5",
- "content-disposition": "~0.5.4",
- "content-type": "~1.0.4",
- "cookie": "~0.7.1",
- "cookie-signature": "~1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.3.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "~0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "~6.15.1",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "~0.19.0",
- "serve-static": "~1.16.2",
- "setprototypeof": "1.2.0",
- "statuses": "~2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/express/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
- "engines": {
- "node": "^12.20 || >= 14.13"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
- "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "~2.0.2",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/finalhandler/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "license": "MIT",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
- "engines": {
- "node": ">=12.20.0"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fraction.js": {
- "version": "5.3.4",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
- "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/rawify"
- }
- },
- "node_modules/framer-motion": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
- "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==",
- "license": "MIT",
- "dependencies": {
- "motion-dom": "^12.38.0",
- "motion-utils": "^12.36.0",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "@emotion/is-prop-valid": "*",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@emotion/is-prop-valid": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gaxios": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
- "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
- "license": "Apache-2.0",
- "dependencies": {
- "extend": "^3.0.2",
- "https-proxy-agent": "^7.0.1",
- "node-fetch": "^3.3.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gcp-metadata": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
- "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
- "license": "Apache-2.0",
- "dependencies": {
- "gaxios": "^7.0.0",
- "google-logging-utils": "^1.0.0",
- "json-bigint": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/get-tsconfig": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
- "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/google-auth-library": {
- "version": "10.6.2",
- "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
- "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
- "license": "Apache-2.0",
- "dependencies": {
- "base64-js": "^1.3.0",
- "ecdsa-sig-formatter": "^1.0.11",
- "gaxios": "^7.1.4",
- "gcp-metadata": "8.1.2",
- "google-logging-utils": "1.1.3",
- "jws": "^4.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/google-logging-utils": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
- "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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==",
- "license": "ISC"
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
- "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/jiti": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
- "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "license": "MIT"
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-bigint": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
- "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
- "license": "MIT",
- "dependencies": {
- "bignumber.js": "^9.0.0"
- }
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
- "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/long": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
- "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
- "license": "Apache-2.0"
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/lucide-react": {
- "version": "0.546.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz",
- "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==",
- "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==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/motion": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz",
- "integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==",
- "license": "MIT",
- "dependencies": {
- "framer-motion": "^12.38.0",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "@emotion/is-prop-valid": "*",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@emotion/is-prop-valid": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/motion-dom": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz",
- "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==",
- "license": "MIT",
- "dependencies": {
- "motion-utils": "^12.36.0"
- }
- },
- "node_modules/motion-utils": {
- "version": "12.36.0",
- "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
- "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==",
- "license": "MIT"
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.12",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
- "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "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/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
- "license": "MIT",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.44",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz",
- "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==",
- "license": "MIT"
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/p-retry": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
- "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
- "license": "MIT",
- "dependencies": {
- "@types/retry": "0.12.0",
- "retry": "^0.13.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
- "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
- "license": "MIT"
- },
- "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/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
- "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
- "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/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/protobufjs": {
- "version": "7.5.8",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.8.tgz",
- "integrity": "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.5",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.1",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.1",
- "@types/node": ">=13.7.0",
- "long": "^5.0.0"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/qs": {
- "version": "6.15.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
- "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
- "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/react": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
- "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
- "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.6"
- }
- },
- "node_modules/react-refresh": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
- "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
- "devOptional": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
- }
- },
- "node_modules/retry": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
- "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/robust-predicates": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",
- "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==",
- "license": "Unlicense"
- },
- "node_modules/rollup": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz",
- "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.60.3",
- "@rollup/rollup-android-arm64": "4.60.3",
- "@rollup/rollup-darwin-arm64": "4.60.3",
- "@rollup/rollup-darwin-x64": "4.60.3",
- "@rollup/rollup-freebsd-arm64": "4.60.3",
- "@rollup/rollup-freebsd-x64": "4.60.3",
- "@rollup/rollup-linux-arm-gnueabihf": "4.60.3",
- "@rollup/rollup-linux-arm-musleabihf": "4.60.3",
- "@rollup/rollup-linux-arm64-gnu": "4.60.3",
- "@rollup/rollup-linux-arm64-musl": "4.60.3",
- "@rollup/rollup-linux-loong64-gnu": "4.60.3",
- "@rollup/rollup-linux-loong64-musl": "4.60.3",
- "@rollup/rollup-linux-ppc64-gnu": "4.60.3",
- "@rollup/rollup-linux-ppc64-musl": "4.60.3",
- "@rollup/rollup-linux-riscv64-gnu": "4.60.3",
- "@rollup/rollup-linux-riscv64-musl": "4.60.3",
- "@rollup/rollup-linux-s390x-gnu": "4.60.3",
- "@rollup/rollup-linux-x64-gnu": "4.60.3",
- "@rollup/rollup-linux-x64-musl": "4.60.3",
- "@rollup/rollup-openbsd-x64": "4.60.3",
- "@rollup/rollup-openharmony-arm64": "4.60.3",
- "@rollup/rollup-win32-arm64-msvc": "4.60.3",
- "@rollup/rollup-win32-ia32-msvc": "4.60.3",
- "@rollup/rollup-win32-x64-gnu": "4.60.3",
- "@rollup/rollup-win32-x64-msvc": "4.60.3",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/rw": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
- "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
- "node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/send": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
- "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.1",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "~2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "~2.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/send/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/serve-static": {
- "version": "1.16.3",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
- "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "~0.19.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
- "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz",
- "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
- "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.16",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
- "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "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/tsx": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
- "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.27.0",
- "get-tsconfig": "^4.7.5"
- },
- "bin": {
- "tsx": "dist/cli.mjs"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
- "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
- "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
- "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
- "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
- "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
- "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
- "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
- "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
- "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
- "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
- "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
- "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
- "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
- "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
- "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
- "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
- "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
- "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
- "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
- "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
- "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
- "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
- "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
- "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/esbuild": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
- "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
- "devOptional": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.7",
- "@esbuild/android-arm": "0.27.7",
- "@esbuild/android-arm64": "0.27.7",
- "@esbuild/android-x64": "0.27.7",
- "@esbuild/darwin-arm64": "0.27.7",
- "@esbuild/darwin-x64": "0.27.7",
- "@esbuild/freebsd-arm64": "0.27.7",
- "@esbuild/freebsd-x64": "0.27.7",
- "@esbuild/linux-arm": "0.27.7",
- "@esbuild/linux-arm64": "0.27.7",
- "@esbuild/linux-ia32": "0.27.7",
- "@esbuild/linux-loong64": "0.27.7",
- "@esbuild/linux-mips64el": "0.27.7",
- "@esbuild/linux-ppc64": "0.27.7",
- "@esbuild/linux-riscv64": "0.27.7",
- "@esbuild/linux-s390x": "0.27.7",
- "@esbuild/linux-x64": "0.27.7",
- "@esbuild/netbsd-arm64": "0.27.7",
- "@esbuild/netbsd-x64": "0.27.7",
- "@esbuild/openbsd-arm64": "0.27.7",
- "@esbuild/openbsd-x64": "0.27.7",
- "@esbuild/openharmony-arm64": "0.27.7",
- "@esbuild/sunos-x64": "0.27.7",
- "@esbuild/win32-arm64": "0.27.7",
- "@esbuild/win32-ia32": "0.27.7",
- "@esbuild/win32-x64": "0.27.7"
- }
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "license": "MIT"
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
- "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/uuid": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz",
- "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist-node/bin/uuid"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/vite": {
- "version": "6.4.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz",
- "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.25.0",
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "jiti": ">=1.21.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
- }
- },
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/ws": {
- "version": "8.20.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
- "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "license": "ISC"
- }
- }
-}
diff --git a/architectural-grid11/package.json b/architectural-grid11/package.json
deleted file mode 100644
index 57a6077..0000000
--- a/architectural-grid11/package.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "name": "react-example",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "tsx server.ts",
- "build": "vite build && esbuild server.ts --bundle --platform=node --format=cjs --packages=external --sourcemap --outfile=dist/server.cjs",
- "start": "node dist/server.cjs",
- "clean": "rm -rf dist",
- "lint": "tsc --noEmit"
- },
- "dependencies": {
- "@google/genai": "^1.29.0",
- "@tailwindcss/vite": "^4.1.14",
- "@types/d3": "^7.4.3",
- "@types/uuid": "^10.0.0",
- "@vitejs/plugin-react": "^5.0.4",
- "d3": "^7.9.0",
- "dotenv": "^17.2.3",
- "esbuild": "^0.28.0",
- "express": "^4.21.2",
- "lucide-react": "^0.546.0",
- "motion": "^12.23.24",
- "react": "^19.0.1",
- "react-dom": "^19.0.1",
- "uuid": "^14.0.0",
- "vite": "^6.2.3"
- },
- "devDependencies": {
- "@types/express": "^4.17.21",
- "@types/node": "^22.14.0",
- "autoprefixer": "^10.4.21",
- "tailwindcss": "^4.1.14",
- "tsx": "^4.21.0",
- "typescript": "~5.8.2",
- "vite": "^6.2.3"
- }
-}
diff --git a/architectural-grid11/server.ts b/architectural-grid11/server.ts
deleted file mode 100644
index 29b5f01..0000000
--- a/architectural-grid11/server.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import express from "express";
-import path from "path";
-import { createServer as createViteServer } from "vite";
-import { v4 as uuidv4 } from "uuid";
-
-interface BrainstormIdea {
- id: string;
- sessionId: string;
- waveNumber: number;
- title: string;
- description: string;
- connectionToSeed: string;
- noveltyScore: number;
- parentIdeaId?: string;
- convertedToNoteId?: string;
- status: 'active' | 'dismissed' | 'converted';
- position?: { x: number; y: number };
-}
-
-interface BrainstormSession {
- id: string;
- seedIdea: string;
- sourceNoteId?: string;
- contextNoteIds?: string[];
- createdAt: string;
- updatedAt: string;
-}
-
-// In-memory store (Simulating Postgres for now)
-const sessions: BrainstormSession[] = [];
-const ideas: BrainstormIdea[] = [];
-
-async function startServer() {
- const app = express();
- const PORT = 3000;
-
- app.use(express.json());
-
- // API Routes
- app.get("/api/health", (req, res) => {
- res.json({ status: "ok" });
- });
-
-// 1. Create session
- app.post("/api/brainstorm/sessions", (req, res) => {
- const { seedIdea, sourceNoteId, contextNoteIds } = req.body;
-
- const session: BrainstormSession = {
- id: uuidv4(),
- seedIdea,
- sourceNoteId,
- contextNoteIds,
- createdAt: new Date().toISOString(),
- updatedAt: new Date().toISOString()
- };
- sessions.unshift(session);
- res.json(session);
- });
-
- // 2. Add ideas to session
- app.post("/api/brainstorm/:sessionId/ideas", (req, res) => {
- const { sessionId } = req.params;
- const { ideas: newIdeasData } = req.body;
-
- const session = sessions.find(s => s.id === sessionId);
- if (!session) return res.status(404).json({ error: "Session not found" });
-
- const newIdeas = newIdeasData.map((item: any) => ({
- id: item.id || uuidv4(),
- sessionId,
- waveNumber: item.waveNumber,
- title: item.title,
- description: item.description,
- connectionToSeed: item.connectionToSeed,
- noveltyScore: item.noveltyScore,
- parentIdeaId: item.parentIdeaId,
- status: 'active'
- }));
-
- newIdeas.forEach((i: any) => ideas.push(i));
- res.json(newIdeas);
- });
-
- // 3. Get all sessions
- app.get("/api/brainstorm/sessions", (req, res) => {
- res.json(sessions);
- });
-
- // 4. Get session with ideas
- app.get("/api/brainstorm/:sessionId", (req, res) => {
- const session = sessions.find(s => s.id === req.params.sessionId);
- if (!session) return res.status(404).json({ error: "Session not found" });
- const sessionIdeas = ideas.filter(i => i.sessionId === session.id);
- res.json({ session, ideas: sessionIdeas });
- });
-
- // 5. Update idea (position, status)
- app.patch("/api/brainstorm/ideas/:ideaId", (req, res) => {
- const index = ideas.findIndex(i => i.id === req.params.ideaId);
- if (index === -1) return res.status(404).json({ error: "Idea not found" });
-
- ideas[index] = { ...ideas[index], ...req.body };
- res.json(ideas[index]);
- });
-
- // Vite middleware for development
- if (process.env.NODE_ENV !== "production") {
- const vite = await createViteServer({
- server: { middlewareMode: true },
- appType: "spa",
- });
- app.use(vite.middlewares);
- } else {
- const distPath = path.join(process.cwd(), 'dist');
- app.use(express.static(distPath));
- app.get('*', (req, res) => {
- res.sendFile(path.join(distPath, 'index.html'));
- });
- }
-
- app.listen(PORT, "0.0.0.0", () => {
- console.log(`Server running on http://localhost:${PORT}`);
- });
-}
-
-startServer();
diff --git a/architectural-grid11/src/App.tsx b/architectural-grid11/src/App.tsx
deleted file mode 100644
index 4a4b9da..0000000
--- a/architectural-grid11/src/App.tsx
+++ /dev/null
@@ -1,603 +0,0 @@
-/**
- * @license
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React, { useState, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-
-// Components
-import { Sidebar } from './components/Sidebar';
-import { NotebooksView } from './components/NotebooksView';
-import { AgentsView } from './components/AgentsView';
-import { SettingsView } from './components/SettingsView';
-import { TrashView } from './components/TrashView';
-import { BrainstormView } from './components/BrainstormView/BrainstormView';
-import { InsightsView } from './components/InsightsView';
-import { TemporalView } from './components/TemporalView';
-import { AISidebar } from './components/AISidebar';
-import { SlashMenu } from './components/SlashMenu';
-
-// Data & Types
-import { CARNETS, ALL_NOTES } from './constants';
-import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog } from './types';
-
-export default function App() {
- const [activeView, setActiveView] = useState('notebooks');
- const [activeSettingsTab, setActiveSettingsTab] = useState('general');
- const [selectedAgentId, setSelectedAgentId] = useState(null);
- const [isDarkMode, setIsDarkMode] = useState(false);
- const [carnets, setCarnets] = useState(CARNETS);
- const [notes, setNotes] = useState(ALL_NOTES);
- const [accessLogs, setAccessLogs] = useState([
- // Note n1: 14-day cycle
- { noteId: 'n1', accessedAt: new Date(Date.now() - 70 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 56 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 42 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n2: 7-day cycle
- { noteId: 'n2', accessedAt: new Date(Date.now() - 35 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 21 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n3: 3-day cycle (frequent check)
- { noteId: 'n3', accessedAt: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 9 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- ]);
-
- const logNoteAccess = (noteId: string, action: 'view' | 'edit' | 'search_hit' = 'view') => {
- const newLog: NoteAccessLog = {
- noteId,
- accessedAt: new Date().toISOString(),
- action
- };
- setAccessLogs(prev => [...prev, newLog]);
- };
-
- const [activeCarnetId, setActiveCarnetId] = useState('4');
- const [activeNoteId, setActiveNoteId] = useState(null);
- const [brainstormSeed, setBrainstormSeed] = useState(null);
-
- const handleBrainstormNote = (note: Note) => {
- setActiveView('brainstorm');
- // We'll use a small delay or a ref to pass this to BrainstormView if needed,
- // but better to just share state or use a CustomEvent
- window.dispatchEvent(new CustomEvent('start-brainstorm', {
- detail: { seed: note.title, sourceNoteId: note.id }
- }));
- };
-
- React.useEffect(() => {
- if (activeNoteId) {
- logNoteAccess(activeNoteId);
- }
- }, [activeNoteId]);
-
- React.useEffect(() => {
- const handleSwitchView = (e: any) => {
- if (e.detail) {
- setActiveView(e.detail as NavigationView);
- }
- };
- window.addEventListener('switch-view', handleSwitchView);
- return () => window.removeEventListener('switch-view', handleSwitchView);
- }, []);
- const [selectedTagIds, setSelectedTagIds] = useState([]);
- const [isAISidebarOpen, setIsAISidebarOpen] = useState(false);
- const [aiTab, setAiTab] = useState('discussion');
- const [selectedTone, setSelectedTone] = useState('Professional');
-
- // Modal States
- const [showNewCarnetModal, setShowNewCarnetModal] = useState<{ isOpen: boolean; parentId?: string; isRenaming?: boolean; carnetId?: string }>({ isOpen: false });
- const [showNewNoteModal, setShowNewNoteModal] = useState(false);
- const [slashMenu, setSlashMenu] = useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- // Form States
- const [newCarnetName, setNewCarnetName] = useState('');
- const [newNoteTitle, setNewNoteTitle] = useState('');
- const [newNoteContent, setNewNoteContent] = useState('');
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const togglePin = (noteId: string) => {
- setNotes(notes.map(n => n.id === noteId ? { ...n, isPinned: !n.isPinned } : n));
- };
-
- const filteredNotes = useMemo(() => {
- let result = notes.filter(n => n.carnetId === activeCarnetId && !n.isDeleted);
-
- if (selectedTagIds.length > 0) {
- result = result.filter(note =>
- selectedTagIds.every(tagId => note.tags?.some(tag => tag.id === tagId))
- );
- }
-
- return [...result].sort((a, b) => {
- if (a.isPinned && !b.isPinned) return -1;
- if (!a.isPinned && b.isPinned) return 1;
- return 0;
- });
- }, [activeCarnetId, notes]);
-
- const activeNote = useMemo(() =>
- notes.find(n => n.id === activeNoteId),
- [activeNoteId, notes]);
-
- const activeCarnet = useMemo(() =>
- carnets.find(c => c.id === activeCarnetId),
- [activeCarnetId, carnets]);
-
- const handleAddCarnet = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newCarnetName.trim()) return;
-
- if (showNewCarnetModal.isRenaming && showNewCarnetModal.carnetId) {
- setCarnets(carnets.map(c => c.id === showNewCarnetModal.carnetId ? { ...c, name: newCarnetName, initial: newCarnetName.charAt(0).toUpperCase() } : c));
- setShowNewCarnetModal({ isOpen: false });
- setNewCarnetName('');
- return;
- }
-
- const newCarnet: Carnet = {
- id: Date.now().toString(),
- name: newCarnetName,
- initial: newCarnetName.charAt(0).toUpperCase(),
- type: 'Project',
- parentId: showNewCarnetModal.parentId
- };
-
- setCarnets([...carnets, newCarnet]);
- setNewCarnetName('');
- setShowNewCarnetModal({ isOpen: false });
- setActiveCarnetId(newCarnet.id);
- };
-
- const handleDeleteCarnet = (id: string) => {
- if (window.confirm('Déplacer ce carnet et ses sous-carnets vers la corbeille ?')) {
- const idsToDelete = new Set([id]);
-
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
-
- const deletedAt = new Date().toISOString();
- setCarnets(carnets.map(c => idsToDelete.has(c.id) ? { ...c, isDeleted: true, deletedAt } : c));
- setNotes(notes.map(n => idsToDelete.has(n.carnetId) ? { ...n, isDeleted: true, deletedAt } : n));
-
- if (idsToDelete.has(activeCarnetId)) {
- setActiveCarnetId('1');
- }
- }
- };
-
- const handleDeleteNote = (id: string) => {
- const deletedAt = new Date().toISOString();
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: true, deletedAt } : n));
- if (activeNoteId === id) setActiveNoteId(null);
- };
-
- const handleRestoreCarnet = (id: string) => {
- setCarnets(carnets.map(c => c.id === id ? { ...c, isDeleted: false, deletedAt: undefined } : c));
- // Optionally restore linked notes too? User might expect that.
- setNotes(notes.map(n => n.carnetId === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handleRestoreNote = (id: string) => {
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handlePermanentDeleteNote = (id: string) => {
- setNotes(notes.filter(n => n.id !== id));
- };
-
- const handlePermanentDeleteCarnet = (id: string) => {
- const idsToDelete = new Set([id]);
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
- setCarnets(carnets.filter(c => !idsToDelete.has(c.id)));
- setNotes(notes.filter(n => !idsToDelete.has(n.carnetId)));
- };
-
- const handleAddNote = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newNoteTitle.trim() || !newNoteContent.trim()) return;
-
- const newNote: Note = {
- id: `n-${Date.now()}`,
- carnetId: activeCarnetId,
- title: newNoteTitle,
- date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
- content: newNoteContent,
- imageUrl: 'https://images.unsplash.com/photo-1487958449943-2429e8be8625?auto=format&fit=crop&q=80&w=800&h=600',
- tags: []
- };
-
- setNotes([newNote, ...notes]);
- setNewNoteTitle('');
- setNewNoteContent('');
- setShowNewNoteModal(false);
- setActiveNoteId(newNote.id);
- };
-
- const handleConvertIdeaToNote = (idea: BrainstormIdea) => {
- const newNote: Note = {
- id: `n-gen-${Date.now()}`,
- carnetId: activeCarnetId,
- title: idea.title,
- date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
- content: `${idea.description}\n\n---\n**Connection to seed:** ${idea.connectionToSeed}\n**Novelty Score:** ${idea.noveltyScore}/10`,
- imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't-ai', label: 'AI Generated', type: 'ai' }]
- };
-
- setNotes([newNote, ...notes]);
- setActiveView('notebooks');
- setActiveNoteId(newNote.id);
- };
-
- return (
-
-
{
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId });
- if (isRenaming && carnetId) {
- const carnet = carnets.find(c => c.id === carnetId);
- if (carnet) setNewCarnetName(carnet.name);
- } else {
- setNewCarnetName('');
- }
- }}
- onDeleteCarnet={handleDeleteCarnet}
- onMoveCarnet={(draggedId, targetId) => {
- if (draggedId === targetId) return;
-
- // Basic circular check
- const isDescendant = (parentId: string, potentialChildId: string): boolean => {
- const childIds = carnets.filter(c => c.parentId === parentId).map(c => c.id);
- if (childIds.includes(potentialChildId)) return true;
- return childIds.some(id => isDescendant(id, potentialChildId));
- };
-
- if (targetId && isDescendant(draggedId, targetId)) {
- console.warn("Cannot move a notebook inside its own descendant");
- return;
- }
-
- setCarnets(prev => prev.map(c => c.id === draggedId ? { ...c, parentId: targetId } : c));
- }}
- />
-
-
-
- {(activeView === 'notebooks' || activeView === 'shared' || activeView === 'reminders') && (
-
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId })}
- onDeleteNote={handleDeleteNote}
- onBrainstormNote={handleBrainstormNote}
- />
-
- )}
-
- {activeView === 'trash' && (
-
- n.isDeleted)}
- deletedCarnets={carnets.filter(c => c.isDeleted)}
- onRestoreNote={handleRestoreNote}
- onRestoreCarnet={handleRestoreCarnet}
- onPermanentDeleteNote={handlePermanentDeleteNote}
- onPermanentDeleteCarnet={handlePermanentDeleteCarnet}
- onEmptyTrash={() => {
- setNotes(notes.filter(n => !n.isDeleted));
- setCarnets(carnets.filter(c => !c.isDeleted));
- }}
- />
-
- )}
-
- {activeView === 'agents' && (
-
-
-
- )}
-
- {activeView === 'settings' && (
-
-
-
- )}
-
- {activeView === 'brainstorm' && (
-
-
-
- )}
-
- {activeView === 'insights' && (
-
- {
- setActiveView('notebooks');
- setActiveNoteId(noteId);
- }}
- />
-
- )}
-
- {activeView === 'temporal' && (
-
- {
- setActiveView('notebooks');
- setActiveNoteId(noteId);
- }}
- />
-
- )}
-
-
-
-
-
- {/* Modals */}
-
- {showNewCarnetModal.isOpen && (
-
-
setShowNewCarnetModal({ isOpen: false })}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {showNewCarnetModal.isRenaming ? 'Rename Carnet' : (showNewCarnetModal.parentId ? 'Create Sub-Carnet' : 'Create New Carnet')}
-
- {showNewCarnetModal.parentId && !showNewCarnetModal.isRenaming && (
-
- Inside: {carnets.find(c => c.id === showNewCarnetModal.parentId)?.name}
-
- )}
-
-
- Notebook Name
- setNewCarnetName(e.target.value)}
- placeholder="E.g., Sustainable Patterns"
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-4 py-3 outline-none focus:border-ink transition-colors font-serif italic text-lg text-ink dark:text-dark-ink"
- />
-
-
- {
- setShowNewCarnetModal({ isOpen: false });
- setNewCarnetName('');
- }}
- className="flex-1 py-3 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
- >
- Cancel
-
-
- {showNewCarnetModal.isRenaming ? 'Rename' : 'Create Notebook'}
-
-
-
-
-
- )}
-
- {showNewNoteModal && (
-
-
setShowNewNoteModal(false)}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {slashMenu?.isOpen && (
- { console.log(type); setSlashMenu(null); }}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
- Add Architectural Note
-
-
- Concept Title
- setNewNoteTitle(e.target.value)}
- placeholder="Enter the title of your study..."
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-serif text-2xl text-ink dark:text-dark-ink"
- />
-
-
- Observations & Analysis
- setNewNoteContent(e.target.value)}
- onKeyDown={handleEditorKeyDown}
- placeholder="Describe the spatial logic, materiality, and light interactions... (Type '/' for commands)"
- rows={6}
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-light leading-relaxed resize-none text-ink dark:text-dark-ink"
- />
-
-
- setShowNewNoteModal(false)}
- className="flex-1 py-4 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
- >
- Cancel
-
-
- Save Note
-
-
-
-
-
- )}
-
-
- );
-}
diff --git a/architectural-grid11/src/components/AISidebar.tsx b/architectural-grid11/src/components/AISidebar.tsx
deleted file mode 100644
index af38b87..0000000
--- a/architectural-grid11/src/components/AISidebar.tsx
+++ /dev/null
@@ -1,466 +0,0 @@
-import React from 'react';
-import {
- Sparkles,
- ChevronRight,
- MessageSquare,
- FileCode,
- Globe,
- Send,
- Scissors,
- Zap,
- Languages,
- Layout,
- ArrowRightLeft,
- BookOpen,
- History,
- Target,
- Network,
- Clock
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { AITab, AITone, Note, Carnet } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AISidebarProps {
- isOpen: boolean;
- setIsOpen: (open: boolean) => void;
- activeNote: Note | undefined;
- aiTab: AITab;
- setAiTab: (tab: AITab) => void;
- selectedTone: AITone;
- setSelectedTone: (tone: AITone) => void;
- carnets: Carnet[];
-}
-
-export const AISidebar: React.FC = ({
- isOpen,
- setIsOpen,
- activeNote,
- aiTab,
- setAiTab,
- selectedTone,
- setSelectedTone,
- carnets
-}) => {
- const [selectedContextId, setSelectedContextId] = React.useState(null);
-
- return (
-
- {isOpen && (
-
-
-
-
-
- IA Assistant
-
- setIsOpen(false)}
- className="p-1 hover:bg-slate-100 rounded-full transition-colors text-muted-ink"
- >
-
-
-
-
- "{activeNote?.title}"
-
-
-
-
- {(['discussion', 'actions', 'explore', 'resources'] as AITab[]).map((tab) => (
- setAiTab(tab)}
- className={`flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative
- ${aiTab === tab ? 'text-manganese' : 'text-muted-ink hover:text-ink/60'}`}
- >
- {tab}
- {aiTab === tab && (
-
- )}
-
- ))}
-
-
-
-
- {aiTab === 'explore' && (
-
-
-
-
Intelligence Modules
-
-
-
-
-
{
- // These will be handled in App.tsx by observing activeView
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'brainstorm' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-ochre/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Brainstorm Wave
-
Unfold dimensions of thought
-
-
-
-
-
{
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'insights' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-indigo-500/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Semantic Network
-
Detect clusters and bridges
-
-
-
-
-
{
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'temporal' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-rose-500/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Temporal Forecast
-
Predict relevance recurrence
-
-
-
-
-
-
-
- Ces modules utilisent les embeddings du modèle Gemini pour analyser graphiquement vos pensées.
-
-
-
- )}
-
- {aiTab === 'discussion' && (
-
-
-
-
-
-
Posez une question à l'Assistant pour commencer.
-
-
-
-
-
Source du Contexte
-
-
-
-
- Note Active
-
-
Auto
-
-
-
-
-
-
-
-
-
-
Ton d'écriture
-
- {(['Professional', 'Creative', 'Academic', 'Casual'] as AITone[]).map((tone) => (
- setSelectedTone(tone)}
- className={`p-3 rounded-xl border text-[11px] font-medium transition-all
- ${selectedTone === tone ? 'bg-manganese text-paper border-manganese shadow-lg shadow-manganese/10' : 'bg-glass border-border text-muted-ink hover:border-ink/20'}`}
- >
- {tone.toUpperCase().substring(0, 3)}
-
- ))}
-
-
-
-
- )}
-
- {aiTab === 'actions' && (
-
-
-
-
-
-
- {[
- { icon:
, label: 'Clarifier', color: 'ochre' },
- { icon:
, label: 'Raccourcir', color: 'rust' },
- { icon:
, label: 'Améliorer', color: 'sage' },
- { icon:
, label: 'Traduire', color: 'slate' },
- ].map((action, i) => (
-
-
- {action.icon}
-
- {action.label}
-
- ))}
-
-
- Convertir en Markdown
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Présentation
-
Convertir en slides interactives
-
-
-
-
-
- Thème
-
- Architectural Mono
- Vibrant Tech
- Minimal Silk
-
-
-
- Style
-
- Professional
- Creative
- Brutalist
-
-
-
-
-
- Générer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Diagramme
-
Visualisation de structure
-
-
-
-
-
- Type
-
- Logic Flow
- Mind Map
- Hierarchy
-
-
-
- Style
-
- Draft
- Polished
- Handwritten
-
-
-
-
-
- Tracer
-
-
-
-
-
-
-
-
- Auto-Save Enabled
-
-
-
- )}
-
- {aiTab === 'resources' && (
-
-
-
-
URL (Optionnel)
-
-
-
-
-
-
-
- Texte de la ressource
-
-
-
-
-
Mode d'intégration
-
- {[
- { id: 'replace', label: 'Remplacer', sub: 'Direct, sans IA' },
- { id: 'append', label: 'Compléter', sub: 'Ajoute sans réécrire' },
- { id: 'merge', label: 'Fusionner', sub: 'Réécrit et intègre' },
- ].map((mode) => (
-
- {mode.label}
- {mode.sub}
-
- ))}
-
-
-
-
-
- Générer l'aperçu
-
-
-
- )}
-
-
-
-
- {aiTab === 'discussion' && (
-
-
- Maj+Entrée = nouvelle ligne
-
- )}
-
-
- )}
-
- );
-};
diff --git a/architectural-grid11/src/components/AgentsView.tsx b/architectural-grid11/src/components/AgentsView.tsx
deleted file mode 100644
index f82c7fa..0000000
--- a/architectural-grid11/src/components/AgentsView.tsx
+++ /dev/null
@@ -1,325 +0,0 @@
-import React from 'react';
-import {
- Plus,
- ArrowLeft,
- Clock,
- Activity,
- Trash2,
- Edit3,
- Play,
- Eye,
- Microscope,
- Globe,
- Layers,
- Zap,
- BookOpen,
- Sparkles,
- ChevronDown,
- Info,
- Check
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Carnet, Note } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AgentsViewProps {
- selectedAgentId: string | null;
- setSelectedAgentId: (id: string | null) => void;
- carnets: Carnet[];
-}
-
-export const AgentsView: React.FC = ({
- selectedAgentId,
- setSelectedAgentId,
- carnets
-}) => {
- const [selectedCarnetForAgent, setSelectedCarnetForAgent] = React.useState('4');
- const [agentType, setAgentType] = React.useState<'Surveillant' | 'Personnalisé' | 'Slides' | 'Diagramme'>('Diagramme');
-
- return (
-
- {!selectedAgentId ? (
- <>
-
-
-
-
Mes Agents
-
Automatisez vos tâches de veille et de recherche.
-
-
-
- Nouvel Agent
-
-
-
-
- {['Tous', 'Veilleur', 'Chercheur', 'Surveillant', 'Personnalisé'].map((tag, i) => (
-
- {tag}
- {i === 0 && }
-
- ))}
-
-
-
-
-
- {[
- { id: 'a1', icon:
, title: 'Surveillant de Notes', status: 'Réussi', type: 'SURVEILLANT', meta: 'Hebdomadaire • 6 exéc.', desc: 'Analyse les notes récentes d’un carnet et suggère des compléments, références et liens.' },
- { id: 'a2', icon:
, title: 'Chercheur de Sujet', status: 'Réussi', type: 'CHERCHEUR', meta: 'Hebdomadaire • 14 exéc.', desc: 'Recherche des informations approfondies sur les derniers modèles de Deepseek et voir l’avis des utilisateurs.' },
- { id: 'a3', icon:
, title: 'Veille IA', status: 'Réussi', type: 'VEILLEUR', meta: 'Quotidien • 20 exéc.', desc: 'Scrape les flux RSS de 6 sites IA (The Verge, TechCrunch...) et génère un résumé.' },
- ].map((agent, i) => (
-
setSelectedAgentId(agent.id)}
- className="bg-white dark:bg-white/5 border border-border rounded-2xl p-6 space-y-6 hover:border-ink/20 transition-all group cursor-pointer shadow-sm relative overflow-hidden"
- >
-
-
-
- {agent.icon}
-
-
-
{agent.title}
-
{agent.type}
-
-
-
e.stopPropagation()}>
-
-
-
-
-
-
-
-
- {agent.desc}
-
-
-
-
-
- {agent.meta.split('•')[0]}
- {agent.meta.split('•')[1]}
-
-
-
-
- Prochaine exécution
- Hebdomadaire
-
-
-
Dernier statut
-
{agent.status}
-
-
-
-
-
-
Modifier
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-slate-50 dark:hover:bg-white/5 flex items-center justify-center transition-colors text-muted-ink hover:text-ink"
- >
-
-
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-rose-50 hover:text-rose-600 hover:border-rose-100 flex items-center justify-center transition-colors text-muted-ink"
- >
-
-
-
-
- ))}
-
-
-
-
-
- {[
- { title: 'Veille IA', desc: 'Scrape les flux RSS de 6 sites IA et génère un résumé hebdomadaire.', icon:
},
- { title: 'Veille Tech', desc: 'Crée un résumé quotidien des news Hacker News et Product Hunt.', icon:
},
- { title: 'Veille Dev', desc: 'Surveille les repos GitHub pour détecter les nouvelles releases.', icon:
},
- ].map((model, i) => (
-
-
- {model.icon}
-
-
{model.title}
-
{model.desc}
-
- Installer
-
-
- ))}
-
-
-
- >
- ) : (
-
-
-
-
-
-
-
Sélectionnez le type d'agent
-
- {[
- { id: 'Surveillant', icon:
, label: 'Surveillant', desc: 'Surveille un carnet et analyse les notes' },
- { id: 'Personnalisé', icon:
, label: 'Personnalisé', desc: 'Agent libre avec votre propre prompt' },
- { id: 'Slides', icon:
, label: 'Slides', desc: 'Crée une présentation PowerPoint à partir de notes' },
- { id: 'Diagramme', icon:
, label: 'Diagramme', desc: 'Crée un diagramme Excalidraw à partir de notes' },
- ].map((type) => (
-
setAgentType(type.id as any)}
- className={`p-6 rounded-2xl border-2 transition-all flex flex-col items-center gap-3 text-center group relative
- ${agentType === type.id ? 'border-blueprint bg-white shadow-xl shadow-blueprint/10' : 'border-border bg-white/50 hover:bg-white'}`}
- >
-
- {type.icon}
-
-
-
{type.label}
-
{type.desc}
-
-
- {agentType === type.id &&
}
-
-
- ))}
-
-
-
-
-
-
-
- CONFIGURATION
-
-
- Supprimer
-
-
-
-
-
-
- DESCRIPTION (OPTIONEL)
-
-
-
-
-
-
-
- CARNET À SURVEILLER
-
-
-
-
-
-
-
- NOTES À ANALYSER
-
-
-
- {[
- 'Résumé du conteneur LXC devSandbox',
- 'Connexion SSH sans mot de passe à devSandbox',
- 'Gateway token (blank to generate)',
- 'Procédure d\'accès à openclaw',
- 'Derniers commits du repo Momento'
- ].map((note, i) => (
-
-
- {i === 0 && }
-
-
- {note}
-
- ))}
-
-
{1} note(s) sélectionnée(s)
-
-
-
-
- TYPE DE DIAGRAMME
-
-
- {[
- 'Auto (détection métier)', 'Flowchart (processus)',
- 'Mindmap (idées)', 'Organigramme (équipes)',
- 'Timeline / roadmap', 'Process map (opérations)',
- 'Architecture cloud (zones/RG)'
- ].map((type, i) => (
-
- {type}
-
- ))}
-
-
-
-
-
- STYLE DU DIAGRAMME EXCALIDRAW
-
-
- {[
- 'Coloré (Excalidraw)', 'Sketch+ (Excalidraw accentué)', 'Austère (sobre)'
- ].map((style, i) => (
-
- {style}
-
- ))}
-
-
-
-
-
-
- )}
-
- );
-};
diff --git a/architectural-grid11/src/components/BrainstormView/BrainstormView.tsx b/architectural-grid11/src/components/BrainstormView/BrainstormView.tsx
deleted file mode 100644
index f9a5ec1..0000000
--- a/architectural-grid11/src/components/BrainstormView/BrainstormView.tsx
+++ /dev/null
@@ -1,445 +0,0 @@
-
-import React, { useState, useEffect, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import {
- Zap,
- Search,
- ArrowRight,
- History,
- Plus,
- Wind,
- PlusCircle,
- FileText,
- ChevronRight,
- Maximize2
-} from 'lucide-react';
-import { WaveCanvas } from './WaveCanvas';
-import { BrainstormSession, BrainstormIdea, Note } from '../../types';
-import { generateBrainstormWave, generateExpansion, getEmbedding, cosineSimilarity } from '../../services/geminiService';
-
-interface BrainstormViewProps {
- notes: Note[];
- onConvertNote: (idea: BrainstormIdea) => void;
-}
-
-export const BrainstormView: React.FC = ({ notes, onConvertNote }) => {
- const [seedInput, setSeedInput] = useState('');
- const [isGenerating, setIsGenerating] = useState(false);
- const [error, setError] = useState(null);
- const [sessions, setSessions] = useState([]);
- const [activeSessionId, setActiveSessionId] = useState(null);
- const [ideas, setIdeas] = useState([]);
- const [selectedIdeaId, setSelectedIdeaId] = useState(null);
-
- useEffect(() => {
- fetch('/api/brainstorm/sessions')
- .then(res => res.json())
- .then(data => setSessions(data))
- .catch(err => console.error("Failed to load sessions", err));
- }, []);
-
- useEffect(() => {
- if (activeSessionId) {
- fetch(`/api/brainstorm/${activeSessionId}`)
- .then(res => res.json())
- .then(data => {
- if (data.ideas) {
- setIdeas(prev => {
- const filtered = prev.filter(i => i.sessionId !== activeSessionId);
- return [...filtered, ...data.ideas];
- });
- }
- })
- .catch(err => console.error("Failed to load ideas", err));
- }
- }, [activeSessionId]);
-
- const activeSession = useMemo(() =>
- sessions.find(s => s.id === activeSessionId),
- [activeSessionId, sessions]);
-
- const activeIdeas = useMemo(() =>
- ideas.filter(i => i.sessionId === activeSessionId),
- [activeSessionId, ideas]);
-
- const selectedIdea = useMemo(() =>
- ideas.find(i => i.id === selectedIdeaId),
- [selectedIdeaId, ideas]);
-
- useEffect(() => {
- const handleRemoteStart = (e: any) => {
- if (e.detail?.seed) {
- handleStartBrainstorm(e.detail.seed, e.detail.sourceNoteId);
- }
- };
- window.addEventListener('start-brainstorm', handleRemoteStart);
- return () => window.removeEventListener('start-brainstorm', handleRemoteStart);
- }, [notes]);
-
- const handleStartBrainstorm = async (seed: string, sourceNoteId?: string) => {
- if (!seed.trim()) return;
-
- setIsGenerating(true);
- setError(null);
-
- try {
- // 1. Create session on backend
- const sessionRes = await fetch('/api/brainstorm/sessions', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- seedIdea: seed,
- sourceNoteId
- })
- });
- const session = await sessionRes.json();
- if (!sessionRes.ok) throw new Error(session.error || "Failed to create session");
-
- setSessions(prev => [session, ...prev]);
- setActiveSessionId(session.id);
- setSeedInput('');
-
- // 2. Generate waves in frontend concurrently
- const contextSummaries = notes.slice(0, 5).map(n => n.title).join(', ');
-
- const wavePromises = [1, 2, 3].map(async (num) => {
- try {
- const generated = await generateBrainstormWave(seed, num, contextSummaries);
- return generated.map(g => ({
- ...g,
- waveNumber: num
- }));
- } catch (e) {
- console.error(`Wave ${num} failed`, e);
- return [];
- }
- });
-
- const wavesResults = await Promise.all(wavePromises);
- const allNewIdeas = wavesResults.flat();
-
- if (allNewIdeas.length === 0) {
- throw new Error("No ideas were generated. Gemini might be shy today.");
- }
-
- // 3. Save ideas to backend
- const ideasRes = await fetch(`/api/brainstorm/${session.id}/ideas`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ideas: allNewIdeas })
- });
- const savedIdeas = await ideasRes.json();
- setIdeas(prev => [...prev, ...savedIdeas]);
-
- } catch (err: any) {
- console.error("Brainstorm failed:", err);
- setError(err.message || "An unexpected error occurred while brainstorming.");
- } finally {
- setIsGenerating(false);
- }
- };
-
- const updateIdea = async (ideaId: string, updates: Partial) => {
- try {
- const res = await fetch(`/api/brainstorm/ideas/${ideaId}`, {
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(updates)
- });
- const updated = await res.json();
- setIdeas(prev => prev.map(i => i.id === ideaId ? updated : i));
- } catch (err) {
- console.error("Update failed", err);
- }
- };
-
- const handleDeepenIdea = async (idea: BrainstormIdea) => {
- setIsGenerating(true);
- try {
- const generated = await generateExpansion(idea.title, idea.description);
- const newIdeasData = generated.map(g => ({
- ...g,
- waveNumber: Math.min(idea.waveNumber + 1, 3),
- parentIdeaId: idea.id
- }));
-
- const res = await fetch(`/api/brainstorm/${idea.sessionId}/ideas`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ideas: newIdeasData })
- });
- const savedIdeas = await res.json();
- setIdeas(prev => [...prev, ...savedIdeas]);
- } catch (err) {
- console.error("Deepen failed", err);
- setError("Failed to expand this idea.");
- } finally {
- setIsGenerating(false);
- }
- };
-
- const handleDismissIdea = (ideaId: string) => {
- updateIdea(ideaId, { status: 'dismissed' });
- setSelectedIdeaId(null);
- };
-
- const handleConvertToNote = (idea: BrainstormIdea) => {
- updateIdea(idea.id, { status: 'converted' });
- onConvertNote(idea);
- };
-
- return (
-
- {/* Header / Start area */}
-
- {/* Architectural Grid Background */}
-
-
-
-
-
-
-
-
-
Waves of Thought
-
-
-
Unfold dimensions of potentiality
-
-
-
-
-
-
-
setSeedInput(e.target.value)}
- onKeyDown={(e) => e.key === 'Enter' && handleStartBrainstorm(seedInput)}
- placeholder="Enter a concept to unfold..."
- className={`w-full relative bg-white dark:bg-[#1A1A1A] border-2 rounded-2xl px-8 py-7 pr-20 outline-none transition-all text-2xl font-serif italic text-ink dark:text-dark-ink shadow-sm group-hover:shadow-md
- ${error ? 'border-rose-400 focus:ring-rose-100 shadow-rose-100' : 'border-border/40 focus:border-ochre/40 focus:ring-4 focus:ring-ochre/5'}`}
- />
-
handleStartBrainstorm(seedInput)}
- disabled={isGenerating || !seedInput.trim()}
- className="absolute right-4 top-4 bottom-4 px-6 bg-ink dark:bg-ochre text-paper rounded-xl disabled:opacity-50 transition-all hover:scale-[1.02] active:scale-[0.98] flex items-center justify-center gap-2 min-w-[70px] shadow-lg"
- >
- {isGenerating ? (
-
- ) : (
-
- )}
-
-
-
-
- {error && (
-
-
-
-
Obstruction detected
-
{error}
-
-
- )}
-
- {isGenerating && !error && (
-
-
- {[0.2, 0.4, 0.6].map((d, i) => (
-
- ))}
-
- Gemini is harvesting seeds of thought from the digital ether...
-
- )}
-
-
-
-
-
- {/* Main Canvas Area */}
-
- {activeSession ? (
-
updateIdea(id, { position: pos })}
- selectedNodeId={selectedIdeaId}
- relatedNotes={notes}
- />
- ) : (
-
-
-
The canvas is waiting for your spark...
-
- )}
-
- {/* Floating UI overlays */}
-
- {activeSession && (
-
-
-
- )}
-
-
-
- {/* Right Sidebar Detail Panel */}
-
- {selectedIdea && (
-
-
-
-
- Vague {selectedIdea.waveNumber}
-
-
- {selectedIdea.status === 'converted' && (
- Note Created
- )}
- setSelectedIdeaId(null)} className="p-2 hover:bg-ink/5 rounded-full transition-colors">
-
-
-
-
-
-
{selectedIdea.title}
-
-
-
- Novelty: {selectedIdea.noveltyScore}/10
-
-
-
-
- {selectedIdea.description}
-
-
-
-
Origin connection
-
- "{selectedIdea.connectionToSeed}"
-
-
-
- {selectedIdea.relatedNoteIds && selectedIdea.relatedNoteIds.length > 0 && (
-
-
Semantic Context
- {selectedIdea.relatedNoteIds.map(noteId => {
- const note = notes.find(n => n.id === noteId);
- return note ? (
-
- ) : null;
- })}
-
- )}
-
-
-
- handleDeepenIdea(selectedIdea)}
- disabled={isGenerating}
- className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-border rounded-2xl hover:border-ochre/40 hover:bg-ochre/5 transition-all group disabled:opacity-50"
- >
-
- Deepen
-
- handleConvertToNote(selectedIdea)}
- disabled={selectedIdea.status === 'converted'}
- className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-border rounded-2xl hover:border-blueprint/40 hover:bg-blueprint/5 transition-all group disabled:opacity-50"
- >
-
- Extract
-
-
-
-
handleDismissIdea(selectedIdea.id)}
- className="w-full py-4 text-[10px] font-bold uppercase tracking-[0.2em] text-concrete hover:text-rose-500 hover:bg-rose-500/5 rounded-xl transition-all border border-transparent hover:border-rose-500/10"
- >
- Not pertinent
-
-
-
-
- )}
-
-
- {/* History Rail */}
-
-
-
-
- {sessions.map(session => (
- setActiveSessionId(session.id)}
- className={`w-10 h-10 min-h-[40px] rounded-xl flex items-center justify-center text-xs font-bold transition-all shrink-0
- ${activeSessionId === session.id ? 'bg-ink text-paper scale-110 shadow-lg' : 'bg-paper dark:bg-white/10 text-concrete hover:bg-black/5 hover:text-ink'}`}
- title={session.seedIdea}
- >
- {session.seedIdea.charAt(0).toUpperCase()}
-
- ))}
-
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/BrainstormView/WaveCanvas.tsx b/architectural-grid11/src/components/BrainstormView/WaveCanvas.tsx
deleted file mode 100644
index fc55a50..0000000
--- a/architectural-grid11/src/components/BrainstormView/WaveCanvas.tsx
+++ /dev/null
@@ -1,250 +0,0 @@
-
-import React, { useEffect, useRef } from 'react';
-import * as d3 from 'd3';
-import { BrainstormSession, BrainstormIdea, Note } from '../../types';
-
-interface WaveCanvasProps {
- session: BrainstormSession;
- ideas: BrainstormIdea[];
- onNodeSelect: (id: string) => void;
- onPositionUpdate: (id: string, pos: { x: number; y: number }) => void;
- selectedNodeId: string | null;
- relatedNotes: Note[];
-}
-
-export const WaveCanvas: React.FC = ({
- session,
- ideas,
- onNodeSelect,
- onPositionUpdate,
- selectedNodeId,
- relatedNotes
-}) => {
- const svgRef = useRef(null);
- const containerRef = useRef(null);
-
- useEffect(() => {
- if (!svgRef.current || !containerRef.current) return;
-
- const width = containerRef.current.clientWidth;
- const height = containerRef.current.clientHeight;
- const centerX = width / 2;
- const centerY = height / 2;
-
- const svg = d3.select(svgRef.current);
- svg.selectAll("*").remove();
-
- const g = svg.append("g");
-
- // Zoom behavior
- const zoom = d3.zoom()
- .scaleExtent([0.1, 5])
- .on("zoom", (event) => {
- g.attr("transform", event.transform);
- });
-
- svg.call(zoom);
-
- // Initial transform to center
- svg.call(zoom.transform, d3.zoomIdentity.translate(centerX, centerY).scale(0.8));
-
- // Data structures for d3
- interface D3Node extends d3.SimulationNodeDatum {
- id: string;
- type: 'root' | 'idea' | 'note';
- wave?: number;
- title: string;
- color: string;
- radius: number;
- status?: string;
- }
-
- interface D3Link extends d3.SimulationLinkDatum {
- source: string | D3Node;
- target: string | D3Node;
- type: 'wave' | 'context' | 'parent';
- }
-
- const nodes: D3Node[] = [];
- const links: D3Link[] = [];
-
- // Root node
- const rootNode: D3Node = {
- id: 'root',
- type: 'root',
- title: session.seedIdea,
- color: '#141414',
- radius: 40,
- fx: 0,
- fy: 0
- };
- nodes.push(rootNode);
-
- // Idea nodes
- const colors = {
- 1: '#fb923c', // orange
- 2: '#60a5fa', // blue
- 3: '#a78bfa' // violet
- };
-
- ideas.forEach(idea => {
- nodes.push({
- id: idea.id,
- type: 'idea',
- wave: idea.waveNumber,
- title: idea.title,
- color: colors[idea.waveNumber as 1|2|3] || '#94a3b8',
- radius: 28,
- status: idea.status,
- x: idea.position?.x,
- y: idea.position?.y
- });
-
- if (idea.parentIdeaId) {
- links.push({
- source: idea.parentIdeaId,
- target: idea.id,
- type: 'parent'
- });
- } else {
- links.push({
- source: 'root',
- target: idea.id,
- type: 'wave'
- });
- }
- });
-
- // Radial layout forces
- const simulation = d3.forceSimulation(nodes)
- .force("link", d3.forceLink(links).id(d => d.id).distance(d => {
- if (d.type === 'wave') {
- const targetNode = nodes.find(n => n.id === (typeof d.target === 'string' ? d.target : (d.target as any).id));
- return (targetNode?.wave || 1) * 200;
- }
- if (d.type === 'parent') return 180;
- return 100;
- }))
- .force("charge", d3.forceManyBody().strength(-800))
- .force("radial", d3.forceRadial(d => {
- if (d.type === 'root') return 0;
- if (d.id.includes('-')) return (d.wave || 1) * 200 + 100; // Deepened ideas push out
- return (d.wave || 1) * 200;
- }, 0, 0).strength(0.8))
- .force("collision", d3.forceCollide().radius(d => d.radius + 30));
-
- // Drawing rings
- const ringRadii = [200, 400, 600];
- g.selectAll(".ring")
- .data(ringRadii)
- .enter()
- .append("circle")
- .attr("class", "ring")
- .attr("r", d => d)
- .attr("fill", "none")
- .attr("stroke", "#e2e8f0")
- .attr("stroke-width", 1)
- .attr("stroke-dasharray", "4,4")
- .style("opacity", 0.5);
-
- // Links
- const link = g.append("g")
- .selectAll("line")
- .data(links)
- .enter()
- .append("line")
- .attr("stroke", d => d.type === 'wave' ? "#cbd5e1" : d.type === 'parent' ? "#fde047" : "#94a3b8")
- .attr("stroke-width", d => d.type === 'wave' ? 1.5 : 2)
- .attr("stroke-dasharray", d => d.type === 'parent' ? "none" : "4,4");
-
- // Nodes
- const node = g.append("g")
- .selectAll(".node")
- .data(nodes)
- .enter()
- .append("g")
- .attr("class", "node")
- .style("opacity", d => d.status === 'dismissed' ? 0.4 : 1)
- .on("click", (event, d) => {
- if (d.type === 'idea') onNodeSelect(d.id);
- })
- .call(d3.drag()
- .on("start", dragstarted)
- .on("drag", dragged)
- .on("end", dragended) as any);
-
- node.append("circle")
- .attr("r", d => d.radius)
- .attr("fill", d => d.status === 'converted' ? '#ecfdf5' : (d.type === 'root' ? '#141414' : '#fff'))
- .attr("stroke", d => d.status === 'converted' ? '#10b981' : d.color)
- .attr("stroke-width", d => d.id === selectedNodeId ? 4 : 2)
- .attr("class", "cursor-pointer transition-all hover:scale-110")
- .style("filter", d => d.id === selectedNodeId ? `drop-shadow(0 0 12px ${d.color}cc)` : "none");
-
- // State indicators (converted)
- node.filter(d => d.status === 'converted')
- .append("path")
- .attr("d", d3.symbol().type(d3.symbolCircle).size(150))
- .attr("fill", "#10b981");
-
- // Icons/Text in nodes
- node.append("text")
- .attr("dy", d => d.type === 'root' ? ".35em" : d.radius + 20)
- .attr("text-anchor", "middle")
- .attr("fill", d => d.type === 'root' ? "#fff" : (d.status === 'dismissed' ? "#94a3b8" : "#141414"))
- .attr("class", d => d.type === 'root' ? "text-[10px] font-bold pointer-events-none tracking-widest" : "text-[11px] font-bold uppercase tracking-tight pointer-events-none")
- .text(d => d.type === 'root' ? "SEED" : d.title.length > 18 ? d.title.substring(0, 18) + "..." : d.title);
-
- if (rootNode) {
- g.append("text")
- .attr("text-anchor", "middle")
- .attr("dy", 80)
- .attr("class", "text-2xl font-serif italic fill-ink dark:fill-dark-ink pointer-events-none shadow-sm")
- .text(session.seedIdea);
- }
-
- simulation.on("tick", () => {
- link
- .attr("x1", d => (d.source as any).x)
- .attr("y1", d => (d.source as any).y)
- .attr("x2", d => (d.target as any).x)
- .attr("y2", d => (d.target as any).y);
-
- node
- .attr("transform", d => `translate(${d.x},${d.y})`);
- });
-
- function dragstarted(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0.3).restart();
- d.fx = d.x;
- d.fy = d.y;
- }
-
- function dragged(event: any, d: D3Node) {
- d.fx = event.x;
- d.fy = event.y;
- }
-
- function dragended(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0);
- d.fx = null;
- d.fy = null;
- if (d.type === 'idea') {
- onPositionUpdate(d.id, { x: event.x, y: event.y });
- }
- }
-
- return () => {
- simulation.stop();
- };
- }, [session, ideas, selectedNodeId, onNodeSelect]);
-
- return (
-
-
-
-
Spatial Exploration Mode
-
-
- );
-};
diff --git a/architectural-grid11/src/components/HierarchicalCarnetSelector.tsx b/architectural-grid11/src/components/HierarchicalCarnetSelector.tsx
deleted file mode 100644
index d04851e..0000000
--- a/architectural-grid11/src/components/HierarchicalCarnetSelector.tsx
+++ /dev/null
@@ -1,208 +0,0 @@
-import React, { useState, useMemo } from 'react';
-import {
- ChevronRight,
- ChevronDown,
- Folder,
- FolderOpen,
- Check,
- Search
-} from 'lucide-react';
-import { Carnet } from '../types';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface HierarchicalCarnetSelectorProps {
- carnets: Carnet[];
- selectedId: string | null;
- onSelect: (id: string) => void;
- className?: string;
- placeholder?: string;
-}
-
-export const HierarchicalCarnetSelector: React.FC = ({
- carnets,
- selectedId,
- onSelect,
- className = "",
- placeholder = "Sélectionner un carnet..."
-}) => {
- const [isOpen, setIsOpen] = useState(false);
- const [searchQuery, setSearchQuery] = useState("");
- const [expandedIds, setExpandedIds] = useState>(new Set(['1', '4'])); // Default expand some
-
- const selectedCarnet = carnets.find(c => c.id === selectedId);
-
- // Derive the path for display
- const path = useMemo(() => {
- if (!selectedCarnet) return [];
- const trail: Carnet[] = [];
- let current = selectedCarnet;
- while (current) {
- trail.unshift(current);
- if (!current.parentId) break;
- const parent = carnets.find(c => c.id === current.parentId);
- if (!parent) break;
- current = parent;
- }
- return trail;
- }, [selectedCarnet, carnets]);
-
- const toggleExpand = (e: React.MouseEvent, id: string) => {
- e.stopPropagation();
- const newExpanded = new Set(expandedIds);
- if (newExpanded.has(id)) {
- newExpanded.delete(id);
- } else {
- newExpanded.add(id);
- }
- setExpandedIds(newExpanded);
- };
-
- const filteredCarnets = useMemo(() => {
- if (!searchQuery) return carnets;
- return carnets.filter(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()));
- }, [carnets, searchQuery]);
-
- const renderTree = (parentId?: string, level = 0) => {
- const children = carnets.filter(c => c.parentId === parentId);
- if (children.length === 0) return null;
-
- return (
- 0 ? "ml-4 border-l border-border/40 pl-2" : ""}>
- {children.map(carnet => {
- const isExpanded = expandedIds.has(carnet.id) || searchQuery.length > 0;
- const hasChildren = carnets.some(c => c.parentId === carnet.id);
- const isSelected = selectedId === carnet.id;
-
- // If searching and this carnet doesn't match AND none of its children match, skip it
- if (searchQuery && !carnet.name.toLowerCase().includes(searchQuery.toLowerCase())) {
- const hasMatchingChild = (id: string): boolean => {
- const childrenOfId = carnets.filter(c => c.parentId === id);
- return childrenOfId.some(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()) || hasMatchingChild(c.id));
- };
- if (!hasMatchingChild(carnet.id)) return null;
- }
-
- return (
-
-
{
- onSelect(carnet.id);
- if (!searchQuery) setIsOpen(false);
- }}
- className={`flex items-center gap-2.5 px-2 py-1.5 rounded-lg cursor-pointer transition-all group
- ${isSelected ? 'bg-blueprint/10 text-blueprint font-bold' : 'hover:bg-slate-50 dark:hover:bg-white/5 text-ink'}`}
- >
-
- {hasChildren ? (
- toggleExpand(e, carnet.id)}
- className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded transition-colors"
- >
- {isExpanded ? : }
-
- ) : null}
-
-
-
- {isExpanded && hasChildren ? : }
-
-
-
{carnet.name}
-
- {isSelected &&
}
-
-
-
- {isExpanded && (
-
- {renderTree(carnet.id, level + 1)}
-
- )}
-
-
- );
- })}
-
- );
- };
-
- return (
-
-
setIsOpen(!isOpen)}
- className="w-full bg-slate-50 dark:bg-black/20 border border-border/80 rounded-xl px-4 py-4 text-sm outline-none focus:ring-4 ring-blueprint/5 focus:border-blueprint/40 transition-all cursor-pointer text-ink flex items-center gap-3"
- >
-
-
- {path.length > 0 ? (
-
- {path.map((item, i) => (
-
- {i > 0 && / }
-
- {item.name}
-
-
- ))}
-
- ) : (
-
{placeholder}
- )}
-
-
-
-
-
- {isOpen && (
- <>
- setIsOpen(false)}
- />
-
-
-
-
- setSearchQuery(e.target.value)}
- placeholder="Filtrer les carnets..."
- className="w-full bg-white border border-border rounded-lg pl-9 pr-4 py-2 text-xs outline-none focus:border-blueprint transition-colors"
- />
-
-
-
-
- {renderTree(undefined)}
-
-
-
-
- Structure des carnets
-
- setIsOpen(false)}
- className="text-[10px] font-bold text-blueprint hover:underline"
- >
- Fermer
-
-
-
- >
- )}
-
-
- );
-};
diff --git a/architectural-grid11/src/components/InsightsView.tsx b/architectural-grid11/src/components/InsightsView.tsx
deleted file mode 100644
index fda8edd..0000000
--- a/architectural-grid11/src/components/InsightsView.tsx
+++ /dev/null
@@ -1,248 +0,0 @@
-
-import React, { useState, useEffect, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import {
- Network,
- Lightbulb,
- Layers,
- Sparkles,
- ArrowRight,
- RefreshCw,
- Trophy,
- Zap,
- Tag,
- Link as LinkIcon
-} from 'lucide-react';
-import { Note, NoteCluster, BridgeNote, ConnectionSuggestion } from '../types';
-import { runClustering, detectBridges, calculateCentroid } from '../services/clusteringService';
-import { nameCluster, suggestBridgeIdeas } from '../services/geminiService';
-import { NetworkGraph } from './NetworkGraph';
-
-interface InsightsViewProps {
- notes: Note[];
- onUpdateNotes: (updatedNotes: Note[]) => void;
- onNoteSelect: (noteId: string) => void;
-}
-
-export const InsightsView: React.FC = ({
- notes,
- onUpdateNotes,
- onNoteSelect
-}) => {
- const [isCalculating, setIsCalculating] = useState(false);
- const [clusters, setClusters] = useState([]);
- const [bridgeNotes, setBridgeNotes] = useState([]);
- const [suggestions, setSuggestions] = useState([]);
- const [selectedClusterId, setSelectedClusterId] = useState(null);
-
- const performAnalysis = async () => {
- setIsCalculating(true);
- try {
- // 1. Run clustering
- const { clusters: newClusters } = runClustering(notes);
-
- // 2. Name clusters (first 5 unique notes per cluster)
- const namedClusters = await Promise.all(newClusters.map(async (c) => {
- const clusterNoteSummaries = notes
- .filter(n => c.noteIds.includes(n.id))
- .slice(0, 5)
- .map(n => n.title);
-
- const name = await nameCluster(clusterNoteSummaries);
- const centroid = calculateCentroid(c.noteIds, notes);
-
- return { ...c, name, centroid };
- }));
-
- // 3. Update notes with cluster IDs
- const updatedNotes = notes.map(n => {
- const cluster = namedClusters.find(c => c.noteIds.includes(n.id));
- return { ...n, clusterId: cluster?.id };
- });
- onUpdateNotes(updatedNotes);
-
- // 4. Detect bridges
- const bridges = detectBridges(updatedNotes, namedClusters);
-
- // 5. Build suggestions for isolated cluster pairs
- // For demo, we'll just pick a few interesting pairs
- const newSuggestions: ConnectionSuggestion[] = [];
- if (namedClusters.length >= 2) {
- // Find clusters with no mutual bridge notes or low connectivity
- for (let i = 0; i < Math.min(namedClusters.length, 3); i++) {
- for (let j = i + 1; j < Math.min(namedClusters.length, 3); j++) {
- const cA = namedClusters[i];
- const cB = namedClusters[j];
-
- const cA_notes = updatedNotes.filter(n => cA.noteIds.includes(n.id)).map(n => n.title).join(', ');
- const cB_notes = updatedNotes.filter(n => cB.noteIds.includes(n.id)).map(n => n.title).join(', ');
-
- const bridgeIdeas = await suggestBridgeIdeas(cA.name, cB.name, cA_notes, cB_notes);
- bridgeIdeas.forEach((idea, idx) => {
- newSuggestions.push({
- id: `suggestion-${i}-${j}-${idx}`,
- ...idea,
- clusterAId: cA.id,
- clusterBId: cB.id
- });
- });
- }
- }
- }
-
- setClusters(namedClusters);
- setBridgeNotes(bridges);
- setSuggestions(newSuggestions);
- } catch (error) {
- console.error("Analysis failed:", error);
- } finally {
- setIsCalculating(false);
- }
- };
-
- useEffect(() => {
- if (notes.some(n => n.embedding) && clusters.length === 0) {
- performAnalysis();
- }
- }, [notes]);
-
- const bridgeList = useMemo(() => {
- return bridgeNotes.map(b => {
- const note = notes.find(n => n.id === b.noteId);
- return { ...b, title: note?.title || 'Unknown Note' };
- });
- }, [bridgeNotes, notes]);
-
- return (
-
- {/* Header */}
-
-
-
-
-
-
-
Semantic Insights
-
-
Discovering the hidden architecture of your knowledge
-
-
- {isCalculating ? : }
- {isCalculating ? 'Mapping...' : 'Re-sync Network'}
-
-
-
-
- {/* Left: Graph View */}
-
-
-
-
- {/* Right: Insight Dashboard */}
-
-
- {/* Stats Summary */}
-
-
-
-
- Clusters
-
-
{clusters.length}
-
-
-
-
- Bridge Notes
-
-
{bridgeNotes.length}
-
-
-
- {/* Bridge Notes Section */}
-
-
-
-
Powerful Bridge Notes
-
-
- {bridgeList.map(bridge => (
-
onNoteSelect(bridge.noteId)}
- className="p-4 rounded-xl bg-white dark:bg-white/5 border border-border hover:border-ochre/40 transition-all cursor-pointer group"
- >
-
-
{bridge.title}
-
- Score: {(bridge.bridgeScore * 100).toFixed(0)}%
-
-
-
- {bridge.connectedClusterIds.map(cid => {
- const c = clusters.find(cl => cl.id === cid);
- return (
-
- );
- })}
-
-
- ))}
- {bridgeList.length === 0 && !isCalculating && (
-
No significant bridge notes found yet. Deepen your research to find new connections.
- )}
-
-
-
- {/* Connection Suggestions */}
-
-
-
-
Missing Links (AI Generated)
-
-
- {suggestions.map((s, idx) => (
-
-
-
-
Bridging {clusters.find(c => c.id === s.clusterAId)?.name} & {clusters.find(c => c.id === s.clusterBId)?.name}
-
-
{s.title}
-
{s.description}
-
-
- {s.reasoning}
-
-
- ))}
- {isCalculating && (
-
- {[1, 2].map(i => (
-
- ))}
-
- )}
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/NetworkGraph.tsx b/architectural-grid11/src/components/NetworkGraph.tsx
deleted file mode 100644
index aa83e68..0000000
--- a/architectural-grid11/src/components/NetworkGraph.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-
-import React, { useEffect, useRef } from 'react';
-import * as d3 from 'd3';
-import { Note, NoteCluster, BridgeNote } from '../types';
-
-interface NetworkGraphProps {
- notes: Note[];
- clusters: NoteCluster[];
- bridgeNotes: BridgeNote[];
- onNoteSelect: (id: string) => void;
-}
-
-export const NetworkGraph: React.FC = ({
- notes,
- clusters,
- bridgeNotes,
- onNoteSelect
-}) => {
- const svgRef = useRef(null);
- const containerRef = useRef(null);
-
- useEffect(() => {
- if (!svgRef.current || !containerRef.current) return;
-
- const width = containerRef.current.clientWidth;
- const height = containerRef.current.clientHeight;
-
- const svg = d3.select(svgRef.current);
- svg.selectAll("*").remove();
-
- const g = svg.append("g");
-
- const zoom = d3.zoom()
- .scaleExtent([0.1, 4])
- .on("zoom", (event) => {
- g.attr("transform", event.transform);
- });
-
- svg.call(zoom);
-
- // Filter notes with embeddings and cluster assignments
- const visibleNotes = notes.filter(n => n.embedding && n.clusterId);
-
- interface D3Node extends d3.SimulationNodeDatum {
- id: string;
- title: string;
- clusterId: string;
- color: string;
- isBridge: boolean;
- radius: number;
- }
-
- interface D3Link extends d3.SimulationLinkDatum {
- source: string;
- target: string;
- strength: number;
- }
-
- const bridgeSet = new Set(bridgeNotes.map(b => b.noteId));
-
- const nodes: D3Node[] = visibleNotes.map(n => {
- const cluster = clusters.find(c => c.id === n.clusterId);
- const isBridge = bridgeSet.has(n.id);
- return {
- id: n.id,
- title: n.title,
- clusterId: n.clusterId!,
- color: cluster?.color || '#cbd5e1',
- isBridge,
- radius: isBridge ? 12 : 8
- };
- });
-
- const links: D3Link[] = [];
- // Only connect strong links
- for (let i = 0; i < visibleNotes.length; i++) {
- for (let j = i + 1; j < visibleNotes.length; j++) {
- const ni = visibleNotes[i];
- const nj = visibleNotes[j];
-
- if (ni.clusterId === nj.clusterId) {
- links.push({ source: ni.id, target: nj.id, strength: 0.5 });
- }
- }
- }
-
- const simulation = d3.forceSimulation(nodes)
- .force("link", d3.forceLink(links).id(d => d.id).distance(100))
- .force("charge", d3.forceManyBody().strength(-200))
- .force("center", d3.forceCenter(width / 2, height / 2))
- .force("collision", d3.forceCollide().radius(d => d.radius + 10));
-
- // Links
- const link = g.append("g")
- .selectAll("line")
- .data(links)
- .enter()
- .append("line")
- .attr("stroke", "#e2e8f0")
- .attr("stroke-opacity", 0.6)
- .attr("stroke-width", 1);
-
- // Nodes
- const node = g.append("g")
- .selectAll(".node")
- .data(nodes)
- .enter()
- .append("g")
- .attr("class", "node cursor-pointer")
- .on("click", (event, d) => onNoteSelect(d.id))
- .call(d3.drag()
- .on("start", dragstarted)
- .on("drag", dragged)
- .on("end", dragended) as any);
-
- node.append("circle")
- .attr("r", d => d.radius)
- .attr("fill", d => d.color)
- .attr("stroke", d => d.isBridge ? "#D4AF37" : "#fff")
- .attr("stroke-width", d => d.isBridge ? 3 : 2)
- .style("filter", d => d.isBridge ? "drop-shadow(0 0 4px rgba(212, 175, 55, 0.4))" : "none");
-
- node.append("text")
- .attr("dy", d => d.radius + 14)
- .attr("text-anchor", "middle")
- .attr("class", "text-[10px] fill-concrete dark:fill-concrete/60 font-medium pointer-events-none")
- .text(d => d.title.length > 20 ? d.title.substring(0, 20) + "..." : d.title);
-
- simulation.on("tick", () => {
- link
- .attr("x1", d => (d.source as any).x)
- .attr("y1", d => (d.source as any).y)
- .attr("x2", d => (d.target as any).x)
- .attr("y2", d => (d.target as any).y);
-
- node
- .attr("transform", d => `translate(${d.x},${d.y})`);
- });
-
- function dragstarted(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0.3).restart();
- d.fx = d.x;
- d.fy = d.y;
- }
-
- function dragged(event: any, d: D3Node) {
- d.fx = event.x;
- d.fy = event.y;
- }
-
- function dragended(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0);
- d.fx = null;
- d.fy = null;
- }
-
- return () => simulation.stop();
- }, [notes, clusters, bridgeNotes, onNoteSelect]);
-
- return (
-
-
- {clusters.map(c => (
-
- ))}
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/NotebooksView.tsx b/architectural-grid11/src/components/NotebooksView.tsx
deleted file mode 100644
index 98817c9..0000000
--- a/architectural-grid11/src/components/NotebooksView.tsx
+++ /dev/null
@@ -1,489 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Search,
- Share2,
- Pin,
- ChevronRight,
- ArrowLeft,
- MoreVertical,
- Sparkles,
- Tag as TagIcon,
- X,
- BookOpen,
- Edit3,
- Eye,
- Trash2,
- Wind
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet, Tag } from '../types';
-import { SlashMenu } from './SlashMenu';
-
-interface NotebooksViewProps {
- activeNoteId: string | null;
- activeCarnet: Carnet | undefined;
- filteredNotes: Note[];
- activeNote: Note | undefined;
- setActiveNoteId: (id: string | null) => void;
- togglePin: (id: string) => void;
- setShowNewNoteModal: (show: boolean) => void;
- isAISidebarOpen: boolean;
- setIsAISidebarOpen: (open: boolean) => void;
- selectedTagIds: string[];
- setSelectedTagIds: (ids: string[]) => void;
- allNotes: Note[];
- activeCarnetId: string;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteNote: (id: string) => void;
- onBrainstormNote: (note: Note) => void;
-}
-
-export const NotebooksView: React.FC = ({
- activeNoteId,
- activeCarnet,
- filteredNotes,
- activeNote,
- setActiveNoteId,
- togglePin,
- setShowNewNoteModal,
- isAISidebarOpen,
- setIsAISidebarOpen,
- selectedTagIds,
- setSelectedTagIds,
- allNotes,
- activeCarnetId,
- setShowNewCarnetModal,
- onDeleteNote,
- onBrainstormNote
-}) => {
- const [isTagsExpanded, setIsTagsExpanded] = React.useState(false);
- const [tagSearchQuery, setTagSearchQuery] = React.useState('');
- const [isEditing, setIsEditing] = React.useState(false);
- const [slashMenu, setSlashMenu] = React.useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const insertCommand = (type: string) => {
- console.log(`Command selected: ${type}`);
- setSlashMenu(null);
- };
-
- const availableTags = React.useMemo(() => {
- const carnetNotes = allNotes.filter(n => n.carnetId === activeCarnetId);
- const tagsMap = new Map();
- carnetNotes.forEach(note => {
- note.tags?.forEach(tag => {
- tagsMap.set(tag.id, tag);
- });
- });
- return Array.from(tagsMap.values()).sort((a, b) => {
- // AI tags first, then alphabetical
- if (a.type === 'ai' && b.type !== 'ai') return -1;
- if (a.type !== 'ai' && b.type === 'ai') return 1;
- return a.label.localeCompare(b.label);
- });
- }, [allNotes, activeCarnetId]);
-
- const visibleTags = React.useMemo(() => {
- let filtered = availableTags;
- if (tagSearchQuery) {
- filtered = availableTags.filter(t =>
- t.label.toLowerCase().includes(tagSearchQuery.toLowerCase())
- );
- } else if (!isTagsExpanded) {
- filtered = availableTags.slice(0, 10);
- // Ensure selected tags are always visible even if not in the first 10
- selectedTagIds.forEach(id => {
- if (!filtered.find(t => t.id === id)) {
- const tag = availableTags.find(t => t.id === id);
- if (tag) filtered.push(tag);
- }
- });
- }
- return filtered;
- }, [availableTags, isTagsExpanded, tagSearchQuery, selectedTagIds]);
-
- const toggleTag = (tagId: string) => {
- if (selectedTagIds.includes(tagId)) {
- setSelectedTagIds(selectedTagIds.filter(id => id !== tagId));
- } else {
- setSelectedTagIds([...selectedTagIds, tagId]);
- }
- };
-
- if (!activeNoteId) {
- return (
-
-
-
-
-
- {filteredNotes.map((note, index) => (
-
setActiveNoteId(note.id)}
- >
-
-
- {note.isPinned && }
- {note.title}
-
-
-
{
- e.stopPropagation();
- onBrainstormNote(note);
- }}
- className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-ochre/10 text-ochre transition-all"
- title="Brainstorm this concept"
- >
-
-
-
{
- e.stopPropagation();
- togglePin(note.id);
- }}
- className={`p-2 rounded-full transition-all ${note.isPinned ? 'text-amber-600 bg-amber-50' : 'opacity-0 group-hover:opacity-60 hover:bg-slate-100 text-ink'}`}
- >
-
-
-
{
- e.stopPropagation();
- onDeleteNote(note.id);
- }}
- className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-rose-50 text-rose-500 transition-all"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- {note.tags?.map(tag => (
-
- {tag.type === 'ai' && }
- {tag.label}
-
- ))}
-
-
- {note.content}
-
-
Read more
-
-
-
- ))}
- {filteredNotes.length === 0 && (
-
-
This notebook is waiting for its first vision.
-
setShowNewNoteModal(true)}
- className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all"
- >
- Begin Drawing
-
-
- )}
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
setActiveNoteId(null)}
- className="flex items-center gap-2 text-ink hover:opacity-60 transition-opacity"
- >
-
- Back to collection
-
-
-
onBrainstormNote(activeNote!)}
- className="flex items-center gap-2 px-3 py-1.5 rounded-full border border-ochre/30 text-ochre hover:bg-ochre/5 transition-all"
- >
-
- Brainstorm
-
-
setIsEditing(!isEditing)}
- className={`flex items-center gap-2 px-4 py-1.5 rounded-lg border transition-all duration-300
- ${isEditing ? 'bg-blueprint text-white border-blueprint shadow-lg shadow-blueprint/20' : 'border-border text-ink hover:bg-slate-50'}`}
- >
- {isEditing ? : }
- {isEditing ? 'Visualiser' : 'Modifier'}
-
-
togglePin(activeNoteId!)}
- className={`p-2 rounded-full transition-all ${activeNote?.isPinned ? 'text-amber-600 bg-amber-50 dark:bg-ochre/10' : 'text-muted-ink hover:text-ink'}`}
- title={activeNote?.isPinned ? "Unpin note" : "Pin note"}
- >
-
-
-
setIsAISidebarOpen(!isAISidebarOpen)}
- className={`flex items-center gap-2 px-3 py-1.5 rounded-full border transition-all duration-300
- ${isAISidebarOpen ? 'bg-ink text-paper border-ink' : 'border-border text-ink hover:bg-white/50 dark:hover:bg-white/5'}`}
- >
-
- AI Assistant
-
-
-
-
-
-
-
-
-
-
-
-
- {slashMenu?.isOpen && (
- insertCommand(type)}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
-
-
-
- {activeCarnet?.name}
-
- {activeNote?.date}
-
-
- {isEditing ? (
-
- ) : (
-
- {activeNote?.title}
-
- )}
-
-
- {activeNote?.tags?.map(tag => (
-
- {tag.type === 'ai' &&
}
- {tag.label}
- {tag.type === 'ai' && (
-
- )}
-
- ))}
-
-
-
-
-
-
-
-
-
- {isEditing ? (
-
- ) : (
-
-
- {activeNote?.content.split('.')[0]}.
-
-
-
- {activeNote?.content.split('\n').map((line, i) => (
-
- {line}
-
- ))}
- {activeNote?.id.startsWith('n-') && (
-
- Architectural grids serve as the invisible scaffolding upon which spatial experiences are constructed. Beyond mere structural repetition, they facilitate a rhythmic dialogue between materiality and void. In this exploration, we examine how light fractures these rigid boundaries, creating a dynamic interplay that evolves with the passage of time.
-
- )}
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/SettingsView.tsx b/architectural-grid11/src/components/SettingsView.tsx
deleted file mode 100644
index 57b3981..0000000
--- a/architectural-grid11/src/components/SettingsView.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import { SettingsTab } from '../types';
-import { SettingsHeader } from './settings/SettingsHeader';
-import { GeneralTab } from './settings/GeneralTab';
-import { AITab } from './settings/AITab';
-import { AppearanceTab } from './settings/AppearanceTab';
-
-interface SettingsViewProps {
- activeSettingsTab: SettingsTab;
- setActiveSettingsTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsView: React.FC = ({
- activeSettingsTab,
- setActiveSettingsTab
-}) => {
- return (
-
-
-
-
-
-
-
-
-
- {activeSettingsTab === 'general' && (
-
- )}
-
- {activeSettingsTab === 'ai' && (
-
- )}
-
- {activeSettingsTab === 'appearance' && (
-
- )}
-
- {['profile', 'data', 'mcp', 'about'].includes(activeSettingsTab) && (
-
-
- ?
-
-
-
Section en développement
-
Le module {activeSettingsTab} sera disponible prochainement.
-
-
- )}
-
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/Sidebar.tsx b/architectural-grid11/src/components/Sidebar.tsx
deleted file mode 100644
index 124ed80..0000000
--- a/architectural-grid11/src/components/Sidebar.tsx
+++ /dev/null
@@ -1,569 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Archive,
- Settings,
- ChevronRight,
- BookOpen,
- Bot,
- Microscope,
- Activity,
- Pin,
- Moon,
- Sun,
- Bell,
- Lock,
- Edit3,
- Trash2,
- Users,
- Clock,
- GripVertical,
- Wind,
- Network
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { NavigationView, Carnet, Note } from '../types';
-
-interface NoteLinkProps {
- note: Note;
- isActive: boolean;
- onClick: () => void;
-}
-
-const NoteLink: React.FC = ({ note, isActive, onClick }) => (
-
-
- {note.isPinned && }
-
-);
-
-interface SidebarItemProps {
- carnet: Carnet;
- isActive: boolean;
- notes: Note[];
- activeNoteId: string | null;
- onCarnetClick: () => void;
- onNoteClick: (noteId: string) => void;
- onAddSubCarnet: () => void;
- onRename: () => void;
- onDelete: () => void;
- children?: React.ReactNode;
- level: number;
- isExpanded: boolean;
- toggleExpand: () => void;
- onMove?: (draggedId: string, targetId?: string) => void;
-}
-
-const SidebarItem: React.FC = ({
- carnet,
- isActive,
- notes,
- activeNoteId,
- onCarnetClick,
- onNoteClick,
- onAddSubCarnet,
- onRename,
- onDelete,
- children,
- level,
- isExpanded,
- toggleExpand,
- onMove
-}) => {
- const hasChildren = React.Children.count(children) > 0;
-
- return (
-
-
- {/* Subtle Drag Handle */}
-
-
-
-
- {/* Hierarchy Guide Line */}
- {level > 0 && (
-
- )}
- {level > 0 && (
-
- )}
-
-
- {hasChildren ? (
-
{
- e.stopPropagation();
- toggleExpand();
- }}
- className="p-1 hover:bg-ink/5 dark:hover:bg-white/5 rounded-md transition-colors text-muted-ink"
- >
-
-
-
-
- ) : (
-
// Spacer for alignment
- )}
-
-
{
- e.preventDefault();
- e.dataTransfer.dropEffect = 'move';
- e.currentTarget.classList.add('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDragLeave={(e) => {
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDrop={(e) => {
- e.preventDefault();
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- const draggedId = e.dataTransfer.getData('carnetId');
- console.log('Dropped carnet:', draggedId, 'on target:', carnet.id);
- if (draggedId && draggedId !== carnet.id) {
- onMove?.(draggedId, carnet.id);
- }
- }}
- draggable
- onDragStart={(e) => {
- console.log('Starting drag for carnet:', carnet.id);
- e.dataTransfer.setData('carnetId', carnet.id);
- e.dataTransfer.effectAllowed = 'move';
- const ghost = e.currentTarget.cloneNode(true) as HTMLElement;
- ghost.style.position = 'absolute';
- ghost.style.top = '-1000px';
- ghost.style.opacity = '0.5';
- document.body.appendChild(ghost);
- e.dataTransfer.setDragImage(ghost, 0, 0);
- setTimeout(() => document.body.removeChild(ghost), 0);
- }}
- >
- {/* active indicator dot */}
- {isActive && (
-
- )}
-
-
- {carnet.initial}
-
-
-
- {carnet.name}
-
- {carnet.isPrivate && }
-
-
-
-
{
- e.stopPropagation();
- onAddSubCarnet();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Add sub-carnet"
- >
-
-
-
{
- e.stopPropagation();
- onRename();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Rename"
- >
-
-
-
{
- e.stopPropagation();
- onDelete();
- }}
- className="p-1 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md transition-all text-concrete hover:text-red-500"
- title="Delete"
- >
-
-
-
- {notes.length > 0 && (
-
- {notes.length}
-
- )}
-
-
-
-
-
-
- {(isExpanded || (isActive && !hasChildren)) && (
-
-
- {/* Vertical line for nested content */}
-
-
-
- {children}
- {isActive && !hasChildren && notes.map(note => (
-
onNoteClick(note.id)}
- />
- ))}
- {isActive && !hasChildren && notes.length === 0 && (
-
- No notes found
-
- )}
-
-
-
- )}
-
-
- );
-};
-
-interface SidebarProps {
- activeView: NavigationView;
- isDarkMode: boolean;
- setIsDarkMode: (val: boolean) => void;
- setActiveView: (view: NavigationView) => void;
- carnets: Carnet[];
- notes: Note[];
- activeCarnetId: string;
- activeNoteId: string | null;
- setActiveCarnetId: (id: string) => void;
- setActiveNoteId: (id: string | null) => void;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteCarnet: (id: string) => void;
- onMoveCarnet: (draggedId: string, targetId?: string) => void;
-}
-
-export const Sidebar: React.FC = ({
- activeView,
- isDarkMode,
- setIsDarkMode,
- setActiveView,
- carnets,
- notes,
- activeCarnetId,
- activeNoteId,
- setActiveCarnetId,
- setActiveNoteId,
- setShowNewCarnetModal,
- onDeleteCarnet,
- onMoveCarnet
-}) => {
- const [expandedIds, setExpandedIds] = React.useState>(new Set(['4'])); // Default expand Research
-
- const toggleExpand = (id: string) => {
- const newSet = new Set(expandedIds);
- if (newSet.has(id)) newSet.delete(id);
- else newSet.add(id);
- setExpandedIds(newSet);
- };
-
- const renderCarnetTree = (parentId: string | undefined = undefined, level: number = 0) => {
- return carnets
- .filter(c => c.parentId === parentId && !c.isDeleted)
- .map(carnet => (
- n.carnetId === carnet.id && !n.isDeleted)}
- activeNoteId={activeNoteId}
- level={level}
- isExpanded={expandedIds.has(carnet.id)}
- toggleExpand={() => toggleExpand(carnet.id)}
- onAddSubCarnet={() => {
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- setShowNewCarnetModal(true, carnet.id);
- }}
- onRename={() => {
- setShowNewCarnetModal(true, undefined, true, carnet.id);
- }}
- onDelete={() => {
- onDeleteCarnet(carnet.id);
- }}
- onCarnetClick={() => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(null);
- // Auto expand when clicking
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- }}
- onNoteClick={(id) => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(id);
- }}
- onMove={onMoveCarnet}
- >
- {renderCarnetTree(carnet.id, level + 1)}
-
- ));
- };
-
- return (
-
-
-
- A
-
-
-
setIsDarkMode(!isDarkMode)}
- className="p-2 text-muted-ink hover:text-ink transition-all bg-white/50 dark:bg-white/10 rounded-full border border-border dark:border-white/10"
- >
- {isDarkMode ? : }
-
-
-
-
-
- 3
-
-
-
-
- setActiveView('notebooks')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'notebooks' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Carnets"
- >
-
-
- setActiveView('reminders')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'reminders' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Rappels"
- >
-
-
- setActiveView('agents')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'agents' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Agents"
- >
-
-
-
-
-
-
-
- {activeView === 'notebooks' ? (
-
-
{
- e.preventDefault();
- e.dataTransfer.dropEffect = 'move';
- e.currentTarget.classList.add('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDragLeave={(e) => {
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDrop={(e) => {
- e.preventDefault();
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- const draggedId = e.dataTransfer.getData('carnetId');
- console.log('Dropped carnet on root:', draggedId);
- if (draggedId) {
- onMoveCarnet(draggedId, undefined);
- }
- }}
- >
-
- Architecture Grid
-
-
setShowNewCarnetModal(true)}
- className="p-1 hover:bg-paper dark:hover:bg-white/5 rounded-md text-concrete hover:text-ink transition-colors"
- title="New Carnet"
- >
-
-
-
-
-
- {renderCarnetTree()}
-
-
- ) : activeView === 'shared' ? (
-
-
- Partagé avec moi
-
-
-
-
Aucun document partagé pour le moment.
-
-
- ) : activeView === 'reminders' ? (
-
-
- Rappels programmés
-
-
-
-
Aucun rappel actif.
-
-
- ) : activeView === 'agents' ? (
-
-
- Intelligence OS
-
-
- {[
- { id: 'a1', name: 'Mes Agents', icon:
},
- { id: 'a2', name: 'Le Lab AI', icon:
},
- { id: 'a3', name: 'Activités', icon:
},
- ].map(item => (
-
-
- {item.icon}
-
- {item.name}
-
- ))}
-
-
-
-
- Capabilities
-
-
setActiveView('brainstorm')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-ochre hover:bg-ochre/5"
- >
-
-
-
- Brainstorm Wave
-
-
-
setActiveView('insights')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-indigo-500 hover:bg-indigo-500/5"
- >
-
-
-
- Semantic Network
-
-
-
setActiveView('temporal')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-rose-500 hover:bg-rose-500/5"
- >
-
-
-
- Temporal Forecast
-
-
-
- ) : null}
-
-
-
-
-
setActiveView('shared')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'shared' ? 'bg-blueprint/5 text-blueprint' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Partagé
-
-
-
-
- Archives
-
-
-
setActiveView('trash')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'trash' ? 'bg-rose-50 text-rose-500' : 'text-muted-ink hover:text-rose-500 hover:bg-rose-50/50'}`}
- >
-
- Corbeille
- {notes.some(n => n.isDeleted) && (
-
- )}
-
-
-
-
Intelligence
-
setActiveView('brainstorm')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'brainstorm' ? 'bg-ochre/10 text-ochre' : 'text-muted-ink hover:text-ochre hover:bg-ochre/5'}`}
- >
-
- Brainstorm Wave
-
-
-
setActiveView('insights')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'insights' ? 'bg-indigo-500/10 text-indigo-500' : 'text-muted-ink hover:text-indigo-500 hover:bg-indigo-500/5'}`}
- >
-
- Semantic Network
-
-
-
setActiveView('temporal')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'temporal' ? 'bg-rose-500/10 text-rose-500' : 'text-muted-ink hover:text-rose-500 hover:bg-rose-500/5'}`}
- >
-
- Temporal Forecast
-
-
-
-
-
-
setActiveView('settings')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'settings' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Paramètres
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/SlashMenu.tsx b/architectural-grid11/src/components/SlashMenu.tsx
deleted file mode 100644
index a715c58..0000000
--- a/architectural-grid11/src/components/SlashMenu.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import {
- Heading1,
- Heading2,
- List,
- Quote,
- Code,
- Image as ImageIcon,
- Type,
- Sparkles
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface SlashMenuProps {
- position: { top: number; left: number };
- onSelect: (type: string) => void;
- onClose: () => void;
-}
-
-export const SlashMenu: React.FC = ({ position, onSelect, onClose }) => {
- const commands = [
- { id: 'h1', label: 'Titre Principal', icon: , desc: 'Grand titre de section' },
- { id: 'h2', label: 'Sous-titre', icon: , desc: 'Titre de niveau 2' },
- { id: 'bullet', label: 'Liste à puces', icon:
, desc: 'Liste simple' },
- { id: 'quote', label: 'Citation', icon:
, desc: 'Bloc de texte mis en avant' },
- { id: 'code', label: 'Bloc de Code', icon: , desc: 'Code ou texte technique' },
- { id: 'image', label: 'Image', icon: , desc: 'Insérer un visuel' },
- { id: 'ai-summary', label: 'Résumé IA', icon: , desc: 'Générer un résumé court', special: true },
- ];
-
- return (
- <>
-
-
-
- Commandes rapides
-
-
- {commands.map((cmd) => (
-
onSelect(cmd.id)}
- className="w-full flex items-start gap-3 px-3 py-2 hover:bg-paper dark:hover:bg-white/5 transition-colors group text-left"
- >
-
- {cmd.icon}
-
-
-
{cmd.label}
-
{cmd.desc}
-
-
- ))}
-
-
- >
- );
-};
diff --git a/architectural-grid11/src/components/TrashView.tsx b/architectural-grid11/src/components/TrashView.tsx
deleted file mode 100644
index dc62521..0000000
--- a/architectural-grid11/src/components/TrashView.tsx
+++ /dev/null
@@ -1,218 +0,0 @@
-import React from 'react';
-import {
- Trash2,
- RotateCcw,
- X,
- FileText,
- Folder,
- Search,
- ChevronRight,
- Clock,
- AlertCircle
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet } from '../types';
-
-interface TrashViewProps {
- deletedNotes: Note[];
- deletedCarnets: Carnet[];
- onRestoreNote: (id: string) => void;
- onRestoreCarnet: (id: string) => void;
- onPermanentDeleteNote: (id: string) => void;
- onPermanentDeleteCarnet: (id: string) => void;
- onEmptyTrash: () => void;
-}
-
-export const TrashView: React.FC = ({
- deletedNotes,
- deletedCarnets,
- onRestoreNote,
- onRestoreCarnet,
- onPermanentDeleteNote,
- onPermanentDeleteCarnet,
- onEmptyTrash
-}) => {
- const [searchQuery, setSearchQuery] = React.useState('');
- const [filterType, setFilterType] = React.useState<'all' | 'notes' | 'carnets'>('all');
-
- const getDaysRemaining = (dateString?: string) => {
- if (!dateString) return 30;
- const deletedDate = new Date(dateString);
- const now = new Date();
- const diffTime = now.getTime() - deletedDate.getTime();
- const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
- return Math.max(0, 30 - diffDays);
- };
-
- const filteredItems = React.useMemo(() => {
- const items = [
- ...deletedNotes.map(n => ({ ...n, itemType: 'note' as const })),
- ...deletedCarnets.map(c => ({ ...c, itemType: 'carnet' as const }))
- ];
-
- return items
- .filter(item => {
- const matchesSearch = ('title' in item ? item.title : item.name).toLowerCase().includes(searchQuery.toLowerCase());
- const matchesType = filterType === 'all' || (filterType === 'notes' && item.itemType === 'note') || (filterType === 'carnets' && item.itemType === 'carnet');
- return matchesSearch && matchesType;
- })
- .sort((a, b) => {
- const dateA = a.deletedAt ? new Date(a.deletedAt).getTime() : 0;
- const dateB = b.deletedAt ? new Date(b.deletedAt).getTime() : 0;
- return dateB - dateA;
- });
- }, [deletedNotes, deletedCarnets, searchQuery, filterType]);
-
- return (
-
-
-
-
-
- Corbeille
-
-
- Auto-suppression après 30 jours
-
-
-
- {filteredItems.length > 0 && (
-
{
- if (window.confirm('Vider la corbeille ? Cette action est irréversible.')) {
- onEmptyTrash();
- }
- }}
- className="px-6 py-3 bg-paper border border-border text-rose-500 rounded-2xl text-[10px] font-bold uppercase tracking-widest hover:bg-rose-50 hover:border-rose-100 transition-all shadow-sm"
- >
- Vider tout
-
- )}
-
-
-
-
-
- setSearchQuery(e.target.value)}
- className="w-full bg-white dark:bg-white/5 border border-border/40 rounded-2xl pl-12 pr-6 py-4 text-sm outline-none focus:ring-4 ring-ink/5 transition-all shadow-sm"
- />
-
-
-
- {(['all', 'notes', 'carnets'] as const).map((type) => (
- setFilterType(type)}
- className={`px-6 py-3 rounded-xl text-[10px] font-bold uppercase tracking-widest transition-all
- ${filterType === type ? 'bg-ink text-paper shadow-lg' : 'text-concrete hover:text-ink'}`}
- >
- {type === 'all' ? 'Tous' : type === 'notes' ? 'Notes' : 'Carnets'}
-
- ))}
-
-
-
-
-
- {filteredItems.length > 0 ? (
-
-
- {filteredItems.map((item) => {
- const daysLeft = getDaysRemaining(item.deletedAt);
- return (
-
- {/* Countdown Progress Bar */}
-
-
-
-
-
-
- {item.itemType === 'note' ? : }
-
-
- item.itemType === 'note' ? onRestoreNote(item.id) : onRestoreCarnet(item.id)}
- className="flex items-center gap-2 px-4 py-2 bg-emerald-50 text-emerald-600 rounded-xl text-[10px] font-bold uppercase tracking-widest hover:bg-emerald-100 transition-colors"
- >
- Restaurer
-
- item.itemType === 'note' ? onPermanentDeleteNote(item.id) : onPermanentDeleteCarnet(item.id)}
- className="p-2 hover:bg-rose-50 text-rose-500 rounded-xl transition-colors"
- title="Supprimer définitivement"
- >
-
-
-
-
-
-
-
- {'title' in item ? item.title : item.name}
-
-
-
- {daysLeft} JOURS RESTANTS
-
-
- {('deletedAt' in item && item.deletedAt) ? new Date(item.deletedAt).toLocaleDateString() : ''}
-
-
-
-
- {item.itemType === 'note' && 'content' in item ? (
-
- {item.content.replace(/[#*`]/g, '')}
-
- ) : (
-
-
- Contenu du dossier préservé
-
-
- )}
-
- );
- })}
-
-
- ) : (
-
-
-
-
-
-
Corbeille vide
-
- Les éléments que vous supprimez apparaîtront ici. Ils seront conservés pendant 30 jours avant suppression définitive.
-
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/settings/AITab.tsx b/architectural-grid11/src/components/settings/AITab.tsx
deleted file mode 100644
index 607c84e..0000000
--- a/architectural-grid11/src/components/settings/AITab.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-import React from 'react';
-import { Sparkles, Edit3, MessageCircle, Languages, Tag, History, FlaskConical } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AISettingCard = ({ icon, title, description, defaultChecked = false }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
-
-
-);
-
-export const AITab: React.FC = () => {
- return (
-
-
-
Configurez vos fonctionnalités IA et préférences
-
-
-
Fonctionnalités IA
-
-
}
- title="Suggestions de titre"
- description="Suggérer des titres pour les notes sans titre après 50+ mots"
- defaultChecked
- />
-
}
- title="IA Note"
- description="Active le bouton de chat IA et les outils d'amélioration du texte"
- defaultChecked
- />
-
}
- title="💡 J'ai remarqué quelque chose..."
- description="Aperçu quotidien de vos notes"
- defaultChecked
- />
-
}
- title="Détection de langue"
- description="Détecte automatiquement la langue de vos notes"
- defaultChecked
- />
-
}
- title="Suggestion des labels"
- description="Suggère et applique des étiquettes automatiquement à vos notes"
- defaultChecked
- />
-
}
- title="Historique des notes"
- description="Active les snapshots de versions et la restauration depuis History"
- defaultChecked
- />
-
-
-
-
- {/* Fréquence */}
-
-
-
Fréquence
-
Fréquence d'analyse des connexions
-
-
-
-
- {/* Mode d'historique */}
-
-
-
Mode d'historique
-
Gestion des snapshots
-
-
-
-
-
-
-
Manuel (bouton commit)
-
Créer des snapshots manuellement
-
-
-
-
-
-
-
Automatique (intelligent)
-
Snapshots automatiques avec détection
-
-
-
-
-
-
- {/* Mode Démo */}
-
-
-
-
-
-
-
- 🧪 Mode Démo
-
-
Accélère Memory Echo pour les tests. Les connexions apparaissent instantanément.
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/settings/AppearanceTab.tsx b/architectural-grid11/src/components/settings/AppearanceTab.tsx
deleted file mode 100644
index ba9ccdf..0000000
--- a/architectural-grid11/src/components/settings/AppearanceTab.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React from 'react';
-import { Palette, Type, LayoutGrid, Maximize } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AppearanceSelect = ({ icon, title, description, options, defaultValue }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
- {options.map((opt: string) => (
- {opt}
- ))}
-
-
-
-
-);
-
-export const AppearanceTab: React.FC = () => {
- return (
-
-
-
Personnaliser l'apparence de l'application
-
-
-
}
- title="Thème"
- description="Sélectionner le mode visuel"
- options={['Clair', 'Sombre', 'Système']}
- defaultValue="Clair"
- />
-
}
- title="Taille de la police"
- description="Ajustez la lisibilité globale de l'interface"
- options={['Petite', 'Moyenne', 'Grande']}
- defaultValue="Moyenne"
- />
-
}
- title="Famille de polices"
- description="La typographie définit l'âme de l'application"
- options={['Inter', 'JetBrains Mono', 'Public Sans', 'Outfit']}
- defaultValue="JetBrains Mono"
- />
-
}
- title="Affichage des notes"
- description="Gestion visuelle de la grille de composition"
- options={['Cartes (grille)', 'Liste', 'Tableau']}
- defaultValue="Cartes (grille)"
- />
-
}
- title="Taille des notes"
- description="Structure de la mise en page des éléments"
- options={['Taille uniforme', 'Variable (Masonry)']}
- defaultValue="Taille uniforme"
- />
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/settings/GeneralTab.tsx b/architectural-grid11/src/components/settings/GeneralTab.tsx
deleted file mode 100644
index 749afbd..0000000
--- a/architectural-grid11/src/components/settings/GeneralTab.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react';
-import { Globe, Bell } from 'lucide-react';
-import { motion } from 'motion/react';
-
-export const GeneralTab: React.FC = () => {
- return (
-
-
-
Paramètres généraux de l'application
-
-
- {/* Langue */}
-
-
-
-
-
-
-
Langue
-
Sélectionner une langue
-
-
-
-
-
- Français
- English
- Español
-
-
-
-
-
- {/* Notifications */}
-
-
-
-
-
-
-
Notifications
-
Gérez vos préférences de notifications
-
-
-
-
-
-
-
Notifications par email
-
Recevoir des notifications importantes par email
-
-
-
-
-
-
-
-
-
-
Notifications bureau
-
Recevoir des notifications dans votre navigateur
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid11/src/components/settings/SettingsHeader.tsx b/architectural-grid11/src/components/settings/SettingsHeader.tsx
deleted file mode 100644
index db56e30..0000000
--- a/architectural-grid11/src/components/settings/SettingsHeader.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import { Settings, Sparkles, Palette, User, Database, Code, Info } from 'lucide-react';
-import { motion } from 'motion/react';
-import { SettingsTab } from '../../types';
-
-interface SettingsHeaderProps {
- activeTab: SettingsTab;
- setActiveTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsHeader: React.FC = ({ activeTab, setActiveTab }) => {
- const tabs = [
- { id: 'general', label: 'Paramètres généraux', icon: },
- { id: 'ai', label: 'Paramètres IA', icon: },
- { id: 'appearance', label: 'Apparence', icon: },
- { id: 'profile', label: 'Profil', icon: },
- { id: 'data', label: 'Gestion des données', icon: },
- { id: 'mcp', label: 'Paramètres MCP', icon: },
- { id: 'about', label: 'À propos', icon: },
- ];
-
- return (
-
- );
-};
diff --git a/architectural-grid11/src/constants.ts b/architectural-grid11/src/constants.ts
deleted file mode 100644
index 8965c08..0000000
--- a/architectural-grid11/src/constants.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Carnet, Note } from './types';
-
-export const CARNETS: Carnet[] = [
- { id: '1', name: 'Daily Notes', initial: 'D', type: 'Private', isPrivate: true },
- { id: '2', name: 'Project: Neo', initial: 'P', type: 'Project' },
- { id: '3', name: 'Shared Docs', initial: 'S', type: 'Shared' },
- { id: '4', name: 'Architecture Research', initial: 'A', type: 'Project' },
- { id: '5', name: 'History of Architecture', initial: 'H', type: 'Project', parentId: '4' },
- { id: '6', name: 'Modernism', initial: 'M', type: 'Project', parentId: '5' },
- { id: '7', name: 'Sustainable Design', initial: 'S', type: 'Project', parentId: '4' },
-];
-
-export const ALL_NOTES: Note[] = [
- {
- id: 'n1',
- carnetId: '4',
- title: 'Grid Systems & Geometry',
- date: 'Oct 26, 2024',
- content: 'Grid Systems are the foundation of cognitive design. We use geometric blocks to define spaces. The repetitive structure creates a sense of order and rhythm in the built environment.',
- imageUrl: 'https://images.unsplash.com/photo-1503387762-592dea58ef23?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't1', label: 'Architecture', type: 'user' },
- { id: 't2', label: 'Systems', type: 'ai' }
- ],
- embedding: [0.1, 0.1]
- },
- {
- id: 'n1-b',
- carnetId: '4',
- title: 'Parametric Grids',
- date: 'Oct 27, 2024',
- content: 'Parametricism allows us to deform traditional grid systems. By using mathematical algorithms, we can create fluid yet structured geometries that respond to environmental data.',
- imageUrl: 'https://images.unsplash.com/photo-1511225070737-5af5ac9a690d?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't1', label: 'Geometry', type: 'user' }],
- embedding: [0.12, 0.08]
- },
- {
- id: 'n2',
- carnetId: '4',
- title: 'Sustainable Materiality',
- date: 'Oct 24, 2024',
- content: 'Exploring cross-laminated timber (CLT) as a sustainable alternative to concrete. Material choice is key to carbon-neutral construction. The warmth of wood contrasts with the coldness of steel.',
- imageUrl: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't3', label: 'Materials', type: 'user' },
- { id: 't4', label: 'Sustainabilty', type: 'ai' }
- ],
- embedding: [0.8, 0.8]
- },
- {
- id: 'n2-b',
- carnetId: '7',
- title: 'Solar Passive Design',
- date: 'Oct 25, 2024',
- content: 'Using orientation to maximize natural heat. Sustainable architecture must prioritize passive systems over active ones. Thermal mass and insulation are critical factors.',
- imageUrl: 'https://images.unsplash.com/photo-1509391366360-fe5bb5843e0c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't4', label: 'Sustainabilty', type: 'user' }],
- embedding: [0.85, 0.75]
- },
- {
- id: 'n3',
- carnetId: '4',
- title: 'Light & Minimalist Space',
- date: 'Oct 22, 2024',
- content: 'Minimalism is about the subtraction of the unnecessary. Light becomes a material in itself. Reflections on glass and white surfaces create depth without clutter.',
- imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't5', label: 'Lighting', type: 'user' },
- { id: 't6', label: 'Atmosphere', type: 'ai' }
- ],
- embedding: [0.2, 0.8]
- },
- {
- id: 'n3-b',
- carnetId: '6',
- title: 'The Glass House Study',
- date: 'Oct 23, 2024',
- content: 'Analyzing the transparency of the Glass House. The boundary between interior and exterior is blurred. A pure expression of modernist ideals and minimal structure.',
- imageUrl: 'https://images.unsplash.com/photo-1464938050520-ef2270bb8ce8?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't6', label: 'Modernism', type: 'user' }],
- embedding: [0.25, 0.85]
- },
- {
- id: 'bridge-1',
- carnetId: '4',
- title: 'Geometric Ecology',
- date: 'Oct 28, 2024',
- content: 'Can we use grid systems to optimize sustainable solar collection? This note bridges the gap between rigid geometry and ecological necessity. Structured sustainability.',
- imageUrl: 'https://images.unsplash.com/photo-1464146072230-91cabc968276?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't1', label: 'Bridge', type: 'ai' }],
- embedding: [0.45, 0.45] // Center point
- }
-];
diff --git a/architectural-grid11/src/index.css b/architectural-grid11/src/index.css
deleted file mode 100644
index 52b4b7c..0000000
--- a/architectural-grid11/src/index.css
+++ /dev/null
@@ -1,98 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap');
-@import "tailwindcss";
-
-@theme {
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
- --font-serif: "Playfair Display", serif;
- --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
-
- /* Foundation */
- --color-paper: #F2F0E9;
- --color-ink: #1C1C1C;
- --color-muted-ink: rgba(28, 28, 28, 0.6);
- --color-border: rgba(28, 28, 28, 0.1);
- --color-concrete: #8D8D8D;
-
- /* Architectural Accents */
- --color-blueprint: #75B2D6;
- --color-slate: #4A4E69;
- --color-ochre: #D4A373;
- --color-sage: #A3B18A;
- --color-rust: #9B2226;
- --color-glass: rgba(255, 255, 255, 0.4);
-
- /* Dark Theme Aliases */
- --color-dark-paper: #0D0D0D;
- --color-dark-ink: #EAEAEA;
- --color-dark-muted: rgba(234, 234, 234, 0.5);
- --color-dark-border: rgba(234, 234, 234, 0.1);
-}
-
-@layer base {
- body {
- @apply bg-paper text-ink font-sans antialiased transition-colors duration-500;
- }
-
- .dark body {
- @apply bg-dark-paper;
- }
-
- .dark {
- --color-paper: #121212;
- --color-ink: #EAEAEA;
- --color-muted-ink: rgba(234, 234, 234, 0.6);
- --color-border: rgba(255, 255, 255, 0.08);
- --color-glass: rgba(0, 0, 0, 0.4);
- --color-concrete: #555555;
- }
-}
-
-.paper-texture {
- background-color: var(--color-paper);
- background-image: url("https://www.transparenttextures.com/patterns/natural-paper.png");
-}
-
-/* Custom Scrollbar - Architectural Minimalist */
-.custom-scrollbar::-webkit-scrollbar {
- width: 3px;
-}
-
-.custom-scrollbar::-webkit-scrollbar-track {
- background: transparent;
-}
-
-.custom-scrollbar::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.08);
- border-radius: 10px;
-}
-
-.custom-scrollbar:hover::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.2);
-}
-
-.ai-glass {
- background: rgba(255, 255, 255, 0.85);
- backdrop-filter: blur(20px);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .ai-glass {
- background: rgba(30, 30, 30, 0.85);
- border: 1px solid rgba(255, 255, 255, 0.1);
-}
-
-.sidebar-shadow {
- box-shadow: 1px 0 10px rgba(0, 0, 0, 0.05);
-}
-
-.active-nav-item {
- background: linear-gradient(to right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.4));
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .active-nav-item {
- background: rgba(255, 255, 255, 0.08);
- border: 1px solid rgba(255, 255, 255, 0.1);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
-}
diff --git a/architectural-grid11/src/main.tsx b/architectural-grid11/src/main.tsx
deleted file mode 100644
index 080dac3..0000000
--- a/architectural-grid11/src/main.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import {StrictMode} from 'react';
-import {createRoot} from 'react-dom/client';
-import App from './App.tsx';
-import './index.css';
-
-createRoot(document.getElementById('root')!).render(
-
-
- ,
-);
diff --git a/architectural-grid11/src/services/geminiService.ts b/architectural-grid11/src/services/geminiService.ts
deleted file mode 100644
index 08781ab..0000000
--- a/architectural-grid11/src/services/geminiService.ts
+++ /dev/null
@@ -1,200 +0,0 @@
-
-import { GoogleGenAI, Type } from "@google/genai";
-import { BrainstormIdea } from "../types";
-
-const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
-
-const BRAINSTORM_SCHEMA = {
- type: Type.OBJECT,
- properties: {
- ideas: {
- type: Type.ARRAY,
- items: {
- type: Type.OBJECT,
- properties: {
- title: { type: Type.STRING },
- description: { type: Type.STRING },
- connection_to_seed: { type: Type.STRING },
- novelty_score: { type: Type.NUMBER }
- },
- required: ["title", "description", "connection_to_seed", "novelty_score"]
- }
- }
- },
- required: ["ideas"]
-};
-
-const SUGGESTIONS_SCHEMA = {
- type: Type.OBJECT,
- properties: {
- suggestions: {
- type: Type.ARRAY,
- items: {
- type: Type.OBJECT,
- properties: {
- title: { type: Type.STRING },
- description: { type: Type.STRING },
- reasoning: { type: Type.STRING }
- },
- required: ["title", "description", "reasoning"]
- }
- }
- },
- required: ["suggestions"]
-};
-
-export async function generateBrainstormWave(
- seedIdea: string,
- waveNumber: number,
- contextSummaries: string = ""
-): Promise[]> {
- const waveDescriptions = [
- "", // index 0 unused
- "VAGUE 1 (proximité directe) : Sous-aspects, reformulations, variations de l'idée. Reste dans le même domaine.",
- "VAGUE 2 (analogies) : Trouve des parallèles dans d'autres domaines. Comment cette idée se manifeste-t-elle ailleurs ? Quelles techniques d'autres industries pourraient s'appliquer ?",
- "VAGUE 3 (disruption) : Inverse l'idée. Pousse-la à l'extrême. Combine-la avec un domaine totalement non lié. Que se passe-t-il si l'opposé est vrai ?"
- ];
-
- const prompt = `
- Idée seed : "${seedIdea}"
- Contexte : ${contextSummaries}
- Génère 5 idées pour la VAGUE ${waveNumber} : ${waveDescriptions[waveNumber]}
- Format JSON selon le schéma.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: [{ role: "user", parts: [{ text: prompt }] }],
- config: {
- systemInstruction: "Tu es un expert en brainstorming. Réponds uniquement en JSON valide.",
- responseMimeType: "application/json",
- responseSchema: BRAINSTORM_SCHEMA,
- temperature: 1.0
- }
- });
-
- const resText = response.text;
- if (!resText) return [];
-
- const parsed = JSON.parse(resText.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim());
- const ideas = Array.isArray(parsed.ideas) ? parsed.ideas : (Array.isArray(parsed) ? parsed : []);
-
- return ideas.map((item: any) => ({
- title: item.title,
- description: item.description,
- connectionToSeed: item.connection_to_seed,
- noveltyScore: item.novelty_score,
- waveNumber
- }));
- } catch (error) {
- console.error(`Error generating brainstorm wave ${waveNumber}:`, error);
- throw error;
- }
-}
-
-export async function generateExpansion(parentIdeaTitle: string, parentIdeaDescription: string): Promise[]> {
- const prompt = `
- Idée source : "${parentIdeaTitle} - ${parentIdeaDescription}"
- Génère 3 idées d'extension ou de sous-aspects.
- Format JSON.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: [{ role: "user", parts: [{ text: prompt }] }],
- config: {
- systemInstruction: "Tu es un expert en brainstorming. Réponds uniquement en JSON valide.",
- responseMimeType: "application/json",
- responseSchema: BRAINSTORM_SCHEMA,
- temperature: 1.0
- }
- });
-
- const resText = response.text;
- if (!resText) return [];
-
- const parsed = JSON.parse(resText.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim());
- const ideas = Array.isArray(parsed.ideas) ? parsed.ideas : (Array.isArray(parsed) ? parsed : []);
-
- return ideas.map((item: any) => ({
- title: item.title,
- description: item.description,
- connectionToSeed: item.connection_to_seed,
- noveltyScore: item.novelty_score
- }));
- } catch (error) {
- console.error("Error generating expansion:", error);
- throw error;
- }
-}
-
-export async function getEmbedding(text: string): Promise {
- try {
- const result = await ai.models.embedContent({
- model: 'gemini-embedding-2-preview',
- contents: [text],
- });
- return result.embeddings[0].values;
- } catch (error) {
- console.error("Error generating embedding:", error);
- throw error;
- }
-}
-
-export function cosineSimilarity(a: number[], b: number[]): number {
- if (!a || !b || a.length !== b.length) return 0;
- const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
- const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
- const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
- if (magnitudeA === 0 || magnitudeB === 0) return 0;
- return dotProduct / (magnitudeA * magnitudeB);
-}
-
-export async function nameCluster(noteSummaries: string[]): Promise {
- const prompt = `Quel thème commun relie ces notes ? Donne un nom court (2-4 mots).\nNotes :\n${noteSummaries.join('\n- ')}`;
- try {
- const result = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: prompt
- });
- return result.text.trim();
- } catch (error) {
- console.error("Error naming cluster:", error);
- return "Thematic Cluster";
- }
-}
-
-export async function suggestBridgeIdeas(
- clusterAName: string,
- clusterBName: string,
- clusterASummaries: string,
- clusterBSummaries: string
-): Promise {
- const prompt = `
- Cluster A (${clusterAName}) contient des notes sur : ${clusterASummaries}
- Cluster B (${clusterBName}) contient des notes sur : ${clusterBSummaries}
-
- Ces deux clusters ne sont pas connectés. Propose 3 idées
- de "notes pont" qui pourraient créer un lien créatif entre eux.
- Pour chaque idée : titre, description, pourquoi ça connecte les deux.
-
- Format JSON.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: prompt,
- config: {
- responseMimeType: "application/json",
- responseSchema: SUGGESTIONS_SCHEMA
- }
- });
- return JSON.parse(response.text);
- } catch (error) {
- console.error("Error suggesting bridge ideas:", error);
- return [];
- }
-}
diff --git a/architectural-grid11/src/types.ts b/architectural-grid11/src/types.ts
deleted file mode 100644
index 96b3f34..0000000
--- a/architectural-grid11/src/types.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-export type NavigationView = 'notebooks' | 'agents' | 'settings' | 'shared' | 'reminders' | 'trash' | 'brainstorm' | 'insights' | 'temporal';
-export type AITone = 'Professional' | 'Creative' | 'Academic' | 'Casual';
-export type AITab = 'discussion' | 'actions' | 'resources' | 'explore';
-export type SettingsTab = 'general' | 'ai' | 'appearance' | 'profile' | 'data' | 'mcp' | 'about';
-
-export interface Tag {
- id: string;
- label: string;
- type: 'ai' | 'user';
-}
-
-export interface Note {
- id: string;
- carnetId: string;
- title: string;
- content: string;
- imageUrl: string;
- date: string;
- tags: Tag[];
- isPinned?: boolean;
- isDeleted?: boolean;
- deletedAt?: string;
- embedding?: number[];
- clusterId?: string;
-}
-
-export interface NoteCluster {
- id: string;
- name: string;
- noteIds: string[];
- centroid? : number[];
- color: string;
-}
-
-export interface BridgeNote {
- noteId: string;
- connectedClusterIds: string[];
- bridgeScore: number;
-}
-
-export interface ConnectionSuggestion {
- id: string;
- title: string;
- description: string;
- reasoning: string;
- clusterAId: string;
- clusterBId: string;
-}
-
-export interface BrainstormSession {
- id: string;
- seedIdea: string;
- sourceNoteId?: string;
- contextNoteIds?: string[];
- exportedNoteId?: string;
- createdAt: string;
- updatedAt: string;
- userId: string;
-}
-
-export type BrainstormIdeaStatus = 'active' | 'dismissed' | 'converted';
-
-export interface BrainstormIdea {
- id: string;
- sessionId: string;
- waveNumber: 1 | 2 | 3;
- title: string;
- description: string;
- connectionToSeed: string;
- noveltyScore: number; // 1-10
- parentIdeaId?: string;
- convertedToNoteId?: string;
- relatedNoteIds?: string[];
- status: BrainstormIdeaStatus;
- position?: { x: number; y: number };
-}
-
-export interface Carnet {
- id: string;
- name: string;
- initial: string;
- type: 'Private' | 'Project' | 'Shared';
- isPrivate?: boolean;
- parentId?: string;
- isDeleted?: boolean;
- deletedAt?: string;
-}
-
-export interface NoteAccessLog {
- noteId: string;
- accessedAt: string;
- action: 'view' | 'edit' | 'search_hit';
-}
-
-export interface NotePrediction {
- noteId: string;
- predictedRelevanceDate: string;
- confidence: number;
- reason: string;
- generatedAt: string;
-}
-
diff --git a/architectural-grid11/tsconfig.json b/architectural-grid11/tsconfig.json
deleted file mode 100644
index d88f175..0000000
--- a/architectural-grid11/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2022",
- "experimentalDecorators": true,
- "useDefineForClassFields": false,
- "module": "ESNext",
- "lib": [
- "ES2022",
- "DOM",
- "DOM.Iterable"
- ],
- "skipLibCheck": true,
- "moduleResolution": "bundler",
- "isolatedModules": true,
- "moduleDetection": "force",
- "allowJs": true,
- "jsx": "react-jsx",
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowImportingTsExtensions": true,
- "noEmit": true
- }
-}
diff --git a/architectural-grid11/vite.config.ts b/architectural-grid11/vite.config.ts
deleted file mode 100644
index 0506f1b..0000000
--- a/architectural-grid11/vite.config.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import tailwindcss from '@tailwindcss/vite';
-import react from '@vitejs/plugin-react';
-import path from 'path';
-import {defineConfig, loadEnv} from 'vite';
-
-export default defineConfig(({mode}) => {
- const env = loadEnv(mode, '.', '');
- return {
- plugins: [react(), tailwindcss()],
- define: {
- 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
- },
- resolve: {
- alias: {
- '@': path.resolve(__dirname, '.'),
- },
- },
- server: {
- // HMR is disabled in AI Studio via DISABLE_HMR env var.
- // Do not modifyâfile watching is disabled to prevent flickering during agent edits.
- hmr: process.env.DISABLE_HMR !== 'true',
- },
- };
-});
diff --git a/architectural-grid12/.env.example b/architectural-grid12/.env.example
deleted file mode 100644
index 7a550fe..0000000
--- a/architectural-grid12/.env.example
+++ /dev/null
@@ -1,9 +0,0 @@
-# GEMINI_API_KEY: Required for Gemini AI API calls.
-# AI Studio automatically injects this at runtime from user secrets.
-# Users configure this via the Secrets panel in the AI Studio UI.
-GEMINI_API_KEY="MY_GEMINI_API_KEY"
-
-# APP_URL: The URL where this applet is hosted.
-# AI Studio automatically injects this at runtime with the Cloud Run service URL.
-# Used for self-referential links, OAuth callbacks, and API endpoints.
-APP_URL="MY_APP_URL"
diff --git a/architectural-grid12/.gitignore b/architectural-grid12/.gitignore
deleted file mode 100644
index 5a86d2a..0000000
--- a/architectural-grid12/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-node_modules/
-build/
-dist/
-coverage/
-.DS_Store
-*.log
-.env*
-!.env.example
diff --git a/architectural-grid12/BRAINSTORM_PROMPT.md b/architectural-grid12/BRAINSTORM_PROMPT.md
deleted file mode 100644
index dfb73b8..0000000
--- a/architectural-grid12/BRAINSTORM_PROMPT.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# IA Agent Coordination Prompt: Brainstorm Wave Integration
-
-## Context
-You are tasked with continuing the development of the "Architectural Grid" application. The core feature "Wave Brainstorming" has been partially implemented with a full-stack architecture (Express + React).
-
-## Current State
-- **Backend (`server.ts`)**: Implements session management, idea generation via Gemini, and expansion logic. Stores data in memory.
-- **Frontend (`BrainstormView.tsx`)**: Manages the life cycle of a brainstorm. Integrates with a Radial D3 Canvas.
-- **Visuals (`WaveCanvas.tsx`)**: Implements a radial force-directed graph with state-aware styling (dismissed/converted).
-- **Navigation**: "Brainstorm Wave" is accessible from the Sidebar. A quick entry point exists from Note Detail view.
-
-## Your Task: Sidebar & Navigation Cleanup
-1. **Source Code Review**: Read `src/components/Sidebar.tsx`, `src/App.tsx`, and `server.ts` to understand how views are toggled.
-2. **Sidebar Links**: Ensure "Brainstorm Wave", "Semantic Network", and "Temporal Forecast" are correctly grouped and labeled in the Sidebar under a "Creative & AI" section.
-3. **Agent View Sidebar**: The user specifically requested these links to be also accessible from the "Sidebar of the Agent view". Review `src/components/AgentsView.tsx` and ensure it has consistent navigation or deep links to these advanced features.
-4. **Semantic Network & Temporal Forecast**: These views are currently placeholders. Ensure the routing and sidebar active state detection work correctly for them.
-
-## Technical Requirements
-- Maintain consistency with the **Tailwind** architectural design (concrete, paper, blueprint tokens).
-- Use **Lucide-React** icons (`Wind` for Brainstorm, `Share2` for Semantic Network, `Clock` for Temporal).
-- Ensure transitions between views are smooth using `motion/react`.
-
----
-*Copy and paste this into the next AI Agent session to ensure full context transfer.*
diff --git a/architectural-grid12/README.md b/architectural-grid12/README.md
deleted file mode 100644
index 0078184..0000000
--- a/architectural-grid12/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-# Run and deploy your AI Studio app
-
-This contains everything you need to run your app locally.
-
-View your app in AI Studio: https://ai.studio/apps/b7b577c6-4d9f-44ac-8fe1-85bc3c6d6e66
-
-## Run Locally
-
-**Prerequisites:** Node.js
-
-
-1. Install dependencies:
- `npm install`
-2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
-3. Run the app:
- `npm run dev`
diff --git a/architectural-grid12/index.html b/architectural-grid12/index.html
deleted file mode 100644
index 21dfe69..0000000
--- a/architectural-grid12/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- My Google AI Studio App
-
-
-
-
-
-
-
diff --git a/architectural-grid12/metadata.json b/architectural-grid12/metadata.json
deleted file mode 100644
index e131638..0000000
--- a/architectural-grid12/metadata.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Architectural Grid",
- "description": "A minimalist notebook for architectural research and conceptual sketches, featuring a Wave Brainstorming radial canvas for AI-powered idea exploration.",
- "requestFramePermissions": [],
- "majorCapabilities": []
-}
diff --git a/architectural-grid12/server.ts b/architectural-grid12/server.ts
deleted file mode 100644
index 586d965..0000000
--- a/architectural-grid12/server.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-import express from "express";
-import path from "path";
-import { createServer as createViteServer } from "vite";
-import { v4 as uuidv4 } from "uuid";
-import { WebSocketServer, WebSocket } from "ws";
-import { createServer } from "http";
-
-interface BrainstormIdea {
- id: string;
- sessionId: string;
- waveNumber: number;
- title: string;
- description: string;
- connectionToSeed: string;
- noveltyScore: number;
- parentIdeaId?: string;
- convertedToNoteId?: string;
- status: 'active' | 'dismissed' | 'converted';
- position?: { x: number; y: number };
-}
-
-interface BrainstormSession {
- id: string;
- seedIdea: string;
- sourceNoteId?: string;
- contextNoteIds?: string[];
- createdAt: string;
- updatedAt: string;
-}
-
-// In-memory store
-const sessions: BrainstormSession[] = [];
-const ideas: BrainstormIdea[] = [];
-
-async function startServer() {
- const app = express();
- const server = createServer(app);
- const wss = new WebSocketServer({ server });
- const PORT = 3000;
-
- app.use(express.json());
-
- // WebSocket logic
- const rooms = new Map>();
-
- wss.on('connection', (ws) => {
- let currentRoom: string | null = null;
-
- ws.on('message', (message) => {
- const data = JSON.parse(message.toString());
-
- if (data.type === 'join') {
- const { sessionId } = data;
- currentRoom = sessionId;
- if (!rooms.has(sessionId)) rooms.set(sessionId, new Set());
- rooms.get(sessionId)!.add(ws);
- console.log(`User joined session: ${sessionId}`);
- }
-
- if (data.type === 'idea_added' || data.type === 'idea_updated' || data.type === 'activity') {
- if (currentRoom && rooms.has(currentRoom)) {
- rooms.get(currentRoom)!.forEach(client => {
- if (client !== ws && client.readyState === WebSocket.OPEN) {
- client.send(JSON.stringify(data));
- }
- });
- }
- }
- });
-
- ws.on('close', () => {
- if (currentRoom && rooms.has(currentRoom)) {
- rooms.get(currentRoom)!.delete(ws);
- if (rooms.get(currentRoom)!.size === 0) rooms.delete(currentRoom);
- }
- });
- });
-
- // API Routes
- app.get("/api/health", (req, res) => {
- res.json({ status: "ok" });
- });
-
-// 1. Create session
- app.post("/api/brainstorm/sessions", (req, res) => {
- const { seedIdea, sourceNoteId, contextNoteIds } = req.body;
-
- const session: BrainstormSession = {
- id: uuidv4(),
- seedIdea,
- sourceNoteId,
- contextNoteIds,
- createdAt: new Date().toISOString(),
- updatedAt: new Date().toISOString()
- };
- sessions.unshift(session);
- res.json(session);
- });
-
- // 2. Add ideas to session
- app.post("/api/brainstorm/:sessionId/ideas", (req, res) => {
- const { sessionId } = req.params;
- const { ideas: newIdeasData } = req.body;
-
- const session = sessions.find(s => s.id === sessionId);
- if (!session) return res.status(404).json({ error: "Session not found" });
-
- const newIdeas = newIdeasData.map((item: any) => ({
- id: item.id || uuidv4(),
- sessionId,
- waveNumber: item.waveNumber,
- title: item.title,
- description: item.description,
- connectionToSeed: item.connectionToSeed,
- noveltyScore: item.noveltyScore,
- parentIdeaId: item.parentIdeaId,
- status: 'active'
- }));
-
- newIdeas.forEach((i: any) => ideas.push(i));
- res.json(newIdeas);
- });
-
- // 3. Get all sessions
- app.get("/api/brainstorm/sessions", (req, res) => {
- res.json(sessions);
- });
-
- // 4. Get session with ideas
- app.get("/api/brainstorm/:sessionId", (req, res) => {
- const session = sessions.find(s => s.id === req.params.sessionId);
- if (!session) return res.status(404).json({ error: "Session not found" });
- const sessionIdeas = ideas.filter(i => i.sessionId === session.id);
- res.json({ session, ideas: sessionIdeas });
- });
-
- // 5. Update idea (position, status)
- app.patch("/api/brainstorm/ideas/:ideaId", (req, res) => {
- const index = ideas.findIndex(i => i.id === req.params.ideaId);
- if (index === -1) return res.status(404).json({ error: "Idea not found" });
-
- ideas[index] = { ...ideas[index], ...req.body };
- res.json(ideas[index]);
- });
-
- // Vite middleware for development
- if (process.env.NODE_ENV !== "production") {
- const vite = await createViteServer({
- server: { middlewareMode: true },
- appType: "spa",
- });
- app.use(vite.middlewares);
- } else {
- const distPath = path.join(process.cwd(), 'dist');
- app.use(express.static(distPath));
- app.get('*', (req, res) => {
- res.sendFile(path.join(distPath, 'index.html'));
- });
- }
-
- server.listen(PORT, "0.0.0.0", () => {
- console.log(`Server running on http://localhost:${PORT}`);
- });
-}
-
-startServer();
diff --git a/architectural-grid12/src/App.tsx b/architectural-grid12/src/App.tsx
deleted file mode 100644
index 847de4a..0000000
--- a/architectural-grid12/src/App.tsx
+++ /dev/null
@@ -1,612 +0,0 @@
-/**
- * @license
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React, { useState, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-
-// Components
-import { Sidebar } from './components/Sidebar';
-import { NotebooksView } from './components/NotebooksView';
-import { AgentsView } from './components/AgentsView';
-import { SettingsView } from './components/SettingsView';
-import { TrashView } from './components/TrashView';
-import { BrainstormView } from './components/BrainstormView/BrainstormView';
-import { InsightsView } from './components/InsightsView';
-import { TemporalView } from './components/TemporalView';
-import { AISidebar } from './components/AISidebar';
-import { SlashMenu } from './components/SlashMenu';
-
-// Data & Types
-import { CARNETS, ALL_NOTES } from './constants';
-import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog } from './types';
-
-export default function App() {
- const [activeView, setActiveView] = useState('notebooks');
- const [activeSettingsTab, setActiveSettingsTab] = useState('general');
- const [selectedAgentId, setSelectedAgentId] = useState(null);
- const [isDarkMode, setIsDarkMode] = useState(false);
- const [carnets, setCarnets] = useState(CARNETS);
- const [notes, setNotes] = useState(ALL_NOTES);
- const [accessLogs, setAccessLogs] = useState([
- // Note n1: 14-day cycle
- { noteId: 'n1', accessedAt: new Date(Date.now() - 70 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 56 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 42 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n2: 7-day cycle
- { noteId: 'n2', accessedAt: new Date(Date.now() - 35 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 21 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n3: 3-day cycle (frequent check)
- { noteId: 'n3', accessedAt: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 9 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- ]);
-
- const logNoteAccess = (noteId: string, action: 'view' | 'edit' | 'search_hit' = 'view') => {
- const newLog: NoteAccessLog = {
- noteId,
- accessedAt: new Date().toISOString(),
- action
- };
- setAccessLogs(prev => [...prev, newLog]);
- };
-
- const [activeCarnetId, setActiveCarnetId] = useState('4');
- const [activeNoteId, setActiveNoteId] = useState(null);
- const [brainstormSeed, setBrainstormSeed] = useState(null);
-
- const handleBrainstormNote = (note: Note) => {
- setActiveView('brainstorm');
- // We'll use a small delay or a ref to pass this to BrainstormView if needed,
- // but better to just share state or use a CustomEvent
- window.dispatchEvent(new CustomEvent('start-brainstorm', {
- detail: { seed: note.title, sourceNoteId: note.id }
- }));
- };
-
- React.useEffect(() => {
- if (activeNoteId) {
- logNoteAccess(activeNoteId);
- }
- }, [activeNoteId]);
-
- React.useEffect(() => {
- // Check for session in URL
- const params = new URLSearchParams(window.location.search);
- const session = params.get('session');
- if (session) {
- setActiveView('brainstorm');
- // We pass it via a global property or custom event since BrainstormView will fetch sessions
- (window as any).initialSessionId = session;
- }
-
- const handleSwitchView = (e: any) => {
- if (e.detail) {
- setActiveView(e.detail as NavigationView);
- }
- };
- window.addEventListener('switch-view', handleSwitchView);
- return () => window.removeEventListener('switch-view', handleSwitchView);
- }, []);
- const [selectedTagIds, setSelectedTagIds] = useState([]);
- const [isAISidebarOpen, setIsAISidebarOpen] = useState(false);
- const [aiTab, setAiTab] = useState('discussion');
- const [selectedTone, setSelectedTone] = useState('Professional');
-
- // Modal States
- const [showNewCarnetModal, setShowNewCarnetModal] = useState<{ isOpen: boolean; parentId?: string; isRenaming?: boolean; carnetId?: string }>({ isOpen: false });
- const [showNewNoteModal, setShowNewNoteModal] = useState(false);
- const [slashMenu, setSlashMenu] = useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- // Form States
- const [newCarnetName, setNewCarnetName] = useState('');
- const [newNoteTitle, setNewNoteTitle] = useState('');
- const [newNoteContent, setNewNoteContent] = useState('');
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const togglePin = (noteId: string) => {
- setNotes(notes.map(n => n.id === noteId ? { ...n, isPinned: !n.isPinned } : n));
- };
-
- const filteredNotes = useMemo(() => {
- let result = notes.filter(n => n.carnetId === activeCarnetId && !n.isDeleted);
-
- if (selectedTagIds.length > 0) {
- result = result.filter(note =>
- selectedTagIds.every(tagId => note.tags?.some(tag => tag.id === tagId))
- );
- }
-
- return [...result].sort((a, b) => {
- if (a.isPinned && !b.isPinned) return -1;
- if (!a.isPinned && b.isPinned) return 1;
- return 0;
- });
- }, [activeCarnetId, notes]);
-
- const activeNote = useMemo(() =>
- notes.find(n => n.id === activeNoteId),
- [activeNoteId, notes]);
-
- const activeCarnet = useMemo(() =>
- carnets.find(c => c.id === activeCarnetId),
- [activeCarnetId, carnets]);
-
- const handleAddCarnet = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newCarnetName.trim()) return;
-
- if (showNewCarnetModal.isRenaming && showNewCarnetModal.carnetId) {
- setCarnets(carnets.map(c => c.id === showNewCarnetModal.carnetId ? { ...c, name: newCarnetName, initial: newCarnetName.charAt(0).toUpperCase() } : c));
- setShowNewCarnetModal({ isOpen: false });
- setNewCarnetName('');
- return;
- }
-
- const newCarnet: Carnet = {
- id: Date.now().toString(),
- name: newCarnetName,
- initial: newCarnetName.charAt(0).toUpperCase(),
- type: 'Project',
- parentId: showNewCarnetModal.parentId
- };
-
- setCarnets([...carnets, newCarnet]);
- setNewCarnetName('');
- setShowNewCarnetModal({ isOpen: false });
- setActiveCarnetId(newCarnet.id);
- };
-
- const handleDeleteCarnet = (id: string) => {
- if (window.confirm('Déplacer ce carnet et ses sous-carnets vers la corbeille ?')) {
- const idsToDelete = new Set([id]);
-
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
-
- const deletedAt = new Date().toISOString();
- setCarnets(carnets.map(c => idsToDelete.has(c.id) ? { ...c, isDeleted: true, deletedAt } : c));
- setNotes(notes.map(n => idsToDelete.has(n.carnetId) ? { ...n, isDeleted: true, deletedAt } : n));
-
- if (idsToDelete.has(activeCarnetId)) {
- setActiveCarnetId('1');
- }
- }
- };
-
- const handleDeleteNote = (id: string) => {
- const deletedAt = new Date().toISOString();
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: true, deletedAt } : n));
- if (activeNoteId === id) setActiveNoteId(null);
- };
-
- const handleRestoreCarnet = (id: string) => {
- setCarnets(carnets.map(c => c.id === id ? { ...c, isDeleted: false, deletedAt: undefined } : c));
- // Optionally restore linked notes too? User might expect that.
- setNotes(notes.map(n => n.carnetId === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handleRestoreNote = (id: string) => {
- setNotes(notes.map(n => n.id === id ? { ...n, isDeleted: false, deletedAt: undefined } : n));
- };
-
- const handlePermanentDeleteNote = (id: string) => {
- setNotes(notes.filter(n => n.id !== id));
- };
-
- const handlePermanentDeleteCarnet = (id: string) => {
- const idsToDelete = new Set([id]);
- const addChildren = (parentId: string) => {
- carnets.forEach(c => {
- if (c.parentId === parentId) {
- idsToDelete.add(c.id);
- addChildren(c.id);
- }
- });
- };
- addChildren(id);
- setCarnets(carnets.filter(c => !idsToDelete.has(c.id)));
- setNotes(notes.filter(n => !idsToDelete.has(n.carnetId)));
- };
-
- const handleAddNote = (e: React.FormEvent) => {
- e.preventDefault();
- if (!newNoteTitle.trim() || !newNoteContent.trim()) return;
-
- const newNote: Note = {
- id: `n-${Date.now()}`,
- carnetId: activeCarnetId,
- title: newNoteTitle,
- date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
- content: newNoteContent,
- imageUrl: 'https://images.unsplash.com/photo-1487958449943-2429e8be8625?auto=format&fit=crop&q=80&w=800&h=600',
- tags: []
- };
-
- setNotes([newNote, ...notes]);
- setNewNoteTitle('');
- setNewNoteContent('');
- setShowNewNoteModal(false);
- setActiveNoteId(newNote.id);
- };
-
- const handleConvertIdeaToNote = (idea: BrainstormIdea) => {
- const newNote: Note = {
- id: `n-gen-${Date.now()}`,
- carnetId: activeCarnetId,
- title: idea.title,
- date: new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(new Date()),
- content: `${idea.description}\n\n---\n**Connection to seed:** ${idea.connectionToSeed}\n**Novelty Score:** ${idea.noveltyScore}/10`,
- imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't-ai', label: 'AI Generated', type: 'ai' }]
- };
-
- setNotes([newNote, ...notes]);
- setActiveView('notebooks');
- setActiveNoteId(newNote.id);
- };
-
- return (
-
-
{
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId });
- if (isRenaming && carnetId) {
- const carnet = carnets.find(c => c.id === carnetId);
- if (carnet) setNewCarnetName(carnet.name);
- } else {
- setNewCarnetName('');
- }
- }}
- onDeleteCarnet={handleDeleteCarnet}
- onMoveCarnet={(draggedId, targetId) => {
- if (draggedId === targetId) return;
-
- // Basic circular check
- const isDescendant = (parentId: string, potentialChildId: string): boolean => {
- const childIds = carnets.filter(c => c.parentId === parentId).map(c => c.id);
- if (childIds.includes(potentialChildId)) return true;
- return childIds.some(id => isDescendant(id, potentialChildId));
- };
-
- if (targetId && isDescendant(draggedId, targetId)) {
- console.warn("Cannot move a notebook inside its own descendant");
- return;
- }
-
- setCarnets(prev => prev.map(c => c.id === draggedId ? { ...c, parentId: targetId } : c));
- }}
- />
-
-
-
- {(activeView === 'notebooks' || activeView === 'shared' || activeView === 'reminders') && (
-
- setShowNewCarnetModal({ isOpen: show, parentId, isRenaming, carnetId })}
- onDeleteNote={handleDeleteNote}
- onBrainstormNote={handleBrainstormNote}
- />
-
- )}
-
- {activeView === 'trash' && (
-
- n.isDeleted)}
- deletedCarnets={carnets.filter(c => c.isDeleted)}
- onRestoreNote={handleRestoreNote}
- onRestoreCarnet={handleRestoreCarnet}
- onPermanentDeleteNote={handlePermanentDeleteNote}
- onPermanentDeleteCarnet={handlePermanentDeleteCarnet}
- onEmptyTrash={() => {
- setNotes(notes.filter(n => !n.isDeleted));
- setCarnets(carnets.filter(c => !c.isDeleted));
- }}
- />
-
- )}
-
- {activeView === 'agents' && (
-
-
-
- )}
-
- {activeView === 'settings' && (
-
-
-
- )}
-
- {activeView === 'brainstorm' && (
-
-
-
- )}
-
- {activeView === 'insights' && (
-
- {
- setActiveView('notebooks');
- setActiveNoteId(noteId);
- }}
- />
-
- )}
-
- {activeView === 'temporal' && (
-
- {
- setActiveView('notebooks');
- setActiveNoteId(noteId);
- }}
- />
-
- )}
-
-
-
-
-
- {/* Modals */}
-
- {showNewCarnetModal.isOpen && (
-
-
setShowNewCarnetModal({ isOpen: false })}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {showNewCarnetModal.isRenaming ? 'Rename Carnet' : (showNewCarnetModal.parentId ? 'Create Sub-Carnet' : 'Create New Carnet')}
-
- {showNewCarnetModal.parentId && !showNewCarnetModal.isRenaming && (
-
- Inside: {carnets.find(c => c.id === showNewCarnetModal.parentId)?.name}
-
- )}
-
-
- Notebook Name
- setNewCarnetName(e.target.value)}
- placeholder="E.g., Sustainable Patterns"
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-4 py-3 outline-none focus:border-ink transition-colors font-serif italic text-lg text-ink dark:text-dark-ink"
- />
-
-
- {
- setShowNewCarnetModal({ isOpen: false });
- setNewCarnetName('');
- }}
- className="flex-1 py-3 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
- >
- Cancel
-
-
- {showNewCarnetModal.isRenaming ? 'Rename' : 'Create Notebook'}
-
-
-
-
-
- )}
-
- {showNewNoteModal && (
-
-
setShowNewNoteModal(false)}
- className="absolute inset-0 bg-ink/40 backdrop-blur-sm"
- />
-
-
- {slashMenu?.isOpen && (
- { console.log(type); setSlashMenu(null); }}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
- Add Architectural Note
-
-
- Concept Title
- setNewNoteTitle(e.target.value)}
- placeholder="Enter the title of your study..."
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-serif text-2xl text-ink dark:text-dark-ink"
- />
-
-
- Observations & Analysis
- setNewNoteContent(e.target.value)}
- onKeyDown={handleEditorKeyDown}
- placeholder="Describe the spatial logic, materiality, and light interactions... (Type '/' for commands)"
- rows={6}
- className="w-full bg-white dark:bg-[#2A2A2A] border border-border rounded-lg px-5 py-4 outline-none focus:border-ink transition-colors font-light leading-relaxed resize-none text-ink dark:text-dark-ink"
- />
-
-
- setShowNewNoteModal(false)}
- className="flex-1 py-4 border border-border rounded-lg text-sm font-medium hover:bg-slate-50 dark:hover:bg-white/5 transition-colors text-ink dark:text-dark-ink"
- >
- Cancel
-
-
- Save Note
-
-
-
-
-
- )}
-
-
- );
-}
diff --git a/architectural-grid12/src/components/AISidebar.tsx b/architectural-grid12/src/components/AISidebar.tsx
deleted file mode 100644
index af38b87..0000000
--- a/architectural-grid12/src/components/AISidebar.tsx
+++ /dev/null
@@ -1,466 +0,0 @@
-import React from 'react';
-import {
- Sparkles,
- ChevronRight,
- MessageSquare,
- FileCode,
- Globe,
- Send,
- Scissors,
- Zap,
- Languages,
- Layout,
- ArrowRightLeft,
- BookOpen,
- History,
- Target,
- Network,
- Clock
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { AITab, AITone, Note, Carnet } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AISidebarProps {
- isOpen: boolean;
- setIsOpen: (open: boolean) => void;
- activeNote: Note | undefined;
- aiTab: AITab;
- setAiTab: (tab: AITab) => void;
- selectedTone: AITone;
- setSelectedTone: (tone: AITone) => void;
- carnets: Carnet[];
-}
-
-export const AISidebar: React.FC = ({
- isOpen,
- setIsOpen,
- activeNote,
- aiTab,
- setAiTab,
- selectedTone,
- setSelectedTone,
- carnets
-}) => {
- const [selectedContextId, setSelectedContextId] = React.useState(null);
-
- return (
-
- {isOpen && (
-
-
-
-
-
- IA Assistant
-
- setIsOpen(false)}
- className="p-1 hover:bg-slate-100 rounded-full transition-colors text-muted-ink"
- >
-
-
-
-
- "{activeNote?.title}"
-
-
-
-
- {(['discussion', 'actions', 'explore', 'resources'] as AITab[]).map((tab) => (
- setAiTab(tab)}
- className={`flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative
- ${aiTab === tab ? 'text-manganese' : 'text-muted-ink hover:text-ink/60'}`}
- >
- {tab}
- {aiTab === tab && (
-
- )}
-
- ))}
-
-
-
-
- {aiTab === 'explore' && (
-
-
-
-
Intelligence Modules
-
-
-
-
-
{
- // These will be handled in App.tsx by observing activeView
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'brainstorm' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-ochre/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Brainstorm Wave
-
Unfold dimensions of thought
-
-
-
-
-
{
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'insights' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-indigo-500/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Semantic Network
-
Detect clusters and bridges
-
-
-
-
-
{
- window.dispatchEvent(new CustomEvent('switch-view', { detail: 'temporal' }));
- }}
- className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-rose-500/30 transition-all text-left overflow-hidden"
- >
-
-
-
-
-
-
-
-
-
Temporal Forecast
-
Predict relevance recurrence
-
-
-
-
-
-
-
- Ces modules utilisent les embeddings du modèle Gemini pour analyser graphiquement vos pensées.
-
-
-
- )}
-
- {aiTab === 'discussion' && (
-
-
-
-
-
-
Posez une question à l'Assistant pour commencer.
-
-
-
-
-
Source du Contexte
-
-
-
-
- Note Active
-
-
Auto
-
-
-
-
-
-
-
-
-
-
Ton d'écriture
-
- {(['Professional', 'Creative', 'Academic', 'Casual'] as AITone[]).map((tone) => (
- setSelectedTone(tone)}
- className={`p-3 rounded-xl border text-[11px] font-medium transition-all
- ${selectedTone === tone ? 'bg-manganese text-paper border-manganese shadow-lg shadow-manganese/10' : 'bg-glass border-border text-muted-ink hover:border-ink/20'}`}
- >
- {tone.toUpperCase().substring(0, 3)}
-
- ))}
-
-
-
-
- )}
-
- {aiTab === 'actions' && (
-
-
-
-
-
-
- {[
- { icon:
, label: 'Clarifier', color: 'ochre' },
- { icon:
, label: 'Raccourcir', color: 'rust' },
- { icon:
, label: 'Améliorer', color: 'sage' },
- { icon:
, label: 'Traduire', color: 'slate' },
- ].map((action, i) => (
-
-
- {action.icon}
-
- {action.label}
-
- ))}
-
-
- Convertir en Markdown
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Présentation
-
Convertir en slides interactives
-
-
-
-
-
- Thème
-
- Architectural Mono
- Vibrant Tech
- Minimal Silk
-
-
-
- Style
-
- Professional
- Creative
- Brutalist
-
-
-
-
-
- Générer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Diagramme
-
Visualisation de structure
-
-
-
-
-
- Type
-
- Logic Flow
- Mind Map
- Hierarchy
-
-
-
- Style
-
- Draft
- Polished
- Handwritten
-
-
-
-
-
- Tracer
-
-
-
-
-
-
-
-
- Auto-Save Enabled
-
-
-
- )}
-
- {aiTab === 'resources' && (
-
-
-
-
URL (Optionnel)
-
-
-
-
-
-
-
- Texte de la ressource
-
-
-
-
-
Mode d'intégration
-
- {[
- { id: 'replace', label: 'Remplacer', sub: 'Direct, sans IA' },
- { id: 'append', label: 'Compléter', sub: 'Ajoute sans réécrire' },
- { id: 'merge', label: 'Fusionner', sub: 'Réécrit et intègre' },
- ].map((mode) => (
-
- {mode.label}
- {mode.sub}
-
- ))}
-
-
-
-
-
- Générer l'aperçu
-
-
-
- )}
-
-
-
-
- {aiTab === 'discussion' && (
-
-
- Maj+Entrée = nouvelle ligne
-
- )}
-
-
- )}
-
- );
-};
diff --git a/architectural-grid12/src/components/AgentsView.tsx b/architectural-grid12/src/components/AgentsView.tsx
deleted file mode 100644
index f82c7fa..0000000
--- a/architectural-grid12/src/components/AgentsView.tsx
+++ /dev/null
@@ -1,325 +0,0 @@
-import React from 'react';
-import {
- Plus,
- ArrowLeft,
- Clock,
- Activity,
- Trash2,
- Edit3,
- Play,
- Eye,
- Microscope,
- Globe,
- Layers,
- Zap,
- BookOpen,
- Sparkles,
- ChevronDown,
- Info,
- Check
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Carnet, Note } from '../types';
-import { HierarchicalCarnetSelector } from './HierarchicalCarnetSelector';
-
-interface AgentsViewProps {
- selectedAgentId: string | null;
- setSelectedAgentId: (id: string | null) => void;
- carnets: Carnet[];
-}
-
-export const AgentsView: React.FC = ({
- selectedAgentId,
- setSelectedAgentId,
- carnets
-}) => {
- const [selectedCarnetForAgent, setSelectedCarnetForAgent] = React.useState('4');
- const [agentType, setAgentType] = React.useState<'Surveillant' | 'Personnalisé' | 'Slides' | 'Diagramme'>('Diagramme');
-
- return (
-
- {!selectedAgentId ? (
- <>
-
-
-
-
Mes Agents
-
Automatisez vos tâches de veille et de recherche.
-
-
-
- Nouvel Agent
-
-
-
-
- {['Tous', 'Veilleur', 'Chercheur', 'Surveillant', 'Personnalisé'].map((tag, i) => (
-
- {tag}
- {i === 0 && }
-
- ))}
-
-
-
-
-
- {[
- { id: 'a1', icon:
, title: 'Surveillant de Notes', status: 'Réussi', type: 'SURVEILLANT', meta: 'Hebdomadaire • 6 exéc.', desc: 'Analyse les notes récentes d’un carnet et suggère des compléments, références et liens.' },
- { id: 'a2', icon:
, title: 'Chercheur de Sujet', status: 'Réussi', type: 'CHERCHEUR', meta: 'Hebdomadaire • 14 exéc.', desc: 'Recherche des informations approfondies sur les derniers modèles de Deepseek et voir l’avis des utilisateurs.' },
- { id: 'a3', icon:
, title: 'Veille IA', status: 'Réussi', type: 'VEILLEUR', meta: 'Quotidien • 20 exéc.', desc: 'Scrape les flux RSS de 6 sites IA (The Verge, TechCrunch...) et génère un résumé.' },
- ].map((agent, i) => (
-
setSelectedAgentId(agent.id)}
- className="bg-white dark:bg-white/5 border border-border rounded-2xl p-6 space-y-6 hover:border-ink/20 transition-all group cursor-pointer shadow-sm relative overflow-hidden"
- >
-
-
-
- {agent.icon}
-
-
-
{agent.title}
-
{agent.type}
-
-
-
e.stopPropagation()}>
-
-
-
-
-
-
-
-
- {agent.desc}
-
-
-
-
-
- {agent.meta.split('•')[0]}
- {agent.meta.split('•')[1]}
-
-
-
-
- Prochaine exécution
- Hebdomadaire
-
-
-
Dernier statut
-
{agent.status}
-
-
-
-
-
-
Modifier
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-slate-50 dark:hover:bg-white/5 flex items-center justify-center transition-colors text-muted-ink hover:text-ink"
- >
-
-
-
{ e.stopPropagation(); }}
- className="py-2 border border-border rounded-lg hover:bg-rose-50 hover:text-rose-600 hover:border-rose-100 flex items-center justify-center transition-colors text-muted-ink"
- >
-
-
-
-
- ))}
-
-
-
-
-
- {[
- { title: 'Veille IA', desc: 'Scrape les flux RSS de 6 sites IA et génère un résumé hebdomadaire.', icon:
},
- { title: 'Veille Tech', desc: 'Crée un résumé quotidien des news Hacker News et Product Hunt.', icon:
},
- { title: 'Veille Dev', desc: 'Surveille les repos GitHub pour détecter les nouvelles releases.', icon:
},
- ].map((model, i) => (
-
-
- {model.icon}
-
-
{model.title}
-
{model.desc}
-
- Installer
-
-
- ))}
-
-
-
- >
- ) : (
-
-
-
-
-
-
-
Sélectionnez le type d'agent
-
- {[
- { id: 'Surveillant', icon:
, label: 'Surveillant', desc: 'Surveille un carnet et analyse les notes' },
- { id: 'Personnalisé', icon:
, label: 'Personnalisé', desc: 'Agent libre avec votre propre prompt' },
- { id: 'Slides', icon:
, label: 'Slides', desc: 'Crée une présentation PowerPoint à partir de notes' },
- { id: 'Diagramme', icon:
, label: 'Diagramme', desc: 'Crée un diagramme Excalidraw à partir de notes' },
- ].map((type) => (
-
setAgentType(type.id as any)}
- className={`p-6 rounded-2xl border-2 transition-all flex flex-col items-center gap-3 text-center group relative
- ${agentType === type.id ? 'border-blueprint bg-white shadow-xl shadow-blueprint/10' : 'border-border bg-white/50 hover:bg-white'}`}
- >
-
- {type.icon}
-
-
-
{type.label}
-
{type.desc}
-
-
- {agentType === type.id &&
}
-
-
- ))}
-
-
-
-
-
-
-
- CONFIGURATION
-
-
- Supprimer
-
-
-
-
-
-
- DESCRIPTION (OPTIONEL)
-
-
-
-
-
-
-
- CARNET À SURVEILLER
-
-
-
-
-
-
-
- NOTES À ANALYSER
-
-
-
- {[
- 'Résumé du conteneur LXC devSandbox',
- 'Connexion SSH sans mot de passe à devSandbox',
- 'Gateway token (blank to generate)',
- 'Procédure d\'accès à openclaw',
- 'Derniers commits du repo Momento'
- ].map((note, i) => (
-
-
- {i === 0 && }
-
-
- {note}
-
- ))}
-
-
{1} note(s) sélectionnée(s)
-
-
-
-
- TYPE DE DIAGRAMME
-
-
- {[
- 'Auto (détection métier)', 'Flowchart (processus)',
- 'Mindmap (idées)', 'Organigramme (équipes)',
- 'Timeline / roadmap', 'Process map (opérations)',
- 'Architecture cloud (zones/RG)'
- ].map((type, i) => (
-
- {type}
-
- ))}
-
-
-
-
-
- STYLE DU DIAGRAMME EXCALIDRAW
-
-
- {[
- 'Coloré (Excalidraw)', 'Sketch+ (Excalidraw accentué)', 'Austère (sobre)'
- ].map((style, i) => (
-
- {style}
-
- ))}
-
-
-
-
-
-
- )}
-
- );
-};
diff --git a/architectural-grid12/src/components/BrainstormView/BrainstormView.tsx b/architectural-grid12/src/components/BrainstormView/BrainstormView.tsx
deleted file mode 100644
index 1567e75..0000000
--- a/architectural-grid12/src/components/BrainstormView/BrainstormView.tsx
+++ /dev/null
@@ -1,749 +0,0 @@
-
-import React, { useState, useEffect, useMemo, useRef } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import {
- Zap,
- Search,
- ArrowRight,
- History,
- Plus,
- Wind,
- PlusCircle,
- FileText,
- ChevronRight,
- Maximize2,
- Share2,
- Users,
- Check,
- Download,
- Activity,
- X
-} from 'lucide-react';
-import { v4 as uuidv4 } from 'uuid';
-import { WaveCanvas } from './WaveCanvas';
-import { BrainstormSession, BrainstormIdea, Note } from '../../types';
-import { generateBrainstormWave, generateExpansion, getEmbedding, cosineSimilarity } from '../../services/geminiService';
-
-interface BrainstormViewProps {
- notes: Note[];
- onConvertNote: (idea: BrainstormIdea) => void;
-}
-
-export const BrainstormView: React.FC = ({ notes, onConvertNote }) => {
- const [seedInput, setSeedInput] = useState('');
- const [isGenerating, setIsGenerating] = useState(false);
- const [error, setError] = useState(null);
- const [sessions, setSessions] = useState([]);
- const [activeSessionId, setActiveSessionId] = useState(null);
- const [ideas, setIdeas] = useState([]);
- const [selectedIdeaId, setSelectedIdeaId] = useState(null);
- const [editingNodeId, setEditingNodeId] = useState(null);
- const [manualTitle, setManualTitle] = useState('');
- const [shareStatus, setShareStatus] = useState<'idle' | 'copying' | 'copied'>('idle');
- const [showActivity, setShowActivity] = useState(false);
- const [activities, setActivities] = useState<{ id: string; type: string; message: string; timestamp: string }[]>([]);
-
- const socketRef = useRef(null);
-
- const addActivity = (message: string, type: string = 'info', broadcast: boolean = true) => {
- const newActivity = {
- id: uuidv4(),
- type,
- message,
- timestamp: new Date().toLocaleTimeString()
- };
- setActivities(prev => [newActivity, ...prev].slice(0, 50));
- if (broadcast && socketRef.current?.readyState === WebSocket.OPEN) {
- socketRef.current.send(JSON.stringify({ type: 'activity', activity: newActivity }));
- }
- };
-
- // WebSocket Connection
- useEffect(() => {
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
- const socket = new WebSocket(`${protocol}//${window.location.host}`);
- socketRef.current = socket;
-
- socket.onopen = () => {
- console.log('WS Shared Brainstorm connected');
- if (activeSessionId) {
- socket.send(JSON.stringify({ type: 'join', sessionId: activeSessionId }));
- }
- };
-
- socket.onmessage = (event) => {
- const data = JSON.parse(event.data);
- if (data.type === 'idea_added') {
- const newIdea = data.idea;
- setIdeas(prev => {
- if (prev.find(i => i.id === newIdea.id)) return prev;
- return [...prev, newIdea];
- });
- }
- if (data.type === 'idea_updated') {
- const updatedIdea = data.idea;
- setIdeas(prev => prev.map(i => i.id === updatedIdea.id ? updatedIdea : i));
- }
- if (data.type === 'activity') {
- setActivities(prev => [data.activity, ...prev].slice(0, 50));
- }
- };
-
- return () => {
- socket.close();
- };
- }, []);
-
- // Sync session joining
- useEffect(() => {
- if (socketRef.current?.readyState === WebSocket.OPEN && activeSessionId) {
- socketRef.current.send(JSON.stringify({ type: 'join', sessionId: activeSessionId }));
- }
- }, [activeSessionId]);
-
- useEffect(() => {
- fetch('/api/brainstorm/sessions')
- .then(res => res.json())
- .then(data => {
- setSessions(data);
- // Check for initial session from URL parameter (passed via window by App.tsx)
- const initialId = (window as any).initialSessionId;
- if (initialId && data.find((s: any) => s.id === initialId)) {
- setActiveSessionId(initialId);
- delete (window as any).initialSessionId;
- }
- })
- .catch(err => console.error("Failed to load sessions", err));
- }, []);
-
- useEffect(() => {
- if (activeSessionId) {
- fetch(`/api/brainstorm/${activeSessionId}`)
- .then(res => res.json())
- .then(data => {
- if (data.ideas) {
- setIdeas(prev => {
- const filtered = prev.filter(i => i.sessionId !== activeSessionId);
- return [...filtered, ...data.ideas];
- });
- }
- })
- .catch(err => console.error("Failed to load ideas", err));
- }
- }, [activeSessionId]);
-
- const activeSession = useMemo(() =>
- sessions.find(s => s.id === activeSessionId),
- [activeSessionId, sessions]);
-
- const activeIdeas = useMemo(() =>
- ideas.filter(i => i.sessionId === activeSessionId),
- [activeSessionId, ideas]);
-
- const selectedIdea = useMemo(() =>
- ideas.find(i => i.id === selectedIdeaId),
- [selectedIdeaId, ideas]);
-
- useEffect(() => {
- const handleRemoteStart = (e: any) => {
- if (e.detail?.seed) {
- handleStartBrainstorm(e.detail.seed, e.detail.sourceNoteId);
- }
- };
- window.addEventListener('start-brainstorm', handleRemoteStart);
- return () => window.removeEventListener('start-brainstorm', handleRemoteStart);
- }, [notes]);
-
- const handleStartBrainstorm = async (seed: string, sourceNoteId?: string) => {
- if (!seed.trim()) return;
-
- setIsGenerating(true);
- setError(null);
-
- try {
- // 1. Create session on backend
- const sessionRes = await fetch('/api/brainstorm/sessions', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- seedIdea: seed,
- sourceNoteId
- })
- });
- const session = await sessionRes.json();
- if (!sessionRes.ok) throw new Error(session.error || "Failed to create session");
-
- setSessions(prev => [session, ...prev]);
- setActiveSessionId(session.id);
- setSeedInput('');
-
- // 2. Generate waves in frontend concurrently
- const contextSummaries = notes.slice(0, 5).map(n => n.title).join(', ');
-
- const wavePromises = [1, 2, 3].map(async (num) => {
- try {
- const generated = await generateBrainstormWave(seed, num, contextSummaries);
- return generated.map(g => ({
- ...g,
- waveNumber: num
- }));
- } catch (e) {
- console.error(`Wave ${num} failed`, e);
- return [];
- }
- });
-
- const wavesResults = await Promise.all(wavePromises);
- const allNewIdeas = wavesResults.flat();
-
- if (allNewIdeas.length === 0) {
- throw new Error("No ideas were generated. Gemini might be shy today.");
- }
-
- // 3. Save ideas to backend
- const ideasRes = await fetch(`/api/brainstorm/${session.id}/ideas`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ideas: allNewIdeas })
- });
- const savedIdeas = await ideasRes.json();
- setIdeas(prev => [...prev, ...savedIdeas]);
-
- addActivity(`Generated ${savedIdeas.length} ideas for Wave ${allNewIdeas[0]?.waveNumber || ''}`);
-
- // Notify others
- savedIdeas.forEach((idea: any) => {
- socketRef.current?.send(JSON.stringify({ type: 'idea_added', idea }));
- });
-
- } catch (err: any) {
- console.error("Brainstorm failed:", err);
- setError(err.message || "An unexpected error occurred while brainstorming.");
- } finally {
- setIsGenerating(false);
- }
- };
-
- const updateIdea = async (ideaId: string, updates: Partial) => {
- try {
- const res = await fetch(`/api/brainstorm/ideas/${ideaId}`, {
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(updates)
- });
- const updated = await res.json();
- setIdeas(prev => prev.map(i => i.id === ideaId ? updated : i));
-
- // Notify others
- socketRef.current?.send(JSON.stringify({ type: 'idea_updated', idea: updated }));
- } catch (err) {
- console.error("Update failed", err);
- }
- };
-
- const handleDeepenIdea = async (idea: BrainstormIdea) => {
- setIsGenerating(true);
- try {
- const generated = await generateExpansion(idea.title, idea.description);
- const newIdeasData = generated.map(g => ({
- ...g,
- waveNumber: Math.min(idea.waveNumber + 1, 3),
- parentIdeaId: idea.id
- }));
-
- const res = await fetch(`/api/brainstorm/${idea.sessionId}/ideas`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ideas: newIdeasData })
- });
- const savedIdeas = await res.json();
- setIdeas(prev => [...prev, ...savedIdeas]);
- addActivity(`Expanded idea: ${idea.title}`);
-
- // Notify others
- savedIdeas.forEach((i: any) => {
- socketRef.current?.send(JSON.stringify({ type: 'idea_added', idea: i }));
- });
- } catch (err) {
- console.error("Deepen failed", err);
- setError("Failed to expand this idea.");
- } finally {
- setIsGenerating(false);
- }
- };
-
- const handleDismissIdea = (ideaId: string) => {
- updateIdea(ideaId, { status: 'dismissed' });
- setSelectedIdeaId(null);
- };
-
- const handleConvertToNote = (idea: BrainstormIdea) => {
- updateIdea(idea.id, { status: 'converted' });
- onConvertNote(idea);
- };
-
- const handleManualAdd = async (title: string, parentId?: string) => {
- if (!title.trim() || !activeSessionId) return;
-
- setIsGenerating(true);
- try {
- let finalParentId = parentId;
- let waveNumber = 1;
-
- if (parentId) {
- const p = ideas.find(i => i.id === parentId);
- if (p) waveNumber = Math.min(p.waveNumber + 1, 3);
- } else if (activeIdeas.length > 0) {
- // Semantic auto-placement if no parent is specified
- try {
- const newEmbedding = await getEmbedding(title);
- let bestSim = -1;
- let bestParent: BrainstormIdea | null = null;
-
- for (const idea of activeIdeas) {
- const ideaEmbedding = await getEmbedding(idea.title + " " + idea.description);
- const sim = cosineSimilarity(newEmbedding, ideaEmbedding);
- if (sim > bestSim) {
- bestSim = sim;
- bestParent = idea;
- }
- }
-
- if (bestParent && bestSim > 0.7) {
- finalParentId = bestParent.id;
- waveNumber = Math.min(bestParent.waveNumber + 1, 3);
- }
- } catch (e) {
- console.error("Semantic placement failed", e);
- }
- }
-
- const newIdeaData = [{
- title: title,
- description: "",
- waveNumber: waveNumber,
- connectionToSeed: finalParentId
- ? `Manual addition (auto-linked)`
- : "Manual addition to root",
- noveltyScore: 5,
- parentIdeaId: finalParentId
- }];
-
- const res = await fetch(`/api/brainstorm/${activeSessionId}/ideas`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ ideas: newIdeaData })
- });
- const saved = await res.json();
- setIdeas(prev => [...prev, ...saved]);
-
- addActivity(`Manually added idea: ${title}`);
-
- // Notify
- saved.forEach((i: any) => socketRef.current?.send(JSON.stringify({ type: 'idea_added', idea: i })));
-
- setEditingNodeId(null);
- setManualTitle('');
- } catch (err) {
- console.error("Manual add failed", err);
- } finally {
- setIsGenerating(false);
- }
- };
-
- const handleInvite = () => {
- if (!activeSessionId) return;
- const shareUrl = `${window.location.origin}${window.location.pathname}?session=${activeSessionId}`;
- navigator.clipboard.writeText(shareUrl);
- setShareStatus('copied');
- addActivity(`Invitation link copied to clipboard`);
- setTimeout(() => setShareStatus('idle'), 2000);
- };
-
- const handleExport = () => {
- if (!activeSession) return;
-
- let markdown = `# Brainstorm : ${activeSession.seedIdea}\n\n`;
- markdown += `Date : ${new Date(activeSession.createdAt).toLocaleDateString()}\n\n`;
-
- [1, 2, 3].forEach(waveNum => {
- const waveIdeas = activeIdeas.filter(i => i.waveNumber === waveNum);
- if (waveIdeas.length > 0) {
- markdown += `## Vague ${waveNum}\n\n`;
- waveIdeas.forEach(idea => {
- markdown += `### ${idea.title}\n`;
- markdown += `${idea.description}\n`;
- markdown += `*Score de nouveauté : ${idea.noveltyScore}/10*\n`;
- markdown += `*Connexion : ${idea.connectionToSeed}*\n\n`;
- });
- }
- });
-
- onConvertNote({
- id: uuidv4(),
- title: `Brainstorm Export: ${activeSession.seedIdea}`,
- description: markdown,
- sessionId: activeSession.id,
- waveNumber: 0,
- connectionToSeed: "Export",
- noveltyScore: 10,
- status: 'converted'
- });
-
- addActivity(`Session exported to notes`);
- };
-
- return (
-
- {/* Header / Start area */}
-
- {/* Architectural Grid Background */}
-
-
-
-
-
-
-
-
-
Waves of Thought
-
-
-
Unfold dimensions of potentiality
-
-
-
- {activeSession && (
-
-
-
- Export
-
-
setShowActivity(!showActivity)}
- className={`flex items-center gap-2 px-4 py-2 border border-border rounded-xl text-xs font-bold uppercase tracking-widest transition-all shadow-sm ${showActivity ? 'bg-ink text-paper' : 'bg-white dark:bg-white/5 text-concrete hover:text-ink'}`}
- title="Show Activity"
- >
-
- Activity
-
-
- {shareStatus === 'copied' ? : }
- {shareStatus === 'copied' ? 'Link Copied' : 'Invite'}
-
-
-
- )}
-
-
-
-
-
setSeedInput(e.target.value)}
- onKeyDown={(e) => e.key === 'Enter' && handleStartBrainstorm(seedInput)}
- placeholder="Enter a concept to unfold..."
- className={`w-full relative bg-white dark:bg-[#1A1A1A] border-2 rounded-2xl px-8 py-7 pr-20 outline-none transition-all text-2xl font-serif italic text-ink dark:text-dark-ink shadow-sm group-hover:shadow-md
- ${error ? 'border-rose-400 focus:ring-rose-100 shadow-rose-100' : 'border-border/40 focus:border-ochre/40 focus:ring-4 focus:ring-ochre/5'}`}
- />
-
handleStartBrainstorm(seedInput)}
- disabled={isGenerating || !seedInput.trim()}
- className="absolute right-4 top-4 bottom-4 px-6 bg-ink dark:bg-ochre text-paper rounded-xl disabled:opacity-50 transition-all hover:scale-[1.02] active:scale-[0.98] flex items-center justify-center gap-2 min-w-[70px] shadow-lg"
- >
- {isGenerating ? (
-
- ) : (
-
- )}
-
-
-
-
- {error && (
-
-
-
-
Obstruction detected
-
{error}
-
-
- )}
-
- {isGenerating && !error && (
-
-
- {[0.2, 0.4, 0.6].map((d, i) => (
-
- ))}
-
- Gemini is harvesting seeds of thought from the digital ether...
-
- )}
-
-
-
-
-
- {/* Main Canvas Area */}
-
- {activeSession ? (
-
setSelectedIdeaId(null)} className="w-full h-full">
- {
- setSelectedIdeaId(id);
- }}
- onPositionUpdate={(id, pos) => updateIdea(id, { position: pos })}
- onAddChild={(id) => {
- setSelectedIdeaId(id);
- setEditingNodeId(id);
- }}
- onManualSubmit={handleManualAdd}
- onManualCancel={() => setEditingNodeId(null)}
- editingNodeId={editingNodeId}
- selectedNodeId={selectedIdeaId}
- relatedNotes={notes}
- />
-
- ) : (
-
-
-
The canvas is waiting for your spark...
-
- )}
-
- {/* Floating UI overlays */}
-
- {activeSession && (
-
-
-
- setEditingNodeId('new')}
- className="px-6 py-3 bg-paper dark:bg-black/60 backdrop-blur-xl border border-border shadow-xl rounded-full flex items-center gap-2 text-[10px] font-bold uppercase tracking-widest text-concrete hover:bg-ink hover:text-paper transition-all"
- >
-
- Add Manual Idea
-
-
- )}
-
-
-
- {/* Activity Sidebar */}
-
- {showActivity && (
-
-
-
-
setShowActivity(false)} className="p-1 hover:bg-white/10 rounded-lg">
-
-
-
-
- {activities.length === 0 ? (
-
Aucune activité pour le moment
- ) : (
- activities.map((act) => (
-
-
- {act.message}
- {act.timestamp}
-
- ))
- )}
-
-
- )}
-
-
- {/* Right Sidebar Detail Panel */}
-
- {selectedIdea && (
-
-
-
-
- Vague {selectedIdea.waveNumber}
-
-
- {selectedIdea.status === 'converted' && (
- Note Created
- )}
- setSelectedIdeaId(null)} className="p-2 hover:bg-ink/5 rounded-full transition-colors">
-
-
-
-
-
-
{selectedIdea.title}
-
-
-
- Novelty: {selectedIdea.noveltyScore}/10
-
-
-
-
- {selectedIdea.description}
-
-
-
-
Origin connection
-
- "{selectedIdea.connectionToSeed}"
-
-
-
- {selectedIdea.relatedNoteIds && selectedIdea.relatedNoteIds.length > 0 && (
-
-
Semantic Context
- {selectedIdea.relatedNoteIds.map(noteId => {
- const note = notes.find(n => n.id === noteId);
- return note ? (
-
- ) : null;
- })}
-
- )}
-
-
-
-
handleDeepenIdea(selectedIdea)}
- disabled={isGenerating}
- className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-border rounded-2xl hover:border-ochre/40 hover:bg-ochre/5 transition-all group disabled:opacity-50"
- >
-
- AI Expand
-
-
setEditingNodeId(selectedIdea.id)}
- className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-border rounded-2xl hover:border-ink/40 hover:bg-ink/5 transition-all group disabled:opacity-50"
- >
-
- Add Child
-
-
handleConvertToNote(selectedIdea)}
- disabled={selectedIdea.status === 'converted'}
- className="flex flex-col items-center justify-center p-6 border-2 border-dashed border-border rounded-2xl hover:border-blueprint/40 hover:bg-blueprint/5 transition-all group disabled:opacity-50 whitespace-nowrap"
- >
-
- Extract Note
-
-
-
-
handleDismissIdea(selectedIdea.id)}
- className="w-full py-4 text-[10px] font-bold uppercase tracking-[0.2em] text-concrete hover:text-rose-500 hover:bg-rose-500/5 rounded-xl transition-all border border-transparent hover:border-rose-500/10"
- >
- Not pertinent
-
-
-
-
- )}
-
-
- {/* History Rail */}
-
-
-
-
- {sessions.map(session => (
- setActiveSessionId(session.id)}
- className={`w-10 h-10 min-h-[40px] rounded-xl flex items-center justify-center text-xs font-bold transition-all shrink-0
- ${activeSessionId === session.id ? 'bg-ink text-paper scale-110 shadow-lg' : 'bg-paper dark:bg-white/10 text-concrete hover:bg-black/5 hover:text-ink'}`}
- title={session.seedIdea}
- >
- {session.seedIdea.charAt(0).toUpperCase()}
-
- ))}
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/HierarchicalCarnetSelector.tsx b/architectural-grid12/src/components/HierarchicalCarnetSelector.tsx
deleted file mode 100644
index d04851e..0000000
--- a/architectural-grid12/src/components/HierarchicalCarnetSelector.tsx
+++ /dev/null
@@ -1,208 +0,0 @@
-import React, { useState, useMemo } from 'react';
-import {
- ChevronRight,
- ChevronDown,
- Folder,
- FolderOpen,
- Check,
- Search
-} from 'lucide-react';
-import { Carnet } from '../types';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface HierarchicalCarnetSelectorProps {
- carnets: Carnet[];
- selectedId: string | null;
- onSelect: (id: string) => void;
- className?: string;
- placeholder?: string;
-}
-
-export const HierarchicalCarnetSelector: React.FC = ({
- carnets,
- selectedId,
- onSelect,
- className = "",
- placeholder = "Sélectionner un carnet..."
-}) => {
- const [isOpen, setIsOpen] = useState(false);
- const [searchQuery, setSearchQuery] = useState("");
- const [expandedIds, setExpandedIds] = useState>(new Set(['1', '4'])); // Default expand some
-
- const selectedCarnet = carnets.find(c => c.id === selectedId);
-
- // Derive the path for display
- const path = useMemo(() => {
- if (!selectedCarnet) return [];
- const trail: Carnet[] = [];
- let current = selectedCarnet;
- while (current) {
- trail.unshift(current);
- if (!current.parentId) break;
- const parent = carnets.find(c => c.id === current.parentId);
- if (!parent) break;
- current = parent;
- }
- return trail;
- }, [selectedCarnet, carnets]);
-
- const toggleExpand = (e: React.MouseEvent, id: string) => {
- e.stopPropagation();
- const newExpanded = new Set(expandedIds);
- if (newExpanded.has(id)) {
- newExpanded.delete(id);
- } else {
- newExpanded.add(id);
- }
- setExpandedIds(newExpanded);
- };
-
- const filteredCarnets = useMemo(() => {
- if (!searchQuery) return carnets;
- return carnets.filter(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()));
- }, [carnets, searchQuery]);
-
- const renderTree = (parentId?: string, level = 0) => {
- const children = carnets.filter(c => c.parentId === parentId);
- if (children.length === 0) return null;
-
- return (
- 0 ? "ml-4 border-l border-border/40 pl-2" : ""}>
- {children.map(carnet => {
- const isExpanded = expandedIds.has(carnet.id) || searchQuery.length > 0;
- const hasChildren = carnets.some(c => c.parentId === carnet.id);
- const isSelected = selectedId === carnet.id;
-
- // If searching and this carnet doesn't match AND none of its children match, skip it
- if (searchQuery && !carnet.name.toLowerCase().includes(searchQuery.toLowerCase())) {
- const hasMatchingChild = (id: string): boolean => {
- const childrenOfId = carnets.filter(c => c.parentId === id);
- return childrenOfId.some(c => c.name.toLowerCase().includes(searchQuery.toLowerCase()) || hasMatchingChild(c.id));
- };
- if (!hasMatchingChild(carnet.id)) return null;
- }
-
- return (
-
-
{
- onSelect(carnet.id);
- if (!searchQuery) setIsOpen(false);
- }}
- className={`flex items-center gap-2.5 px-2 py-1.5 rounded-lg cursor-pointer transition-all group
- ${isSelected ? 'bg-blueprint/10 text-blueprint font-bold' : 'hover:bg-slate-50 dark:hover:bg-white/5 text-ink'}`}
- >
-
- {hasChildren ? (
- toggleExpand(e, carnet.id)}
- className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded transition-colors"
- >
- {isExpanded ? : }
-
- ) : null}
-
-
-
- {isExpanded && hasChildren ? : }
-
-
-
{carnet.name}
-
- {isSelected &&
}
-
-
-
- {isExpanded && (
-
- {renderTree(carnet.id, level + 1)}
-
- )}
-
-
- );
- })}
-
- );
- };
-
- return (
-
-
setIsOpen(!isOpen)}
- className="w-full bg-slate-50 dark:bg-black/20 border border-border/80 rounded-xl px-4 py-4 text-sm outline-none focus:ring-4 ring-blueprint/5 focus:border-blueprint/40 transition-all cursor-pointer text-ink flex items-center gap-3"
- >
-
-
- {path.length > 0 ? (
-
- {path.map((item, i) => (
-
- {i > 0 && / }
-
- {item.name}
-
-
- ))}
-
- ) : (
-
{placeholder}
- )}
-
-
-
-
-
- {isOpen && (
- <>
- setIsOpen(false)}
- />
-
-
-
-
- setSearchQuery(e.target.value)}
- placeholder="Filtrer les carnets..."
- className="w-full bg-white border border-border rounded-lg pl-9 pr-4 py-2 text-xs outline-none focus:border-blueprint transition-colors"
- />
-
-
-
-
- {renderTree(undefined)}
-
-
-
-
- Structure des carnets
-
- setIsOpen(false)}
- className="text-[10px] font-bold text-blueprint hover:underline"
- >
- Fermer
-
-
-
- >
- )}
-
-
- );
-};
diff --git a/architectural-grid12/src/components/InsightsView.tsx b/architectural-grid12/src/components/InsightsView.tsx
deleted file mode 100644
index fda8edd..0000000
--- a/architectural-grid12/src/components/InsightsView.tsx
+++ /dev/null
@@ -1,248 +0,0 @@
-
-import React, { useState, useEffect, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import {
- Network,
- Lightbulb,
- Layers,
- Sparkles,
- ArrowRight,
- RefreshCw,
- Trophy,
- Zap,
- Tag,
- Link as LinkIcon
-} from 'lucide-react';
-import { Note, NoteCluster, BridgeNote, ConnectionSuggestion } from '../types';
-import { runClustering, detectBridges, calculateCentroid } from '../services/clusteringService';
-import { nameCluster, suggestBridgeIdeas } from '../services/geminiService';
-import { NetworkGraph } from './NetworkGraph';
-
-interface InsightsViewProps {
- notes: Note[];
- onUpdateNotes: (updatedNotes: Note[]) => void;
- onNoteSelect: (noteId: string) => void;
-}
-
-export const InsightsView: React.FC = ({
- notes,
- onUpdateNotes,
- onNoteSelect
-}) => {
- const [isCalculating, setIsCalculating] = useState(false);
- const [clusters, setClusters] = useState([]);
- const [bridgeNotes, setBridgeNotes] = useState([]);
- const [suggestions, setSuggestions] = useState([]);
- const [selectedClusterId, setSelectedClusterId] = useState(null);
-
- const performAnalysis = async () => {
- setIsCalculating(true);
- try {
- // 1. Run clustering
- const { clusters: newClusters } = runClustering(notes);
-
- // 2. Name clusters (first 5 unique notes per cluster)
- const namedClusters = await Promise.all(newClusters.map(async (c) => {
- const clusterNoteSummaries = notes
- .filter(n => c.noteIds.includes(n.id))
- .slice(0, 5)
- .map(n => n.title);
-
- const name = await nameCluster(clusterNoteSummaries);
- const centroid = calculateCentroid(c.noteIds, notes);
-
- return { ...c, name, centroid };
- }));
-
- // 3. Update notes with cluster IDs
- const updatedNotes = notes.map(n => {
- const cluster = namedClusters.find(c => c.noteIds.includes(n.id));
- return { ...n, clusterId: cluster?.id };
- });
- onUpdateNotes(updatedNotes);
-
- // 4. Detect bridges
- const bridges = detectBridges(updatedNotes, namedClusters);
-
- // 5. Build suggestions for isolated cluster pairs
- // For demo, we'll just pick a few interesting pairs
- const newSuggestions: ConnectionSuggestion[] = [];
- if (namedClusters.length >= 2) {
- // Find clusters with no mutual bridge notes or low connectivity
- for (let i = 0; i < Math.min(namedClusters.length, 3); i++) {
- for (let j = i + 1; j < Math.min(namedClusters.length, 3); j++) {
- const cA = namedClusters[i];
- const cB = namedClusters[j];
-
- const cA_notes = updatedNotes.filter(n => cA.noteIds.includes(n.id)).map(n => n.title).join(', ');
- const cB_notes = updatedNotes.filter(n => cB.noteIds.includes(n.id)).map(n => n.title).join(', ');
-
- const bridgeIdeas = await suggestBridgeIdeas(cA.name, cB.name, cA_notes, cB_notes);
- bridgeIdeas.forEach((idea, idx) => {
- newSuggestions.push({
- id: `suggestion-${i}-${j}-${idx}`,
- ...idea,
- clusterAId: cA.id,
- clusterBId: cB.id
- });
- });
- }
- }
- }
-
- setClusters(namedClusters);
- setBridgeNotes(bridges);
- setSuggestions(newSuggestions);
- } catch (error) {
- console.error("Analysis failed:", error);
- } finally {
- setIsCalculating(false);
- }
- };
-
- useEffect(() => {
- if (notes.some(n => n.embedding) && clusters.length === 0) {
- performAnalysis();
- }
- }, [notes]);
-
- const bridgeList = useMemo(() => {
- return bridgeNotes.map(b => {
- const note = notes.find(n => n.id === b.noteId);
- return { ...b, title: note?.title || 'Unknown Note' };
- });
- }, [bridgeNotes, notes]);
-
- return (
-
- {/* Header */}
-
-
-
-
-
-
-
Semantic Insights
-
-
Discovering the hidden architecture of your knowledge
-
-
- {isCalculating ? : }
- {isCalculating ? 'Mapping...' : 'Re-sync Network'}
-
-
-
-
- {/* Left: Graph View */}
-
-
-
-
- {/* Right: Insight Dashboard */}
-
-
- {/* Stats Summary */}
-
-
-
-
- Clusters
-
-
{clusters.length}
-
-
-
-
- Bridge Notes
-
-
{bridgeNotes.length}
-
-
-
- {/* Bridge Notes Section */}
-
-
-
-
Powerful Bridge Notes
-
-
- {bridgeList.map(bridge => (
-
onNoteSelect(bridge.noteId)}
- className="p-4 rounded-xl bg-white dark:bg-white/5 border border-border hover:border-ochre/40 transition-all cursor-pointer group"
- >
-
-
{bridge.title}
-
- Score: {(bridge.bridgeScore * 100).toFixed(0)}%
-
-
-
- {bridge.connectedClusterIds.map(cid => {
- const c = clusters.find(cl => cl.id === cid);
- return (
-
- );
- })}
-
-
- ))}
- {bridgeList.length === 0 && !isCalculating && (
-
No significant bridge notes found yet. Deepen your research to find new connections.
- )}
-
-
-
- {/* Connection Suggestions */}
-
-
-
-
Missing Links (AI Generated)
-
-
- {suggestions.map((s, idx) => (
-
-
-
-
Bridging {clusters.find(c => c.id === s.clusterAId)?.name} & {clusters.find(c => c.id === s.clusterBId)?.name}
-
-
{s.title}
-
{s.description}
-
-
- {s.reasoning}
-
-
- ))}
- {isCalculating && (
-
- {[1, 2].map(i => (
-
- ))}
-
- )}
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/NetworkGraph.tsx b/architectural-grid12/src/components/NetworkGraph.tsx
deleted file mode 100644
index aa83e68..0000000
--- a/architectural-grid12/src/components/NetworkGraph.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-
-import React, { useEffect, useRef } from 'react';
-import * as d3 from 'd3';
-import { Note, NoteCluster, BridgeNote } from '../types';
-
-interface NetworkGraphProps {
- notes: Note[];
- clusters: NoteCluster[];
- bridgeNotes: BridgeNote[];
- onNoteSelect: (id: string) => void;
-}
-
-export const NetworkGraph: React.FC = ({
- notes,
- clusters,
- bridgeNotes,
- onNoteSelect
-}) => {
- const svgRef = useRef(null);
- const containerRef = useRef(null);
-
- useEffect(() => {
- if (!svgRef.current || !containerRef.current) return;
-
- const width = containerRef.current.clientWidth;
- const height = containerRef.current.clientHeight;
-
- const svg = d3.select(svgRef.current);
- svg.selectAll("*").remove();
-
- const g = svg.append("g");
-
- const zoom = d3.zoom()
- .scaleExtent([0.1, 4])
- .on("zoom", (event) => {
- g.attr("transform", event.transform);
- });
-
- svg.call(zoom);
-
- // Filter notes with embeddings and cluster assignments
- const visibleNotes = notes.filter(n => n.embedding && n.clusterId);
-
- interface D3Node extends d3.SimulationNodeDatum {
- id: string;
- title: string;
- clusterId: string;
- color: string;
- isBridge: boolean;
- radius: number;
- }
-
- interface D3Link extends d3.SimulationLinkDatum {
- source: string;
- target: string;
- strength: number;
- }
-
- const bridgeSet = new Set(bridgeNotes.map(b => b.noteId));
-
- const nodes: D3Node[] = visibleNotes.map(n => {
- const cluster = clusters.find(c => c.id === n.clusterId);
- const isBridge = bridgeSet.has(n.id);
- return {
- id: n.id,
- title: n.title,
- clusterId: n.clusterId!,
- color: cluster?.color || '#cbd5e1',
- isBridge,
- radius: isBridge ? 12 : 8
- };
- });
-
- const links: D3Link[] = [];
- // Only connect strong links
- for (let i = 0; i < visibleNotes.length; i++) {
- for (let j = i + 1; j < visibleNotes.length; j++) {
- const ni = visibleNotes[i];
- const nj = visibleNotes[j];
-
- if (ni.clusterId === nj.clusterId) {
- links.push({ source: ni.id, target: nj.id, strength: 0.5 });
- }
- }
- }
-
- const simulation = d3.forceSimulation(nodes)
- .force("link", d3.forceLink(links).id(d => d.id).distance(100))
- .force("charge", d3.forceManyBody().strength(-200))
- .force("center", d3.forceCenter(width / 2, height / 2))
- .force("collision", d3.forceCollide().radius(d => d.radius + 10));
-
- // Links
- const link = g.append("g")
- .selectAll("line")
- .data(links)
- .enter()
- .append("line")
- .attr("stroke", "#e2e8f0")
- .attr("stroke-opacity", 0.6)
- .attr("stroke-width", 1);
-
- // Nodes
- const node = g.append("g")
- .selectAll(".node")
- .data(nodes)
- .enter()
- .append("g")
- .attr("class", "node cursor-pointer")
- .on("click", (event, d) => onNoteSelect(d.id))
- .call(d3.drag()
- .on("start", dragstarted)
- .on("drag", dragged)
- .on("end", dragended) as any);
-
- node.append("circle")
- .attr("r", d => d.radius)
- .attr("fill", d => d.color)
- .attr("stroke", d => d.isBridge ? "#D4AF37" : "#fff")
- .attr("stroke-width", d => d.isBridge ? 3 : 2)
- .style("filter", d => d.isBridge ? "drop-shadow(0 0 4px rgba(212, 175, 55, 0.4))" : "none");
-
- node.append("text")
- .attr("dy", d => d.radius + 14)
- .attr("text-anchor", "middle")
- .attr("class", "text-[10px] fill-concrete dark:fill-concrete/60 font-medium pointer-events-none")
- .text(d => d.title.length > 20 ? d.title.substring(0, 20) + "..." : d.title);
-
- simulation.on("tick", () => {
- link
- .attr("x1", d => (d.source as any).x)
- .attr("y1", d => (d.source as any).y)
- .attr("x2", d => (d.target as any).x)
- .attr("y2", d => (d.target as any).y);
-
- node
- .attr("transform", d => `translate(${d.x},${d.y})`);
- });
-
- function dragstarted(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0.3).restart();
- d.fx = d.x;
- d.fy = d.y;
- }
-
- function dragged(event: any, d: D3Node) {
- d.fx = event.x;
- d.fy = event.y;
- }
-
- function dragended(event: any, d: D3Node) {
- if (!event.active) simulation.alphaTarget(0);
- d.fx = null;
- d.fy = null;
- }
-
- return () => simulation.stop();
- }, [notes, clusters, bridgeNotes, onNoteSelect]);
-
- return (
-
-
- {clusters.map(c => (
-
- ))}
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/NotebooksView.tsx b/architectural-grid12/src/components/NotebooksView.tsx
deleted file mode 100644
index 98817c9..0000000
--- a/architectural-grid12/src/components/NotebooksView.tsx
+++ /dev/null
@@ -1,489 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Search,
- Share2,
- Pin,
- ChevronRight,
- ArrowLeft,
- MoreVertical,
- Sparkles,
- Tag as TagIcon,
- X,
- BookOpen,
- Edit3,
- Eye,
- Trash2,
- Wind
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet, Tag } from '../types';
-import { SlashMenu } from './SlashMenu';
-
-interface NotebooksViewProps {
- activeNoteId: string | null;
- activeCarnet: Carnet | undefined;
- filteredNotes: Note[];
- activeNote: Note | undefined;
- setActiveNoteId: (id: string | null) => void;
- togglePin: (id: string) => void;
- setShowNewNoteModal: (show: boolean) => void;
- isAISidebarOpen: boolean;
- setIsAISidebarOpen: (open: boolean) => void;
- selectedTagIds: string[];
- setSelectedTagIds: (ids: string[]) => void;
- allNotes: Note[];
- activeCarnetId: string;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteNote: (id: string) => void;
- onBrainstormNote: (note: Note) => void;
-}
-
-export const NotebooksView: React.FC = ({
- activeNoteId,
- activeCarnet,
- filteredNotes,
- activeNote,
- setActiveNoteId,
- togglePin,
- setShowNewNoteModal,
- isAISidebarOpen,
- setIsAISidebarOpen,
- selectedTagIds,
- setSelectedTagIds,
- allNotes,
- activeCarnetId,
- setShowNewCarnetModal,
- onDeleteNote,
- onBrainstormNote
-}) => {
- const [isTagsExpanded, setIsTagsExpanded] = React.useState(false);
- const [tagSearchQuery, setTagSearchQuery] = React.useState('');
- const [isEditing, setIsEditing] = React.useState(false);
- const [slashMenu, setSlashMenu] = React.useState<{ isOpen: boolean; top: number; left: number } | null>(null);
-
- const handleEditorKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === '/') {
- const selection = window.getSelection();
- if (selection && selection.rangeCount > 0) {
- const range = selection.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- setSlashMenu({
- isOpen: true,
- top: rect.bottom + window.scrollY,
- left: rect.left + window.scrollX
- });
- }
- }
- };
-
- const insertCommand = (type: string) => {
- console.log(`Command selected: ${type}`);
- setSlashMenu(null);
- };
-
- const availableTags = React.useMemo(() => {
- const carnetNotes = allNotes.filter(n => n.carnetId === activeCarnetId);
- const tagsMap = new Map();
- carnetNotes.forEach(note => {
- note.tags?.forEach(tag => {
- tagsMap.set(tag.id, tag);
- });
- });
- return Array.from(tagsMap.values()).sort((a, b) => {
- // AI tags first, then alphabetical
- if (a.type === 'ai' && b.type !== 'ai') return -1;
- if (a.type !== 'ai' && b.type === 'ai') return 1;
- return a.label.localeCompare(b.label);
- });
- }, [allNotes, activeCarnetId]);
-
- const visibleTags = React.useMemo(() => {
- let filtered = availableTags;
- if (tagSearchQuery) {
- filtered = availableTags.filter(t =>
- t.label.toLowerCase().includes(tagSearchQuery.toLowerCase())
- );
- } else if (!isTagsExpanded) {
- filtered = availableTags.slice(0, 10);
- // Ensure selected tags are always visible even if not in the first 10
- selectedTagIds.forEach(id => {
- if (!filtered.find(t => t.id === id)) {
- const tag = availableTags.find(t => t.id === id);
- if (tag) filtered.push(tag);
- }
- });
- }
- return filtered;
- }, [availableTags, isTagsExpanded, tagSearchQuery, selectedTagIds]);
-
- const toggleTag = (tagId: string) => {
- if (selectedTagIds.includes(tagId)) {
- setSelectedTagIds(selectedTagIds.filter(id => id !== tagId));
- } else {
- setSelectedTagIds([...selectedTagIds, tagId]);
- }
- };
-
- if (!activeNoteId) {
- return (
-
-
-
-
-
- {filteredNotes.map((note, index) => (
-
setActiveNoteId(note.id)}
- >
-
-
- {note.isPinned && }
- {note.title}
-
-
-
{
- e.stopPropagation();
- onBrainstormNote(note);
- }}
- className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-ochre/10 text-ochre transition-all"
- title="Brainstorm this concept"
- >
-
-
-
{
- e.stopPropagation();
- togglePin(note.id);
- }}
- className={`p-2 rounded-full transition-all ${note.isPinned ? 'text-amber-600 bg-amber-50' : 'opacity-0 group-hover:opacity-60 hover:bg-slate-100 text-ink'}`}
- >
-
-
-
{
- e.stopPropagation();
- onDeleteNote(note.id);
- }}
- className="p-2 rounded-full opacity-0 group-hover:opacity-60 hover:opacity-100 hover:bg-rose-50 text-rose-500 transition-all"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- {note.tags?.map(tag => (
-
- {tag.type === 'ai' && }
- {tag.label}
-
- ))}
-
-
- {note.content}
-
-
Read more
-
-
-
- ))}
- {filteredNotes.length === 0 && (
-
-
This notebook is waiting for its first vision.
-
setShowNewNoteModal(true)}
- className="px-6 py-2 border border-ink text-[13px] uppercase tracking-[0.2em] hover:bg-ink hover:text-paper transition-all"
- >
- Begin Drawing
-
-
- )}
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
setActiveNoteId(null)}
- className="flex items-center gap-2 text-ink hover:opacity-60 transition-opacity"
- >
-
- Back to collection
-
-
-
onBrainstormNote(activeNote!)}
- className="flex items-center gap-2 px-3 py-1.5 rounded-full border border-ochre/30 text-ochre hover:bg-ochre/5 transition-all"
- >
-
- Brainstorm
-
-
setIsEditing(!isEditing)}
- className={`flex items-center gap-2 px-4 py-1.5 rounded-lg border transition-all duration-300
- ${isEditing ? 'bg-blueprint text-white border-blueprint shadow-lg shadow-blueprint/20' : 'border-border text-ink hover:bg-slate-50'}`}
- >
- {isEditing ? : }
- {isEditing ? 'Visualiser' : 'Modifier'}
-
-
togglePin(activeNoteId!)}
- className={`p-2 rounded-full transition-all ${activeNote?.isPinned ? 'text-amber-600 bg-amber-50 dark:bg-ochre/10' : 'text-muted-ink hover:text-ink'}`}
- title={activeNote?.isPinned ? "Unpin note" : "Pin note"}
- >
-
-
-
setIsAISidebarOpen(!isAISidebarOpen)}
- className={`flex items-center gap-2 px-3 py-1.5 rounded-full border transition-all duration-300
- ${isAISidebarOpen ? 'bg-ink text-paper border-ink' : 'border-border text-ink hover:bg-white/50 dark:hover:bg-white/5'}`}
- >
-
- AI Assistant
-
-
-
-
-
-
-
-
-
-
-
-
- {slashMenu?.isOpen && (
- insertCommand(type)}
- onClose={() => setSlashMenu(null)}
- />
- )}
-
-
-
-
- {activeCarnet?.name}
-
- {activeNote?.date}
-
-
- {isEditing ? (
-
- ) : (
-
- {activeNote?.title}
-
- )}
-
-
- {activeNote?.tags?.map(tag => (
-
- {tag.type === 'ai' &&
}
- {tag.label}
- {tag.type === 'ai' && (
-
- )}
-
- ))}
-
-
-
-
-
-
-
-
-
- {isEditing ? (
-
- ) : (
-
-
- {activeNote?.content.split('.')[0]}.
-
-
-
- {activeNote?.content.split('\n').map((line, i) => (
-
- {line}
-
- ))}
- {activeNote?.id.startsWith('n-') && (
-
- Architectural grids serve as the invisible scaffolding upon which spatial experiences are constructed. Beyond mere structural repetition, they facilitate a rhythmic dialogue between materiality and void. In this exploration, we examine how light fractures these rigid boundaries, creating a dynamic interplay that evolves with the passage of time.
-
- )}
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/SettingsView.tsx b/architectural-grid12/src/components/SettingsView.tsx
deleted file mode 100644
index 57b3981..0000000
--- a/architectural-grid12/src/components/SettingsView.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-import { SettingsTab } from '../types';
-import { SettingsHeader } from './settings/SettingsHeader';
-import { GeneralTab } from './settings/GeneralTab';
-import { AITab } from './settings/AITab';
-import { AppearanceTab } from './settings/AppearanceTab';
-
-interface SettingsViewProps {
- activeSettingsTab: SettingsTab;
- setActiveSettingsTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsView: React.FC = ({
- activeSettingsTab,
- setActiveSettingsTab
-}) => {
- return (
-
-
-
-
-
-
-
-
-
- {activeSettingsTab === 'general' && (
-
- )}
-
- {activeSettingsTab === 'ai' && (
-
- )}
-
- {activeSettingsTab === 'appearance' && (
-
- )}
-
- {['profile', 'data', 'mcp', 'about'].includes(activeSettingsTab) && (
-
-
- ?
-
-
-
Section en développement
-
Le module {activeSettingsTab} sera disponible prochainement.
-
-
- )}
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/Sidebar.tsx b/architectural-grid12/src/components/Sidebar.tsx
deleted file mode 100644
index 124ed80..0000000
--- a/architectural-grid12/src/components/Sidebar.tsx
+++ /dev/null
@@ -1,569 +0,0 @@
-import React from 'react';
-import {
- Plus,
- Archive,
- Settings,
- ChevronRight,
- BookOpen,
- Bot,
- Microscope,
- Activity,
- Pin,
- Moon,
- Sun,
- Bell,
- Lock,
- Edit3,
- Trash2,
- Users,
- Clock,
- GripVertical,
- Wind,
- Network
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { NavigationView, Carnet, Note } from '../types';
-
-interface NoteLinkProps {
- note: Note;
- isActive: boolean;
- onClick: () => void;
-}
-
-const NoteLink: React.FC = ({ note, isActive, onClick }) => (
-
-
- {note.isPinned && }
-
-);
-
-interface SidebarItemProps {
- carnet: Carnet;
- isActive: boolean;
- notes: Note[];
- activeNoteId: string | null;
- onCarnetClick: () => void;
- onNoteClick: (noteId: string) => void;
- onAddSubCarnet: () => void;
- onRename: () => void;
- onDelete: () => void;
- children?: React.ReactNode;
- level: number;
- isExpanded: boolean;
- toggleExpand: () => void;
- onMove?: (draggedId: string, targetId?: string) => void;
-}
-
-const SidebarItem: React.FC = ({
- carnet,
- isActive,
- notes,
- activeNoteId,
- onCarnetClick,
- onNoteClick,
- onAddSubCarnet,
- onRename,
- onDelete,
- children,
- level,
- isExpanded,
- toggleExpand,
- onMove
-}) => {
- const hasChildren = React.Children.count(children) > 0;
-
- return (
-
-
- {/* Subtle Drag Handle */}
-
-
-
-
- {/* Hierarchy Guide Line */}
- {level > 0 && (
-
- )}
- {level > 0 && (
-
- )}
-
-
- {hasChildren ? (
-
{
- e.stopPropagation();
- toggleExpand();
- }}
- className="p-1 hover:bg-ink/5 dark:hover:bg-white/5 rounded-md transition-colors text-muted-ink"
- >
-
-
-
-
- ) : (
-
// Spacer for alignment
- )}
-
-
{
- e.preventDefault();
- e.dataTransfer.dropEffect = 'move';
- e.currentTarget.classList.add('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDragLeave={(e) => {
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDrop={(e) => {
- e.preventDefault();
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- const draggedId = e.dataTransfer.getData('carnetId');
- console.log('Dropped carnet:', draggedId, 'on target:', carnet.id);
- if (draggedId && draggedId !== carnet.id) {
- onMove?.(draggedId, carnet.id);
- }
- }}
- draggable
- onDragStart={(e) => {
- console.log('Starting drag for carnet:', carnet.id);
- e.dataTransfer.setData('carnetId', carnet.id);
- e.dataTransfer.effectAllowed = 'move';
- const ghost = e.currentTarget.cloneNode(true) as HTMLElement;
- ghost.style.position = 'absolute';
- ghost.style.top = '-1000px';
- ghost.style.opacity = '0.5';
- document.body.appendChild(ghost);
- e.dataTransfer.setDragImage(ghost, 0, 0);
- setTimeout(() => document.body.removeChild(ghost), 0);
- }}
- >
- {/* active indicator dot */}
- {isActive && (
-
- )}
-
-
- {carnet.initial}
-
-
-
- {carnet.name}
-
- {carnet.isPrivate && }
-
-
-
-
{
- e.stopPropagation();
- onAddSubCarnet();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Add sub-carnet"
- >
-
-
-
{
- e.stopPropagation();
- onRename();
- }}
- className="p-1 hover:bg-ink/10 dark:hover:bg-white/10 rounded-md transition-all text-concrete hover:text-ink"
- title="Rename"
- >
-
-
-
{
- e.stopPropagation();
- onDelete();
- }}
- className="p-1 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md transition-all text-concrete hover:text-red-500"
- title="Delete"
- >
-
-
-
- {notes.length > 0 && (
-
- {notes.length}
-
- )}
-
-
-
-
-
-
- {(isExpanded || (isActive && !hasChildren)) && (
-
-
- {/* Vertical line for nested content */}
-
-
-
- {children}
- {isActive && !hasChildren && notes.map(note => (
-
onNoteClick(note.id)}
- />
- ))}
- {isActive && !hasChildren && notes.length === 0 && (
-
- No notes found
-
- )}
-
-
-
- )}
-
-
- );
-};
-
-interface SidebarProps {
- activeView: NavigationView;
- isDarkMode: boolean;
- setIsDarkMode: (val: boolean) => void;
- setActiveView: (view: NavigationView) => void;
- carnets: Carnet[];
- notes: Note[];
- activeCarnetId: string;
- activeNoteId: string | null;
- setActiveCarnetId: (id: string) => void;
- setActiveNoteId: (id: string | null) => void;
- setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void;
- onDeleteCarnet: (id: string) => void;
- onMoveCarnet: (draggedId: string, targetId?: string) => void;
-}
-
-export const Sidebar: React.FC = ({
- activeView,
- isDarkMode,
- setIsDarkMode,
- setActiveView,
- carnets,
- notes,
- activeCarnetId,
- activeNoteId,
- setActiveCarnetId,
- setActiveNoteId,
- setShowNewCarnetModal,
- onDeleteCarnet,
- onMoveCarnet
-}) => {
- const [expandedIds, setExpandedIds] = React.useState>(new Set(['4'])); // Default expand Research
-
- const toggleExpand = (id: string) => {
- const newSet = new Set(expandedIds);
- if (newSet.has(id)) newSet.delete(id);
- else newSet.add(id);
- setExpandedIds(newSet);
- };
-
- const renderCarnetTree = (parentId: string | undefined = undefined, level: number = 0) => {
- return carnets
- .filter(c => c.parentId === parentId && !c.isDeleted)
- .map(carnet => (
- n.carnetId === carnet.id && !n.isDeleted)}
- activeNoteId={activeNoteId}
- level={level}
- isExpanded={expandedIds.has(carnet.id)}
- toggleExpand={() => toggleExpand(carnet.id)}
- onAddSubCarnet={() => {
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- setShowNewCarnetModal(true, carnet.id);
- }}
- onRename={() => {
- setShowNewCarnetModal(true, undefined, true, carnet.id);
- }}
- onDelete={() => {
- onDeleteCarnet(carnet.id);
- }}
- onCarnetClick={() => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(null);
- // Auto expand when clicking
- if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id);
- }}
- onNoteClick={(id) => {
- setActiveCarnetId(carnet.id);
- setActiveNoteId(id);
- }}
- onMove={onMoveCarnet}
- >
- {renderCarnetTree(carnet.id, level + 1)}
-
- ));
- };
-
- return (
-
-
-
- A
-
-
-
setIsDarkMode(!isDarkMode)}
- className="p-2 text-muted-ink hover:text-ink transition-all bg-white/50 dark:bg-white/10 rounded-full border border-border dark:border-white/10"
- >
- {isDarkMode ? : }
-
-
-
-
-
- 3
-
-
-
-
- setActiveView('notebooks')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'notebooks' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Carnets"
- >
-
-
- setActiveView('reminders')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'reminders' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Rappels"
- >
-
-
- setActiveView('agents')}
- className={`p-1.5 rounded-full transition-all ${activeView === 'agents' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink'}`}
- title="Agents"
- >
-
-
-
-
-
-
-
- {activeView === 'notebooks' ? (
-
-
{
- e.preventDefault();
- e.dataTransfer.dropEffect = 'move';
- e.currentTarget.classList.add('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDragLeave={(e) => {
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- }}
- onDrop={(e) => {
- e.preventDefault();
- e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20');
- const draggedId = e.dataTransfer.getData('carnetId');
- console.log('Dropped carnet on root:', draggedId);
- if (draggedId) {
- onMoveCarnet(draggedId, undefined);
- }
- }}
- >
-
- Architecture Grid
-
-
setShowNewCarnetModal(true)}
- className="p-1 hover:bg-paper dark:hover:bg-white/5 rounded-md text-concrete hover:text-ink transition-colors"
- title="New Carnet"
- >
-
-
-
-
-
- {renderCarnetTree()}
-
-
- ) : activeView === 'shared' ? (
-
-
- Partagé avec moi
-
-
-
-
Aucun document partagé pour le moment.
-
-
- ) : activeView === 'reminders' ? (
-
-
- Rappels programmés
-
-
-
-
Aucun rappel actif.
-
-
- ) : activeView === 'agents' ? (
-
-
- Intelligence OS
-
-
- {[
- { id: 'a1', name: 'Mes Agents', icon:
},
- { id: 'a2', name: 'Le Lab AI', icon:
},
- { id: 'a3', name: 'Activités', icon:
},
- ].map(item => (
-
-
- {item.icon}
-
- {item.name}
-
- ))}
-
-
-
-
- Capabilities
-
-
setActiveView('brainstorm')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-ochre hover:bg-ochre/5"
- >
-
-
-
- Brainstorm Wave
-
-
-
setActiveView('insights')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-indigo-500 hover:bg-indigo-500/5"
- >
-
-
-
- Semantic Network
-
-
-
setActiveView('temporal')}
- className="w-full flex items-center gap-3 px-4 py-3 text-[13px] transition-all font-medium group rounded-xl text-muted-ink hover:text-rose-500 hover:bg-rose-500/5"
- >
-
-
-
- Temporal Forecast
-
-
-
- ) : null}
-
-
-
-
-
setActiveView('shared')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'shared' ? 'bg-blueprint/5 text-blueprint' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Partagé
-
-
-
-
- Archives
-
-
-
setActiveView('trash')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'trash' ? 'bg-rose-50 text-rose-500' : 'text-muted-ink hover:text-rose-500 hover:bg-rose-50/50'}`}
- >
-
- Corbeille
- {notes.some(n => n.isDeleted) && (
-
- )}
-
-
-
-
Intelligence
-
setActiveView('brainstorm')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'brainstorm' ? 'bg-ochre/10 text-ochre' : 'text-muted-ink hover:text-ochre hover:bg-ochre/5'}`}
- >
-
- Brainstorm Wave
-
-
-
setActiveView('insights')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'insights' ? 'bg-indigo-500/10 text-indigo-500' : 'text-muted-ink hover:text-indigo-500 hover:bg-indigo-500/5'}`}
- >
-
- Semantic Network
-
-
-
setActiveView('temporal')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'temporal' ? 'bg-rose-500/10 text-rose-500' : 'text-muted-ink hover:text-rose-500 hover:bg-rose-500/5'}`}
- >
-
- Temporal Forecast
-
-
-
-
-
-
setActiveView('settings')}
- className={`w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl ${activeView === 'settings' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-black/5'}`}
- >
-
- Paramètres
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/SlashMenu.tsx b/architectural-grid12/src/components/SlashMenu.tsx
deleted file mode 100644
index a715c58..0000000
--- a/architectural-grid12/src/components/SlashMenu.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import {
- Heading1,
- Heading2,
- List,
- Quote,
- Code,
- Image as ImageIcon,
- Type,
- Sparkles
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-
-interface SlashMenuProps {
- position: { top: number; left: number };
- onSelect: (type: string) => void;
- onClose: () => void;
-}
-
-export const SlashMenu: React.FC = ({ position, onSelect, onClose }) => {
- const commands = [
- { id: 'h1', label: 'Titre Principal', icon: , desc: 'Grand titre de section' },
- { id: 'h2', label: 'Sous-titre', icon: , desc: 'Titre de niveau 2' },
- { id: 'bullet', label: 'Liste à puces', icon:
, desc: 'Liste simple' },
- { id: 'quote', label: 'Citation', icon:
, desc: 'Bloc de texte mis en avant' },
- { id: 'code', label: 'Bloc de Code', icon: , desc: 'Code ou texte technique' },
- { id: 'image', label: 'Image', icon: , desc: 'Insérer un visuel' },
- { id: 'ai-summary', label: 'Résumé IA', icon: , desc: 'Générer un résumé court', special: true },
- ];
-
- return (
- <>
-
-
-
- Commandes rapides
-
-
- {commands.map((cmd) => (
-
onSelect(cmd.id)}
- className="w-full flex items-start gap-3 px-3 py-2 hover:bg-paper dark:hover:bg-white/5 transition-colors group text-left"
- >
-
- {cmd.icon}
-
-
-
{cmd.label}
-
{cmd.desc}
-
-
- ))}
-
-
- >
- );
-};
diff --git a/architectural-grid12/src/components/TemporalView.tsx b/architectural-grid12/src/components/TemporalView.tsx
deleted file mode 100644
index 7672e48..0000000
--- a/architectural-grid12/src/components/TemporalView.tsx
+++ /dev/null
@@ -1,169 +0,0 @@
-import React, { useMemo } from 'react';
-import { motion } from 'motion/react';
-import {
- Clock,
- Calendar,
- TrendingUp,
- Zap,
- History,
- ArrowRight,
- Sparkles,
- PieChart
-} from 'lucide-react';
-import { Note, NoteAccessLog, NotePrediction } from '../types';
-import { predictNextAccess, detectAccessCycle } from '../services/temporalService';
-
-interface TemporalViewProps {
- notes: Note[];
- accessLogs: NoteAccessLog[];
- onNoteSelect: (id: string) => void;
-}
-
-export const TemporalView: React.FC = ({ notes, accessLogs, onNoteSelect }) => {
- const predictions = useMemo(() => {
- return notes
- .map(note => {
- const noteLogs = accessLogs.filter(l => l.noteId === note.id);
- const prediction = predictNextAccess(note, noteLogs);
- return { note, prediction };
- })
- .filter(p => p.prediction !== null) as { note: Note; prediction: NotePrediction }[];
- }, [notes, accessLogs]);
-
- const cyclicalNotes = useMemo(() => {
- return notes
- .map(note => {
- const noteLogs = accessLogs.filter(l => l.noteId === note.id);
- const cycle = detectAccessCycle(noteLogs);
- return { note, cycle };
- })
- .filter(p => p.cycle !== null) as { note: Note; cycle: number }[];
- }, [notes, accessLogs]);
-
- return (
-
-
-
-
-
-
-
Temporal Forecast
-
-
Predicting the recurrence of insight
-
-
-
-
-
- {/* Daily Briefing / Predictions */}
-
-
-
-
Intelligence Briefing
-
-
-
- {predictions.map(({ note, prediction }) => (
-
onNoteSelect(note.id)}
- className="p-6 rounded-2xl bg-white dark:bg-white/5 border border-border/60 hover:border-rose-400/40 transition-all cursor-pointer shadow-sm relative overflow-hidden group"
- >
-
-
-
-
-
-
- Coming Up
-
-
- {new Date(prediction.predictedRelevanceDate).toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
-
-
-
- {note.title}
-
- "{prediction.reason}"
-
-
-
-
Confidence {Math.round(prediction.confidence * 100)}%
-
-
-
- ))}
-
- {predictions.length === 0 && (
-
-
-
No upcoming predictions
-
The system needs more usage data to find cyclical patterns in your research.
-
- )}
-
-
-
- {/* Cyclical Patterns */}
-
-
-
-
Detected Cycles
-
-
-
- {cyclicalNotes.map(({ note, cycle }) => (
-
-
- {Math.round(cycle)}
- days
-
-
-
{note.title}
-
-
Recurring theme in your architectural process
-
-
-
-
onNoteSelect(note.id)} className="p-2 hover:bg-black/5 rounded-full">
-
-
-
- ))}
-
-
-
- {/* Productivity Stats */}
-
-
-
-
Memory Strength
-
84%
-
Active connections in your semantic network
-
-
-
Peak Cycle
-
28 Days
-
The rhythm of your creative output
-
-
-
-
-
4 Notes resurfacing this week
-
-
- Build Morning Briefing
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/TrashView.tsx b/architectural-grid12/src/components/TrashView.tsx
deleted file mode 100644
index dc62521..0000000
--- a/architectural-grid12/src/components/TrashView.tsx
+++ /dev/null
@@ -1,218 +0,0 @@
-import React from 'react';
-import {
- Trash2,
- RotateCcw,
- X,
- FileText,
- Folder,
- Search,
- ChevronRight,
- Clock,
- AlertCircle
-} from 'lucide-react';
-import { motion, AnimatePresence } from 'motion/react';
-import { Note, Carnet } from '../types';
-
-interface TrashViewProps {
- deletedNotes: Note[];
- deletedCarnets: Carnet[];
- onRestoreNote: (id: string) => void;
- onRestoreCarnet: (id: string) => void;
- onPermanentDeleteNote: (id: string) => void;
- onPermanentDeleteCarnet: (id: string) => void;
- onEmptyTrash: () => void;
-}
-
-export const TrashView: React.FC = ({
- deletedNotes,
- deletedCarnets,
- onRestoreNote,
- onRestoreCarnet,
- onPermanentDeleteNote,
- onPermanentDeleteCarnet,
- onEmptyTrash
-}) => {
- const [searchQuery, setSearchQuery] = React.useState('');
- const [filterType, setFilterType] = React.useState<'all' | 'notes' | 'carnets'>('all');
-
- const getDaysRemaining = (dateString?: string) => {
- if (!dateString) return 30;
- const deletedDate = new Date(dateString);
- const now = new Date();
- const diffTime = now.getTime() - deletedDate.getTime();
- const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
- return Math.max(0, 30 - diffDays);
- };
-
- const filteredItems = React.useMemo(() => {
- const items = [
- ...deletedNotes.map(n => ({ ...n, itemType: 'note' as const })),
- ...deletedCarnets.map(c => ({ ...c, itemType: 'carnet' as const }))
- ];
-
- return items
- .filter(item => {
- const matchesSearch = ('title' in item ? item.title : item.name).toLowerCase().includes(searchQuery.toLowerCase());
- const matchesType = filterType === 'all' || (filterType === 'notes' && item.itemType === 'note') || (filterType === 'carnets' && item.itemType === 'carnet');
- return matchesSearch && matchesType;
- })
- .sort((a, b) => {
- const dateA = a.deletedAt ? new Date(a.deletedAt).getTime() : 0;
- const dateB = b.deletedAt ? new Date(b.deletedAt).getTime() : 0;
- return dateB - dateA;
- });
- }, [deletedNotes, deletedCarnets, searchQuery, filterType]);
-
- return (
-
-
-
-
-
- Corbeille
-
-
- Auto-suppression après 30 jours
-
-
-
- {filteredItems.length > 0 && (
-
{
- if (window.confirm('Vider la corbeille ? Cette action est irréversible.')) {
- onEmptyTrash();
- }
- }}
- className="px-6 py-3 bg-paper border border-border text-rose-500 rounded-2xl text-[10px] font-bold uppercase tracking-widest hover:bg-rose-50 hover:border-rose-100 transition-all shadow-sm"
- >
- Vider tout
-
- )}
-
-
-
-
-
- setSearchQuery(e.target.value)}
- className="w-full bg-white dark:bg-white/5 border border-border/40 rounded-2xl pl-12 pr-6 py-4 text-sm outline-none focus:ring-4 ring-ink/5 transition-all shadow-sm"
- />
-
-
-
- {(['all', 'notes', 'carnets'] as const).map((type) => (
- setFilterType(type)}
- className={`px-6 py-3 rounded-xl text-[10px] font-bold uppercase tracking-widest transition-all
- ${filterType === type ? 'bg-ink text-paper shadow-lg' : 'text-concrete hover:text-ink'}`}
- >
- {type === 'all' ? 'Tous' : type === 'notes' ? 'Notes' : 'Carnets'}
-
- ))}
-
-
-
-
-
- {filteredItems.length > 0 ? (
-
-
- {filteredItems.map((item) => {
- const daysLeft = getDaysRemaining(item.deletedAt);
- return (
-
- {/* Countdown Progress Bar */}
-
-
-
-
-
-
- {item.itemType === 'note' ? : }
-
-
- item.itemType === 'note' ? onRestoreNote(item.id) : onRestoreCarnet(item.id)}
- className="flex items-center gap-2 px-4 py-2 bg-emerald-50 text-emerald-600 rounded-xl text-[10px] font-bold uppercase tracking-widest hover:bg-emerald-100 transition-colors"
- >
- Restaurer
-
- item.itemType === 'note' ? onPermanentDeleteNote(item.id) : onPermanentDeleteCarnet(item.id)}
- className="p-2 hover:bg-rose-50 text-rose-500 rounded-xl transition-colors"
- title="Supprimer définitivement"
- >
-
-
-
-
-
-
-
- {'title' in item ? item.title : item.name}
-
-
-
- {daysLeft} JOURS RESTANTS
-
-
- {('deletedAt' in item && item.deletedAt) ? new Date(item.deletedAt).toLocaleDateString() : ''}
-
-
-
-
- {item.itemType === 'note' && 'content' in item ? (
-
- {item.content.replace(/[#*`]/g, '')}
-
- ) : (
-
-
- Contenu du dossier préservé
-
-
- )}
-
- );
- })}
-
-
- ) : (
-
-
-
-
-
-
Corbeille vide
-
- Les éléments que vous supprimez apparaîtront ici. Ils seront conservés pendant 30 jours avant suppression définitive.
-
-
-
- )}
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/settings/AITab.tsx b/architectural-grid12/src/components/settings/AITab.tsx
deleted file mode 100644
index 607c84e..0000000
--- a/architectural-grid12/src/components/settings/AITab.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-import React from 'react';
-import { Sparkles, Edit3, MessageCircle, Languages, Tag, History, FlaskConical } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AISettingCard = ({ icon, title, description, defaultChecked = false }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
-
-
-);
-
-export const AITab: React.FC = () => {
- return (
-
-
-
Configurez vos fonctionnalités IA et préférences
-
-
-
Fonctionnalités IA
-
-
}
- title="Suggestions de titre"
- description="Suggérer des titres pour les notes sans titre après 50+ mots"
- defaultChecked
- />
-
}
- title="IA Note"
- description="Active le bouton de chat IA et les outils d'amélioration du texte"
- defaultChecked
- />
-
}
- title="💡 J'ai remarqué quelque chose..."
- description="Aperçu quotidien de vos notes"
- defaultChecked
- />
-
}
- title="Détection de langue"
- description="Détecte automatiquement la langue de vos notes"
- defaultChecked
- />
-
}
- title="Suggestion des labels"
- description="Suggère et applique des étiquettes automatiquement à vos notes"
- defaultChecked
- />
-
}
- title="Historique des notes"
- description="Active les snapshots de versions et la restauration depuis History"
- defaultChecked
- />
-
-
-
-
- {/* Fréquence */}
-
-
-
Fréquence
-
Fréquence d'analyse des connexions
-
-
-
-
- {/* Mode d'historique */}
-
-
-
Mode d'historique
-
Gestion des snapshots
-
-
-
-
-
-
-
Manuel (bouton commit)
-
Créer des snapshots manuellement
-
-
-
-
-
-
-
Automatique (intelligent)
-
Snapshots automatiques avec détection
-
-
-
-
-
-
- {/* Mode Démo */}
-
-
-
-
-
-
-
- 🧪 Mode Démo
-
-
Accélère Memory Echo pour les tests. Les connexions apparaissent instantanément.
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/settings/AppearanceTab.tsx b/architectural-grid12/src/components/settings/AppearanceTab.tsx
deleted file mode 100644
index ba9ccdf..0000000
--- a/architectural-grid12/src/components/settings/AppearanceTab.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React from 'react';
-import { Palette, Type, LayoutGrid, Maximize } from 'lucide-react';
-import { motion } from 'motion/react';
-
-const AppearanceSelect = ({ icon, title, description, options, defaultValue }: any) => (
-
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
-
-
-
- {options.map((opt: string) => (
- {opt}
- ))}
-
-
-
-
-);
-
-export const AppearanceTab: React.FC = () => {
- return (
-
-
-
Personnaliser l'apparence de l'application
-
-
-
}
- title="Thème"
- description="Sélectionner le mode visuel"
- options={['Clair', 'Sombre', 'Système']}
- defaultValue="Clair"
- />
-
}
- title="Taille de la police"
- description="Ajustez la lisibilité globale de l'interface"
- options={['Petite', 'Moyenne', 'Grande']}
- defaultValue="Moyenne"
- />
-
}
- title="Famille de polices"
- description="La typographie définit l'âme de l'application"
- options={['Inter', 'JetBrains Mono', 'Public Sans', 'Outfit']}
- defaultValue="JetBrains Mono"
- />
-
}
- title="Affichage des notes"
- description="Gestion visuelle de la grille de composition"
- options={['Cartes (grille)', 'Liste', 'Tableau']}
- defaultValue="Cartes (grille)"
- />
-
}
- title="Taille des notes"
- description="Structure de la mise en page des éléments"
- options={['Taille uniforme', 'Variable (Masonry)']}
- defaultValue="Taille uniforme"
- />
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/settings/GeneralTab.tsx b/architectural-grid12/src/components/settings/GeneralTab.tsx
deleted file mode 100644
index 749afbd..0000000
--- a/architectural-grid12/src/components/settings/GeneralTab.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react';
-import { Globe, Bell } from 'lucide-react';
-import { motion } from 'motion/react';
-
-export const GeneralTab: React.FC = () => {
- return (
-
-
-
Paramètres généraux de l'application
-
-
- {/* Langue */}
-
-
-
-
-
-
-
Langue
-
Sélectionner une langue
-
-
-
-
-
- Français
- English
- Español
-
-
-
-
-
- {/* Notifications */}
-
-
-
-
-
-
-
Notifications
-
Gérez vos préférences de notifications
-
-
-
-
-
-
-
Notifications par email
-
Recevoir des notifications importantes par email
-
-
-
-
-
-
-
-
-
-
Notifications bureau
-
Recevoir des notifications dans votre navigateur
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/architectural-grid12/src/components/settings/SettingsHeader.tsx b/architectural-grid12/src/components/settings/SettingsHeader.tsx
deleted file mode 100644
index db56e30..0000000
--- a/architectural-grid12/src/components/settings/SettingsHeader.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import { Settings, Sparkles, Palette, User, Database, Code, Info } from 'lucide-react';
-import { motion } from 'motion/react';
-import { SettingsTab } from '../../types';
-
-interface SettingsHeaderProps {
- activeTab: SettingsTab;
- setActiveTab: (tab: SettingsTab) => void;
-}
-
-export const SettingsHeader: React.FC = ({ activeTab, setActiveTab }) => {
- const tabs = [
- { id: 'general', label: 'Paramètres généraux', icon: },
- { id: 'ai', label: 'Paramètres IA', icon: },
- { id: 'appearance', label: 'Apparence', icon: },
- { id: 'profile', label: 'Profil', icon: },
- { id: 'data', label: 'Gestion des données', icon: },
- { id: 'mcp', label: 'Paramètres MCP', icon: },
- { id: 'about', label: 'À propos', icon: },
- ];
-
- return (
-
- );
-};
diff --git a/architectural-grid12/src/constants.ts b/architectural-grid12/src/constants.ts
deleted file mode 100644
index 8965c08..0000000
--- a/architectural-grid12/src/constants.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Carnet, Note } from './types';
-
-export const CARNETS: Carnet[] = [
- { id: '1', name: 'Daily Notes', initial: 'D', type: 'Private', isPrivate: true },
- { id: '2', name: 'Project: Neo', initial: 'P', type: 'Project' },
- { id: '3', name: 'Shared Docs', initial: 'S', type: 'Shared' },
- { id: '4', name: 'Architecture Research', initial: 'A', type: 'Project' },
- { id: '5', name: 'History of Architecture', initial: 'H', type: 'Project', parentId: '4' },
- { id: '6', name: 'Modernism', initial: 'M', type: 'Project', parentId: '5' },
- { id: '7', name: 'Sustainable Design', initial: 'S', type: 'Project', parentId: '4' },
-];
-
-export const ALL_NOTES: Note[] = [
- {
- id: 'n1',
- carnetId: '4',
- title: 'Grid Systems & Geometry',
- date: 'Oct 26, 2024',
- content: 'Grid Systems are the foundation of cognitive design. We use geometric blocks to define spaces. The repetitive structure creates a sense of order and rhythm in the built environment.',
- imageUrl: 'https://images.unsplash.com/photo-1503387762-592dea58ef23?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't1', label: 'Architecture', type: 'user' },
- { id: 't2', label: 'Systems', type: 'ai' }
- ],
- embedding: [0.1, 0.1]
- },
- {
- id: 'n1-b',
- carnetId: '4',
- title: 'Parametric Grids',
- date: 'Oct 27, 2024',
- content: 'Parametricism allows us to deform traditional grid systems. By using mathematical algorithms, we can create fluid yet structured geometries that respond to environmental data.',
- imageUrl: 'https://images.unsplash.com/photo-1511225070737-5af5ac9a690d?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't1', label: 'Geometry', type: 'user' }],
- embedding: [0.12, 0.08]
- },
- {
- id: 'n2',
- carnetId: '4',
- title: 'Sustainable Materiality',
- date: 'Oct 24, 2024',
- content: 'Exploring cross-laminated timber (CLT) as a sustainable alternative to concrete. Material choice is key to carbon-neutral construction. The warmth of wood contrasts with the coldness of steel.',
- imageUrl: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't3', label: 'Materials', type: 'user' },
- { id: 't4', label: 'Sustainabilty', type: 'ai' }
- ],
- embedding: [0.8, 0.8]
- },
- {
- id: 'n2-b',
- carnetId: '7',
- title: 'Solar Passive Design',
- date: 'Oct 25, 2024',
- content: 'Using orientation to maximize natural heat. Sustainable architecture must prioritize passive systems over active ones. Thermal mass and insulation are critical factors.',
- imageUrl: 'https://images.unsplash.com/photo-1509391366360-fe5bb5843e0c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't4', label: 'Sustainabilty', type: 'user' }],
- embedding: [0.85, 0.75]
- },
- {
- id: 'n3',
- carnetId: '4',
- title: 'Light & Minimalist Space',
- date: 'Oct 22, 2024',
- content: 'Minimalism is about the subtraction of the unnecessary. Light becomes a material in itself. Reflections on glass and white surfaces create depth without clutter.',
- imageUrl: 'https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [
- { id: 't5', label: 'Lighting', type: 'user' },
- { id: 't6', label: 'Atmosphere', type: 'ai' }
- ],
- embedding: [0.2, 0.8]
- },
- {
- id: 'n3-b',
- carnetId: '6',
- title: 'The Glass House Study',
- date: 'Oct 23, 2024',
- content: 'Analyzing the transparency of the Glass House. The boundary between interior and exterior is blurred. A pure expression of modernist ideals and minimal structure.',
- imageUrl: 'https://images.unsplash.com/photo-1464938050520-ef2270bb8ce8?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't6', label: 'Modernism', type: 'user' }],
- embedding: [0.25, 0.85]
- },
- {
- id: 'bridge-1',
- carnetId: '4',
- title: 'Geometric Ecology',
- date: 'Oct 28, 2024',
- content: 'Can we use grid systems to optimize sustainable solar collection? This note bridges the gap between rigid geometry and ecological necessity. Structured sustainability.',
- imageUrl: 'https://images.unsplash.com/photo-1464146072230-91cabc968276?auto=format&fit=crop&q=80&w=800&h=600',
- tags: [{ id: 't1', label: 'Bridge', type: 'ai' }],
- embedding: [0.45, 0.45] // Center point
- }
-];
diff --git a/architectural-grid12/src/index.css b/architectural-grid12/src/index.css
deleted file mode 100644
index 52b4b7c..0000000
--- a/architectural-grid12/src/index.css
+++ /dev/null
@@ -1,98 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap');
-@import "tailwindcss";
-
-@theme {
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
- --font-serif: "Playfair Display", serif;
- --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
-
- /* Foundation */
- --color-paper: #F2F0E9;
- --color-ink: #1C1C1C;
- --color-muted-ink: rgba(28, 28, 28, 0.6);
- --color-border: rgba(28, 28, 28, 0.1);
- --color-concrete: #8D8D8D;
-
- /* Architectural Accents */
- --color-blueprint: #75B2D6;
- --color-slate: #4A4E69;
- --color-ochre: #D4A373;
- --color-sage: #A3B18A;
- --color-rust: #9B2226;
- --color-glass: rgba(255, 255, 255, 0.4);
-
- /* Dark Theme Aliases */
- --color-dark-paper: #0D0D0D;
- --color-dark-ink: #EAEAEA;
- --color-dark-muted: rgba(234, 234, 234, 0.5);
- --color-dark-border: rgba(234, 234, 234, 0.1);
-}
-
-@layer base {
- body {
- @apply bg-paper text-ink font-sans antialiased transition-colors duration-500;
- }
-
- .dark body {
- @apply bg-dark-paper;
- }
-
- .dark {
- --color-paper: #121212;
- --color-ink: #EAEAEA;
- --color-muted-ink: rgba(234, 234, 234, 0.6);
- --color-border: rgba(255, 255, 255, 0.08);
- --color-glass: rgba(0, 0, 0, 0.4);
- --color-concrete: #555555;
- }
-}
-
-.paper-texture {
- background-color: var(--color-paper);
- background-image: url("https://www.transparenttextures.com/patterns/natural-paper.png");
-}
-
-/* Custom Scrollbar - Architectural Minimalist */
-.custom-scrollbar::-webkit-scrollbar {
- width: 3px;
-}
-
-.custom-scrollbar::-webkit-scrollbar-track {
- background: transparent;
-}
-
-.custom-scrollbar::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.08);
- border-radius: 10px;
-}
-
-.custom-scrollbar:hover::-webkit-scrollbar-thumb {
- background: rgba(28, 28, 28, 0.2);
-}
-
-.ai-glass {
- background: rgba(255, 255, 255, 0.85);
- backdrop-filter: blur(20px);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .ai-glass {
- background: rgba(30, 30, 30, 0.85);
- border: 1px solid rgba(255, 255, 255, 0.1);
-}
-
-.sidebar-shadow {
- box-shadow: 1px 0 10px rgba(0, 0, 0, 0.05);
-}
-
-.active-nav-item {
- background: linear-gradient(to right, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.4));
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.5);
-}
-
-.dark .active-nav-item {
- background: rgba(255, 255, 255, 0.08);
- border: 1px solid rgba(255, 255, 255, 0.1);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
-}
diff --git a/architectural-grid12/src/main.tsx b/architectural-grid12/src/main.tsx
deleted file mode 100644
index 080dac3..0000000
--- a/architectural-grid12/src/main.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import {StrictMode} from 'react';
-import {createRoot} from 'react-dom/client';
-import App from './App.tsx';
-import './index.css';
-
-createRoot(document.getElementById('root')!).render(
-
-
- ,
-);
diff --git a/architectural-grid12/src/services/clusteringService.ts b/architectural-grid12/src/services/clusteringService.ts
deleted file mode 100644
index 7be16ef..0000000
--- a/architectural-grid12/src/services/clusteringService.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-
-import { Note, NoteCluster, BridgeNote } from '../types';
-import { cosineSimilarity } from './geminiService';
-
-export function dbscan(notes: Note[], eps: number, minPts: number): number[] {
- const n = notes.length;
- const labels = new Array(n).fill(-1); // -1 = noise, 0+ = cluster id
- let clusterId = 0;
-
- for (let i = 0; i < n; i++) {
- if (labels[i] !== -1) continue;
-
- const neighbors = getNeighbors(i, notes, eps);
-
- if (neighbors.length < minPts) {
- labels[i] = -1; // remains noise for now
- continue;
- }
-
- labels[i] = clusterId;
- const queue = neighbors.filter(idx => idx !== i);
-
- for (let j = 0; j < queue.length; j++) {
- const pIdx = queue[j];
-
- if (labels[pIdx] === -1) {
- labels[pIdx] = clusterId; // noisy point becomes border point
- }
-
- if (labels[pIdx] !== -1 && labels[pIdx] < clusterId) {
- // This should not happen in standard DBSCAN unless we re-visit
- }
-
- if (labels[pIdx] === clusterId && labels[pIdx] !== -1) {
- // Skip if already processed in this cluster
- }
-
- // If it was already labeled, skip re-neighboring
- const pWasNoise = labels[pIdx] === -1;
- if (labels[pIdx] === -1) labels[pIdx] = clusterId;
-
- // If point was not processed
- if (pWasNoise || labels[pIdx] === clusterId ) {
- // This is a simplified queue processing
- }
- }
-
- // Standard DBSCAN expansion
- expandCluster(i, neighbors, labels, clusterId, notes, eps, minPts);
- clusterId++;
- }
-
- return labels;
-}
-
-function expandCluster(pIdx: number, neighbors: number[], labels: number[], clusterId: number, notes: Note[], eps: number, minPts: number) {
- let i = 0;
- while (i < neighbors.length) {
- const qIdx = neighbors[i];
- if (labels[qIdx] === -1) {
- labels[qIdx] = clusterId;
- } else if (labels[qIdx] === undefined || labels[qIdx] === -1) {
- // unreachable
- }
-
- if (labels[qIdx] === clusterId || labels[qIdx] === -1) {
- const qNeighbors = getNeighbors(qIdx, notes, eps);
- if (qNeighbors.length >= minPts) {
- for(const qn of qNeighbors) {
- if (labels[qn] === -1) {
- labels[qn] = clusterId;
- neighbors.push(qn);
- } else if (!labels.hasOwnProperty(qn)) {
- // logic error
- }
- }
- }
- }
- i++;
- }
-}
-
-// Clean DBSCAN implementation
-export function runClustering(notes: Note[], eps: number = 0.15, minPts: number = 2): { labels: number[], clusters: NoteCluster[] } {
- const validNotes = notes.filter(n => n.embedding && n.embedding.length > 0);
- if (validNotes.length === 0) return { labels: [], clusters: [] };
-
- const n = validNotes.length;
- const labels = new Array(n).fill(-1);
- let cId = 0;
-
- for (let i = 0; i < n; i++) {
- if (labels[i] !== -1) continue;
-
- const neighbors = findNeighbors(i, validNotes, eps);
- if (neighbors.length < minPts) {
- labels[i] = -1;
- } else {
- labels[i] = cId;
- expand(i, neighbors, labels, cId, validNotes, eps, minPts);
- cId++;
- }
- }
-
- const clusters: NoteCluster[] = [];
- const colorPalette = ['#F87171', '#60A5FA', '#34D399', '#FBBF24', '#A78BFA', '#F472B6', '#2DD4BF'];
-
- for (let i = 0; i < cId; i++) {
- const noteIds = validNotes.filter((_, idx) => labels[idx] === i).map(n => n.id);
- clusters.push({
- id: `cluster-${i}`,
- name: `Cluster ${i + 1}`,
- noteIds,
- color: colorPalette[i % colorPalette.length]
- });
- }
-
- return { labels, clusters };
-}
-
-function findNeighbors(idx: number, notes: Note[], eps: number): number[] {
- const neighbors: number[] = [];
- const targetEmbedding = notes[idx].embedding!;
- for (let i = 0; i < notes.length; i++) {
- const sim = cosineSimilarity(targetEmbedding, notes[i].embedding!);
- const dist = 1 - sim;
- if (dist <= eps) {
- neighbors.push(i);
- }
- }
- return neighbors;
-}
-
-function expand(rootIdx: number, neighbors: number[], labels: number[], cId: number, notes: Note[], eps: number, minPts: number) {
- const queue = [...neighbors];
- for (let i = 0; i < queue.length; i++) {
- const qIdx = queue[i];
- if (labels[qIdx] === -1) {
- labels[qIdx] = cId;
- }
- if (labels[qIdx] !== -1 && labels[qIdx] !== cId) continue;
- if (labels[qIdx] === cId) {
- // already visited but let's check neighbors if we just added it
- }
-
- // If point was noise, it now belongs to cluster, but we don't necessarily expand from it unless it's a core point
- // This is the standard DBSCAN: noise points can become border points
- }
-
- // Re-implementing correctly
- let head = 0;
- while(head < queue.length) {
- const qIdx = queue[head];
- if (labels[qIdx] === -1) labels[qIdx] = cId;
- if (labels[qIdx] === cId) {
- const qNeighbors = findNeighbors(qIdx, notes, eps);
- if (qNeighbors.length >= minPts) {
- for(const qn of qNeighbors) {
- if (labels[qn] === -1) {
- labels[qn] = cId;
- queue.push(qn);
- }
- }
- }
- }
- head++;
- }
-}
-
-function getNeighbors(idx: number, notes: Note[], eps: number): number[] {
- const neighbors: number[] = [];
- const target = notes[idx].embedding!;
- for (let i = 0; i < notes.length; i++) {
- if (!notes[i].embedding) continue;
- const dist = 1 - cosineSimilarity(target, notes[i].embedding!);
- if (dist <= eps) neighbors.push(i);
- }
- return neighbors;
-}
-
-export function detectBridges(notes: Note[], clusters: NoteCluster[], threshold: number = 0.5): BridgeNote[] {
- const bridges: BridgeNote[] = [];
- const validNotes = notes.filter(n => n.embedding);
-
- for (const note of validNotes) {
- const connectedClusters = new Set();
-
- for (const cluster of clusters) {
- // Check if note has strong links to ANY note in this cluster
- const clusterNotes = notes.filter(n => cluster.noteIds.includes(n.id) && n.embedding);
- const hasStrongLink = clusterNotes.some(cn => cosineSimilarity(note.embedding!, cn.embedding!) > threshold);
-
- if (hasStrongLink) {
- connectedClusters.add(cluster.id);
- }
- }
-
- if (connectedClusters.size >= 2) {
- bridges.push({
- noteId: note.id,
- connectedClusterIds: Array.from(connectedClusters),
- bridgeScore: connectedClusters.size / Math.max(clusters.length, 1)
- });
- }
- }
-
- return bridges.sort((a, b) => b.bridgeScore - a.bridgeScore);
-}
-
-export function calculateCentroid(noteIds: string[], allNotes: Note[]): number[] | undefined {
- const clusterNotes = allNotes.filter(n => noteIds.includes(n.id) && n.embedding);
- if (clusterNotes.length === 0) return undefined;
-
- const embeddingDim = clusterNotes[0].embedding!.length;
- const centroid = new Array(embeddingDim).fill(0);
-
- for (const note of clusterNotes) {
- for (let i = 0; i < embeddingDim; i++) {
- centroid[i] += note.embedding![i];
- }
- }
-
- for (let i = 0; i < embeddingDim; i++) {
- centroid[i] /= clusterNotes.length;
- }
-
- return centroid;
-}
diff --git a/architectural-grid12/src/services/geminiService.ts b/architectural-grid12/src/services/geminiService.ts
deleted file mode 100644
index 08781ab..0000000
--- a/architectural-grid12/src/services/geminiService.ts
+++ /dev/null
@@ -1,200 +0,0 @@
-
-import { GoogleGenAI, Type } from "@google/genai";
-import { BrainstormIdea } from "../types";
-
-const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
-
-const BRAINSTORM_SCHEMA = {
- type: Type.OBJECT,
- properties: {
- ideas: {
- type: Type.ARRAY,
- items: {
- type: Type.OBJECT,
- properties: {
- title: { type: Type.STRING },
- description: { type: Type.STRING },
- connection_to_seed: { type: Type.STRING },
- novelty_score: { type: Type.NUMBER }
- },
- required: ["title", "description", "connection_to_seed", "novelty_score"]
- }
- }
- },
- required: ["ideas"]
-};
-
-const SUGGESTIONS_SCHEMA = {
- type: Type.OBJECT,
- properties: {
- suggestions: {
- type: Type.ARRAY,
- items: {
- type: Type.OBJECT,
- properties: {
- title: { type: Type.STRING },
- description: { type: Type.STRING },
- reasoning: { type: Type.STRING }
- },
- required: ["title", "description", "reasoning"]
- }
- }
- },
- required: ["suggestions"]
-};
-
-export async function generateBrainstormWave(
- seedIdea: string,
- waveNumber: number,
- contextSummaries: string = ""
-): Promise[]> {
- const waveDescriptions = [
- "", // index 0 unused
- "VAGUE 1 (proximité directe) : Sous-aspects, reformulations, variations de l'idée. Reste dans le même domaine.",
- "VAGUE 2 (analogies) : Trouve des parallèles dans d'autres domaines. Comment cette idée se manifeste-t-elle ailleurs ? Quelles techniques d'autres industries pourraient s'appliquer ?",
- "VAGUE 3 (disruption) : Inverse l'idée. Pousse-la à l'extrême. Combine-la avec un domaine totalement non lié. Que se passe-t-il si l'opposé est vrai ?"
- ];
-
- const prompt = `
- Idée seed : "${seedIdea}"
- Contexte : ${contextSummaries}
- Génère 5 idées pour la VAGUE ${waveNumber} : ${waveDescriptions[waveNumber]}
- Format JSON selon le schéma.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: [{ role: "user", parts: [{ text: prompt }] }],
- config: {
- systemInstruction: "Tu es un expert en brainstorming. Réponds uniquement en JSON valide.",
- responseMimeType: "application/json",
- responseSchema: BRAINSTORM_SCHEMA,
- temperature: 1.0
- }
- });
-
- const resText = response.text;
- if (!resText) return [];
-
- const parsed = JSON.parse(resText.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim());
- const ideas = Array.isArray(parsed.ideas) ? parsed.ideas : (Array.isArray(parsed) ? parsed : []);
-
- return ideas.map((item: any) => ({
- title: item.title,
- description: item.description,
- connectionToSeed: item.connection_to_seed,
- noveltyScore: item.novelty_score,
- waveNumber
- }));
- } catch (error) {
- console.error(`Error generating brainstorm wave ${waveNumber}:`, error);
- throw error;
- }
-}
-
-export async function generateExpansion(parentIdeaTitle: string, parentIdeaDescription: string): Promise[]> {
- const prompt = `
- Idée source : "${parentIdeaTitle} - ${parentIdeaDescription}"
- Génère 3 idées d'extension ou de sous-aspects.
- Format JSON.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: [{ role: "user", parts: [{ text: prompt }] }],
- config: {
- systemInstruction: "Tu es un expert en brainstorming. Réponds uniquement en JSON valide.",
- responseMimeType: "application/json",
- responseSchema: BRAINSTORM_SCHEMA,
- temperature: 1.0
- }
- });
-
- const resText = response.text;
- if (!resText) return [];
-
- const parsed = JSON.parse(resText.replace(/^```json\n?/, '').replace(/\n?```$/, '').trim());
- const ideas = Array.isArray(parsed.ideas) ? parsed.ideas : (Array.isArray(parsed) ? parsed : []);
-
- return ideas.map((item: any) => ({
- title: item.title,
- description: item.description,
- connectionToSeed: item.connection_to_seed,
- noveltyScore: item.novelty_score
- }));
- } catch (error) {
- console.error("Error generating expansion:", error);
- throw error;
- }
-}
-
-export async function getEmbedding(text: string): Promise {
- try {
- const result = await ai.models.embedContent({
- model: 'gemini-embedding-2-preview',
- contents: [text],
- });
- return result.embeddings[0].values;
- } catch (error) {
- console.error("Error generating embedding:", error);
- throw error;
- }
-}
-
-export function cosineSimilarity(a: number[], b: number[]): number {
- if (!a || !b || a.length !== b.length) return 0;
- const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
- const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
- const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
- if (magnitudeA === 0 || magnitudeB === 0) return 0;
- return dotProduct / (magnitudeA * magnitudeB);
-}
-
-export async function nameCluster(noteSummaries: string[]): Promise {
- const prompt = `Quel thème commun relie ces notes ? Donne un nom court (2-4 mots).\nNotes :\n${noteSummaries.join('\n- ')}`;
- try {
- const result = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: prompt
- });
- return result.text.trim();
- } catch (error) {
- console.error("Error naming cluster:", error);
- return "Thematic Cluster";
- }
-}
-
-export async function suggestBridgeIdeas(
- clusterAName: string,
- clusterBName: string,
- clusterASummaries: string,
- clusterBSummaries: string
-): Promise {
- const prompt = `
- Cluster A (${clusterAName}) contient des notes sur : ${clusterASummaries}
- Cluster B (${clusterBName}) contient des notes sur : ${clusterBSummaries}
-
- Ces deux clusters ne sont pas connectés. Propose 3 idées
- de "notes pont" qui pourraient créer un lien créatif entre eux.
- Pour chaque idée : titre, description, pourquoi ça connecte les deux.
-
- Format JSON.
- `;
-
- try {
- const response = await ai.models.generateContent({
- model: "gemini-3-flash-preview",
- contents: prompt,
- config: {
- responseMimeType: "application/json",
- responseSchema: SUGGESTIONS_SCHEMA
- }
- });
- return JSON.parse(response.text);
- } catch (error) {
- console.error("Error suggesting bridge ideas:", error);
- return [];
- }
-}
diff --git a/architectural-grid12/src/services/temporalService.ts b/architectural-grid12/src/services/temporalService.ts
deleted file mode 100644
index 9864727..0000000
--- a/architectural-grid12/src/services/temporalService.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { Note, NoteAccessLog, NotePrediction } from '../types';
-
-/**
- * Simulates finding the dominant frequency in access logs for a specific note
- * returning the period in days.
- */
-export function detectAccessCycle(logs: NoteAccessLog[]): number | null {
- if (logs.length < 5) return null;
-
- const accessDays = logs
- .map(log => new Date(log.accessedAt).getTime())
- .sort((a, b) => a - b);
-
- const intervals: number[] = [];
- for (let i = 1; i < accessDays.length; i++) {
- intervals.push((accessDays[i] - accessDays[i - 1]) / (1000 * 60 * 60 * 24));
- }
-
- // Simple heuristic: if intervals are consistently around a value, that's our cycle
- // We'll calculate the median interval
- const sortedIntervals = [...intervals].sort((a, b) => a - b);
- const median = sortedIntervals[Math.floor(sortedIntervals.length / 2)];
-
- // Check if enough intervals are close to median
- const withinThreshold = intervals.filter(v => Math.abs(v - median) < Math.max(2, median * 0.2));
-
- if (withinThreshold.length >= intervals.length * 0.6) {
- return median;
- }
-
- return null;
-}
-
-export function predictNextAccess(note: Note, logs: NoteAccessLog[]): NotePrediction | null {
- const cycleDays = detectAccessCycle(logs);
- if (!cycleDays) return null;
-
- const lastAccess = new Date(logs[logs.length - 1].accessedAt);
- const nextAccessDate = new Date(lastAccess.getTime() + cycleDays * 24 * 60 * 60 * 1000);
-
- const now = new Date();
- const daysUntilNext = (nextAccessDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
-
- // Only predict if it's coming up in the next 2 weeks
- if (daysUntilNext > 0 && daysUntilNext < 14) {
- return {
- noteId: note.id,
- predictedRelevanceDate: nextAccessDate.toISOString(),
- confidence: 0.7,
- reason: `Historical access pattern suggests a ${Math.round(cycleDays)}-day cycle.`,
- generatedAt: now.toISOString()
- };
- }
-
- return null;
-}
-
-export function getCoaccessedNotes(baseNoteId: string, logs: NoteAccessLog[], allNotes: Note[]): Note[] {
- const WINDOW_MS = 30 * 60 * 1000; // 30 minutes
-
- const baseNoteLogs = logs.filter(l => l.noteId === baseNoteId);
- const coaccessedIds = new Set();
-
- baseNoteLogs.forEach(baseLog => {
- const baseTime = new Date(baseLog.accessedAt).getTime();
- logs.forEach(otherLog => {
- if (otherLog.noteId === baseNoteId) return;
- const otherTime = new Date(otherLog.accessedAt).getTime();
- if (Math.abs(baseTime - otherTime) < WINDOW_MS) {
- coaccessedIds.add(otherLog.noteId);
- }
- });
- });
-
- return allNotes.filter(n => coaccessedIds.has(n.id));
-}
diff --git a/architectural-grid12/src/types.ts b/architectural-grid12/src/types.ts
deleted file mode 100644
index 96b3f34..0000000
--- a/architectural-grid12/src/types.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-export type NavigationView = 'notebooks' | 'agents' | 'settings' | 'shared' | 'reminders' | 'trash' | 'brainstorm' | 'insights' | 'temporal';
-export type AITone = 'Professional' | 'Creative' | 'Academic' | 'Casual';
-export type AITab = 'discussion' | 'actions' | 'resources' | 'explore';
-export type SettingsTab = 'general' | 'ai' | 'appearance' | 'profile' | 'data' | 'mcp' | 'about';
-
-export interface Tag {
- id: string;
- label: string;
- type: 'ai' | 'user';
-}
-
-export interface Note {
- id: string;
- carnetId: string;
- title: string;
- content: string;
- imageUrl: string;
- date: string;
- tags: Tag[];
- isPinned?: boolean;
- isDeleted?: boolean;
- deletedAt?: string;
- embedding?: number[];
- clusterId?: string;
-}
-
-export interface NoteCluster {
- id: string;
- name: string;
- noteIds: string[];
- centroid? : number[];
- color: string;
-}
-
-export interface BridgeNote {
- noteId: string;
- connectedClusterIds: string[];
- bridgeScore: number;
-}
-
-export interface ConnectionSuggestion {
- id: string;
- title: string;
- description: string;
- reasoning: string;
- clusterAId: string;
- clusterBId: string;
-}
-
-export interface BrainstormSession {
- id: string;
- seedIdea: string;
- sourceNoteId?: string;
- contextNoteIds?: string[];
- exportedNoteId?: string;
- createdAt: string;
- updatedAt: string;
- userId: string;
-}
-
-export type BrainstormIdeaStatus = 'active' | 'dismissed' | 'converted';
-
-export interface BrainstormIdea {
- id: string;
- sessionId: string;
- waveNumber: 1 | 2 | 3;
- title: string;
- description: string;
- connectionToSeed: string;
- noveltyScore: number; // 1-10
- parentIdeaId?: string;
- convertedToNoteId?: string;
- relatedNoteIds?: string[];
- status: BrainstormIdeaStatus;
- position?: { x: number; y: number };
-}
-
-export interface Carnet {
- id: string;
- name: string;
- initial: string;
- type: 'Private' | 'Project' | 'Shared';
- isPrivate?: boolean;
- parentId?: string;
- isDeleted?: boolean;
- deletedAt?: string;
-}
-
-export interface NoteAccessLog {
- noteId: string;
- accessedAt: string;
- action: 'view' | 'edit' | 'search_hit';
-}
-
-export interface NotePrediction {
- noteId: string;
- predictedRelevanceDate: string;
- confidence: number;
- reason: string;
- generatedAt: string;
-}
-
diff --git a/architectural-grid12/tsconfig.json b/architectural-grid12/tsconfig.json
deleted file mode 100644
index d88f175..0000000
--- a/architectural-grid12/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2022",
- "experimentalDecorators": true,
- "useDefineForClassFields": false,
- "module": "ESNext",
- "lib": [
- "ES2022",
- "DOM",
- "DOM.Iterable"
- ],
- "skipLibCheck": true,
- "moduleResolution": "bundler",
- "isolatedModules": true,
- "moduleDetection": "force",
- "allowJs": true,
- "jsx": "react-jsx",
- "paths": {
- "@/*": [
- "./*"
- ]
- },
- "allowImportingTsExtensions": true,
- "noEmit": true
- }
-}
diff --git a/architectural-grid12/vite.config.ts b/architectural-grid12/vite.config.ts
deleted file mode 100644
index 0506f1b..0000000
--- a/architectural-grid12/vite.config.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import tailwindcss from '@tailwindcss/vite';
-import react from '@vitejs/plugin-react';
-import path from 'path';
-import {defineConfig, loadEnv} from 'vite';
-
-export default defineConfig(({mode}) => {
- const env = loadEnv(mode, '.', '');
- return {
- plugins: [react(), tailwindcss()],
- define: {
- 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
- },
- resolve: {
- alias: {
- '@': path.resolve(__dirname, '.'),
- },
- },
- server: {
- // HMR is disabled in AI Studio via DISABLE_HMR env var.
- // Do not modifyâfile watching is disabled to prevent flickering during agent edits.
- hmr: process.env.DISABLE_HMR !== 'true',
- },
- };
-});
diff --git a/architectural-grid14/.env.example b/architectural-grid14/.env.example
deleted file mode 100644
index 7a550fe..0000000
--- a/architectural-grid14/.env.example
+++ /dev/null
@@ -1,9 +0,0 @@
-# GEMINI_API_KEY: Required for Gemini AI API calls.
-# AI Studio automatically injects this at runtime from user secrets.
-# Users configure this via the Secrets panel in the AI Studio UI.
-GEMINI_API_KEY="MY_GEMINI_API_KEY"
-
-# APP_URL: The URL where this applet is hosted.
-# AI Studio automatically injects this at runtime with the Cloud Run service URL.
-# Used for self-referential links, OAuth callbacks, and API endpoints.
-APP_URL="MY_APP_URL"
diff --git a/architectural-grid14/.gitignore b/architectural-grid14/.gitignore
deleted file mode 100644
index 5a86d2a..0000000
--- a/architectural-grid14/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-node_modules/
-build/
-dist/
-coverage/
-.DS_Store
-*.log
-.env*
-!.env.example
diff --git a/architectural-grid14/BRAINSTORM_PROMPT.md b/architectural-grid14/BRAINSTORM_PROMPT.md
deleted file mode 100644
index dfb73b8..0000000
--- a/architectural-grid14/BRAINSTORM_PROMPT.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# IA Agent Coordination Prompt: Brainstorm Wave Integration
-
-## Context
-You are tasked with continuing the development of the "Architectural Grid" application. The core feature "Wave Brainstorming" has been partially implemented with a full-stack architecture (Express + React).
-
-## Current State
-- **Backend (`server.ts`)**: Implements session management, idea generation via Gemini, and expansion logic. Stores data in memory.
-- **Frontend (`BrainstormView.tsx`)**: Manages the life cycle of a brainstorm. Integrates with a Radial D3 Canvas.
-- **Visuals (`WaveCanvas.tsx`)**: Implements a radial force-directed graph with state-aware styling (dismissed/converted).
-- **Navigation**: "Brainstorm Wave" is accessible from the Sidebar. A quick entry point exists from Note Detail view.
-
-## Your Task: Sidebar & Navigation Cleanup
-1. **Source Code Review**: Read `src/components/Sidebar.tsx`, `src/App.tsx`, and `server.ts` to understand how views are toggled.
-2. **Sidebar Links**: Ensure "Brainstorm Wave", "Semantic Network", and "Temporal Forecast" are correctly grouped and labeled in the Sidebar under a "Creative & AI" section.
-3. **Agent View Sidebar**: The user specifically requested these links to be also accessible from the "Sidebar of the Agent view". Review `src/components/AgentsView.tsx` and ensure it has consistent navigation or deep links to these advanced features.
-4. **Semantic Network & Temporal Forecast**: These views are currently placeholders. Ensure the routing and sidebar active state detection work correctly for them.
-
-## Technical Requirements
-- Maintain consistency with the **Tailwind** architectural design (concrete, paper, blueprint tokens).
-- Use **Lucide-React** icons (`Wind` for Brainstorm, `Share2` for Semantic Network, `Clock` for Temporal).
-- Ensure transitions between views are smooth using `motion/react`.
-
----
-*Copy and paste this into the next AI Agent session to ensure full context transfer.*
diff --git a/architectural-grid14/README.md b/architectural-grid14/README.md
deleted file mode 100644
index 0078184..0000000
--- a/architectural-grid14/README.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-# Run and deploy your AI Studio app
-
-This contains everything you need to run your app locally.
-
-View your app in AI Studio: https://ai.studio/apps/b7b577c6-4d9f-44ac-8fe1-85bc3c6d6e66
-
-## Run Locally
-
-**Prerequisites:** Node.js
-
-
-1. Install dependencies:
- `npm install`
-2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
-3. Run the app:
- `npm run dev`
diff --git a/architectural-grid14/index.html b/architectural-grid14/index.html
deleted file mode 100644
index 21dfe69..0000000
--- a/architectural-grid14/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- My Google AI Studio App
-
-
-
-
-
-
-
diff --git a/architectural-grid14/metadata.json b/architectural-grid14/metadata.json
deleted file mode 100644
index e131638..0000000
--- a/architectural-grid14/metadata.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Architectural Grid",
- "description": "A minimalist notebook for architectural research and conceptual sketches, featuring a Wave Brainstorming radial canvas for AI-powered idea exploration.",
- "requestFramePermissions": [],
- "majorCapabilities": []
-}
diff --git a/architectural-grid14/package-lock.json b/architectural-grid14/package-lock.json
deleted file mode 100644
index dab57bd..0000000
--- a/architectural-grid14/package-lock.json
+++ /dev/null
@@ -1,5508 +0,0 @@
-{
- "name": "react-example",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "react-example",
- "version": "0.0.0",
- "dependencies": {
- "@google/genai": "^1.29.0",
- "@tailwindcss/vite": "^4.1.14",
- "@types/d3": "^7.4.3",
- "@types/uuid": "^10.0.0",
- "@types/ws": "^8.18.1",
- "@vitejs/plugin-react": "^5.0.4",
- "d3": "^7.9.0",
- "dotenv": "^17.2.3",
- "esbuild": "^0.28.0",
- "express": "^4.21.2",
- "lucide-react": "^0.546.0",
- "motion": "^12.23.24",
- "react": "^19.0.1",
- "react-dom": "^19.0.1",
- "uuid": "^14.0.0",
- "vite": "^6.2.3",
- "ws": "^8.20.1"
- },
- "devDependencies": {
- "@types/express": "^4.17.21",
- "@types/node": "^22.14.0",
- "autoprefixer": "^10.4.21",
- "tailwindcss": "^4.1.14",
- "tsx": "^4.21.0",
- "typescript": "~5.8.2",
- "vite": "^6.2.3"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
- "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
- "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
- "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/remapping": "^2.3.5",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
- "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
- "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.2",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
- "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
- "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.0"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
- "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
- "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
- "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
- "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
- "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
- "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
- "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
- "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
- "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
- "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
- "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
- "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
- "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
- "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
- "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
- "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
- "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
- "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
- "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
- "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
- "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
- "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
- "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
- "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
- "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
- "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
- "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
- "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@google/genai": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz",
- "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "google-auth-library": "^10.3.0",
- "p-retry": "^4.6.2",
- "protobufjs": "^7.5.4",
- "ws": "^8.18.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@modelcontextprotocol/sdk": "^1.25.2"
- },
- "peerDependenciesMeta": {
- "@modelcontextprotocol/sdk": {
- "optional": true
- }
- }
- },
- "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==",
- "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==",
- "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==",
- "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==",
- "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==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@protobufjs/aspromise": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
- "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/base64": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
- "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/codegen": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
- "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/eventemitter": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
- "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/fetch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
- "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.1",
- "@protobufjs/inquire": "^1.1.0"
- }
- },
- "node_modules/@protobufjs/float": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
- "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/inquire": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz",
- "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/path": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
- "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/pool": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
- "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@protobufjs/utf8": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
- "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
- "license": "BSD-3-Clause"
- },
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.3",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
- "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
- "license": "MIT"
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz",
- "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz",
- "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz",
- "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz",
- "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz",
- "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz",
- "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz",
- "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz",
- "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz",
- "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz",
- "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz",
- "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz",
- "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz",
- "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz",
- "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz",
- "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz",
- "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz",
- "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz",
- "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz",
- "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz",
- "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
- },
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz",
- "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz",
- "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz",
- "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz",
- "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz",
- "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz",
- "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.21.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.32.0",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.3.0"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz",
- "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==",
- "license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.3.0",
- "@tailwindcss/oxide-darwin-arm64": "4.3.0",
- "@tailwindcss/oxide-darwin-x64": "4.3.0",
- "@tailwindcss/oxide-freebsd-x64": "4.3.0",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0",
- "@tailwindcss/oxide-linux-arm64-musl": "4.3.0",
- "@tailwindcss/oxide-linux-x64-gnu": "4.3.0",
- "@tailwindcss/oxide-linux-x64-musl": "4.3.0",
- "@tailwindcss/oxide-wasm32-wasi": "4.3.0",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0",
- "@tailwindcss/oxide-win32-x64-msvc": "4.3.0"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz",
- "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz",
- "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz",
- "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz",
- "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz",
- "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz",
- "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz",
- "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz",
- "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz",
- "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz",
- "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.10.0",
- "@emnapi/runtime": "^1.10.0",
- "@emnapi/wasi-threads": "^1.2.1",
- "@napi-rs/wasm-runtime": "^1.1.4",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz",
- "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz",
- "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 20"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz",
- "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.3.0",
- "@tailwindcss/oxide": "4.3.0",
- "tailwindcss": "4.3.0"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- }
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.6",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
- "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/d3": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
- "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-array": "*",
- "@types/d3-axis": "*",
- "@types/d3-brush": "*",
- "@types/d3-chord": "*",
- "@types/d3-color": "*",
- "@types/d3-contour": "*",
- "@types/d3-delaunay": "*",
- "@types/d3-dispatch": "*",
- "@types/d3-drag": "*",
- "@types/d3-dsv": "*",
- "@types/d3-ease": "*",
- "@types/d3-fetch": "*",
- "@types/d3-force": "*",
- "@types/d3-format": "*",
- "@types/d3-geo": "*",
- "@types/d3-hierarchy": "*",
- "@types/d3-interpolate": "*",
- "@types/d3-path": "*",
- "@types/d3-polygon": "*",
- "@types/d3-quadtree": "*",
- "@types/d3-random": "*",
- "@types/d3-scale": "*",
- "@types/d3-scale-chromatic": "*",
- "@types/d3-selection": "*",
- "@types/d3-shape": "*",
- "@types/d3-time": "*",
- "@types/d3-time-format": "*",
- "@types/d3-timer": "*",
- "@types/d3-transition": "*",
- "@types/d3-zoom": "*"
- }
- },
- "node_modules/@types/d3-array": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
- "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-axis": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz",
- "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-brush": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz",
- "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-chord": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz",
- "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-color": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
- "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
- "license": "MIT"
- },
- "node_modules/@types/d3-contour": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz",
- "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-array": "*",
- "@types/geojson": "*"
- }
- },
- "node_modules/@types/d3-delaunay": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
- "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-dispatch": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz",
- "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-drag": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
- "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-dsv": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz",
- "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-ease": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
- "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-fetch": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz",
- "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-dsv": "*"
- }
- },
- "node_modules/@types/d3-force": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
- "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-format": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz",
- "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-geo": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz",
- "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==",
- "license": "MIT",
- "dependencies": {
- "@types/geojson": "*"
- }
- },
- "node_modules/@types/d3-hierarchy": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz",
- "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-interpolate": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
- "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-color": "*"
- }
- },
- "node_modules/@types/d3-path": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
- "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-polygon": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz",
- "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==",
- "license": "MIT"
- },
- "node_modules/@types/d3-quadtree": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz",
- "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-random": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz",
- "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==",
- "license": "MIT"
- },
- "node_modules/@types/d3-scale": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
- "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-time": "*"
- }
- },
- "node_modules/@types/d3-scale-chromatic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
- "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==",
- "license": "MIT"
- },
- "node_modules/@types/d3-selection": {
- "version": "3.0.11",
- "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
- "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
- "license": "MIT"
- },
- "node_modules/@types/d3-shape": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
- "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-path": "*"
- }
- },
- "node_modules/@types/d3-time": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
- "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
- "license": "MIT"
- },
- "node_modules/@types/d3-time-format": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz",
- "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==",
- "license": "MIT"
- },
- "node_modules/@types/d3-timer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
- "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
- "license": "MIT"
- },
- "node_modules/@types/d3-transition": {
- "version": "3.0.9",
- "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
- "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/d3-zoom": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
- "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
- "license": "MIT",
- "dependencies": {
- "@types/d3-interpolate": "*",
- "@types/d3-selection": "*"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "license": "MIT"
- },
- "node_modules/@types/express": {
- "version": "4.17.25",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
- "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.33",
- "@types/qs": "*",
- "@types/serve-static": "^1"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "4.19.8",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
- "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/geojson": {
- "version": "7946.0.16",
- "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
- "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
- "license": "MIT"
- },
- "node_modules/@types/http-errors": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
- "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/mime": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
- "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "22.19.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz",
- "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/@types/qs": {
- "version": "6.15.1",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz",
- "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
- "license": "MIT"
- },
- "node_modules/@types/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
- "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/serve-static": {
- "version": "1.15.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
- "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/http-errors": "*",
- "@types/node": "*",
- "@types/send": "<1"
- }
- },
- "node_modules/@types/serve-static/node_modules/@types/send": {
- "version": "0.17.6",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
- "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/mime": "^1",
- "@types/node": "*"
- }
- },
- "node_modules/@types/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
- "license": "MIT"
- },
- "node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
- "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.29.0",
- "@babel/plugin-transform-react-jsx-self": "^7.27.1",
- "@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-rc.3",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.18.0"
- },
- "engines": {
- "node": "^20.19.0 || >=22.12.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
- "node_modules/autoprefixer": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
- "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.2",
- "caniuse-lite": "^1.0.30001787",
- "fraction.js": "^5.3.4",
- "picocolors": "^1.1.1",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.29",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz",
- "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==",
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/bignumber.js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
- "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/body-parser": {
- "version": "1.20.5",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
- "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "~1.2.0",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "on-finished": "~2.4.1",
- "qs": "~6.15.1",
- "raw-body": "~2.5.3",
- "type-is": "~1.6.18",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/body-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/body-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/browserslist": {
- "version": "4.28.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
- "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.10.12",
- "caniuse-lite": "^1.0.30001782",
- "electron-to-chromium": "^1.5.328",
- "node-releases": "^2.0.36",
- "update-browserslist-db": "^1.2.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001792",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz",
- "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==",
- "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/commander": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
- "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
- "license": "MIT"
- },
- "node_modules/d3": {
- "version": "7.9.0",
- "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
- "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "3",
- "d3-axis": "3",
- "d3-brush": "3",
- "d3-chord": "3",
- "d3-color": "3",
- "d3-contour": "4",
- "d3-delaunay": "6",
- "d3-dispatch": "3",
- "d3-drag": "3",
- "d3-dsv": "3",
- "d3-ease": "3",
- "d3-fetch": "3",
- "d3-force": "3",
- "d3-format": "3",
- "d3-geo": "3",
- "d3-hierarchy": "3",
- "d3-interpolate": "3",
- "d3-path": "3",
- "d3-polygon": "3",
- "d3-quadtree": "3",
- "d3-random": "3",
- "d3-scale": "4",
- "d3-scale-chromatic": "3",
- "d3-selection": "3",
- "d3-shape": "3",
- "d3-time": "3",
- "d3-time-format": "4",
- "d3-timer": "3",
- "d3-transition": "3",
- "d3-zoom": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "license": "ISC",
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-axis": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
- "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-brush": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
- "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "3",
- "d3-transition": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-chord": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
- "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
- "license": "ISC",
- "dependencies": {
- "d3-path": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-contour": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
- "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "^3.2.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-delaunay": {
- "version": "6.0.4",
- "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
- "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
- "license": "ISC",
- "dependencies": {
- "delaunator": "5"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dispatch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
- "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-drag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
- "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-selection": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
- "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
- "license": "ISC",
- "dependencies": {
- "commander": "7",
- "iconv-lite": "0.6",
- "rw": "1"
- },
- "bin": {
- "csv2json": "bin/dsv2json.js",
- "csv2tsv": "bin/dsv2dsv.js",
- "dsv2dsv": "bin/dsv2dsv.js",
- "dsv2json": "bin/dsv2json.js",
- "json2csv": "bin/json2dsv.js",
- "json2dsv": "bin/json2dsv.js",
- "json2tsv": "bin/json2dsv.js",
- "tsv2csv": "bin/dsv2dsv.js",
- "tsv2json": "bin/dsv2json.js"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv/node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-fetch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
- "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
- "license": "ISC",
- "dependencies": {
- "d3-dsv": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-force": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
- "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-quadtree": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
- "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-geo": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
- "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.5.0 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-hierarchy": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
- "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
- "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-polygon": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
- "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-quadtree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
- "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-random": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
- "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale-chromatic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
- "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-interpolate": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-selection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
- "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-shape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
- "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
- "license": "ISC",
- "dependencies": {
- "d3-path": "^3.1.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "license": "ISC",
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "license": "ISC",
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-transition": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
- "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
- "license": "ISC",
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-dispatch": "1 - 3",
- "d3-ease": "1 - 3",
- "d3-interpolate": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "d3-selection": "2 - 3"
- }
- },
- "node_modules/d3-zoom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
- "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
- "license": "ISC",
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "2 - 3",
- "d3-transition": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/delaunator": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz",
- "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==",
- "license": "ISC",
- "dependencies": {
- "robust-predicates": "^3.0.2"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "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==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dotenv": {
- "version": "17.4.2",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
- "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.354",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.354.tgz",
- "integrity": "sha512-JaBHwWcfIdmSAfWM5l3uwjGd431j8YEMikZ+K/2nXVuBqJKyZ0f+2h4n4JY5AyNiZmnY9qQr2RU3v9DxDmHMNg==",
- "license": "ISC"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.21.3",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz",
- "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/esbuild": {
- "version": "0.28.0",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
- "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.0",
- "@esbuild/android-arm": "0.28.0",
- "@esbuild/android-arm64": "0.28.0",
- "@esbuild/android-x64": "0.28.0",
- "@esbuild/darwin-arm64": "0.28.0",
- "@esbuild/darwin-x64": "0.28.0",
- "@esbuild/freebsd-arm64": "0.28.0",
- "@esbuild/freebsd-x64": "0.28.0",
- "@esbuild/linux-arm": "0.28.0",
- "@esbuild/linux-arm64": "0.28.0",
- "@esbuild/linux-ia32": "0.28.0",
- "@esbuild/linux-loong64": "0.28.0",
- "@esbuild/linux-mips64el": "0.28.0",
- "@esbuild/linux-ppc64": "0.28.0",
- "@esbuild/linux-riscv64": "0.28.0",
- "@esbuild/linux-s390x": "0.28.0",
- "@esbuild/linux-x64": "0.28.0",
- "@esbuild/netbsd-arm64": "0.28.0",
- "@esbuild/netbsd-x64": "0.28.0",
- "@esbuild/openbsd-arm64": "0.28.0",
- "@esbuild/openbsd-x64": "0.28.0",
- "@esbuild/openharmony-arm64": "0.28.0",
- "@esbuild/sunos-x64": "0.28.0",
- "@esbuild/win32-arm64": "0.28.0",
- "@esbuild/win32-ia32": "0.28.0",
- "@esbuild/win32-x64": "0.28.0"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.22.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
- "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "~1.20.5",
- "content-disposition": "~0.5.4",
- "content-type": "~1.0.4",
- "cookie": "~0.7.1",
- "cookie-signature": "~1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.3.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "~0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "~6.15.1",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "~0.19.0",
- "serve-static": "~1.16.2",
- "setprototypeof": "1.2.0",
- "statuses": "~2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/express/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
- "engines": {
- "node": "^12.20 || >= 14.13"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
- "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "~2.0.2",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/finalhandler/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "license": "MIT",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
- "engines": {
- "node": ">=12.20.0"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fraction.js": {
- "version": "5.3.4",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
- "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/rawify"
- }
- },
- "node_modules/framer-motion": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
- "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==",
- "license": "MIT",
- "dependencies": {
- "motion-dom": "^12.38.0",
- "motion-utils": "^12.36.0",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "@emotion/is-prop-valid": "*",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@emotion/is-prop-valid": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gaxios": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
- "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
- "license": "Apache-2.0",
- "dependencies": {
- "extend": "^3.0.2",
- "https-proxy-agent": "^7.0.1",
- "node-fetch": "^3.3.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gcp-metadata": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
- "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
- "license": "Apache-2.0",
- "dependencies": {
- "gaxios": "^7.0.0",
- "google-logging-utils": "^1.0.0",
- "json-bigint": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/get-tsconfig": {
- "version": "4.14.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
- "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/google-auth-library": {
- "version": "10.6.2",
- "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
- "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
- "license": "Apache-2.0",
- "dependencies": {
- "base64-js": "^1.3.0",
- "ecdsa-sig-formatter": "^1.0.11",
- "gaxios": "^7.1.4",
- "gcp-metadata": "8.1.2",
- "google-logging-utils": "1.1.3",
- "jws": "^4.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/google-logging-utils": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
- "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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==",
- "license": "ISC"
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
- "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/jiti": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
- "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "license": "MIT"
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-bigint": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
- "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
- "license": "MIT",
- "dependencies": {
- "bignumber.js": "^9.0.0"
- }
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
- "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "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"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/long": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
- "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
- "license": "Apache-2.0"
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/lucide-react": {
- "version": "0.546.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz",
- "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==",
- "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==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/motion": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz",
- "integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==",
- "license": "MIT",
- "dependencies": {
- "framer-motion": "^12.38.0",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "@emotion/is-prop-valid": "*",
- "react": "^18.0.0 || ^19.0.0",
- "react-dom": "^18.0.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@emotion/is-prop-valid": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/motion-dom": {
- "version": "12.38.0",
- "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz",
- "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==",
- "license": "MIT",
- "dependencies": {
- "motion-utils": "^12.36.0"
- }
- },
- "node_modules/motion-utils": {
- "version": "12.36.0",
- "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
- "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==",
- "license": "MIT"
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.12",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
- "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "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/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
- "license": "MIT",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.44",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz",
- "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==",
- "license": "MIT"
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/p-retry": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
- "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
- "license": "MIT",
- "dependencies": {
- "@types/retry": "0.12.0",
- "retry": "^0.13.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
- "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
- "license": "MIT"
- },
- "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/picomatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
- "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
- "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
- "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/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/protobufjs": {
- "version": "7.5.8",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.8.tgz",
- "integrity": "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@protobufjs/aspromise": "^1.1.2",
- "@protobufjs/base64": "^1.1.2",
- "@protobufjs/codegen": "^2.0.5",
- "@protobufjs/eventemitter": "^1.1.0",
- "@protobufjs/fetch": "^1.1.0",
- "@protobufjs/float": "^1.0.2",
- "@protobufjs/inquire": "^1.1.1",
- "@protobufjs/path": "^1.1.2",
- "@protobufjs/pool": "^1.1.0",
- "@protobufjs/utf8": "^1.1.1",
- "@types/node": ">=13.7.0",
- "long": "^5.0.0"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/qs": {
- "version": "6.15.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
- "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
- "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/react": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz",
- "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.6",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
- "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.6"
- }
- },
- "node_modules/react-refresh": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
- "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
- "devOptional": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
- }
- },
- "node_modules/retry": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
- "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/robust-predicates": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",
- "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==",
- "license": "Unlicense"
- },
- "node_modules/rollup": {
- "version": "4.60.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz",
- "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.60.3",
- "@rollup/rollup-android-arm64": "4.60.3",
- "@rollup/rollup-darwin-arm64": "4.60.3",
- "@rollup/rollup-darwin-x64": "4.60.3",
- "@rollup/rollup-freebsd-arm64": "4.60.3",
- "@rollup/rollup-freebsd-x64": "4.60.3",
- "@rollup/rollup-linux-arm-gnueabihf": "4.60.3",
- "@rollup/rollup-linux-arm-musleabihf": "4.60.3",
- "@rollup/rollup-linux-arm64-gnu": "4.60.3",
- "@rollup/rollup-linux-arm64-musl": "4.60.3",
- "@rollup/rollup-linux-loong64-gnu": "4.60.3",
- "@rollup/rollup-linux-loong64-musl": "4.60.3",
- "@rollup/rollup-linux-ppc64-gnu": "4.60.3",
- "@rollup/rollup-linux-ppc64-musl": "4.60.3",
- "@rollup/rollup-linux-riscv64-gnu": "4.60.3",
- "@rollup/rollup-linux-riscv64-musl": "4.60.3",
- "@rollup/rollup-linux-s390x-gnu": "4.60.3",
- "@rollup/rollup-linux-x64-gnu": "4.60.3",
- "@rollup/rollup-linux-x64-musl": "4.60.3",
- "@rollup/rollup-openbsd-x64": "4.60.3",
- "@rollup/rollup-openharmony-arm64": "4.60.3",
- "@rollup/rollup-win32-arm64-msvc": "4.60.3",
- "@rollup/rollup-win32-ia32-msvc": "4.60.3",
- "@rollup/rollup-win32-x64-gnu": "4.60.3",
- "@rollup/rollup-win32-x64-msvc": "4.60.3",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/rw": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
- "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
- "node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/send": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
- "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.1",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "~2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "~2.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/send/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/serve-static": {
- "version": "1.16.3",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
- "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "~0.19.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
- "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz",
- "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
- "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.16",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
- "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "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/tsx": {
- "version": "4.21.0",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
- "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.27.0",
- "get-tsconfig": "^4.7.5"
- },
- "bin": {
- "tsx": "dist/cli.mjs"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
- "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
- "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
- "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
- "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
- "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
- "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
- "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
- "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
- "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
- "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
- "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
- "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
- "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
- "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
- "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
- "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
- "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
- "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
- "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
- "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
- "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
- "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
- "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
- "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-x64": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
- "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tsx/node_modules/esbuild": {
- "version": "0.27.7",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
- "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
- "devOptional": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.7",
- "@esbuild/android-arm": "0.27.7",
- "@esbuild/android-arm64": "0.27.7",
- "@esbuild/android-x64": "0.27.7",
- "@esbuild/darwin-arm64": "0.27.7",
- "@esbuild/darwin-x64": "0.27.7",
- "@esbuild/freebsd-arm64": "0.27.7",
- "@esbuild/freebsd-x64": "0.27.7",
- "@esbuild/linux-arm": "0.27.7",
- "@esbuild/linux-arm64": "0.27.7",
- "@esbuild/linux-ia32": "0.27.7",
- "@esbuild/linux-loong64": "0.27.7",
- "@esbuild/linux-mips64el": "0.27.7",
- "@esbuild/linux-ppc64": "0.27.7",
- "@esbuild/linux-riscv64": "0.27.7",
- "@esbuild/linux-s390x": "0.27.7",
- "@esbuild/linux-x64": "0.27.7",
- "@esbuild/netbsd-arm64": "0.27.7",
- "@esbuild/netbsd-x64": "0.27.7",
- "@esbuild/openbsd-arm64": "0.27.7",
- "@esbuild/openbsd-x64": "0.27.7",
- "@esbuild/openharmony-arm64": "0.27.7",
- "@esbuild/sunos-x64": "0.27.7",
- "@esbuild/win32-arm64": "0.27.7",
- "@esbuild/win32-ia32": "0.27.7",
- "@esbuild/win32-x64": "0.27.7"
- }
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "license": "MIT"
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
- "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/uuid": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz",
- "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist-node/bin/uuid"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/vite": {
- "version": "6.4.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz",
- "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.25.0",
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "jiti": ">=1.21.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/vite/node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
- }
- },
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/ws": {
- "version": "8.20.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
- "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "license": "ISC"
- }
- }
-}
diff --git a/architectural-grid14/package.json b/architectural-grid14/package.json
deleted file mode 100644
index 87ebc6f..0000000
--- a/architectural-grid14/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "name": "react-example",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "tsx server.ts",
- "build": "vite build && esbuild server.ts --bundle --platform=node --format=cjs --packages=external --sourcemap --outfile=dist/server.cjs",
- "start": "node dist/server.cjs",
- "clean": "rm -rf dist",
- "lint": "tsc --noEmit"
- },
- "dependencies": {
- "@google/genai": "^1.29.0",
- "@tailwindcss/vite": "^4.1.14",
- "@types/d3": "^7.4.3",
- "@types/uuid": "^10.0.0",
- "@types/ws": "^8.18.1",
- "@vitejs/plugin-react": "^5.0.4",
- "d3": "^7.9.0",
- "dotenv": "^17.2.3",
- "esbuild": "^0.28.0",
- "express": "^4.21.2",
- "lucide-react": "^0.546.0",
- "motion": "^12.23.24",
- "react": "^19.0.1",
- "react-dom": "^19.0.1",
- "uuid": "^14.0.0",
- "vite": "^6.2.3",
- "ws": "^8.20.1"
- },
- "devDependencies": {
- "@types/express": "^4.17.21",
- "@types/node": "^22.14.0",
- "autoprefixer": "^10.4.21",
- "tailwindcss": "^4.1.14",
- "tsx": "^4.21.0",
- "typescript": "~5.8.2",
- "vite": "^6.2.3"
- }
-}
diff --git a/architectural-grid14/src/App.tsx b/architectural-grid14/src/App.tsx
deleted file mode 100644
index 2a30191..0000000
--- a/architectural-grid14/src/App.tsx
+++ /dev/null
@@ -1,619 +0,0 @@
-/**
- * @license
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React, { useState, useMemo } from 'react';
-import { motion, AnimatePresence } from 'motion/react';
-
-// Components
-import { Sidebar } from './components/Sidebar';
-import { NotebooksView } from './components/NotebooksView';
-import { AgentsView } from './components/AgentsView';
-import { SettingsView } from './components/SettingsView';
-import { TrashView } from './components/TrashView';
-import { BrainstormView } from './components/BrainstormView/BrainstormView';
-import { InsightsView } from './components/InsightsView';
-import { TemporalView } from './components/TemporalView';
-import { AISidebar } from './components/AISidebar';
-import { SlashMenu } from './components/SlashMenu';
-
-// Data & Types
-import { CARNETS, ALL_NOTES } from './constants';
-import { NavigationView, SettingsTab, AITab, AITone, Carnet, Note, BrainstormIdea, NoteAccessLog } from './types';
-
-export default function App() {
- const [activeView, setActiveView] = useState('notebooks');
- const [activeSettingsTab, setActiveSettingsTab] = useState('general');
- const [selectedAgentId, setSelectedAgentId] = useState(null);
- const [isDarkMode, setIsDarkMode] = useState(false);
- const [carnets, setCarnets] = useState(CARNETS);
- const [notes, setNotes] = useState(ALL_NOTES);
- const [accessLogs, setAccessLogs] = useState([
- // Note n1: 14-day cycle
- { noteId: 'n1', accessedAt: new Date(Date.now() - 70 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 56 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 42 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n1', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n2: 7-day cycle
- { noteId: 'n2', accessedAt: new Date(Date.now() - 35 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 21 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n2', accessedAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
-
- // Note n3: 3-day cycle (frequent check)
- { noteId: 'n3', accessedAt: new Date(Date.now() - 12 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 9 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- { noteId: 'n3', accessedAt: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(), action: 'view' },
- ]);
-
- const logNoteAccess = (noteId: string, action: 'view' | 'edit' | 'search_hit' = 'view') => {
- const newLog: NoteAccessLog = {
- noteId,
- accessedAt: new Date().toISOString(),
- action
- };
- setAccessLogs(prev => [...prev, newLog]);
- };
-
- const [activeCarnetId, setActiveCarnetId] = useState('4');
- const [activeNoteId, setActiveNoteId] = useState(null);
- const [brainstormSeed, setBrainstormSeed] = useState