commit a9460556e458f4dda45649a10cf38a7fb9da35d5 Author: techjarves Date: Thu Jun 4 09:15:28 2026 +0530 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35a19d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Ignore large Stable Diffusion model weights (exceeds GitHub file limits) +app/models/*.safetensors +app/models/*.gguf +app/models/*.ckpt +app/models +app/outputs/ + +# Ignore portable Node.js binaries and packages +app/tools/ +**/node_modules/ +node_modules/ + +# Ignore backend folder completely (contains massive DLLs, EXEs, and ZIPs >1GB) +app/backend/ + +# Ignore local IDE and OS temp files +.vscode/ +.idea/ +.DS_Store +Thumbs.db +*.log +*.tmp + + + +# output images folder +/app/outputs \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..606d29a --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +
+ +# Local AI Image Generator + +### A fully self-contained, offline-first AI Art Studio for Windows + + + + + +
+ +## 📖 Overview + +**Local AI Image Generator** is a packaged, production-grade desktop environment designed to run Stable Diffusion models natively on Windows with maximum performance and zero installation complexity. + +Say goodbye to manual Python installations, corrupted PyTorch dependencies, global Node.js setups, or broken CUDA toolchains. This workspace automatically downloads, configures, and serves the entire local image generation stack inside a single directory. + +--- + +## ⚡ Quick Start + +### 1. Launch +Double-click **`start.bat`** in the root directory. + +*On your first launch, the automated installer script will download a portable Node.js build, configure dependencies, detect your GPU, download pre-compiled backend binaries, and compile the user interface.* + +### 2. Put Weights in Place +Place any `.safetensors`, `.gguf`, or `.ckpt` model file into: +``` +app/models/ +``` +*(Or use the **Model Manager** tab in the browser dashboard to download one from our curated library).* + +### 3. Generate Offline +Open **`http://localhost:1420`** in your default web browser, select your model, write a prompt, and start creating! + +--- + +## ✨ Features + + + + + + + + + + + + + + +
+

100% Offline & Private

+

All inference runs entirely on your local GPU/CPU. Your prompts, images, and data never leave your computer.

+
+

Auto-Detected GPU Acceleration

+

Seamlessly detects and configures **CUDA** for Nvidia cards, or falls back to the high-performance **Vulkan** engine for AMD & Intel Arc GPUs.

+
+

No Global Dependencies

+

Zero system footprint. Node.js is downloaded as a portable binary into a sandbox folder, leaving your environment paths untouched.

+
+

Dynamic Backend Controller

+

A native Node.js process manager hosts the React frontend, streams system telemetry, manages downloads, and handles inference server lifecycles.

+
+

Real-time Hardware Telemetry

+

Monitor your PC's real-time CPU, RAM, GPU, and VRAM utilization directly inside the workspace UI.

+
+

Drag & Drop Model Importing

+

Upload local model files from other folders on your PC or download weights directly from Hugging Face via the built-in UI downloader.

+
+ +--- + +## 🏗️ Project Structure + +``` +local-ai-image-generator/ +├── start.bat # main double-click launcher +├── .gitignore +├── README.md +│ +├── scripts/ +│ ├── setup.ps1 # dynamic 4-stage dependency manager +│ ├── reset.ps1 # repair utility (clears builds, keeps your models/images) +│ └── serve.cjs # static UI server & backend controller +│ +└── app/ + ├── frontend/ # React + Vite dashboard source code + ├── backend/ # pre-compiled stable-diffusion.cpp GPU binaries + │ ├── win/cuda/ # CUDA acceleration backend (sd-cuda.exe) + │ └── win/vulkan/ # Vulkan acceleration backend (sd-vulkan.exe) + ├── models/ # weight repository (.safetensors, .gguf, .ckpt) + ├── outputs/ # generated PNGs and JSON parameters metadata + ├── tools/node/ # portable Node.js sandbox + └── dist/ # built frontend assets (compiled on setup) +``` + +--- + + +## 🖥️ GPU Compatibility Matrix + +The application server configures itself to utilize the best performance pathways on your PC: + +| GPU Brand | Tech | Status | Setup Output | +| :--- | :--- | :--- | :--- | +| **Nvidia** | CUDA | ✅ Native Support | Maps `sd-cuda.exe` with Nvidia SDK 12 optimizations. | +| **AMD Radeon** | Vulkan | ✅ Native Support | Maps `sd-vulkan.exe` with Vulkan API acceleration. | +| **Intel Arc** | Vulkan | ✅ Native Support | Maps `sd-vulkan.exe` for GPU acceleration. | +| **None / Integrated** | CPU | ⚠️ Thread Fallback | Runs on logical threads (slow, for testing). | + +--- + +## 🛠️ Troubleshooting + +### 🔄 Resetting / Repairing +If you encounter corrupted downloads or want to rebuild your frontend assets, run: +```powershell +scripts/reset.ps1 +``` +*Note: This cleans the portable environment files and downloads fresh copies, but **safely preserves your downloaded models inside `app/models/` and images in `app/outputs/`**.* + +### 🔌 Port Conflict Warnings +The launcher utilizes two ports on local address `127.0.0.1`: +- **`1420`** (Frontend Dashboard Server) +- **`8080`** (Local Inference C++ API Server) + +Ensure no other applications or development services are binding to these ports before launching. + +--- + +## 📝 License + +This project bundles [stable-diffusion.cpp](https://github.com/leejet/stable-diffusion.cpp) under the MIT License. Individual model weights are subject to their respective licenses — please check model cards on Hugging Face or Civitai before commercial application. \ No newline at end of file diff --git a/app/dist/assets/event-DL84ZN__.js b/app/dist/assets/event-DL84ZN__.js new file mode 100644 index 0000000..cb3444b --- /dev/null +++ b/app/dist/assets/event-DL84ZN__.js @@ -0,0 +1 @@ +import{i as D,t as i}from"./index-Ddpqcst7.js";var _;(function(r){r.WINDOW_RESIZED="tauri://resize",r.WINDOW_MOVED="tauri://move",r.WINDOW_CLOSE_REQUESTED="tauri://close-requested",r.WINDOW_DESTROYED="tauri://destroyed",r.WINDOW_FOCUS="tauri://focus",r.WINDOW_BLUR="tauri://blur",r.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",r.WINDOW_THEME_CHANGED="tauri://theme-changed",r.WINDOW_CREATED="tauri://window-created",r.WINDOW_SUSPENDED="tauri://suspended",r.WINDOW_RESUMED="tauri://resumed",r.WEBVIEW_CREATED="tauri://webview-created",r.DRAG_ENTER="tauri://drag-enter",r.DRAG_OVER="tauri://drag-over",r.DRAG_DROP="tauri://drag-drop",r.DRAG_LEAVE="tauri://drag-leave"})(_||(_={}));async function l(r,a){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(r,a),await D("plugin:event|unlisten",{event:r,eventId:a})}async function n(r,a,e){var t;const W=typeof e?.target=="string"?{kind:"AnyLabel",label:e.target}:(t=e?.target)!==null&&t!==void 0?t:{kind:"Any"};return D("plugin:event|listen",{event:r,target:W,handler:i(a)}).then(d=>async()=>l(r,d))}export{_ as TauriEvent,n as listen}; diff --git a/app/dist/assets/index-BVK0F0Ah.css b/app/dist/assets/index-BVK0F0Ah.css new file mode 100644 index 0000000..976f5a1 --- /dev/null +++ b/app/dist/assets/index-BVK0F0Ah.css @@ -0,0 +1 @@ +:root{font-family:Outfit,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-shape-corner-small: 8px;--md-shape-corner-medium: 12px;--md-shape-corner-large: 16px;--md-shape-corner-extra-large: 22px;--md-shape-corner-full: 9999px;--md-transition-duration: .25s;--md-transition-easing: cubic-bezier(.4, 0, .2, 1);--md-sys-color-primary: #4f46e5;--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: rgba(79, 70, 229, .06);--md-sys-color-on-primary-container: #4338ca;--md-sys-color-secondary: #0ea5e9;--md-sys-color-on-secondary: #ffffff;--md-sys-color-secondary-container: rgba(14, 165, 233, .06);--md-sys-color-on-secondary-container: #0369a1;--md-sys-color-tertiary: #d946ef;--md-sys-color-on-tertiary: #ffffff;--md-sys-color-background: #f8fafc;--md-sys-color-on-background: #0f172a;--md-sys-color-surface: rgba(255, 255, 255, .75);--md-sys-color-on-surface: #0f172a;--md-sys-color-surface-variant: rgba(241, 245, 249, .8);--md-sys-color-on-surface-variant: #475569;--md-sys-color-outline: #64748b;--md-sys-color-outline-variant: #94a3b8;--border-color: rgba(15, 23, 42, .08);--border-color-muted: rgba(15, 23, 42, .05);--md-sys-color-error: #ef4444;--md-sys-color-on-error: #ffffff;--md-sys-color-success: #10b981;--md-sys-color-on-success: #ffffff;--md-sys-color-card-border: rgba(15, 23, 42, .06);--glass-shadow: 0 8px 32px 0 rgba(15, 23, 42, .04);--glass-blur: blur(16px)}html[data-theme=dark]{--md-sys-color-primary: #6366f1;--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: rgba(99, 102, 241, .12);--md-sys-color-on-primary-container: #c7d2fe;--md-sys-color-secondary: #38bdf8;--md-sys-color-on-secondary: #0f172a;--md-sys-color-secondary-container: rgba(56, 189, 248, .08);--md-sys-color-on-secondary-container: #bae6fd;--md-sys-color-tertiary: #f472b6;--md-sys-color-on-tertiary: #0f172a;--md-sys-color-background: #090a0f;--md-sys-color-on-background: #f4f4f5;--md-sys-color-surface: rgba(18, 20, 29, .65);--md-sys-color-on-surface: #f4f4f5;--md-sys-color-surface-variant: rgba(26, 29, 41, .55);--md-sys-color-on-surface-variant: #a1a1aa;--md-sys-color-outline: #a1a1aa;--md-sys-color-outline-variant: #71717a;--border-color: rgba(255, 255, 255, .09);--border-color-muted: rgba(255, 255, 255, .05);--md-sys-color-error: #f87171;--md-sys-color-on-error: #ffffff;--md-sys-color-success: #34d399;--md-sys-color-on-success: #090a0f;--md-sys-color-card-border: rgba(255, 255, 255, .04);--glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, .3);--glass-blur: blur(16px)}*{box-sizing:border-box;margin:0;padding:0}body{background-color:var(--md-sys-color-background);background-image:radial-gradient(at 0% 0%,var(--md-sys-color-primary-container) 0px,transparent 50%),radial-gradient(at 100% 0%,var(--md-sys-color-secondary-container) 0px,transparent 40%);color:var(--md-sys-color-on-background);overflow:hidden;height:100vh;width:100vw;font-size:16px;transition:background-color var(--md-transition-duration) ease}.app-container{display:flex;flex-direction:row;height:100vh;width:100vw;overflow:hidden}.sidebar{width:280px;background-color:var(--md-sys-color-surface);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border-right:1px solid var(--border-color);display:flex;flex-direction:column;padding:28px 18px;justify-content:space-between;box-shadow:var(--glass-shadow);z-index:11;transition:all var(--md-transition-duration) var(--md-transition-easing)}.sidebar-logo{display:flex;align-items:center;gap:12px;padding:0 12px 28px}.sidebar-logo-icon{color:var(--md-sys-color-primary);width:26px;height:26px;filter:drop-shadow(0 2px 8px rgba(99,102,241,.3))}.sidebar-logo-text{font-size:1.15rem;font-weight:700;letter-spacing:-.02em;color:var(--md-sys-color-on-background)}.nav-list{display:flex;flex-direction:column;gap:6px;margin-bottom:auto}.nav-item{display:flex;align-items:center;gap:12px;padding:10px 16px;height:48px;border-radius:var(--md-shape-corner-medium);color:var(--md-sys-color-on-surface-variant);font-size:.9rem;font-weight:500;cursor:pointer;transition:all var(--md-transition-duration) var(--md-transition-easing);-webkit-user-select:none;user-select:none;text-decoration:none;position:relative}.nav-item:hover{background-color:var(--md-sys-color-surface-variant);color:var(--md-sys-color-primary);transform:translate(2px)}.nav-item.active{background-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-weight:600}.nav-item.active:before{content:"";position:absolute;left:0;top:14px;bottom:14px;width:4px;background-color:var(--md-sys-color-primary);border-radius:0 4px 4px 0}.sidebar-footer{padding:18px 12px 0;border-top:1px solid var(--border-color);font-size:.78rem;color:var(--md-sys-color-on-surface-variant);display:flex;flex-direction:column;gap:6px;opacity:.95}.main-content{flex:1;display:flex;flex-direction:column;background-color:transparent;overflow:hidden}.top-status-bar{height:64px;background-color:var(--md-sys-color-surface);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border-bottom:1px solid var(--border-color);display:flex;align-items:center;justify-content:space-between;padding:0 24px;z-index:10;box-shadow:var(--glass-shadow)}.current-model-info{display:flex;align-items:center;gap:10px;font-size:.88rem}.status-indicator{width:8px;height:8px;border-radius:50%;background-color:var(--md-sys-color-success);box-shadow:0 0 8px var(--md-sys-color-success)}.status-indicator.busy{background-color:var(--md-sys-color-primary);box-shadow:0 0 8px var(--md-sys-color-primary);animation:pulse 1.8s infinite}.status-indicator.offline{background-color:var(--md-sys-color-on-surface-variant);box-shadow:none;opacity:.6}.telemetry-group{display:flex;align-items:center;gap:8px}.telemetry-chip{display:flex;align-items:center;gap:6px;background-color:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);border-radius:var(--md-shape-corner-medium);padding:6px 12px;font-size:.8rem;font-weight:500;color:var(--md-sys-color-on-surface-variant);transition:all var(--md-transition-duration)}.telemetry-chip-icon{width:14px;height:14px}.readiness-card{margin:0 0 18px;border-left:4px solid var(--md-sys-color-primary)}.readiness-card-warning{border-left-color:var(--md-sys-color-error)}.readiness-header{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.readiness-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap}.readiness-actions .m3-btn{height:34px;padding:0 14px}.readiness-issues,.readiness-cleanup-list{display:flex;flex-direction:column;gap:6px;margin-top:12px;font-size:.82rem;color:var(--md-sys-color-on-surface-variant)}.readiness-issues span{color:var(--md-sys-color-error)}.theme-toggle-btn{background:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);color:var(--md-sys-color-on-surface-variant);cursor:pointer;display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--md-shape-corner-medium);transition:all var(--md-transition-duration) var(--md-transition-easing);margin-right:6px}.theme-toggle-btn:hover{color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);background-color:var(--md-sys-color-primary-container);transform:scale(1.05)}.workspace-area{flex:1;overflow-y:auto;padding:28px}.workspace-title-section{margin-bottom:24px}.workspace-title{font-size:1.6rem;font-weight:700;color:var(--md-sys-color-on-background);letter-spacing:-.02em}.workspace-subtitle{font-size:.9rem;color:var(--md-sys-color-on-surface-variant);margin-top:4px;opacity:.8}.m3-card{background-color:var(--md-sys-color-surface);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);border:1px solid var(--md-sys-color-card-border);border-radius:var(--md-shape-corner-large);padding:24px;margin-bottom:24px;box-shadow:var(--glass-shadow);transition:all var(--md-transition-duration) var(--md-transition-easing)}.m3-card:hover{border-color:#6366f126}.m3-card-title{font-size:1.05rem;font-weight:600;margin-bottom:20px;color:var(--md-sys-color-on-surface);display:flex;align-items:center;gap:8px}.m3-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:38px;padding:0 20px;border-radius:var(--md-shape-corner-medium);font-size:.88rem;font-weight:550;font-family:inherit;border:none;cursor:pointer;transition:all var(--md-transition-duration) var(--md-transition-easing);-webkit-user-select:none;user-select:none;line-height:1;white-space:nowrap}.m3-btn svg{flex:0 0 auto}.m3-btn .progress-spinner{width:14px;height:14px;border-width:2px;border-color:currentColor;border-right-color:transparent;border-bottom-color:transparent}.m3-btn:disabled{opacity:.45;cursor:not-allowed}.m3-btn-filled{background:linear-gradient(135deg,var(--md-sys-color-primary),#8b5cf6);color:var(--md-sys-color-on-primary);box-shadow:0 4px 12px #6366f133}.m3-btn-filled:hover:not(:disabled){box-shadow:0 6px 20px #6366f159;transform:translateY(-1px);filter:brightness(1.04)}.m3-btn-tonal{background-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.m3-btn-tonal:hover:not(:disabled){background-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);transform:translateY(-1px)}.m3-btn-outlined{background-color:transparent;border:1px solid var(--border-color);color:var(--md-sys-color-on-surface)}.m3-btn-outlined:hover:not(:disabled){background-color:var(--md-sys-color-surface-variant);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.m3-btn-error{background-color:#f43f5e14;border:1px solid rgba(244,63,94,.18);color:#e11d48;box-shadow:0 2px 8px #f43f5e0d}.m3-btn-error:hover:not(:disabled){background-color:#f43f5e26;border-color:#f43f5e4d;transform:translateY(-1px)}html[data-theme=dark] .m3-btn-error{background-color:#fb718517;border:1px solid rgba(251,113,133,.22);color:#fda4af;box-shadow:0 2px 8px #fb71850a}html[data-theme=dark] .m3-btn-error:hover:not(:disabled){background-color:#fb718529;border-color:#fb718559}.m3-field-group{display:flex;flex-direction:column;gap:18px}.m3-text-field{display:flex;flex-direction:column;gap:6px}.m3-text-field-label{font-size:.82rem;font-weight:600;letter-spacing:.01em;color:var(--md-sys-color-on-surface-variant)}.m3-input,.m3-textarea{width:100%;background-color:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);border-radius:var(--md-shape-corner-medium);padding:10px 14px;font-family:inherit;font-size:.92rem;color:var(--md-sys-color-on-surface);transition:all var(--md-transition-duration) var(--md-transition-easing);outline:none}.m3-input{height:42px}.m3-textarea{min-height:90px;resize:vertical}.m3-input:focus,.m3-textarea:focus{border-color:var(--md-sys-color-primary);background-color:var(--md-sys-color-surface);box-shadow:0 0 0 3px #6366f11f}.m3-slider-group{display:flex;flex-direction:column;gap:4px}.m3-slider-header{display:flex;justify-content:space-between;align-items:center}.m3-slider-label{font-size:.82rem;font-weight:600;color:var(--md-sys-color-on-surface-variant)}.m3-slider-value{font-size:.78rem;font-weight:700;color:var(--md-sys-color-primary);background-color:var(--md-sys-color-primary-container);padding:2px 8px;border-radius:var(--md-shape-corner-full)}.m3-slider{-webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:var(--md-shape-corner-full);background:var(--border-color);outline:none;margin:12px 0;transition:background .25s}.m3-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:var(--md-sys-color-primary);border:2px solid var(--md-sys-color-surface);box-shadow:0 0 8px #6366f159;cursor:pointer;transition:all var(--md-transition-duration) var(--md-transition-easing)}.m3-slider::-webkit-slider-thumb:hover{transform:scale(1.25);box-shadow:0 0 12px #6366f199}.m3-switch-row{display:flex;justify-content:space-between;align-items:center;padding:8px 0}.m3-switch-info{display:flex;flex-direction:column;gap:2px}.m3-switch-title{font-size:.9rem;font-weight:600;color:var(--md-sys-color-on-surface)}.m3-switch-description{font-size:.78rem;color:var(--md-sys-color-on-surface-variant);opacity:.8}.m3-switch{position:relative;display:inline-block;width:46px;height:26px}.m3-switch input{opacity:0;width:0;height:0}.m3-switch-slider{position:absolute;cursor:pointer;inset:0;background-color:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);border-radius:26px;transition:.25s}.m3-switch-slider:before{position:absolute;content:"";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--md-sys-color-on-surface-variant);border-radius:50%;transition:.25s}.m3-switch input:checked+.m3-switch-slider{background-color:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary)}.m3-switch input:checked+.m3-switch-slider:before{transform:translate(20px);background-color:var(--md-sys-color-on-primary)}.m3-segmented-button{display:flex;background-color:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);border-radius:var(--md-shape-corner-medium);padding:3px;overflow:hidden;width:100%}.m3-segment-item{flex:1;text-align:center;padding:8px 0;font-size:.82rem;font-weight:600;cursor:pointer;background-color:transparent;color:var(--md-sys-color-on-surface-variant);transition:all var(--md-transition-duration) var(--md-transition-easing);border-radius:calc(var(--md-shape-corner-medium) - 2px);-webkit-user-select:none;user-select:none;border:none}.m3-segment-item:hover:not(.active):not(.disabled){color:var(--md-sys-color-on-surface);background-color:#00000008}html[data-theme=dark] .m3-segment-item:hover:not(.active):not(.disabled){background-color:#ffffff0a}.m3-segment-item.active{background-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);box-shadow:0 2px 8px #6366f133}.m3-segment-item.disabled{opacity:.45;cursor:not-allowed;text-decoration:line-through}.generator-layout{display:grid;grid-template-columns:1fr;gap:24px}@media(min-width:1000px){.generator-layout{grid-template-columns:1.15fr .85fr}}.chips-container{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.status-chip{display:inline-flex;align-items:center;gap:6px;background-color:var(--md-sys-color-surface-variant);border:1px solid var(--border-color);color:var(--md-sys-color-on-surface-variant);padding:5px 12px;border-radius:var(--md-shape-corner-full);font-size:.78rem;font-weight:550;cursor:pointer;transition:all var(--md-transition-duration)}.status-chip:hover{background-color:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.prompt-actions{display:flex;justify-content:space-between;align-items:center;margin-top:16px}.image-to-image-section{margin-top:12px;border-top:1px solid var(--border-color);padding-top:16px}.image-dropzone{border:2.5px dashed var(--border-color);border-radius:var(--md-shape-corner-large);padding:24px;text-align:center;cursor:pointer;background-color:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);transition:all var(--md-transition-duration);position:relative;overflow:hidden;min-height:120px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px}.image-dropzone:hover{background-color:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.dropped-image-preview{max-width:100%;max-height:160px;border-radius:var(--md-shape-corner-medium);object-fit:contain;box-shadow:var(--glass-shadow)}.aspect-ratio-btn{position:relative;transition:all var(--md-transition-duration) var(--md-transition-easing)}.aspect-ratio-btn.active{background-color:var(--md-sys-color-primary-container)!important;border-color:var(--md-sys-color-primary)!important;color:var(--md-sys-color-primary)!important;box-shadow:0 0 0 2px #6366f126}.aspect-ratio-preview{border:1.5px solid currentColor;border-radius:2px;opacity:.6;background-color:transparent;transition:all .2s ease;margin-bottom:6px}.aspect-ratio-btn:hover .aspect-ratio-preview,.aspect-ratio-btn.active .aspect-ratio-preview{opacity:1;background-color:#6366f10f}.ratio-1-1{width:16px;height:16px}.ratio-4-3{width:20px;height:15px}.ratio-16-9{width:24px;height:13.5px}.ratio-9-16{width:13.5px;height:24px}.output-panel{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:380px}.output-image-container{width:100%;aspect-ratio:1;background-color:var(--md-sys-color-surface-variant);border-radius:var(--md-shape-corner-large);border:1px solid var(--border-color);display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative;box-shadow:inset 0 2px 8px #0000000d}.output-image{width:100%;height:100%;object-fit:contain;transition:transform .3s}.output-image:hover{transform:scale(1.015)}.progress-overlay{position:absolute;inset:0;background-color:#090a0fd9;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;gap:14px;padding:24px;z-index:5}.progress-spinner{width:44px;height:44px;border:3px solid rgba(255,255,255,.15);border-top-color:var(--md-sys-color-primary);border-radius:50%;animation:spin .9s cubic-bezier(.5,.1,.4,.9) infinite;box-shadow:0 0 12px #6366f133}.loading-dot{width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-primary);opacity:.9;animation:pulse 1.2s ease-in-out infinite;box-shadow:0 0 8px var(--md-sys-color-primary)}.progress-text{font-size:1.05rem;font-weight:700;letter-spacing:-.01em}.progress-bar-container{width:80%;height:5px;background-color:#ffffff1f;border-radius:var(--md-shape-corner-full);overflow:hidden;margin:4px 0}.progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--md-sys-color-primary),#d946ef);width:0%;transition:width .4s cubic-bezier(.1,.8,.25,1);box-shadow:0 0 8px #6366f166}.output-placeholder-icon{width:48px;height:48px;color:var(--md-sys-color-on-surface-variant);opacity:.5;filter:drop-shadow(0 2px 10px rgba(0,0,0,.05))}.output-placeholder-text{font-size:.88rem;color:var(--md-sys-color-on-surface-variant);margin-top:12px;text-align:center;line-height:1.5;opacity:.8}.image-actions{display:flex;gap:10px;margin-top:16px;width:100%}.image-actions button{flex:1}.models-grid{display:grid;grid-template-columns:1fr;gap:20px}@media(min-width:800px){.models-grid{grid-template-columns:1fr 1fr}}.model-card{display:flex;flex-direction:column;justify-content:space-between;border:1px solid var(--border-color-muted)}.model-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px}.model-name{font-size:1.05rem;font-weight:600}.model-badge{font-size:.72rem;font-weight:700;padding:3px 8px;border-radius:var(--md-shape-corner-full)}.model-badge-gguf{background-color:#f59e0b26;color:#d97706}.model-badge-safetensors{background-color:#0ea5e926;color:#0284c7}.model-description{font-size:.82rem;color:var(--md-sys-color-on-surface-variant);margin-bottom:16px;line-height:1.45;opacity:.9}.model-status-info{margin-top:auto;padding-top:12px;border-top:1px solid var(--border-color-muted);display:flex;align-items:center;justify-content:space-between}.model-size{font-size:.8rem;font-weight:550;color:var(--md-sys-color-on-surface-variant)}.model-progress-section{width:100%;margin-top:12px}.model-progress-label{display:flex;justify-content:space-between;font-size:.78rem;font-weight:600;margin-bottom:4px}.model-progress-bar{width:100%;height:6px;background-color:var(--border-color-muted);border-radius:var(--md-shape-corner-full);overflow:hidden}.model-progress-fill{height:100%;background:linear-gradient(90deg,var(--md-sys-color-primary),var(--md-sys-color-secondary));width:0%;transition:width .25s ease}.import-box{border:2px dashed var(--border-color);border-radius:var(--md-shape-corner-large);padding:32px;text-align:center;cursor:pointer;transition:all var(--md-transition-duration);background-color:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface-variant);display:flex;flex-direction:column;align-items:center;gap:10px}.import-box:hover{background-color:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-primary)}.import-icon{width:40px;height:40px;color:var(--md-sys-color-primary);filter:drop-shadow(0 2px 6px rgba(99,102,241,.15))}.gallery-section{margin-top:36px}.gallery-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.gallery-selection-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.gallery-selection-actions .m3-btn{height:34px;padding:0 14px}.gallery-selection-count{font-size:.82rem;font-weight:700;color:var(--md-sys-color-primary);padding:7px 10px;border-radius:var(--md-shape-corner-full);background:var(--md-sys-color-primary-container)}.gallery-hint{margin-top:8px;font-size:.78rem;color:var(--md-sys-color-outline)}.gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:12px;margin-top:16px}.gallery-item{aspect-ratio:1;border-radius:var(--md-shape-corner-medium);overflow:hidden;border:1px solid var(--border-color-muted);cursor:pointer;position:relative;contain:layout paint style;transition:border-color var(--md-transition-duration),box-shadow var(--md-transition-duration),transform var(--md-transition-duration)}.gallery-item.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 3px #4f46e540}.gallery-thumb{width:100%;height:100%;object-fit:cover;transition:transform var(--md-transition-duration) var(--md-transition-easing)}.gallery-item:hover .gallery-thumb{transform:scale(1.05)}.gallery-select-badge{position:absolute;top:8px;right:8px;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;color:var(--md-sys-color-on-primary);background:var(--md-sys-color-primary);box-shadow:0 2px 8px #00000047}.app-dialog-backdrop{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;background:#080c18a3;-webkit-backdrop-filter:blur(4px) saturate(.86);backdrop-filter:blur(4px) saturate(.86)}.app-dialog{width:min(460px,100%);background:color-mix(in srgb,var(--md-sys-color-surface) 96%,white 4%);color:var(--md-sys-color-on-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline) 55%,transparent);border-radius:var(--md-shape-corner-large);box-shadow:0 22px 60px #0000006b,0 0 0 1px #ffffff14 inset;padding:24px}.app-dialog-title{font-size:1.15rem;font-weight:800;margin:0 0 10px}.app-dialog-message{font-size:.92rem;line-height:1.45;color:var(--md-sys-color-on-surface-variant);margin:0;white-space:pre-wrap}.app-dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:22px;flex-wrap:wrap}.gallery-empty{text-align:center;padding:36px;color:var(--md-sys-color-on-surface-variant);font-size:.85rem;opacity:.8}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(1.06)}}.sidebar-specs-header{display:flex;align-items:center;gap:6px;margin-bottom:6px;font-weight:600;color:var(--md-sys-color-on-background)}.sidebar-specs-item{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;opacity:.85;margin-bottom:2px;color:var(--md-sys-color-on-background)}.sidebar-specs-os{color:var(--md-sys-color-primary);font-weight:600;margin-top:4px} diff --git a/app/dist/assets/index-Ddpqcst7.js b/app/dist/assets/index-Ddpqcst7.js new file mode 100644 index 0000000..044d4e8 --- /dev/null +++ b/app/dist/assets/index-Ddpqcst7.js @@ -0,0 +1,120 @@ +(function(){const b=document.createElement("link").relList;if(b&&b.supports&&b.supports("modulepreload"))return;for(const j of document.querySelectorAll('link[rel="modulepreload"]'))r(j);new MutationObserver(j=>{for(const A of j)if(A.type==="childList")for(const Y of A.addedNodes)Y.tagName==="LINK"&&Y.rel==="modulepreload"&&r(Y)}).observe(document,{childList:!0,subtree:!0});function N(j){const A={};return j.integrity&&(A.integrity=j.integrity),j.referrerPolicy&&(A.referrerPolicy=j.referrerPolicy),j.crossOrigin==="use-credentials"?A.credentials="include":j.crossOrigin==="anonymous"?A.credentials="omit":A.credentials="same-origin",A}function r(j){if(j.ep)return;j.ep=!0;const A=N(j);fetch(j.href,A)}})();function sm(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var Us={exports:{}},Pn={};var Zd;function z0(){if(Zd)return Pn;Zd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.fragment");function N(r,j,A){var Y=null;if(A!==void 0&&(Y=""+A),j.key!==void 0&&(Y=""+j.key),"key"in j){A={};for(var G in j)G!=="key"&&(A[G]=j[G])}else A=j;return j=A.ref,{$$typeof:f,type:r,key:Y,ref:j!==void 0?j:null,props:A}}return Pn.Fragment=b,Pn.jsx=N,Pn.jsxs=N,Pn}var Vd;function T0(){return Vd||(Vd=1,Us.exports=z0()),Us.exports}var c=T0(),ws={exports:{}},ae={};var Kd;function M0(){if(Kd)return ae;Kd=1;var f=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),j=Symbol.for("react.profiler"),A=Symbol.for("react.consumer"),Y=Symbol.for("react.context"),G=Symbol.for("react.forward_ref"),R=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),D=Symbol.for("react.lazy"),U=Symbol.for("react.activity"),Z=Symbol.iterator;function ee(d){return d===null||typeof d!="object"?null:(d=Z&&d[Z]||d["@@iterator"],typeof d=="function"?d:null)}var X={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},F=Object.assign,re={};function I(d,z,B){this.props=d,this.context=z,this.refs=re,this.updater=B||X}I.prototype.isReactComponent={},I.prototype.setState=function(d,z){if(typeof d!="object"&&typeof d!="function"&&d!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,d,z,"setState")},I.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function ne(){}ne.prototype=I.prototype;function ce(d,z,B){this.props=d,this.context=z,this.refs=re,this.updater=B||X}var Ge=ce.prototype=new ne;Ge.constructor=ce,F(Ge,I.prototype),Ge.isPureReactComponent=!0;var Ve=Array.isArray;function Qe(){}var $={H:null,A:null,T:null,S:null},je=Object.prototype.hasOwnProperty;function ot(d,z,B){var H=B.ref;return{$$typeof:f,type:d,key:z,ref:H!==void 0?H:null,props:B}}function qe(d,z){return ot(d.type,z,d.props)}function Me(d){return typeof d=="object"&&d!==null&&d.$$typeof===f}function Ke(d){var z={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(B){return z[B]})}var $e=/\/+/g;function tt(d,z){return typeof d=="object"&&d!==null&&d.key!=null?Ke(""+d.key):z.toString(36)}function Je(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(Qe,Qe):(d.status="pending",d.then(function(z){d.status==="pending"&&(d.status="fulfilled",d.value=z)},function(z){d.status==="pending"&&(d.status="rejected",d.reason=z)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function x(d,z,B,H,P){var te=typeof d;(te==="undefined"||te==="boolean")&&(d=null);var le=!1;if(d===null)le=!0;else switch(te){case"bigint":case"string":case"number":le=!0;break;case"object":switch(d.$$typeof){case f:case b:le=!0;break;case D:return le=d._init,x(le(d._payload),z,B,H,P)}}if(le)return P=P(d),le=H===""?"."+tt(d,0):H,Ve(P)?(B="",le!=null&&(B=le.replace($e,"$&/")+"/"),x(P,z,B,"",function(ct){return ct})):P!=null&&(Me(P)&&(P=qe(P,B+(P.key==null||d&&d.key===P.key?"":(""+P.key).replace($e,"$&/")+"/")+le)),z.push(P)),1;le=0;var Ue=H===""?".":H+":";if(Ve(d))for(var ze=0;ze>>1,de=x[se];if(0>>1;sej(B,K))Hj(P,B)?(x[se]=P,x[H]=K,se=H):(x[se]=B,x[z]=K,se=z);else if(Hj(P,K))x[se]=P,x[H]=K,se=H;else break e}}return O}function j(x,O){var K=x.sortIndex-O.sortIndex;return K!==0?K:x.id-O.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var A=performance;f.unstable_now=function(){return A.now()}}else{var Y=Date,G=Y.now();f.unstable_now=function(){return Y.now()-G}}var R=[],y=[],D=1,U=null,Z=3,ee=!1,X=!1,F=!1,re=!1,I=typeof setTimeout=="function"?setTimeout:null,ne=typeof clearTimeout=="function"?clearTimeout:null,ce=typeof setImmediate<"u"?setImmediate:null;function Ge(x){for(var O=N(y);O!==null;){if(O.callback===null)r(y);else if(O.startTime<=x)r(y),O.sortIndex=O.expirationTime,b(R,O);else break;O=N(y)}}function Ve(x){if(F=!1,Ge(x),!X)if(N(R)!==null)X=!0,Qe||(Qe=!0,Ke());else{var O=N(y);O!==null&&Je(Ve,O.startTime-x)}}var Qe=!1,$=-1,je=5,ot=-1;function qe(){return re?!0:!(f.unstable_now()-otx&&qe());){var se=U.callback;if(typeof se=="function"){U.callback=null,Z=U.priorityLevel;var de=se(U.expirationTime<=x);if(x=f.unstable_now(),typeof de=="function"){U.callback=de,Ge(x),O=!0;break t}U===N(R)&&r(R),Ge(x)}else r(R);U=N(R)}if(U!==null)O=!0;else{var d=N(y);d!==null&&Je(Ve,d.startTime-x),O=!1}}break e}finally{U=null,Z=K,ee=!1}O=void 0}}finally{O?Ke():Qe=!1}}}var Ke;if(typeof ce=="function")Ke=function(){ce(Me)};else if(typeof MessageChannel<"u"){var $e=new MessageChannel,tt=$e.port2;$e.port1.onmessage=Me,Ke=function(){tt.postMessage(null)}}else Ke=function(){I(Me,0)};function Je(x,O){$=I(function(){x(f.unstable_now())},O)}f.unstable_IdlePriority=5,f.unstable_ImmediatePriority=1,f.unstable_LowPriority=4,f.unstable_NormalPriority=3,f.unstable_Profiling=null,f.unstable_UserBlockingPriority=2,f.unstable_cancelCallback=function(x){x.callback=null},f.unstable_forceFrameRate=function(x){0>x||125se?(x.sortIndex=K,b(y,x),N(R)===null&&x===N(y)&&(F?(ne($),$=-1):F=!0,Je(Ve,K-se))):(x.sortIndex=de,b(R,x),X||ee||(X=!0,Qe||(Qe=!0,Ke()))),x},f.unstable_shouldYield=qe,f.unstable_wrapCallback=function(x){var O=Z;return function(){var K=Z;Z=O;try{return x.apply(this,arguments)}finally{Z=K}}}})(Hs)),Hs}var Wd;function A0(){return Wd||(Wd=1,Rs.exports=N0()),Rs.exports}var Gs={exports:{}},jt={};var Fd;function D0(){if(Fd)return jt;Fd=1;var f=ks();function b(R){var y="https://react.dev/errors/"+R;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Gs.exports=D0(),Gs.exports}var Pd;function O0(){if(Pd)return ei;Pd=1;var f=A0(),b=ks(),N=C0();function r(e){var t="https://react.dev/errors/"+e;if(1de||(e.current=se[de],se[de]=null,de--)}function B(e,t){de++,se[de]=e.current,e.current=t}var H=d(null),P=d(null),te=d(null),le=d(null);function Ue(e,t){switch(B(te,t),B(P,e),B(H,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?hd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=hd(t),e=yd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}z(H),B(H,e)}function ze(){z(H),z(P),z(te)}function ct(e){e.memoizedState!==null&&B(le,e);var t=H.current,l=yd(t,e.type);t!==l&&(B(P,e),B(H,l))}function yt(e){P.current===e&&(z(H),z(P)),le.current===e&&(z(le),$n._currentValue=K)}var wt,Al;function rt(e){if(wt===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);wt=t&&t[1]||"",Al=-1)":-1n||o[a]!==p[n]){var _=` +`+o[a].replace(" at new "," at ");return e.displayName&&_.includes("")&&(_=_.replace("",e.displayName)),_}while(1<=a&&0<=n);break}}}finally{al=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?rt(l):""}function T(e,t){switch(e.tag){case 26:case 27:case 5:return rt(e.type);case 16:return rt("Lazy");case 13:return e.child!==t&&t!==null?rt("Suspense Fallback"):rt("Suspense");case 19:return rt("SuspenseList");case 0:case 15:return sl(e.type,!1);case 11:return sl(e.type.render,!1);case 1:return sl(e.type,!0);case 31:return rt("Activity");default:return""}}function C(e){try{var t="",l=null;do t+=T(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var q=Object.prototype.hasOwnProperty,k=f.unstable_scheduleCallback,He=f.unstable_cancelCallback,zt=f.unstable_shouldYield,st=f.unstable_requestPaint,pe=f.unstable_now,sn=f.unstable_getCurrentPriorityLevel,ni=f.unstable_ImmediatePriority,ii=f.unstable_UserBlockingPriority,L=f.unstable_NormalPriority,ve=f.unstable_LowPriority,we=f.unstable_IdlePriority,gt=f.log,Tt=f.unstable_setDisableYieldValue,Bt=null,dt=null;function Rt(e){if(typeof gt=="function"&&Tt(e),dt&&typeof dt.setStrictMode=="function")try{dt.setStrictMode(Bt,e)}catch{}}var Ee=Math.clz32?Math.clz32:ke,Te=Math.log,xe=Math.LN2;function ke(e){return e>>>=0,e===0?32:31-(Te(e)/xe|0)|0}var ye=256,lt=262144,Be=4194304;function We(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function _t(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,i=e.suspendedLanes,u=e.pingedLanes;e=e.warmLanes;var s=a&134217727;return s!==0?(a=s&~i,a!==0?n=We(a):(u&=s,u!==0?n=We(u):l||(l=s&~e,l!==0&&(n=We(l))))):(s=a&~i,s!==0?n=We(s):u!==0?n=We(u):l||(l=a&~e,l!==0&&(n=We(l)))),n===0?0:t!==0&&t!==n&&(t&i)===0&&(i=n&-n,l=t&-t,i>=l||i===32&&(l&4194048)!==0)?t:n}function fl(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function bu(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ks(){var e=Be;return Be<<=1,(Be&62914560)===0&&(Be=4194304),e}function xu(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function fn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function dm(e,t,l,a,n,i){var u=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var s=e.entanglements,o=e.expirationTimes,p=e.hiddenUpdates;for(l=u&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var vm=/[\n"\\]/g;function Zt(e){return e.replace(vm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Eu(e,t,l,a,n,i,u,s){e.name="",u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"?e.type=u:e.removeAttribute("type"),t!=null?u==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+kt(t)):e.value!==""+kt(t)&&(e.value=""+kt(t)):u!=="submit"&&u!=="reset"||e.removeAttribute("value"),t!=null?Nu(e,u,kt(t)):l!=null?Nu(e,u,kt(l)):a!=null&&e.removeAttribute("value"),n==null&&i!=null&&(e.defaultChecked=!!i),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?e.name=""+kt(s):e.removeAttribute("name")}function cf(e,t,l,a,n,i,u,s){if(i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.type=i),t!=null||l!=null){if(!(i!=="submit"&&i!=="reset"||t!=null)){Mu(e);return}l=l!=null?""+kt(l):"",t=t!=null?""+kt(t):l,s||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=s?e.checked:!!a,e.defaultChecked=!!a,u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.name=u),Mu(e)}function Nu(e,t,l){t==="number"&&si(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function Ea(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Uu=!1;if(dl)try{var mn={};Object.defineProperty(mn,"passive",{get:function(){Uu=!0}}),window.addEventListener("test",mn,mn),window.removeEventListener("test",mn,mn)}catch{Uu=!1}var Cl=null,wu=null,oi=null;function hf(){if(oi)return oi;var e,t=wu,l=t.length,a,n="value"in Cl?Cl.value:Cl.textContent,i=n.length;for(e=0;e=gn),bf=" ",xf=!1;function _f(e,t){switch(e){case"keyup":return Vm.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function jf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Ca=!1;function Jm(e,t){switch(e){case"compositionend":return jf(t);case"keypress":return t.which!==32?null:(xf=!0,bf);case"textInput":return e=t.data,e===bf&&xf?null:e;default:return null}}function $m(e,t){if(Ca)return e==="compositionend"||!qu&&_f(e,t)?(e=hf(),oi=wu=Cl=null,Ca=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Cf(l)}}function Uf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Uf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function wf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=si(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=si(e.document)}return t}function Xu(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var ah=dl&&"documentMode"in document&&11>=document.documentMode,Oa=null,Qu=null,bn=null,ku=!1;function Bf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;ku||Oa==null||Oa!==si(a)||(a=Oa,"selectionStart"in a&&Xu(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),bn&&Sn(bn,a)||(bn=a,a=au(Qu,"onSelect"),0>=u,n-=u,nl=1<<32-Ee(t)+n|l<ue?(he=V,V=null):he=V.sibling;var be=v(h,V,g[ue],M);if(be===null){V===null&&(V=he);break}e&&V&&be.alternate===null&&t(h,V),m=i(be,m,ue),Se===null?J=be:Se.sibling=be,Se=be,V=he}if(ue===g.length)return l(h,V),ge&&hl(h,ue),J;if(V===null){for(;ueue?(he=V,V=null):he=V.sibling;var Pl=v(h,V,be.value,M);if(Pl===null){V===null&&(V=he);break}e&&V&&Pl.alternate===null&&t(h,V),m=i(Pl,m,ue),Se===null?J=Pl:Se.sibling=Pl,Se=Pl,V=he}if(be.done)return l(h,V),ge&&hl(h,ue),J;if(V===null){for(;!be.done;ue++,be=g.next())be=E(h,be.value,M),be!==null&&(m=i(be,m,ue),Se===null?J=be:Se.sibling=be,Se=be);return ge&&hl(h,ue),J}for(V=a(V);!be.done;ue++,be=g.next())be=S(V,h,ue,be.value,M),be!==null&&(e&&be.alternate!==null&&V.delete(be.key===null?ue:be.key),m=i(be,m,ue),Se===null?J=be:Se.sibling=be,Se=be);return e&&V.forEach(function(j0){return t(h,j0)}),ge&&hl(h,ue),J}function Oe(h,m,g,M){if(typeof g=="object"&&g!==null&&g.type===F&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case ee:e:{for(var J=g.key;m!==null;){if(m.key===J){if(J=g.type,J===F){if(m.tag===7){l(h,m.sibling),M=n(m,g.props.children),M.return=h,h=M;break e}}else if(m.elementType===J||typeof J=="object"&&J!==null&&J.$$typeof===je&&da(J)===m.type){l(h,m.sibling),M=n(m,g.props),Mn(M,g),M.return=h,h=M;break e}l(h,m);break}else t(h,m);m=m.sibling}g.type===F?(M=ca(g.props.children,h.mode,M,g.key),M.return=h,h=M):(M=bi(g.type,g.key,g.props,null,h.mode,M),Mn(M,g),M.return=h,h=M)}return u(h);case X:e:{for(J=g.key;m!==null;){if(m.key===J)if(m.tag===4&&m.stateNode.containerInfo===g.containerInfo&&m.stateNode.implementation===g.implementation){l(h,m.sibling),M=n(m,g.children||[]),M.return=h,h=M;break e}else{l(h,m);break}else t(h,m);m=m.sibling}M=Fu(g,h.mode,M),M.return=h,h=M}return u(h);case je:return g=da(g),Oe(h,m,g,M)}if(Je(g))return Q(h,m,g,M);if(Ke(g)){if(J=Ke(g),typeof J!="function")throw Error(r(150));return g=J.call(g),W(h,m,g,M)}if(typeof g.then=="function")return Oe(h,m,Ei(g),M);if(g.$$typeof===ce)return Oe(h,m,ji(h,g),M);Ni(h,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,m!==null&&m.tag===6?(l(h,m.sibling),M=n(m,g),M.return=h,h=M):(l(h,m),M=Wu(g,h.mode,M),M.return=h,h=M),u(h)):l(h,m)}return function(h,m,g,M){try{Tn=0;var J=Oe(h,m,g,M);return Qa=null,J}catch(V){if(V===Xa||V===Ti)throw V;var Se=Gt(29,V,null,h.mode);return Se.lanes=M,Se.return=h,Se}}}var ha=no(!0),io=no(!1),Rl=!1;function fc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function oc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Hl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Gl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(_e&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=Si(e),Xf(e,null,l),t}return vi(e,a,t,l),Si(e)}function En(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,$s(e,l)}}function rc(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var u={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};i===null?n=i=u:i=i.next=u,l=l.next}while(l!==null);i===null?n=i=t:i=i.next=t}else n=i=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var dc=!1;function Nn(){if(dc){var e=Ya;if(e!==null)throw e}}function An(e,t,l,a){dc=!1;var n=e.updateQueue;Rl=!1;var i=n.firstBaseUpdate,u=n.lastBaseUpdate,s=n.shared.pending;if(s!==null){n.shared.pending=null;var o=s,p=o.next;o.next=null,u===null?i=p:u.next=p,u=o;var _=e.alternate;_!==null&&(_=_.updateQueue,s=_.lastBaseUpdate,s!==u&&(s===null?_.firstBaseUpdate=p:s.next=p,_.lastBaseUpdate=o))}if(i!==null){var E=n.baseState;u=0,_=p=o=null,s=i;do{var v=s.lane&-536870913,S=v!==s.lane;if(S?(me&v)===v:(a&v)===v){v!==0&&v===La&&(dc=!0),_!==null&&(_=_.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var Q=e,W=s;v=t;var Oe=l;switch(W.tag){case 1:if(Q=W.payload,typeof Q=="function"){E=Q.call(Oe,E,v);break e}E=Q;break e;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=W.payload,v=typeof Q=="function"?Q.call(Oe,E,v):Q,v==null)break e;E=U({},E,v);break e;case 2:Rl=!0}}v=s.callback,v!==null&&(e.flags|=64,S&&(e.flags|=8192),S=n.callbacks,S===null?n.callbacks=[v]:S.push(v))}else S={lane:v,tag:s.tag,payload:s.payload,callback:s.callback,next:null},_===null?(p=_=S,o=E):_=_.next=S,u|=v;if(s=s.next,s===null){if(s=n.shared.pending,s===null)break;S=s,s=S.next,S.next=null,n.lastBaseUpdate=S,n.shared.pending=null}}while(!0);_===null&&(o=E),n.baseState=o,n.firstBaseUpdate=p,n.lastBaseUpdate=_,i===null&&(n.shared.lanes=0),Ql|=u,e.lanes=u,e.memoizedState=E}}function uo(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function co(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;ei?i:8;var u=x.T,s={};x.T=s,Cc(e,!1,t,l);try{var o=n(),p=x.S;if(p!==null&&p(s,o),o!==null&&typeof o=="object"&&typeof o.then=="function"){var _=dh(o,a);On(e,t,_,Qt(e))}else On(e,t,a,Qt(e))}catch(E){On(e,t,{then:function(){},status:"rejected",reason:E},Qt())}finally{O.p=i,u!==null&&s.types!==null&&(u.types=s.types),x.T=u}}function vh(){}function Ac(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=Lo(e).queue;qo(e,n,t,K,l===null?vh:function(){return Yo(e),l(a)})}function Lo(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:K,baseState:K,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:vl,lastRenderedState:K},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:vl,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Yo(e){var t=Lo(e);t.next===null&&(t=e.alternate.memoizedState),On(e,t.next.queue,{},Qt())}function Dc(){return St($n)}function Xo(){return et().memoizedState}function Qo(){return et().memoizedState}function Sh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=Qt();e=Hl(l);var a=Gl(t,e,l);a!==null&&(Ut(a,t,l),En(a,t,l)),t={cache:ic()},e.payload=t;return}t=t.return}}function bh(e,t,l){var a=Qt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Gi(e)?Zo(t,l):(l=Ju(e,t,l,a),l!==null&&(Ut(l,e,a),Vo(l,t,a)))}function ko(e,t,l){var a=Qt();On(e,t,l,a)}function On(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Gi(e))Zo(t,n);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var u=t.lastRenderedState,s=i(u,l);if(n.hasEagerState=!0,n.eagerState=s,Ht(s,u))return vi(e,t,n,0),Re===null&&pi(),!1}catch{}if(l=Ju(e,t,n,a),l!==null)return Ut(l,e,a),Vo(l,t,a),!0}return!1}function Cc(e,t,l,a){if(a={lane:2,revertLane:fs(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Gi(e)){if(t)throw Error(r(479))}else t=Ju(e,l,a,2),t!==null&&Ut(t,e,2)}function Gi(e){var t=e.alternate;return e===ie||t!==null&&t===ie}function Zo(e,t){Za=Ci=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Vo(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,$s(e,l)}}var Un={readContext:St,use:wi,useCallback:Fe,useContext:Fe,useEffect:Fe,useImperativeHandle:Fe,useLayoutEffect:Fe,useInsertionEffect:Fe,useMemo:Fe,useReducer:Fe,useRef:Fe,useState:Fe,useDebugValue:Fe,useDeferredValue:Fe,useTransition:Fe,useSyncExternalStore:Fe,useId:Fe,useHostTransitionStatus:Fe,useFormState:Fe,useActionState:Fe,useOptimistic:Fe,useMemoCache:Fe,useCacheRefresh:Fe};Un.useEffectEvent=Fe;var Ko={readContext:St,use:wi,useCallback:function(e,t){return Mt().memoizedState=[e,t===void 0?null:t],e},useContext:St,useEffect:Do,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Ri(4194308,4,wo.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Ri(4194308,4,e,t)},useInsertionEffect:function(e,t){Ri(4,2,e,t)},useMemo:function(e,t){var l=Mt();t=t===void 0?null:t;var a=e();if(ya){Rt(!0);try{e()}finally{Rt(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=Mt();if(l!==void 0){var n=l(t);if(ya){Rt(!0);try{l(t)}finally{Rt(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=bh.bind(null,ie,e),[a.memoizedState,e]},useRef:function(e){var t=Mt();return e={current:e},t.memoizedState=e},useState:function(e){e=zc(e);var t=e.queue,l=ko.bind(null,ie,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:Ec,useDeferredValue:function(e,t){var l=Mt();return Nc(l,e,t)},useTransition:function(){var e=zc(!1);return e=qo.bind(null,ie,e.queue,!0,!1),Mt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ie,n=Mt();if(ge){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),Re===null)throw Error(r(349));(me&127)!==0||ho(a,t,l)}n.memoizedState=l;var i={value:l,getSnapshot:t};return n.queue=i,Do(go.bind(null,a,i,e),[e]),a.flags|=2048,Ka(9,{destroy:void 0},yo.bind(null,a,i,l,t),null),l},useId:function(){var e=Mt(),t=Re.identifierPrefix;if(ge){var l=il,a=nl;l=(a&~(1<<32-Ee(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Oi++,0<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof a.is=="string"?u.createElement("select",{is:a.is}):u.createElement("select"),a.multiple?i.multiple=!0:a.size&&(i.size=a.size);break;default:i=typeof a.is=="string"?u.createElement(n,{is:a.is}):u.createElement(n)}}i[pt]=t,i[Et]=a;e:for(u=t.child;u!==null;){if(u.tag===5||u.tag===6)i.appendChild(u.stateNode);else if(u.tag!==4&&u.tag!==27&&u.child!==null){u.child.return=u,u=u.child;continue}if(u===t)break e;for(;u.sibling===null;){if(u.return===null||u.return===t)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}t.stateNode=i;e:switch(xt(i,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&bl(t)}}return Ye(t),Zc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&bl(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=te.current,Ga(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=vt,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[pt]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||dd(e.nodeValue,l)),e||wl(t,!0)}else e=nu(e).createTextNode(a),e[pt]=t,t.stateNode=e}return Ye(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=Ga(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[pt]=t}else sa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ye(t),e=!1}else l=tc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(Lt(t),t):(Lt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Ye(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=Ga(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(r(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[pt]=t}else sa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Ye(t),n=!1}else n=tc(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(Lt(t),t):(Lt(t),null)}return Lt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),i=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(i=a.memoizedState.cachePool.pool),i!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Qi(t,t.updateQueue),Ye(t),null);case 4:return ze(),e===null&&ms(t.stateNode.containerInfo),Ye(t),null;case 10:return gl(t.type),Ye(t),null;case 19:if(z(Pe),a=t.memoizedState,a===null)return Ye(t),null;if(n=(t.flags&128)!==0,i=a.rendering,i===null)if(n)Bn(a,!1);else{if(Ie!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(i=Di(e),i!==null){for(t.flags|=128,Bn(a,!1),e=i.updateQueue,t.updateQueue=e,Qi(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Qf(l,e),l=l.sibling;return B(Pe,Pe.current&1|2),ge&&hl(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&pe()>Ji&&(t.flags|=128,n=!0,Bn(a,!1),t.lanes=4194304)}else{if(!n)if(e=Di(i),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Qi(t,e),Bn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!i.alternate&&!ge)return Ye(t),null}else 2*pe()-a.renderingStartTime>Ji&&l!==536870912&&(t.flags|=128,n=!0,Bn(a,!1),t.lanes=4194304);a.isBackwards?(i.sibling=t.child,t.child=i):(e=a.last,e!==null?e.sibling=i:t.child=i,a.last=i)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=pe(),e.sibling=null,l=Pe.current,B(Pe,n?l&1|2:l&1),ge&&hl(t,a.treeForkCount),e):(Ye(t),null);case 22:case 23:return Lt(t),hc(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Ye(t),t.subtreeFlags&6&&(t.flags|=8192)):Ye(t),l=t.updateQueue,l!==null&&Qi(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&z(ra),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),gl(at),Ye(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Th(e,t){switch(Pu(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return gl(at),ze(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return yt(t),null;case 31:if(t.memoizedState!==null){if(Lt(t),t.alternate===null)throw Error(r(340));sa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Lt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));sa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return z(Pe),null;case 4:return ze(),null;case 10:return gl(t.type),null;case 22:case 23:return Lt(t),hc(),e!==null&&z(ra),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return gl(at),null;case 25:return null;default:return null}}function pr(e,t){switch(Pu(t),t.tag){case 3:gl(at),ze();break;case 26:case 27:case 5:yt(t);break;case 4:ze();break;case 31:t.memoizedState!==null&&Lt(t);break;case 13:Lt(t);break;case 19:z(Pe);break;case 10:gl(t.type);break;case 22:case 23:Lt(t),hc(),e!==null&&z(ra);break;case 24:gl(at)}}function Rn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var i=l.create,u=l.inst;a=i(),u.destroy=a}l=l.next}while(l!==n)}}catch(s){Ae(t,t.return,s)}}function Yl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var i=n.next;a=i;do{if((a.tag&e)===e){var u=a.inst,s=u.destroy;if(s!==void 0){u.destroy=void 0,n=t;var o=l,p=s;try{p()}catch(_){Ae(n,o,_)}}}a=a.next}while(a!==i)}}catch(_){Ae(t,t.return,_)}}function vr(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{co(t,l)}catch(a){Ae(e,e.return,a)}}}function Sr(e,t,l){l.props=ga(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){Ae(e,t,a)}}function Hn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){Ae(e,t,n)}}function ul(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Ae(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Ae(e,t,n)}else l.current=null}function br(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){Ae(e,e.return,n)}}function Vc(e,t,l){try{var a=e.stateNode;Kh(a,e.type,l,t),a[Et]=t}catch(n){Ae(e,e.return,n)}}function xr(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Jl(e.type)||e.tag===4}function Kc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||xr(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Jl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Jc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=rl));else if(a!==4&&(a===27&&Jl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Jc(e,t,l),e=e.sibling;e!==null;)Jc(e,t,l),e=e.sibling}function ki(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&Jl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(ki(e,t,l),e=e.sibling;e!==null;)ki(e,t,l),e=e.sibling}function _r(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);xt(t,a,l),t[pt]=e,t[Et]=l}catch(i){Ae(e,e.return,i)}}var xl=!1,ut=!1,$c=!1,jr=typeof WeakSet=="function"?WeakSet:Set,ht=null;function Mh(e,t){if(e=e.containerInfo,gs=ru,e=wf(e),Xu(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,i=a.focusNode;a=a.focusOffset;try{l.nodeType,i.nodeType}catch{l=null;break e}var u=0,s=-1,o=-1,p=0,_=0,E=e,v=null;t:for(;;){for(var S;E!==l||n!==0&&E.nodeType!==3||(s=u+n),E!==i||a!==0&&E.nodeType!==3||(o=u+a),E.nodeType===3&&(u+=E.nodeValue.length),(S=E.firstChild)!==null;)v=E,E=S;for(;;){if(E===e)break t;if(v===l&&++p===n&&(s=u),v===i&&++_===a&&(o=u),(S=E.nextSibling)!==null)break;E=v,v=E.parentNode}E=S}l=s===-1||o===-1?null:{start:s,end:o}}else l=null}l=l||{start:0,end:0}}else l=null;for(ps={focusedElem:e,selectionRange:l},ru=!1,ht=t;ht!==null;)if(t=ht,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,ht=e;else for(;ht!==null;){switch(t=ht,i=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),xt(i,a,l),i[pt]=e,mt(i),a=i;break e;case"link":var u=Ad("link","href",n).get(a+(l.href||""));if(u){for(var s=0;sOe&&(u=Oe,Oe=W,W=u);var h=Of(s,W),m=Of(s,Oe);if(h&&m&&(S.rangeCount!==1||S.anchorNode!==h.node||S.anchorOffset!==h.offset||S.focusNode!==m.node||S.focusOffset!==m.offset)){var g=E.createRange();g.setStart(h.node,h.offset),S.removeAllRanges(),W>Oe?(S.addRange(g),S.extend(m.node,m.offset)):(g.setEnd(m.node,m.offset),S.addRange(g))}}}}for(E=[],S=s;S=S.parentNode;)S.nodeType===1&&E.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof s.focus=="function"&&s.focus(),s=0;sl?32:l,x.T=null,l=ls,ls=null;var i=Zl,u=Ml;if(ft=0,Ia=Zl=null,Ml=0,(_e&6)!==0)throw Error(r(331));var s=_e;if(_e|=4,wr(i.current),Cr(i,i.current,u,l),_e=s,Qn(0,!1),dt&&typeof dt.onPostCommitFiberRoot=="function")try{dt.onPostCommitFiberRoot(Bt,i)}catch{}return!0}finally{O.p=n,x.T=a,Ir(e,t)}}function ed(e,t,l){t=Kt(l,t),t=Bc(e.stateNode,t,2),e=Gl(e,t,2),e!==null&&(fn(e,2),cl(e))}function Ae(e,t,l){if(e.tag===3)ed(e,e,l);else for(;t!==null;){if(t.tag===3){ed(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(kl===null||!kl.has(a))){e=Kt(l,e),l=tr(2),a=Gl(t,l,2),a!==null&&(lr(l,a,t,e),fn(a,2),cl(a));break}}t=t.return}}function us(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Ah;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Ic=!0,n.add(l),e=wh.bind(null,e,t,l),t.then(e,e))}function wh(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Re===e&&(me&l)===l&&(Ie===4||Ie===3&&(me&62914560)===me&&300>pe()-Ki?(_e&2)===0&&Pa(e,0):Pc|=l,Fa===me&&(Fa=0)),cl(e)}function td(e,t){t===0&&(t=Ks()),e=ua(e,t),e!==null&&(fn(e,t),cl(e))}function Bh(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),td(e,l)}function Rh(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),td(e,l)}function Hh(e,t){return k(e,t)}var eu=null,tn=null,cs=!1,tu=!1,ss=!1,Kl=0;function cl(e){e!==tn&&e.next===null&&(tn===null?eu=tn=e:tn=tn.next=e),tu=!0,cs||(cs=!0,qh())}function Qn(e,t){if(!ss&&tu){ss=!0;do for(var l=!1,a=eu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var i=0;else{var u=a.suspendedLanes,s=a.pingedLanes;i=(1<<31-Ee(42|e)+1)-1,i&=n&~(u&~s),i=i&201326741?i&201326741|1:i?i|2:0}i!==0&&(l=!0,id(a,i))}else i=me,i=_t(a,a===Re?i:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(i&3)===0||fl(a,i)||(l=!0,id(a,i));a=a.next}while(l);ss=!1}}function Gh(){ld()}function ld(){tu=cs=!1;var e=0;Kl!==0&&$h()&&(e=Kl);for(var t=pe(),l=null,a=eu;a!==null;){var n=a.next,i=ad(a,t);i===0?(a.next=null,l===null?eu=n:l.next=n,n===null&&(tn=l)):(l=a,(e!==0||(i&3)!==0)&&(tu=!0)),a=n}ft!==0&&ft!==5||Qn(e),Kl!==0&&(Kl=0)}function ad(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,i=e.pendingLanes&-62914561;0s)break;var _=o.transferSize,E=o.initiatorType;_&&md(E)&&(o=o.responseEnd,u+=_*(o"u"?null:document;function Td(e,t,l){var a=ln;if(a&&typeof t=="string"&&t){var n=Zt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),zd.has(n)||(zd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),xt(t,"link",e),mt(t),a.head.appendChild(t)))}}function n0(e){El.D(e),Td("dns-prefetch",e,null)}function i0(e,t){El.C(e,t),Td("preconnect",e,t)}function u0(e,t,l){El.L(e,t,l);var a=ln;if(a&&e&&t){var n='link[rel="preload"][as="'+Zt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Zt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Zt(l.imageSizes)+'"]')):n+='[href="'+Zt(e)+'"]';var i=n;switch(t){case"style":i=an(e);break;case"script":i=nn(e)}Pt.has(i)||(e=U({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Pt.set(i,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(Kn(i))||t==="script"&&a.querySelector(Jn(i))||(t=a.createElement("link"),xt(t,"link",e),mt(t),a.head.appendChild(t)))}}function c0(e,t){El.m(e,t);var l=ln;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+Zt(a)+'"][href="'+Zt(e)+'"]',i=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":i=nn(e)}if(!Pt.has(i)&&(e=U({rel:"modulepreload",href:e},t),Pt.set(i,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Jn(i)))return}a=l.createElement("link"),xt(a,"link",e),mt(a),l.head.appendChild(a)}}}function s0(e,t,l){El.S(e,t,l);var a=ln;if(a&&e){var n=Ta(a).hoistableStyles,i=an(e);t=t||"default";var u=n.get(i);if(!u){var s={loading:0,preload:null};if(u=a.querySelector(Kn(i)))s.loading=5;else{e=U({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Pt.get(i))&&zs(e,l);var o=u=a.createElement("link");mt(o),xt(o,"link",e),o._p=new Promise(function(p,_){o.onload=p,o.onerror=_}),o.addEventListener("load",function(){s.loading|=1}),o.addEventListener("error",function(){s.loading|=2}),s.loading|=4,uu(u,t,a)}u={type:"stylesheet",instance:u,count:1,state:s},n.set(i,u)}}}function f0(e,t){El.X(e,t);var l=ln;if(l&&e){var a=Ta(l).hoistableScripts,n=nn(e),i=a.get(n);i||(i=l.querySelector(Jn(n)),i||(e=U({src:e,async:!0},t),(t=Pt.get(n))&&Ts(e,t),i=l.createElement("script"),mt(i),xt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function o0(e,t){El.M(e,t);var l=ln;if(l&&e){var a=Ta(l).hoistableScripts,n=nn(e),i=a.get(n);i||(i=l.querySelector(Jn(n)),i||(e=U({src:e,async:!0,type:"module"},t),(t=Pt.get(n))&&Ts(e,t),i=l.createElement("script"),mt(i),xt(i,"link",e),l.head.appendChild(i)),i={type:"script",instance:i,count:1,state:null},a.set(n,i))}}function Md(e,t,l,a){var n=(n=te.current)?iu(n):null;if(!n)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=an(l.href),l=Ta(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=an(l.href);var i=Ta(n).hoistableStyles,u=i.get(e);if(u||(n=n.ownerDocument||n,u={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},i.set(e,u),(i=n.querySelector(Kn(e)))&&!i._p&&(u.instance=i,u.state.loading=5),Pt.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Pt.set(e,l),i||r0(n,e,l,u.state))),t&&a===null)throw Error(r(528,""));return u}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=nn(l),l=Ta(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function an(e){return'href="'+Zt(e)+'"'}function Kn(e){return'link[rel="stylesheet"]['+e+"]"}function Ed(e){return U({},e,{"data-precedence":e.precedence,precedence:null})}function r0(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),xt(t,"link",l),mt(t),e.head.appendChild(t))}function nn(e){return'[src="'+Zt(e)+'"]'}function Jn(e){return"script[async]"+e}function Nd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+Zt(l.href)+'"]');if(a)return t.instance=a,mt(a),a;var n=U({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),mt(a),xt(a,"style",n),uu(a,l.precedence,e),t.instance=a;case"stylesheet":n=an(l.href);var i=e.querySelector(Kn(n));if(i)return t.state.loading|=4,t.instance=i,mt(i),i;a=Ed(l),(n=Pt.get(n))&&zs(a,n),i=(e.ownerDocument||e).createElement("link"),mt(i);var u=i;return u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),xt(i,"link",a),t.state.loading|=4,uu(i,l.precedence,e),t.instance=i;case"script":return i=nn(l.src),(n=e.querySelector(Jn(i)))?(t.instance=n,mt(n),n):(a=l,(n=Pt.get(i))&&(a=U({},l),Ts(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),mt(n),xt(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,uu(a,l.precedence,e));return t.instance}function uu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,i=n,u=0;u title"):null)}function d0(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Cd(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function m0(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=an(a.href),i=t.querySelector(Kn(n));if(i){t=i._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=su.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=i,mt(i);return}i=t.ownerDocument||t,a=Ed(a),(n=Pt.get(n))&&zs(a,n),i=i.createElement("link"),mt(i);var u=i;u._p=new Promise(function(s,o){u.onload=s,u.onerror=o}),xt(i,"link",a),l.instance=i}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=su.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Ms=0;function h0(e,t){return e.stylesheets&&e.count===0&&ou(e,e.stylesheets),0Ms?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function su(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)ou(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var fu=null;function ou(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,fu=new Map,t.forEach(y0,e),fu=null,su.call(e))}function y0(e,t){if(!(t.state.loading&4)){var l=fu.get(e);if(l)var a=l.get(null);else{l=new Map,fu.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),i=0;i"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(b){console.error(b)}}return f(),Bs.exports=O0(),Bs.exports}var w0=U0();const B0=sm(w0);const fm=(...f)=>f.filter((b,N,r)=>!!b&&b.trim()!==""&&r.indexOf(b)===N).join(" ").trim();const R0=f=>f.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const H0=f=>f.replace(/^([A-Z])|[\s-_]+(\w)/g,(b,N,r)=>r?r.toUpperCase():N.toLowerCase());const tm=f=>{const b=H0(f);return b.charAt(0).toUpperCase()+b.slice(1)};var qs={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};const G0=f=>{for(const b in f)if(b.startsWith("aria-")||b==="role"||b==="title")return!0;return!1},q0=w.createContext({}),L0=()=>w.useContext(q0),Y0=w.forwardRef(({color:f,size:b,strokeWidth:N,absoluteStrokeWidth:r,className:j="",children:A,iconNode:Y,...G},R)=>{const{size:y=24,strokeWidth:D=2,absoluteStrokeWidth:U=!1,color:Z="currentColor",className:ee=""}=L0()??{},X=r??U?Number(N??D)*24/Number(b??y):N??D;return w.createElement("svg",{ref:R,...qs,width:b??y??qs.width,height:b??y??qs.height,stroke:f??Z,strokeWidth:X,className:fm("lucide",ee,j),...!A&&!G0(G)&&{"aria-hidden":"true"},...G},[...Y.map(([F,re])=>w.createElement(F,re)),...Array.isArray(A)?A:[A]])});const Xe=(f,b)=>{const N=w.forwardRef(({className:r,...j},A)=>w.createElement(Y0,{ref:A,iconNode:b,className:fm(`lucide-${R0(tm(f))}`,`lucide-${f}`,r),...j}));return N.displayName=tm(f),N};const X0=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Ls=Xe("check",X0);const Q0=[["path",{d:"M12 13v8l-4-4",key:"1f5nwf"}],["path",{d:"m12 21 4-4",key:"1lfcce"}],["path",{d:"M4.393 15.269A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.436 8.284",key:"ui1hmy"}]],lm=Xe("cloud-download",Q0);const k0=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],Z0=Xe("copy",k0);const V0=[["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M17 20v2",key:"1rnc9c"}],["path",{d:"M17 2v2",key:"11trls"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M2 17h2",key:"7oei6x"}],["path",{d:"M2 7h2",key:"asdhe0"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"M20 17h2",key:"1fpfkl"}],["path",{d:"M20 7h2",key:"1o8tra"}],["path",{d:"M7 20v2",key:"4gnj0m"}],["path",{d:"M7 2v2",key:"1i4yhu"}],["rect",{x:"4",y:"4",width:"16",height:"16",rx:"2",key:"1vbyd7"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1",key:"z9xiuo"}]],om=Xe("cpu",V0);const K0=[["path",{d:"M6 2v14a2 2 0 0 0 2 2h14",key:"ron5a4"}],["path",{d:"M18 22V8a2 2 0 0 0-2-2H2",key:"7s9ehn"}]],J0=Xe("crop",K0);const $0=[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]],Ys=Xe("database",$0);const W0=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],am=Xe("download",W0);const F0=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}],["path",{d:"M12 10v6",key:"1bos4e"}],["path",{d:"m15 13-3 3-3-3",key:"6j2sf0"}]],I0=Xe("folder-down",F0);const P0=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],nm=Xe("folder-open",P0);const ey=[["path",{d:"M10 16h.01",key:"1bzywj"}],["path",{d:"M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"18tbho"}],["path",{d:"M21.946 12.013H2.054",key:"zqlbp7"}],["path",{d:"M6 16h.01",key:"1pmjb7"}]],Su=Xe("hard-drive",ey);const ty=[["path",{d:"M16 5h6",key:"1vod17"}],["path",{d:"M19 2v6",key:"4bpg5p"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5",key:"1ue2ih"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}]],ly=Xe("image-plus",ty);const ay=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],ny=Xe("image",ay);const iy=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],uy=Xe("info",iy);const cy=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],sy=Xe("layers",cy);const fy=[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]],oy=Xe("library",fy);const ry=[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],dy=Xe("moon",ry);const my=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],ta=Xe("refresh-cw",my);const hy=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],yy=Xe("shield",hy);const gy=[["path",{d:"M10 8h4",key:"1sr2af"}],["path",{d:"M12 21v-9",key:"17s77i"}],["path",{d:"M12 8V3",key:"13r4qs"}],["path",{d:"M17 16h4",key:"h1uq16"}],["path",{d:"M19 12V3",key:"o1uvq1"}],["path",{d:"M19 21v-5",key:"qua636"}],["path",{d:"M3 14h4",key:"bcjad9"}],["path",{d:"M5 10V3",key:"cb8scm"}],["path",{d:"M5 21v-7",key:"1w1uti"}]],Zs=Xe("sliders-vertical",gy);const py=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],vu=Xe("sparkles",py);const vy=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Xs=Xe("square",vy);const Sy=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],by=Xe("sun",Sy);const xy=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],_y=Xe("terminal",xy);const jy=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],ti=Xe("trash-2",jy);const zy=[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],Ty=Xe("triangle-alert",zy);function My({activeTab:f,setActiveTab:b,specs:N}){return c.jsxs("div",{className:"sidebar",children:[c.jsxs("div",{children:[c.jsxs("div",{className:"sidebar-logo",children:[c.jsx(yy,{className:"sidebar-logo-icon"}),c.jsx("span",{className:"sidebar-logo-text",children:"Local AI Studio"})]}),c.jsxs("div",{className:"nav-list",children:[c.jsxs("div",{className:`nav-item ${f==="generator"?"active":""}`,onClick:()=>b("generator"),children:[c.jsx(ny,{size:20}),c.jsx("span",{children:"Image Generator"})]}),c.jsxs("div",{className:`nav-item ${f==="models"?"active":""}`,onClick:()=>b("models"),children:[c.jsx(I0,{size:20}),c.jsx("span",{children:"Model Manager"})]}),c.jsxs("div",{className:`nav-item ${f==="constraints"?"active":""}`,onClick:()=>b("constraints"),children:[c.jsx(Zs,{size:20}),c.jsx("span",{children:"Image Constraints"})]})]})]}),c.jsxs("div",{className:"sidebar-footer",children:[c.jsxs("div",{className:"sidebar-specs-header",children:[c.jsx(_y,{size:12}),c.jsx("span",{children:"Host Specifications"})]}),c.jsxs("div",{className:"sidebar-specs-item",title:N.cpu_name,children:["CPU: ",N.cpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",title:N.gpu_name,children:["GPU: ",N.gpu_name]}),c.jsxs("div",{className:"sidebar-specs-item",children:["Memory: ",N.ram_total_gb.toFixed(0)," GB RAM (",N.cpu_cores_physical," Cores)"]}),c.jsxs("div",{className:"sidebar-specs-os",children:["OS: ",N.os_name]})]})]})}const Ey=w.memo(My);function Ny({telemetry:f,serverRunning:b,activeModel:N,onStopServer:r,isStoppingServer:j=!1,theme:A,setTheme:Y}){const G=D=>{const U=Number(D);return Number.isFinite(U)&&U>0?U.toFixed(U>=10?0:1):"--"},R=()=>b?"Server Active":"Local Mode",y=()=>b?"status-indicator busy":"status-indicator offline";return c.jsxs("div",{className:"top-status-bar",children:[c.jsxs("div",{className:"current-model-info",children:[c.jsx("div",{className:y()}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:R()}),N&&c.jsxs(c.Fragment,{children:[c.jsx("span",{style:{color:"var(--md-sys-color-outline-variant)"},children:"|"}),c.jsx("span",{style:{color:"var(--md-sys-color-primary)",fontWeight:700},children:N})]})]}),c.jsxs("div",{className:"telemetry-group",children:[c.jsx("button",{className:"theme-toggle-btn",onClick:()=>Y(A==="dark"?"light":"dark"),title:`Switch to ${A==="dark"?"light":"dark"} theme`,children:A==="dark"?c.jsx(by,{size:18}):c.jsx(dy,{size:18})}),b&&c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:r,disabled:j,title:"Stop local model server",children:[j?c.jsx(ta,{className:"progress-spinner",size:14}):c.jsx(Xs,{size:14}),c.jsx("span",{children:j?"Stopping":"Stop Server"})]}),c.jsxs("div",{className:"telemetry-chip",title:"CPU Utilization",children:[c.jsx(om,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-primary)"}}),c.jsxs("span",{children:["CPU: ",Number.isFinite(Number(f.cpu_usage))?f.cpu_usage:"--","%"]})]}),c.jsxs("div",{className:"telemetry-chip",title:"System Memory Usage",children:[c.jsx(Su,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-secondary)"}}),c.jsxs("span",{children:["RAM: ",G(f.ram_used_gb)," / ",G(f.ram_total_gb)," GB"]})]}),f.vram_total_gb>0&&c.jsxs("div",{className:"telemetry-chip",title:`${f.gpu_name} VRAM`,children:[c.jsx(Ys,{className:"telemetry-chip-icon",style:{color:"var(--md-sys-color-tertiary)"}}),c.jsxs("span",{children:["VRAM: ",G(f.vram_used_gb)," / ",G(f.vram_total_gb)," GB"]})]})]})]})}const Ay=w.memo(Ny),Dy="modulepreload",Cy=function(f){return"/"+f},im={},Oy=function(b,N,r){let j=Promise.resolve();if(N&&N.length>0){let R=function(y){return Promise.all(y.map(D=>Promise.resolve(D).then(U=>({status:"fulfilled",value:U}),U=>({status:"rejected",reason:U}))))};document.getElementsByTagName("link");const Y=document.querySelector("meta[property=csp-nonce]"),G=Y?.nonce||Y?.getAttribute("nonce");j=R(N.map(y=>{if(y=Cy(y),y in im)return;im[y]=!0;const D=y.endsWith(".css"),U=D?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${y}"]${U}`))return;const Z=document.createElement("link");if(Z.rel=D?"stylesheet":Dy,D||(Z.as="script"),Z.crossOrigin="",Z.href=y,G&&Z.setAttribute("nonce",G),document.head.appendChild(Z),D)return new Promise((ee,X)=>{Z.addEventListener("load",ee),Z.addEventListener("error",()=>X(new Error(`Unable to preload CSS for ${y}`)))})}))}function A(Y){const G=new Event("vite:preloadError",{cancelable:!0});if(G.payload=Y,window.dispatchEvent(G),!G.defaultPrevented)throw Y}return j.then(Y=>{for(const G of Y||[])G.status==="rejected"&&A(G.reason);return b().catch(A)})};function o1(f,b=!1){return window.__TAURI_INTERNALS__.transformCallback(f,b)}async function xa(f,b={},N){return window.__TAURI_INTERNALS__.invoke(f,b,N)}const Nl=()=>typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0;let ea=null;const Uy="polish-setup-v1",ba=()=>typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");function li(f){const b=Number(f)||0;if(b<=0)return"0 B";const N=["B","KB","MB","GB","TB"],r=Math.min(N.length-1,Math.floor(Math.log(b)/Math.log(1024)));return`${(b/1024**r).toFixed(r===0?0:1)} ${N[r]}`}function ai(f){return typeof f=="string"?{filename:f,sizeBytes:0,size:"Unknown"}:{filename:f?.filename||f?.name||"",sizeBytes:Number(f?.sizeBytes||0),size:f?.size||(f?.sizeBytes?li(f.sizeBytes):"Unknown")}}async function cn(f,b="The local server returned an invalid response."){const N=await f.text();let r={};try{r=JSON.parse(N||"{}")}catch{const A=N.trim().startsWith("{const ee=y.steps;for(let $=1;$<=ee;$++){if(Y&&Y.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(je=>setTimeout(je,3e3/ee)),A&&A(Math.round($/ee*100))}const X=f.toLowerCase(),F=Math.abs(y.seed)||Math.floor(Math.random()*1e3);let re="#3B82F6",I="#8B5CF6",ne="",ce="Abstract Generation";X.includes("moon")||X.includes("space")||X.includes("astronomy")||X.includes("sky")?(re="#1E293B",I="#0F172A",ce="Luminous Moon in Starry Sky",ne=` + + + + + + + + + + + + `):X.includes("cat")||X.includes("kitten")||X.includes("feline")?(re="#4F46E5",I="#7C3AED",ce="Stylized Cat Portrait",ne=` + + + + + + + + + + + + + + + + `):X.includes("dog")||X.includes("puppy")||X.includes("canine")?(re="#D97706",I="#B45309",ce="Friendly Dog Portrait",ne=` + + + + + + + + + + + + + `):X.includes("city")||X.includes("cyberpunk")||X.includes("tokyo")||X.includes("neon")?(re="#111827",I="#311042",ce="Neon Cyberpunk Skyline",ne=` + + + + + + + + + + + + + `):X.includes("car")||X.includes("vehicle")||X.includes("supercar")?(re="#DC2626",I="#991B1B",ce="Futuristic Concept Car",ne=` + + + + + + + + + + + + + `):(re="#06B6D4",I="#0891B2",ce="Abstract Creative Concept",ne=` + + + + `);const Ge=` + + + + + + + + + + + + + + + + + ${ne} + + + + + + + ${ce} + Seed: ${F} • Steps: ${y.steps} • Scale: ${y.cfg_scale} + + `;return{image:`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(Ge)))}`,seed:y.seed,duration_sec:3}},U=!!y.image,Z={prompt:y.prompt,negative_prompt:y.negative_prompt||"",n:1,size:`${y.width}x${y.height}`,response_format:"b64_json",steps:y.steps,cfg_scale:y.cfg_scale,seed:y.seed,sample_method:y.sampler};U&&(Z.init_images=[y.image],Z.denoising_strength=y.denoising_strength);try{const ee=await fetch(`${R}/v1/images/generations`,{method:"POST",headers:{"Content-Type":"application/json"},signal:Y,body:JSON.stringify(Z)});if(ee.ok){const X=await ee.json(),F=X?.data?.[0]?.b64_json??X?.images?.[0];if(F)return{image:`data:image/png;base64,${F}`,seed:X.data?.[0]?.seed??y.seed,duration_sec:4.5}}else{let X=`Generation failed (HTTP ${ee.status})`;try{const F=await ee.json();(F?.detail||F?.error?.message)&&(X=F.detail||F.error.message)}catch{}throw new Error(X)}}catch(ee){if(ee.name==="AbortError"||ee.message.startsWith("Generation failed"))throw ee;console.warn("Could not reach local server. Falling back to simulation mode.",ee)}return await D()}async function Ky(f,b,N){if(f instanceof File){const G=f;if(!ba())throw new Error("File import requires the local image generator server.");return await Jy(G,b,N),{response:"Model imported successfully"}}if(Nl()){const{listen:G}=await Oy(async()=>{const{listen:y}=await import("./event-DL84ZN__.js");return{listen:y}},[]);let R=null;b&&(R=await G("import-progress",y=>{b(y.payload)}));try{return{response:await xa("import_model_file",{sourcePath:f}),unlisten:R}}catch(y){throw R&&R(),y}}const r=f.split(/[\\/]/).pop()||"imported_model.gguf";console.log(`Web Mode: Simulating copying ${r} to USB models folder`);const j=40;for(let G=1;G<=j;G++){if(N?.aborted)throw new DOMException("The user aborted a request.","AbortError");await new Promise(U=>setTimeout(U,150));const R=G/j*100,y=40+Math.sin(G)*5+Math.random()*2,D=(j-G)*.15;b&&b({filename:r,progress:R,speed_mb_s:y,eta_secs:D,status:"Copying to USB..."})}const A=localStorage.getItem("imported-models"),Y=A?JSON.parse(A):[];return Y.includes(r)||(Y.push({filename:r,sizeBytes:0,size:"Unknown"}),localStorage.setItem("imported-models",JSON.stringify(Y))),{response:"Model imported successfully"}}function Jy(f,b,N){return new Promise((r,j)=>{const A=new XMLHttpRequest,Y=Date.now();let G=!1;A.open("POST",`/api/import-model?filename=${encodeURIComponent(f.name)}`),A.setRequestHeader("Content-Type","application/octet-stream");const R=()=>{G=!0,A.abort()};N&&(N.aborted?R():N.addEventListener("abort",R,{once:!0})),A.upload.onprogress=y=>{if(!y.lengthComputable||!b)return;const D=Math.max(.1,(Date.now()-Y)/1e3),U=y.loaded/D,Z=Math.max(0,y.total-y.loaded);b({filename:f.name,progress:y.loaded/y.total*100,speed_mb_s:U/(1024*1024),eta_secs:Z/Math.max(1,U),status:"Copying to models folder..."})},A.onload=()=>{let y={};try{y=JSON.parse(A.responseText||"{}")}catch{}A.status>=200&&A.status<300&&y.ok!==!1?(b&&b({filename:f.name,progress:100,speed_mb_s:0,eta_secs:0,status:"Import complete"}),r(y)):j(new Error(y.error||`Import failed (HTTP ${A.status})`))},A.onerror=()=>j(new Error("Import failed while uploading the file.")),A.onabort=()=>j(new DOMException(G?"Import cancelled by user.":"Import aborted.","AbortError")),A.send(f)})}async function $y(f){if(Nl())return await xa("delete_model_file",{filename:f});if(typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"))try{const j=await fetch("/api/delete-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:f})}),A=await j.json();if(!j.ok)throw new Error(A.error||"Failed to delete model file");return A}catch(j){throw console.error("Failed to delete model via local API:",j),j}const N=localStorage.getItem("imported-models");let r=N?JSON.parse(N):[];return r=r.filter(j=>ai(j).filename!==f),localStorage.setItem("imported-models",JSON.stringify(r)),`Simulated deletion of ${f} from browser session`}async function rm(){const b="http://127.0.0.1:8080";try{return(await fetch(`${b}/v1/models`,{method:"GET"})).ok}catch{return!1}}async function Wy(f=30){const b=Nl()||ba()?f:3;for(let N=0;NsetTimeout(j,500))}return!1}async function Fy(f){try{return await(await fetch("/api/download-model",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:f})})).json()}catch(b){return console.error("Failed to start model download:",b),{ok:!1,error:b.message}}}async function Iy(){try{return await(await fetch("/api/cancel-download",{method:"POST"})).json()}catch(f){return console.error("Failed to cancel model download:",f),{ok:!1,error:f.message}}}async function um(){try{return await(await fetch("/api/download-progress")).json()}catch(f){return console.error("Failed to get download progress:",f),{active:!1,error:f.message}}}async function Py(){try{return await(await fetch("/api/generation-progress")).json()}catch(f){return console.error("Failed to get generation progress:",f),{active:!1,error:f.message}}}const e1=w.memo(({img:f,idx:b,isSelected:N,onClick:r})=>{const j=A=>{r(b,A)};return c.jsxs("div",{className:`gallery-item ${N?"selected":""}`,onClick:j,title:`Prompt: ${f.prompt} +Seed: ${f.seed}`,children:[c.jsx("img",{src:f.url,className:"gallery-thumb",alt:"Thumbnail",loading:"lazy",decoding:"async"}),N&&c.jsx("div",{className:"gallery-select-badge",children:c.jsx(Ls,{size:14})})]})});function t1({prompt:f,setPrompt:b,negativePrompt:N,setNegativePrompt:r,constraints:j,setConstraints:A,activeModel:Y,generatedImages:G,setGeneratedImages:R,isGenerating:y,setIsGenerating:D,generationProgress:U,setGenerationProgress:Z,setActiveTab:ee,inputImage:X,setInputImage:F,showAlert:re=async({message:ne})=>window.alert(ne),showConfirm:I=async({message:ne})=>window.confirm(ne)}){const[ne,ce]=w.useState(null),[Ge,Ve]=w.useState(null),[Qe,$]=w.useState(null),[je,ot]=w.useState(!1),[qe,Me]=w.useState(0),[Ke,$e]=w.useState(0),[tt,Je]=w.useState(0),[x,O]=w.useState(""),[K,se]=w.useState(!1),[de,d]=w.useState(!1),[z,B]=w.useState(!1),[H,P]=w.useState(null),[te,le]=w.useState(null),[Ue,ze]=w.useState([]),ct=w.useRef(null),yt=w.useRef(null),wt=w.useRef(null),Al=()=>{yt.current.click()},rt=L=>{const ve=L.target.files[0];if(ve){const we=new FileReader;we.onload=()=>{F(we.result)},we.readAsDataURL(ve)}},al=L=>{L.stopPropagation(),F(null),yt.current&&(yt.current.value="")},sl=async()=>{if(!f.trim())return;le(null),B(!0),P(null);let L=!1;try{const Te=await Sa();if(Te&&Te.settings){const xe=Te.settings,ke=xe.model?xe.model.split(/[\\/]/).pop():null,ye=Y?Y.split(/[\\/]/).pop():null;(ke!==ye||parseInt(xe.steps)!==parseInt(j.steps)||Math.abs(parseFloat(xe.cfgScale)-parseFloat(j.cfgScale))>.05||xe.sampler!==j.sampler||parseInt(xe.threads)!==parseInt(j.threads)||!!xe.useGpu!=(j.useGpu!==!1)||(xe.backendType||(xe.useGpu===!1?"cpu":"auto"))!==(j.backendType||(j.useGpu===!1?"cpu":"auto")))&&(L=!0)}else L=!0}catch{L=!0}if(L)try{console.log("Settings out of sync, restarting backend..."),await Qs(Y,j);let Te=!1,xe=null;for(let ke=0;ke<240;ke++){const ye=await Sa();if(ye.loading&&P({progress:ye.loading.progress||0,phase:ye.loading.phase||"Loading model...",speed:ye.loading.speed||"",current:ye.loading.current||0,total:ye.loading.total||0,backendMode:ye.loading.backendMode||ye.settings?.backendMode||"",device:ye.loading.device||ye.settings?.backendDevice||""}),ye.ready){Te=!0;break}if(ye.error){xe=ye.error;break}if(!ye.running&&ke>3){xe="The backend process terminated immediately on startup.";break}await new Promise(lt=>setTimeout(lt,500))}if(!Te)throw new Error(xe||"Backend server failed to start after applying configuration changes.")}catch(Te){console.error("Failed to restart backend:",Te),le(Te.message||"Failed to sync settings with backend."),B(!1);return}B(!1),P(null),ct.current&&clearInterval(ct.current),D(!0),Z(0),Me(0),Je(0),O(""),se(!1),$(null),ce(null);const ve=(j.width>=1024?140:35)*.04,we=j.width>=1024?140:35,gt=(j.backendType||(j.useGpu===!1?"cpu":"auto"))!=="cpu";let Tt=gt?ve:we,Bt=!1,dt=0,Rt=0,Ee=0;$e(Math.round(j.steps*Tt)),ct.current=setInterval(async()=>{Ee++,Me(Ee);try{const Te=await Py();if(Te&&Te.active){const xe=Te.step||0,ke=Te.steps||j.steps||20,ye=Te.speed||"";Je(xe),O(ye);let lt=0;ke>0&&(lt=Math.round(xe/ke*100)),lt=Math.min(99,lt),Z(_t=>Math.max(_t,lt));let Be=0;const We=parseFloat(ye);if(!isNaN(We)&&We>0){const _t=Math.max(0,ke-xe);ye.includes("it/s")?Be=_t/We:ye.includes("s/it")&&(Be=_t*We)}else{const _t=gt?ve:we;Be=Math.max(0,(ke-xe)*_t)}if(gt&&!Bt){const _t=ye.includes("it/s")&&We<.2,fl=ye.includes("s/it")&&We>5;(_t||fl)&&(Bt=!0,se(!0))}$e(Math.round(Be))}else Z(xe=>Math.min(15,xe+1)),$e(xe=>Math.max(1,xe-1))}catch(Te){console.warn("Failed to get generation progress, running simulation fallback:",Te),gt&&!Bt&&Ee>j.steps*ve*1.3&&(Bt=!0,se(!0),Tt=we,dt=Ee,Rt=Math.min(95,Math.round(Ee/(j.steps*ve)*100)));let xe=Math.min(j.steps-1,Math.floor(Ee/Tt)),ke=j.steps*Tt;if(Ee>=ke){const Be=Math.ceil(Ee/Math.max(.5,xe));Tt=Math.max(Tt+15,Be+15),ke=j.steps*Tt,xe=Math.min(j.steps-1,Math.floor(Ee/Tt))}Je(xe);const ye=Math.max(1,ke-Ee);$e(Math.round(ye));let lt=0;if(Bt){const Be=99-Rt,We=ke-dt;if(We>0){const _t=Math.min(1,(Ee-dt)/We);if(_t<.85)lt=Math.round(Rt+_t*Be);else{const fl=(Ee-(dt+We*.85))/(Tt*2),bu=1-Math.exp(-fl);lt=Math.min(99,Math.round(Rt+.85*Be+.14*Be*bu))}}else lt=99}else if(EeMath.max(Be,lt))}},1e3);try{wt.current=new AbortController;const Te=await Vy(f,N,j,Y,X,Be=>Z(We=>Math.max(We,Be)),wt.current.signal);ct.current&&clearInterval(ct.current),Z(100),Je(j.steps),$e(0),O("");const xe={prompt:f,negativePrompt:N,seed:Te.seed,steps:j.steps,cfgScale:j.cfgScale,width:j.width,height:j.height,sampler:j.sampler,model:Y,duration_sec:Te.duration_sec,timestamp:new Date().toLocaleTimeString(),inputImage:!!X};let ke=null,ye=null;try{if(ke=await Qy(Te.image,xe),ye=ke.url,!ye)throw new Error("The local server saved the image but did not return a file URL.")}catch(Be){throw console.error("Generated image could not be saved:",Be),new Error(`Image generated but could not be saved to USB: ${Be.message||Be}`)}ce(ye),Ve(Te.seed),$(Te.duration_sec);const lt={...xe,...ke||{},url:ye};R(Be=>[lt,...Be])}catch(Te){Te.name==="AbortError"?console.log("Generation request was aborted by the user"):(console.error("Generation failed:",Te),le(Te.message||"Generation failed. Please try again.")),ct.current&&clearInterval(ct.current)}finally{D(!1),wt.current=null}},T=async()=>{if(await I({title:"Stop Generation?",message:"The current image generation will be cancelled and the local model server may restart.",confirmLabel:"Stop",danger:!0}))if(ct.current&&clearInterval(ct.current),d(!0),wt.current&&wt.current.abort(),Nl())try{console.log("Cancelling: Stopping server to kill generation threads..."),await Vs(),Y&&(console.log("Cancelling: Restarting server for future generations..."),await Qs(Y,j),await Wy()||console.warn("Server failed to restart properly."))}catch(L){console.error("Failed to restart server on cancellation:",L)}finally{d(!1),D(!1),Z(0)}else d(!1),D(!1),Z(0)},C=async()=>{if(ne)try{if(ne.startsWith("data:image")){const ve=await(await fetch(ne)).blob();await navigator.clipboard.write([new ClipboardItem({[ve.type]:ve})])}else{const L=new Image;L.crossOrigin="anonymous",L.src=ne,L.onload=async()=>{const ve=document.createElement("canvas");ve.width=L.width,ve.height=L.height,ve.getContext("2d").drawImage(L,0,0),ve.toBlob(async gt=>{await navigator.clipboard.write([new ClipboardItem({[gt.type]:gt})])},"image/png")}}ot(!0),setTimeout(()=>ot(!1),2e3)}catch(L){console.error("Failed to copy image:",L)}},q=()=>{if(!ne)return;const L=document.createElement("a");L.href=ne,L.download=`diffusion-${Ge||Date.now()}.png`,document.body.appendChild(L),L.click(),document.body.removeChild(L)},k=(L,ve=`diffusion-${Date.now()}.png`)=>{if(!L)return;const we=document.createElement("a");we.href=L,we.download=ve,document.body.appendChild(we),we.click(),document.body.removeChild(we)},He=w.useCallback(L=>{b(L.prompt),r(L.negativePrompt),A(ve=>({...ve,steps:L.steps,cfgScale:L.cfgScale,width:L.width,height:L.height,sampler:L.sampler,seed:L.seed})),ce(L.url),Ve(L.seed),$(null)},[b,r,A]),zt=w.useCallback((L,ve)=>{const we=ve.ctrlKey||ve.metaKey||ve.shiftKey;ze(gt=>we?gt.includes(L)?gt.filter(Tt=>Tt!==L):[...gt,L]:[L]),G[L]&&He(G[L])},[G,He]),st=Ue.map(L=>G[L]).filter(Boolean),pe=()=>{ze([])},sn=()=>{st[0]&&He(st[0])},ni=()=>{st.forEach((L,ve)=>{const we=L.seed??Date.now();k(L.url,`diffusion-${we}-${ve+1}.png`)})},ii=async()=>{if(st.length===0)return;const L=st.length;if(await I({title:"Delete Selected Outputs?",message:`Delete ${L} selected output${L===1?"":"s"} from USB? This removes the image and metadata files.`,confirmLabel:"Delete",danger:!0}))try{await ky(st);const we=new Set(Ue);R(gt=>gt.filter((Tt,Bt)=>!we.has(Bt))),ze([]),st.some(gt=>gt.url===ne)&&(ce(null),Ve(null),$(null))}catch(we){console.error("Failed to delete selected outputs:",we),re({title:"Delete Failed",message:we.message||String(we),danger:!0})}};return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Generator Dashboard"}),c.jsx("p",{className:"workspace-subtitle",children:"Create high-fidelity images completely locally on your external drive."})]}),c.jsxs("div",{className:"generator-layout",children:[c.jsx("div",{children:c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(vu,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"Generation Workspace"]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Positive Prompt"}),c.jsx("textarea",{className:"m3-textarea",value:f,onChange:L=>b(L.target.value),placeholder:"Enter a descriptive prompt (e.g. 'A futuristic city in cyberpunk aesthetic, high details, cinematic lighting')...",disabled:y})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Negative Prompt (Optional)"}),c.jsx("input",{type:"text",className:"m3-input",value:N,onChange:L=>r(L.target.value),placeholder:"Items to avoid (e.g. 'blurry, low quality, deformed hands, texts')...",disabled:y})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Active Image Constraints"}),c.jsxs("div",{className:"chips-container",children:[c.jsxs("div",{className:"status-chip",onClick:()=>ee("constraints"),children:[c.jsx(Zs,{size:14}),c.jsxs("span",{children:["Resolution: ",j.width,"x",j.height]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>ee("constraints"),children:[c.jsx(ta,{size:14}),c.jsxs("span",{children:["Steps: ",j.steps]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>ee("constraints"),children:[c.jsx(sy,{size:14}),c.jsxs("span",{children:["CFG: ",j.cfgScale.toFixed(1)]})]}),c.jsxs("div",{className:"status-chip",onClick:()=>ee("constraints"),children:[c.jsx(vu,{size:14}),c.jsxs("span",{children:["Sampler: ",j.sampler]})]}),c.jsx("div",{className:"status-chip",onClick:()=>ee("constraints"),children:c.jsxs("span",{children:["Seed: ",j.seed===-1?"Random":j.seed]})})]})]}),c.jsxs("div",{className:"image-to-image-section",children:[c.jsx("label",{className:"m3-text-field-label",style:{display:"block",marginBottom:"8px"},children:"Image-to-Image Source (Optional)"}),c.jsxs("div",{className:"image-dropzone",onClick:Al,children:[c.jsx("input",{type:"file",ref:yt,style:{display:"none"},accept:"image/*",onChange:rt,disabled:y}),X?c.jsxs("div",{style:{position:"relative",width:"100%",height:"100%"},children:[c.jsx("img",{src:X,className:"dropped-image-preview",alt:"Source"}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{position:"absolute",top:"4px",right:"4px",height:"30px",width:"30px",borderRadius:"50%",padding:0},onClick:al,children:"×"})]}):c.jsxs(c.Fragment,{children:[c.jsx(ly,{size:24,style:{color:"var(--md-sys-color-primary)"}}),c.jsx("span",{style:{fontSize:"0.85rem",fontWeight:500},children:"Click or drag image here for Image-to-Image guidance"})]})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"48px",marginTop:"8px"},onClick:sl,disabled:y||!f.trim()||!Y,children:[c.jsx(vu,{size:18}),c.jsx("span",{children:Y?"Generate Local Image":"Select Model to Generate"})]})]})]})}),c.jsxs("div",{className:"m3-card output-panel",children:[c.jsx("div",{className:"output-image-container",children:y||de||z?c.jsx("div",{className:"progress-overlay",children:z?c.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"16px",padding:"20px"},children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700,textAlign:"center"},children:"Syncing Settings & Initializing..."}),H?c.jsxs("div",{style:{width:"min(360px, 90%)"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",gap:"12px",fontSize:"0.82rem",fontWeight:700,marginBottom:"6px"},children:[c.jsxs("span",{children:[H.phase,H.speed?` (${H.speed})`:""]}),c.jsx("span",{children:H.total>0?`Loaded ${H.current} / ${H.total} tensors`:`${Math.round(H.progress)}%`})]}),c.jsx("div",{className:"progress-bar-container",style:{margin:0},children:c.jsx("div",{className:"progress-bar-fill",style:{width:`${Math.min(100,Math.max(0,H.progress))}%`,transition:"width 0.25s ease"}})}),(H.backendMode||H.device)&&c.jsxs("div",{style:{fontSize:"0.78rem",opacity:.8,textAlign:"center",marginTop:"8px"},children:["Loading on ",H.backendMode||"backend",H.device?` • ${H.device}`:""]})]}):c.jsx("p",{style:{fontSize:"0.85rem",opacity:.8,textAlign:"center",maxWidth:"280px",margin:0},children:"Adjusting inference settings and restarting the local model server."})]}):de?c.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"16px",padding:"20px"},children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700,textAlign:"center"},children:"Cancelling Generation..."}),c.jsx("p",{style:{fontSize:"0.85rem",opacity:.8,textAlign:"center",maxWidth:"280px",margin:0},children:"Stopping CPU/GPU execution threads and reloading model weights. Please wait a moment."})]}):c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"progress-spinner"}),c.jsx("div",{className:"progress-text",style:{fontSize:"1.1rem",fontWeight:700},children:"Generating Locally..."}),K&&c.jsx("div",{style:{fontSize:"0.8rem",color:"var(--md-sys-color-primary)",fontWeight:600,background:"var(--md-sys-color-primary-container)",padding:"4px 12px",borderRadius:"12px",margin:"4px 0 8px 0",animation:"pulse 2s infinite"},children:"⚠️ CPU Fallback Detected (Running Slower)"}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"16px",width:"80%",margin:"8px 0 0 0",fontSize:"0.85rem",opacity:.9},children:[c.jsxs("div",{style:{textAlign:"left"},children:[c.jsx("strong",{children:"Step:"})," ",tt," / ",j.steps," (",j.steps-tt," left)"]}),c.jsxs("div",{style:{textAlign:"right"},children:[c.jsx("strong",{children:"Elapsed:"})," ",qe,"s",x&&` (${x})`]})]}),c.jsx("div",{className:"progress-bar-container",style:{margin:"4px 0 10px 0"},children:c.jsx("div",{className:"progress-bar-fill",style:{width:`${U}%`,transition:"width 1s linear"}})}),c.jsxs("div",{style:{fontSize:"0.85rem",opacity:.8,display:"flex",gap:"8px",alignItems:"center"},children:[c.jsxs("span",{children:["Progress: ",U,"%"]}),c.jsx("span",{children:"•"}),c.jsxs("span",{children:["Est. remaining: ",Ke,"s"]})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{marginTop:"16px",height:"36px",padding:"0 24px"},onClick:T,children:"Stop Generating"})]})}):ne?c.jsx("img",{src:ne,className:"output-image",alt:"Generated Output"}):te?c.jsxs("div",{style:{textAlign:"center",padding:"24px",color:"var(--md-sys-color-error)",display:"flex",flexDirection:"column",alignItems:"center",gap:"16px"},children:[c.jsx("div",{style:{background:"rgba(239, 68, 68, 0.1)",padding:"16px",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center"},children:c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"48",height:"48",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})})}),c.jsx("h3",{style:{margin:0,fontSize:"1.2rem",fontWeight:"bold"},children:"Generation Failed"}),c.jsx("p",{style:{margin:0,fontSize:"0.95rem",opacity:.9,maxWidth:"320px",lineHeight:"1.4"},children:te}),c.jsxs("div",{style:{marginTop:"8px",fontSize:"0.85rem",opacity:.8,color:"var(--md-sys-color-on-surface-variant)"},children:["Hint: Try lowering the resolution in the ",c.jsx("strong",{children:"Image Constraints"})," settings (e.g., to 512x512)."]})]}):c.jsxs("div",{style:{textAlign:"center"},children:[c.jsx(vu,{className:"output-placeholder-icon"}),c.jsxs("p",{className:"output-placeholder-text",children:["Your generated image will appear here.",c.jsx("br",{}),"Enter a prompt on the left and click Generate."]})]})}),ne&&!y&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{style:{width:"100%",display:"flex",justifyContent:"space-between",marginTop:"12px",fontSize:"0.8rem",color:"var(--md-sys-color-outline)"},children:[c.jsxs("span",{children:["Seed: ",Ge]}),Qe&&c.jsxs("span",{children:["Inference Time: ",Qe.toFixed(1),"s"]})]}),c.jsxs("div",{className:"image-actions",children:[c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:C,children:[je?c.jsx(Ls,{size:16}):c.jsx(Z0,{size:16}),c.jsx("span",{children:je?"Copied":"Copy"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:q,children:[c.jsx(am,{size:16}),c.jsx("span",{children:"Save to USB"})]})]})]})]})]}),c.jsxs("div",{className:"gallery-section",children:[c.jsxs("div",{className:"gallery-header",children:[c.jsx("h3",{className:"m3-card-title",style:{marginBottom:0},children:"Recent Outputs Gallery"}),st.length>0&&c.jsxs("div",{className:"gallery-selection-actions",children:[c.jsxs("span",{className:"gallery-selection-count",children:[st.length," selected"]}),c.jsxs("button",{className:"m3-btn m3-btn-tonal",onClick:sn,children:[c.jsx(Ls,{size:14}),c.jsx("span",{children:"Use"})]}),c.jsxs("button",{className:"m3-btn m3-btn-outlined",onClick:ni,children:[c.jsx(am,{size:14}),c.jsx("span",{children:"Download"})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ii,children:[c.jsx(ti,{size:14}),c.jsx("span",{children:"Delete"})]}),c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:pe,children:"Clear"})]})]}),G.length===0?c.jsx("div",{className:"m3-card gallery-empty",children:"No images generated in this session yet. Everything will be saved directly on your external drive."}):c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"gallery-hint",children:"Click to select one image. Ctrl-click or Shift-click to select multiple."}),c.jsx("div",{className:"gallery-grid",children:G.map((L,ve)=>c.jsx(e1,{img:L,idx:ve,isSelected:Ue.includes(ve),onClick:zt},L.image||ve))})]})]})]})}const l1=w.memo(t1),a1=[{group:"SDXL - Best Quality",items:[{name:"Juggernaut XL v9 Lightning",filename:"Juggernaut_RunDiffusionPhoto2_Lightning_4Steps.safetensors",format:"Safetensors",approxSize:"6.6 GB",resolution:"1024x1024",notes:"Photorealistic SDXL model tuned for 4-8 step Lightning generation.",url:"https://huggingface.co/RunDiffusion/Juggernaut-XL-Lightning/resolve/main/Juggernaut_RunDiffusionPhoto2_Lightning_4Steps.safetensors"},{name:"DreamShaper XL Lightning",filename:"DreamShaperXL_Lightning.safetensors",format:"Safetensors",approxSize:"6.6 GB",resolution:"1024x1024",notes:"All-around SDXL model for fantasy art, renders, illustration, and stylized images.",url:"https://huggingface.co/Lykon/dreamshaper-xl-lightning/resolve/main/DreamShaperXL_Lightning.safetensors"},{name:"SDXL Base 1.0 Q4_0 GGUF",filename:"stable-diffusion-xl-base-1.0-Q4_0.gguf",format:"GGUF",approxSize:"3.8 GB",resolution:"1024x1024",notes:"Quantized SDXL base model for lower VRAM or CPU-friendly generation.",url:"https://huggingface.co/hum-ma/SDXL-models-GGUF/resolve/7e15380138e7069ca3aaef5bf0401c3406e3a593/stable-diffusion-xl-base-1.0-Q4_0.gguf"}]},{group:"SD 1.5 - Ultra Fast / Low VRAM",items:[{name:"DreamShaper 8",filename:"DreamShaper_8_pruned.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"General-purpose SD 1.5 model for illustration, anime, and semi-realistic portraits.",url:"https://huggingface.co/Lykon/DreamShaper/resolve/main/DreamShaper_8_pruned.safetensors"},{name:"CyberRealistic V8",filename:"CyberRealistic_V8_FP16.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"High-fidelity realism and photorealism in the SD 1.5 ecosystem.",url:"https://huggingface.co/cyberdelia/CyberRealistic/resolve/main/CyberRealistic_V8_FP16.safetensors"},{name:"ReV Animated v1.2.2",filename:"rev-animated-v1-2-2.safetensors",format:"Safetensors",approxSize:"2.1 GB",resolution:"512x512",notes:"Semi-realistic, 2.5D, anime, fantasy, and stylized digital art.",url:"https://huggingface.co/danbrown/RevAnimated-v1-2-2/resolve/main/rev-animated-v1-2-2.safetensors"}]}];function n1({activeModel:f,setActiveModel:b,serverRunning:N,setServerRunning:r,constraints:j,showAlert:A=async({message:G})=>window.alert(G),showConfirm:Y=async({message:G})=>window.confirm(G)}){const[G,R]=w.useState([]),[y,D]=w.useState(null),[U,Z]=w.useState(0),[ee,X]=w.useState(""),[F,re]=w.useState(null),[I,ne]=w.useState(null),[ce,Ge]=w.useState(null),[Ve,Qe]=w.useState({filename:"",speed:"0.0",eta:0,status:""}),[$,je]=w.useState(""),[ot,qe]=w.useState(null),[Me,Ke]=w.useState(!1),[$e,tt]=w.useState({progress:0,phase:""}),[Je,x]=w.useState(null),[O,K]=w.useState({backendMode:"",backendBinary:"",backendDevice:""}),se=G.map(T=>ai(T).filename),de=F!==null||Me;w.useEffect(()=>{B(),d()},[]),w.useEffect(()=>{if(!N&&!F){K({backendMode:"",backendBinary:"",backendDevice:""});return}let T=!1;const C=async()=>{try{const k=await Sa();if(T)return;K({backendMode:k.settings?.backendMode||k.loading?.backendMode||"",backendBinary:k.settings?.backendBinary||k.loading?.backendBinary||"",backendDevice:k.settings?.backendDevice||k.loading?.device||""})}catch{}};C();const q=setInterval(C,2e3);return()=>{T=!0,clearInterval(q)}},[N,F]);const d=async()=>{try{const T=await um();T.active&&T.filename&&z(T.filename)}catch(T){console.error("Check active download failed:",T)}},z=T=>{D(T);const C=setInterval(async()=>{try{const q=await um();q.active?(Z(q.progress===-1?0:q.progress),X(`${q.speed} • ETA ${q.eta}s`)):(clearInterval(C),D(null),q.error?String(q.error).toLowerCase().includes("cancelled")||A({title:"Download Failed",message:q.error,danger:!0}):B())}catch(q){console.error("Polling error:",q)}},1e3)},B=async()=>{try{const T=await Yy();R(T.map(ai).filter(C=>C.filename))}catch(T){console.error(T)}},H=async(T,C)=>{if(y||se.includes(C)&&!await Y({title:"Overwrite Model?",message:`"${C}" is already downloaded. Do you want to download and overwrite it?`,confirmLabel:"Overwrite"}))return;const q=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,k=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");if(!q&&!k){A({title:"Server Required",message:"Model download requires the local image generator server.",danger:!0});return}try{const He=await Fy(T);He.ok?z(C):A({title:"Download Failed",message:He.error||"Unknown error",danger:!0})}catch(He){A({title:"Download Error",message:He.message,danger:!0})}},P=async T=>{if(T.preventDefault(),!$.trim())return;let C="model.gguf";try{const q=new URL($.trim());if(q.protocol!=="http:"&&q.protocol!=="https:")throw new Error("URL protocol must be http or https");if(C=q.pathname.split("/").pop()||"",!C)throw new Error("Could not extract filename from URL");const k=C.toLowerCase();if(!k.endsWith(".gguf")&&!k.endsWith(".safetensors")&&!k.endsWith(".ckpt"))throw new Error("URL must point to a .gguf, .safetensors, or .ckpt weights file")}catch(q){A({title:"Invalid URL",message:q.message,danger:!0});return}await H($.trim(),C),je("")},te=T=>{H(T.url,T.filename)},le=async()=>{await Iy(),D(null),Z(0),X(""),await B()},Ue=async T=>{if(f&&f!==T&&N){x(T);return}await ze(T)},ze=async T=>{const C=typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0,q=typeof window<"u"&&(window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1");if(!C&&!q){const k=await rm(),He=`.\\backend\\win\\vulkan\\sd-vulkan.exe --listen-port 8080 --model .\\models\\${T} --threads 8`;k?await Y({title:"Web Browser Mode",message:`To load "${T}" on the active GPU server, restart your terminal backend with: + +${He} + +Update the UI status anyway?`,confirmLabel:"Update UI"})&&(b(T),r(!0)):await Y({title:"Backend Not Running",message:`C++ backend server is not running on port 8080. + +To run locally, start: + +${He} + +Proceed in Simulation Mode instead?`,confirmLabel:"Proceed"})&&(b(T),r(!1));return}re(T),ne({progress:0,phase:"Starting backend...",speed:"",current:0,total:0,model:T,backendMode:"",backendBinary:"",device:""});try{const k=await Qs(T,j);console.log(k);let He=!1,zt=null;for(let st=0;st<240;st++){const pe=await Sa();if(pe.loading&&ne({progress:pe.loading.progress||0,phase:pe.loading.phase||"Loading model...",speed:pe.loading.speed||"",current:pe.loading.current||0,total:pe.loading.total||0,model:pe.loading.model||T,backendMode:pe.loading.backendMode||pe.settings?.backendMode||"",backendBinary:pe.loading.backendBinary||pe.settings?.backendBinary||"",device:pe.loading.device||pe.settings?.backendDevice||""}),pe.ready){He=!0;break}if(pe.error){zt=pe.error;break}if(!pe.running&&st>3){zt="The backend process terminated immediately on startup.";break}await new Promise(sn=>setTimeout(sn,500))}if(He)ne(st=>({...st||{},progress:100,phase:"Model ready",speed:"",current:st?.current||0,total:st?.total||0,model:T})),b(T),r(!0);else throw new Error(zt||"Model server failed to respond on port 8080.")}catch(k){console.error("Failed to load model:",k),A({title:"Model Load Failed",message:k.message||String(k),danger:!0})}finally{setTimeout(()=>ne(null),800),re(null)}},ct=async()=>{const T=Je;x(null),await yt(),T&&await ze(T)},yt=async()=>{if(Me)return;Ke(!0),tt({progress:10,phase:"Stopping backend process..."});const T=setInterval(async()=>{try{const C=await Sa();C.unloading?.active?tt({progress:C.unloading.progress||50,phase:C.unloading.phase||"Unloading model..."}):tt(q=>({progress:Math.min(95,q.progress+10),phase:q.phase||"Unloading model..."}))}catch{}},300);try{await Vs(),tt({progress:100,phase:"Model unloaded"}),b(null),x(null),r(!1)}catch(C){console.error(C),A({title:"Unload Failed",message:C.message||String(C),danger:!0})}finally{clearInterval(T),setTimeout(()=>{Ke(!1),tt({progress:0,phase:""})},500)}},wt=async T=>{if(await Y({title:"Delete Model?",message:`Delete "${T}" from your drive?`,confirmLabel:"Delete",danger:!0}))try{await $y(T),await B(),f===T&&await yt()}catch(C){console.error("Failed to delete model:",C),A({title:"Delete Failed",message:C.message||String(C),danger:!0})}},Al=async(T,C)=>{const q=new AbortController;qe(q),Ge(0),Qe({filename:C,speed:"0.0",eta:0,status:"Initiating file copy..."});try{await Ky(T,k=>{Ge(Math.round(k.progress)),Qe({filename:k.filename,speed:k.speed_mb_s.toFixed(1),eta:Math.round(k.eta_secs),status:k.status})},q.signal),await B()}catch(k){console.error("Import failed:",k),k.name!=="AbortError"&&A({title:"Import Failed",message:k.message||String(k),danger:!0})}finally{Ge(null),qe(null)}},rt=()=>{ot&&ot.abort()},al=T=>{const C=T.target.files[0];C&&Al(C,C.name),T.target.value=""},sl=!!y;return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Model Manager"}),c.jsx("p",{className:"workspace-subtitle",children:"Manage local files and download recommended weights directly to your local models folder."})]}),f&&c.jsx("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-primary)",background:"var(--md-sys-color-primary-container)",color:"var(--md-sys-color-on-primary-container)"},children:c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[c.jsxs("div",{children:[c.jsxs("h4",{style:{fontWeight:700},children:["Active Model: ",f]}),c.jsx("p",{style:{fontSize:"0.85rem",marginTop:"2px",opacity:.9},children:"The local C++ stable-diffusion server is running. Real-time telemetry is displaying performance status in the top bar."}),(O.backendMode||O.backendDevice||O.backendBinary)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginTop:"10px"},children:[O.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(Su,{size:14}),c.jsxs("span",{children:["Loaded on ",O.backendMode]})]}),O.backendDevice&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:O.backendDevice})}),O.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:O.backendBinary})})]})]}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:yt,disabled:Me||F!==null,children:[Me?c.jsx(ta,{className:"progress-spinner",size:16}):c.jsx(ti,{size:16}),c.jsx("span",{children:Me?"Unloading":"Unload Server"})]})]})}),Me&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-error)",marginTop:"16px"},children:[c.jsx("h4",{style:{fontWeight:700,marginBottom:"8px"},children:"Unloading Model"}),c.jsxs("div",{className:"model-progress-section",style:{margin:"8px 0 0 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsx("span",{children:$e.phase||"Unloading model..."}),c.jsxs("span",{children:[Math.round($e.progress),"%"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,$e.progress))}%`,transition:"width 0.25s ease"}})})]})]}),I&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-secondary)",marginTop:"16px"},children:[c.jsxs("h4",{style:{fontWeight:700,marginBottom:"8px"},children:["Loading Model: ",I.model||F]}),(I.backendMode||I.backendBinary||I.device)&&c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px",marginBottom:"10px"},children:[I.backendMode&&c.jsxs("span",{className:"status-chip",style:{cursor:"default"},children:[c.jsx(Su,{size:14}),c.jsxs("span",{children:["Loading on ",I.backendMode]})]}),I.device&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:I.device})}),I.backendBinary&&c.jsx("span",{className:"status-chip",style:{cursor:"default"},children:c.jsx("span",{children:I.backendBinary})})]}),c.jsxs("div",{className:"model-progress-section",style:{margin:"8px 0 0 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{children:[I.phase,I.speed?` (${I.speed})`:""]}),c.jsx("span",{children:I.total>0?`Loaded ${I.current} / ${I.total} tensors`:`${Math.round(I.progress)}%`})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,I.progress))}%`,transition:"width 0.25s ease"}})})]})]}),c.jsxs("div",{className:"m3-card",style:{marginTop:"24px"},children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(Ys,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"Local Models (",G.length,")"]}),G.length===0?c.jsx("p",{style:{fontSize:"0.9rem",color:"var(--md-sys-color-outline)",textAlign:"center",padding:"16px 0"},children:"No models detected in app/models/. Download from the library below or import a file."}):c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"10px"},children:G.map(T=>{const C=T.filename,q=f===C;return c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"12px 16px",background:q?"var(--md-sys-color-primary-container)":"var(--md-sys-color-surface-variant)",color:q?"var(--md-sys-color-on-primary-container)":"var(--md-sys-color-on-surface-variant)",borderRadius:"var(--md-shape-corner-medium)",border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"2px"},children:[c.jsx("span",{style:{fontWeight:600,fontSize:"0.95rem"},children:C}),c.jsxs("span",{style:{fontSize:"0.75rem",opacity:.8},children:["Local Weights File • ",T.size||li(T.sizeBytes)]})]}),c.jsx("div",{style:{display:"flex",gap:"8px"},children:q?c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"36px",padding:"0 16px"},onClick:yt,disabled:Me,children:[Me?c.jsx(ta,{className:"progress-spinner",size:14}):c.jsx(ti,{size:14}),c.jsx("span",{children:Me?"Unloading":"Unload"})]}):c.jsxs(c.Fragment,{children:[c.jsxs("button",{className:"m3-btn m3-btn-filled",style:{height:"36px",padding:"0 16px"},onClick:()=>Ue(C),disabled:de,children:[F===C?c.jsx(ta,{className:"progress-spinner",size:14}):c.jsx(Ys,{size:14}),c.jsx("span",{children:F===C?"Loading":"Load"})]}),c.jsx("button",{className:"m3-btn m3-btn-error",style:{height:"36px",width:"36px",padding:0,minWidth:"36px"},onClick:()=>wt(C),disabled:de,title:"Delete from models folder",children:c.jsx(ti,{size:14})})]})})]},C)})})]}),c.jsx("div",{className:"workspace-title-section",style:{marginTop:"32px",marginBottom:"16px"},children:c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(oy,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Model Library"]})}),c.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"16px"},children:a1.map(T=>c.jsxs("div",{className:"m3-card",style:{margin:0},children:[c.jsx("h4",{style:{fontWeight:700,marginBottom:"12px"},children:T.group}),c.jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(280px, 1fr))",gap:"12px"},children:T.items.map(C=>{const q=se.includes(C.filename),k=y===C.filename;return c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"10px",padding:"14px",background:"var(--md-sys-color-surface-variant)",border:"1px solid var(--md-sys-color-outline-variant)",borderRadius:"var(--md-shape-corner-medium)"},children:[c.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[c.jsx("span",{style:{fontWeight:700},children:C.name}),c.jsxs("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)"},children:[C.format," • approx. ",C.approxSize," • ",C.resolution]})]}),c.jsx("p",{style:{fontSize:"0.78rem",color:"var(--md-sys-color-on-surface-variant)",lineHeight:1.35,margin:0},children:C.notes}),k&&c.jsxs("div",{className:"model-progress-section",style:{marginTop:"2px"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"8px"},children:[c.jsx("span",{className:"loading-dot"}),"Downloading"]}),c.jsx("span",{children:U>0?`${U}%`:"Preparing"})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${Math.min(100,Math.max(0,U))}%`,transition:"width 0.2s ease"}})}),ee&&c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:ee})]}),c.jsxs("button",{className:q?"m3-btn m3-btn-tonal":"m3-btn m3-btn-filled",style:{height:"36px",marginTop:"auto"},onClick:()=>te(C),disabled:q||y!==null,children:[q?c.jsx(Su,{size:14}):k?c.jsx(ta,{className:"progress-spinner",size:14}):c.jsx(lm,{size:14}),c.jsx("span",{children:q?"Downloaded":k?"Downloading":"Download"})]})]},C.filename)})})]},T.group))}),c.jsx("div",{className:"workspace-title-section",style:{marginTop:"32px",marginBottom:"16px"},children:c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(nm,{size:20,style:{color:"var(--md-sys-color-primary)"}}),"Local Model Import"]})}),ce!==null&&c.jsxs("div",{className:"m3-card",style:{borderLeft:"4px solid var(--md-sys-color-primary)",marginTop:"24px"},children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"12px"},children:[c.jsxs("h4",{style:{fontWeight:600},children:["Copying Model to local folder: ",Ve.filename]}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px"},onClick:rt,children:[c.jsx(Xs,{size:14}),c.jsx("span",{children:"Stop Import"})]})]}),c.jsxs("div",{className:"model-progress-section",style:{margin:"12px 0 6px 0"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsxs("span",{children:[Ve.status," (",Ve.speed," MB/s)"]}),c.jsxs("span",{children:[ce,"% (",Ve.eta,"s remaining)"]})]}),c.jsx("div",{className:"model-progress-bar",children:c.jsx("div",{className:"model-progress-fill",style:{width:`${ce}%`,transition:"width 0.15s ease"}})})]})]}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(300px, 1fr))",gap:"16px",marginTop:"16px"},children:[c.jsxs("label",{className:"import-box",style:{margin:0,height:"100%",justifyContent:"center"},children:[c.jsx("input",{type:"file",style:{display:"none"},accept:".gguf,.safetensors,.ckpt",onChange:al,disabled:ce!==null}),c.jsx(nm,{className:"import-icon"}),c.jsx("span",{style:{fontWeight:600},children:"Choose weights file"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",textAlign:"center"},children:"Select `.gguf`, `.safetensors` or `.ckpt` weights."})]}),c.jsxs("div",{className:"m3-card",style:{display:"flex",flexDirection:"column",justifyContent:"center",margin:0,padding:"20px"},children:[c.jsxs("h4",{style:{fontWeight:600,marginBottom:"8px",display:"flex",alignItems:"center",gap:"8px"},children:[c.jsx(lm,{size:16}),"Download Model from URL"]}),c.jsx("p",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginBottom:"12px"},children:"Download any GGUF or Safetensors model from Hugging Face or other sites directly to your models folder."}),sl?c.jsxs("div",{className:"model-progress-section",style:{marginTop:"0px"},children:[c.jsxs("div",{className:"model-progress-label",children:[c.jsx("span",{style:{fontSize:"0.75rem",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",maxWidth:"200px"},title:y,children:y}),c.jsxs("span",{children:[U,"%"]})]}),c.jsx("div",{className:"model-progress-bar",style:{margin:"4px 0"},children:c.jsx("div",{className:"model-progress-fill",style:{width:`${U}%`,transition:"width 0.15s ease"}})}),c.jsx("div",{style:{fontSize:"0.7rem",color:"var(--md-sys-color-outline)",marginTop:"2px"},children:ee}),c.jsxs("button",{className:"m3-btn m3-btn-error",style:{height:"34px",padding:"0 14px",marginTop:"10px"},onClick:le,children:[c.jsx(Xs,{size:14}),c.jsx("span",{children:"Stop Download"})]})]}):c.jsxs("form",{onSubmit:P,style:{display:"flex",gap:"8px"},children:[c.jsx("input",{type:"text",className:"m3-input",style:{flex:1,height:"40px"},placeholder:"e.g. https://huggingface.co/...",value:$,onChange:T=>je(T.target.value),disabled:y!==null}),c.jsx("button",{type:"submit",className:"m3-btn m3-btn-filled",style:{height:"40px"},disabled:y!==null,children:"Download"})]})]})]}),Je&&c.jsx("div",{style:{position:"fixed",inset:0,zIndex:50,background:"rgba(0,0,0,0.55)",display:"flex",alignItems:"center",justifyContent:"center",padding:"24px"},children:c.jsxs("div",{className:"m3-card",style:{maxWidth:"460px",width:"100%",margin:0,border:"1px solid var(--md-sys-color-outline-variant)"},children:[c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"10px",marginBottom:"10px"},children:[c.jsx(Ty,{size:22,style:{color:"var(--md-sys-color-error)"}}),c.jsx("h3",{style:{fontSize:"1.05rem",fontWeight:700},children:"Unload Current Model?"})]}),c.jsxs("p",{style:{fontSize:"0.9rem",color:"var(--md-sys-color-on-surface-variant)",lineHeight:1.45,marginBottom:"16px"},children:['"',f,'" is already loaded. Unload it before loading "',Je,'".']}),c.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"10px"},children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>x(null),disabled:Me,children:"Cancel"}),c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:yt,disabled:Me,children:[c.jsx(ti,{size:14}),c.jsx("span",{children:"Unload Only"})]}),c.jsxs("button",{className:"m3-btn m3-btn-filled",onClick:ct,disabled:Me,children:[Me?c.jsx(ta,{className:"progress-spinner",size:14}):c.jsx(ta,{size:14}),c.jsx("span",{children:"Unload and Load"})]})]})]})})]})}const i1=w.memo(n1),cm=[{id:"1:1",label:"1:1 Square",width:512,height:512,sdxl_width:1024,sdxl_height:1024,desc:"Social posts & avatars"},{id:"4:3",label:"4:3 Photo",width:640,height:480,sdxl_width:1152,sdxl_height:864,desc:"Classic photo look"},{id:"16:9",label:"16:9 Landscape",width:768,height:432,sdxl_width:1216,sdxl_height:684,desc:"Widescreen landscape"},{id:"9:16",label:"9:16 Portrait",width:432,height:768,sdxl_width:684,sdxl_height:1216,desc:"Tall phone screen"}],u1=f=>{if(!f)return!0;const b=f.toLowerCase();return!(b.includes("flux")||b.includes("schnell")||b.includes("sdxl")||b.includes("lightning")||b.includes("turbo")||b.includes("sd3"))};function c1({constraints:f,setConstraints:b,activeModel:N,specs:r,backendOptions:j}){const A=N?u1(N):!1,Y=j?.options?.length?j.options:[{id:"cpu",label:"CPU",available:!0}],G=(D,U)=>{b(Z=>({...Z,[D]:U}))},R=(D,U)=>{const Z=U==="sdxl"&&!A,ee=cm.find(X=>X.id===D);if(ee){let X=Z?ee.sdxl_width:ee.width,F=Z?ee.sdxl_height:ee.height;A&&(X>F?(F=Math.round(F*512/X),X=512):(X=Math.round(X*512/F),F=512),X=Math.round(X/64)*64,F=Math.round(F/64)*64),G("width",X),G("height",F)}},y=D=>{b(U=>({...U,backendType:D,useGpu:D!=="cpu"}))};return c.jsxs("div",{className:"workspace-area",children:[c.jsxs("div",{className:"workspace-title-section",children:[c.jsx("h2",{className:"workspace-title",children:"Image Constraints"}),c.jsx("p",{className:"workspace-subtitle",children:"Configure size, quality, and performance controls for image generation."})]}),c.jsxs("div",{className:"generator-layout",children:[c.jsxs("div",{children:[c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(J0,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"1. Picture Size & Shape"]}),A&&c.jsxs("div",{style:{background:"rgba(251, 191, 36, 0.1)",border:"1px solid rgb(251, 191, 36)",color:"var(--md-sys-color-on-surface)",padding:"12px",borderRadius:"8px",marginBottom:"16px",fontSize:"0.85rem",display:"flex",gap:"8px",alignItems:"flex-start"},children:[c.jsx(uy,{size:16,style:{color:"rgb(251, 191, 36)",flexShrink:0,marginTop:"2px"}}),c.jsxs("div",{children:[c.jsx("strong",{children:"Low-VRAM Protection Active:"})," Capped at 512x512 for the loaded SD 1.x model (",c.jsx("code",{children:N}),"). Generating at larger sizes (like 1024x1024) is disabled to prevent out-of-memory crashes on your ",r&&r.gpu_name&&!r.gpu_name.includes("Loading")?r.gpu_name:"graphics processor","."]})]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"AI Generation Engine Optimization"}),c.jsxs("div",{className:"m3-segmented-button",children:[A?c.jsx("div",{className:"m3-segment-item disabled",style:{opacity:.5,cursor:"not-allowed",textDecoration:"line-through",backgroundColor:"var(--md-sys-color-surface-variant)"},title:"High Quality Mode is disabled for SD 1.x models.",children:"High Quality Mode (1024px)"}):c.jsx("div",{className:`m3-segment-item ${f.width>=1024?"active":""}`,onClick:()=>{G("width",1024),G("height",1024)},children:"High Quality Mode (1024px)"}),c.jsx("div",{className:`m3-segment-item ${f.width<1024||A?"active":""}`,onClick:()=>{G("width",512),G("height",512)},children:"Standard Speed Mode (512px)"})]}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"4px"},children:A?"*Standard Speed Mode (512px) is forced for SD 1.5 / custom models to ensure stable local generations.":"*Use High Quality (1024px) for Flux or SDXL models. Use Standard (512px) for SD 1.5."})]}),c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Select Shape (Aspect Ratio)"}),c.jsx("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"8px"},children:cm.map(D=>{const U=Math.abs(f.width/f.height-D.width/D.height)<.1;return c.jsxs("button",{className:`m3-btn m3-btn-outlined aspect-ratio-btn ${U?"active":""}`,style:{height:"86px",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"8px",borderRadius:"var(--md-shape-corner-medium)",borderColor:"var(--md-sys-color-outline-variant)"},onClick:()=>R(D.id,A?"sd15":f.width>=1024?"sdxl":"sd15"),children:[c.jsx("div",{className:`aspect-ratio-preview ratio-${D.id.replace(":","-")}`}),c.jsx("span",{style:{fontWeight:600,fontSize:"0.85rem",marginTop:"2px"},children:D.label}),c.jsx("span",{style:{fontSize:"0.68rem",opacity:.7},children:A?`Max: ${D.id==="1:1"?"512x512":D.id==="4:3"?"512x384":D.id==="16:9"?"512x288":"288x512"}`:D.desc})]},D.id)})})]})]})]}),c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(Zs,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"2. Quality, Speed & Logic"]}),c.jsxs("div",{className:"m3-field-group",children:[c.jsxs("div",{className:"m3-slider-group",children:[c.jsxs("div",{className:"m3-slider-header",children:[c.jsx("span",{className:"m3-slider-label",children:"Detail Steps (Inference speed)"}),c.jsxs("span",{className:"m3-slider-value",children:[f.steps," steps"]})]}),c.jsx("input",{type:"range",className:"m3-slider",value:f.steps,onChange:D=>G("steps",parseInt(D.target.value)),min:"1",max:"60"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",lineHeight:"1.3"},children:"The number of times the AI cleans up the image. More steps = sharper details, but takes longer."})]}),c.jsxs("div",{className:"m3-slider-group",style:{marginTop:"8px"},children:[c.jsxs("div",{className:"m3-slider-header",children:[c.jsx("span",{className:"m3-slider-label",children:"Prompt Strictness (Instruction obedience)"}),c.jsx("span",{className:"m3-slider-value",children:f.cfgScale.toFixed(1)})]}),c.jsx("input",{type:"range",className:"m3-slider",value:f.cfgScale,onChange:D=>G("cfgScale",parseFloat(D.target.value)),min:"1",max:"15",step:"0.5"}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",lineHeight:"1.3"},children:"How closely the AI follows your text prompt. Lower = more creative. Higher = more strict."})]}),c.jsxs("div",{className:"m3-text-field",style:{marginTop:"8px"},children:[c.jsx("label",{className:"m3-text-field-label",children:"Image Blueprint (DNA Seed)"}),c.jsxs("div",{style:{display:"flex",gap:"8px"},children:[c.jsx("input",{type:"number",className:"m3-input",value:f.seed,onChange:D=>G("seed",parseInt(D.target.value)||-1),placeholder:"-1 for a brand new image...",style:{flex:1,height:"40px"}}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:()=>G("seed",-1),style:{height:"40px"},children:"Random (-1)"})]})]})]})]})]}),c.jsx("div",{children:c.jsxs("div",{className:"m3-card",children:[c.jsxs("h3",{className:"m3-card-title",children:[c.jsx(om,{size:18,style:{color:"var(--md-sys-color-primary)"}}),"3. System Settings"]}),c.jsx("div",{className:"m3-field-group",children:c.jsxs("div",{className:"m3-text-field",children:[c.jsx("label",{className:"m3-text-field-label",children:"Generation Backend"}),c.jsx("div",{className:"m3-segmented-button",children:Y.map(D=>c.jsx("div",{className:`m3-segment-item ${f.backendType===D.id||!f.backendType&&D.id==="cpu"?"active":""}`,onClick:()=>y(D.id),title:D.id==="cuda"?"CUDA appears only when an NVIDIA CUDA backend is available.":void 0,children:D.label},D.id))}),c.jsx("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-outline)",marginTop:"4px",lineHeight:1.35},children:"CPU is slow but safest. Vulkan works on supported GPUs. CUDA is shown only when NVIDIA CUDA support is available."}),j?.unavailable?.length>0&&c.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"4px"},children:j.unavailable.map(D=>c.jsxs("span",{style:{fontSize:"0.75rem",color:"var(--md-sys-color-error)",lineHeight:1.35},children:[D.label," unavailable: ",D.reason]},D.id))})]})})]})})]})]})}const s1=w.memo(c1);function f1(){const f=w.useRef(null),[b,N]=w.useState(null),r=w.useCallback(T=>{const C=f.current;f.current=null,N(null),C&&C(T)},[]),j=w.useCallback(({title:T="Confirm Action",message:C,confirmLabel:q="OK",cancelLabel:k="Cancel",danger:He=!1})=>new Promise(zt=>{f.current=zt,N({type:"confirm",title:T,message:C,confirmLabel:q,cancelLabel:k,danger:He})}),[]),A=w.useCallback(({title:T="Notice",message:C,confirmLabel:q="OK",danger:k=!1})=>new Promise(He=>{f.current=He,N({type:"alert",title:T,message:C,confirmLabel:q,danger:k})}),[]),[Y,G]=w.useState(()=>{const T=localStorage.getItem("theme");return T||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")});w.useEffect(()=>{document.documentElement.setAttribute("data-theme",Y),localStorage.setItem("theme",Y)},[Y]);const[R,y]=w.useState("generator"),[D,U]=w.useState(""),[Z,ee]=w.useState(""),[X,F]=w.useState(null),[re,I]=w.useState(null),[ne,ce]=w.useState(!1),[Ge,Ve]=w.useState(!1),[Qe,$]=w.useState({options:[{id:"cpu",label:"CPU",available:!0}],cudaAvailable:!1,vulkanAvailable:!1,defaultBackendType:"cpu"}),[je,ot]=w.useState(null),[qe,Me]=w.useState([]),[Ke,$e]=w.useState(!1),[tt,Je]=w.useState(!1),[x,O]=w.useState([]),[K,se]=w.useState(!1),[de,d]=w.useState(0),[z,B]=w.useState({os_name:"Loading Specs...",cpu_name:"Loading Specs...",cpu_cores_physical:4,cpu_cores_logical:8,ram_total_gb:0,gpu_name:"Loading Specs..."}),[H,P]=w.useState({cpu_usage:0,ram_used_gb:0,ram_total_gb:0,gpu_name:"Detecting...",vram_used_gb:0,vram_total_gb:0}),[te,le]=w.useState({width:1024,height:1024,steps:4,cfgScale:1,sampler:"euler_a",seed:-1,denoisingStrength:.7,useGpu:!0,useTaesd:!0,useFlashAttn:!0,useTiling:!1,threads:4,backendType:"auto"});w.useEffect(()=>{async function T(){try{const C=await Gy(),q=await Ly();$(q),B(C),le(k=>({...k,threads:C.cpu_cores_physical||4,backendType:k.backendType==="auto"?q.defaultBackendType||"cpu":k.backendType,useGpu:(k.backendType==="auto"?q.defaultBackendType:k.backendType)!=="cpu"}))}catch(C){console.error("Error fetching hardware specs:",C)}}T()},[]);const Ue=w.useCallback(async()=>{$e(!0);try{const[T,C]=await Promise.all([wy(),Ry().catch(()=>[])]);ot(T),Me(C)}finally{$e(!1)}},[]);w.useEffect(()=>{Ue()},[Ue]);const ze=w.useCallback(async()=>{try{const T=await By();await navigator.clipboard.writeText(JSON.stringify(T,null,2)),Je(!0),setTimeout(()=>Je(!1),1800)}catch(T){A({title:"Diagnostics Failed",message:T.message||String(T),danger:!0})}},[A]),ct=w.useCallback(async()=>{if(qe.length===0)return;const T=qe.reduce((q,k)=>q+Number(k.sizeBytes||0),0);if(await j({title:"Clean Safe Files?",message:`Delete ${qe.length} temporary/cache item${qe.length===1?"":"s"} and free about ${li(T)}? + +Models and generated outputs are not included.`,confirmLabel:"Clean",danger:!0})){$e(!0);try{await Hy(qe.map(q=>q.id)),await Ue()}catch(q){A({title:"Cleanup Failed",message:q.message||String(q),danger:!0})}finally{$e(!1)}}},[qe,Ue,A,j]);w.useEffect(()=>{async function T(){const C=await Xy();O(C)}T()},[]),w.useEffect(()=>{re?localStorage.setItem("active-model",re):localStorage.removeItem("active-model")},[re]),w.useEffect(()=>{let T=null;async function C(){const q=await Sa();if(!!q.ready){T&&clearInterval(T);const He=localStorage.getItem("active-model");if(He)I(He),ce(!0);else{try{if(q&&q.settings&&q.settings.model){const zt=q.settings.model.split(/[\\/]/).pop();I(zt)}}catch{}ce(!0)}}else if(!(typeof window<"u"&&window.__TAURI_INTERNALS__!==void 0)){const zt=localStorage.getItem("active-model");zt&&(I(zt),ce(!1))}}return C(),T=setInterval(C,2e3),()=>{T&&clearInterval(T)}},[]),w.useEffect(()=>{async function T(){try{const q=await qy();P(k=>k.cpu_usage===q.cpu_usage&&k.ram_used_gb===q.ram_used_gb&&k.ram_total_gb===q.ram_total_gb&&k.gpu_name===q.gpu_name&&k.vram_used_gb===q.vram_used_gb&&k.vram_total_gb===q.vram_total_gb?k:q)}catch{}}T();const C=setInterval(T,1500);return()=>clearInterval(C)},[]),w.useEffect(()=>{if(re){const T=re.toLowerCase();T.includes("flux")||T.includes("schnell")?le(C=>({...C,steps:4,cfgScale:1,width:1024,height:1024})):T.includes("lightning")||T.includes("turbo")?le(C=>({...C,steps:4,cfgScale:1.5,width:1024,height:1024})):T.includes("sd15")?le(C=>({...C,steps:25,cfgScale:7,width:512,height:512})):T.includes("sd35")?le(C=>({...C,steps:20,cfgScale:4.5,width:1024,height:1024})):le(C=>({...C,steps:20,cfgScale:7,width:512,height:512}))}},[re]);const yt=w.useMemo(()=>{switch(R){case"generator":return c.jsx(l1,{prompt:D,setPrompt:U,negativePrompt:Z,setNegativePrompt:ee,constraints:te,setConstraints:le,activeModel:re,generatedImages:x,setGeneratedImages:O,isGenerating:K,setIsGenerating:se,generationProgress:de,setGenerationProgress:d,setActiveTab:y,inputImage:X,setInputImage:F,showAlert:A,showConfirm:j});case"models":return c.jsx(i1,{activeModel:re,setActiveModel:I,serverRunning:ne,setServerRunning:ce,constraints:te,showAlert:A,showConfirm:j});case"constraints":return c.jsx(s1,{constraints:te,setConstraints:le,activeModel:re,specs:z,backendOptions:Qe});default:return null}},[R,D,Z,te,re,x,K,de,X,ne,z,Qe,A,j]),wt=w.useMemo(()=>c.jsx(Ey,{activeTab:R,setActiveTab:y,specs:z}),[R,z]),Al=w.useCallback(async()=>{if(!(!ne||Ge)){Ve(!0);try{await Vs(),ce(!1),I(null)}catch(T){console.error("Failed to stop server:",T),A({title:"Stop Server Failed",message:T.message||String(T),danger:!0})}finally{Ve(!1)}}},[ne,Ge,A]),rt=[...je?.stale?["Restart Local AI Image Generator so the local server loads the latest API."]:[],...je?.issues||[]],al=qe.reduce((T,C)=>T+Number(C.sizeBytes||0),0),sl=!!(je&&(rt.length>0||qe.length>0));return c.jsxs("div",{className:"app-container",children:[wt,c.jsxs("div",{className:"main-content",children:[c.jsx(Ay,{telemetry:H,serverRunning:ne,activeModel:re,onStopServer:Al,isStoppingServer:Ge,theme:Y,setTheme:G}),sl&&c.jsxs("div",{className:`m3-card readiness-card ${je?.stale||rt.length>0?"readiness-card-warning":""}`,children:[c.jsxs("div",{className:"readiness-header",children:[c.jsxs("div",{children:[c.jsx("h3",{className:"m3-card-title",style:{marginBottom:"4px"},children:je?.stale?"Restart Required":rt.length>0?"System Readiness":"Safe Cleanup Available"}),c.jsx("p",{className:"m3-card-subtitle",style:{margin:0},children:je?.stale?`Running server build: ${je.build||"unknown"}`:rt.length>0?"Local AI Image Generator found setup items that may need attention.":`${qe.length} temporary item${qe.length===1?"":"s"} can be cleaned (${li(al)}).`})]}),c.jsxs("div",{className:"readiness-actions",children:[c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:Ue,disabled:Ke,children:Ke?"Checking":"Refresh"}),c.jsx("button",{className:"m3-btn m3-btn-tonal",onClick:ze,children:tt?"Copied":"Copy Diagnostics"}),qe.length>0&&c.jsxs("button",{className:"m3-btn m3-btn-error",onClick:ct,disabled:Ke,children:["Clean ",li(al)]})]})]}),rt.length>0&&c.jsx("div",{className:"readiness-issues",children:rt.slice(0,4).map(T=>c.jsx("span",{children:T},T))}),qe.length>0&&c.jsx("div",{className:"readiness-cleanup-list",children:qe.slice(0,3).map(T=>c.jsxs("span",{title:T.path,children:[T.name," · ",T.size," · ",T.reason]},T.id))})]}),yt]}),b&&c.jsx("div",{className:"app-dialog-backdrop",role:"presentation",children:c.jsxs("div",{className:"app-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"app-dialog-title",children:[c.jsx("h3",{id:"app-dialog-title",className:"app-dialog-title",children:b.title}),c.jsx("p",{className:"app-dialog-message",children:b.message}),c.jsxs("div",{className:"app-dialog-actions",children:[b.type==="confirm"&&c.jsx("button",{className:"m3-btn m3-btn-outlined",onClick:()=>r(!1),children:b.cancelLabel}),c.jsx("button",{className:`m3-btn ${b.danger?"m3-btn-error":"m3-btn-filled"}`,onClick:()=>r(!0),children:b.confirmLabel})]})]})})]})}B0.createRoot(document.getElementById("root")).render(c.jsx(E0.StrictMode,{children:c.jsx(f1,{})}));export{xa as i,o1 as t}; diff --git a/app/dist/index.html b/app/dist/index.html new file mode 100644 index 0000000..26eec40 --- /dev/null +++ b/app/dist/index.html @@ -0,0 +1,18 @@ + + + + + + + + + + Local AI Image Generator + + + + + +
+ + diff --git a/app/frontend/.gitignore b/app/frontend/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/app/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/app/frontend/index.html b/app/frontend/index.html new file mode 100644 index 0000000..aade2a9 --- /dev/null +++ b/app/frontend/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + Local AI Image Generator + + + +
+ + + diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json new file mode 100644 index 0000000..143e984 --- /dev/null +++ b/app/frontend/package-lock.json @@ -0,0 +1,2028 @@ +{ + "name": "tauri-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tauri-app", + "version": "0.1.0", + "dependencies": { + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-opener": "^2", + "lucide-react": "^1.17.0", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@tauri-apps/cli": "^2", + "@vitejs/plugin-react": "^4.6.0", + "vite": "^7.0.4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz", + "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz", + "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz", + "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz", + "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz", + "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz", + "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz", + "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz", + "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz", + "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz", + "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz", + "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz", + "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz", + "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz", + "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz", + "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz", + "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz", + "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", + "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz", + "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz", + "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz", + "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz", + "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz", + "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz", + "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz", + "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tauri-apps/api": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz", + "integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==", + "license": "Apache-2.0 OR MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + } + }, + "node_modules/@tauri-apps/cli": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.2.tgz", + "integrity": "sha512-bk3HemqvGRoy+5D/dVMUQHKMYLglD0jVnMm/0iGMH6ufZ+p8r14m6BpIixwij3PBvZdvORUp1YifTD8QxVZ1Nw==", + "dev": true, + "license": "Apache-2.0 OR MIT", + "bin": { + "tauri": "tauri.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + }, + "optionalDependencies": { + "@tauri-apps/cli-darwin-arm64": "2.11.2", + "@tauri-apps/cli-darwin-x64": "2.11.2", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.2", + "@tauri-apps/cli-linux-arm64-gnu": "2.11.2", + "@tauri-apps/cli-linux-arm64-musl": "2.11.2", + "@tauri-apps/cli-linux-riscv64-gnu": "2.11.2", + "@tauri-apps/cli-linux-x64-gnu": "2.11.2", + "@tauri-apps/cli-linux-x64-musl": "2.11.2", + "@tauri-apps/cli-win32-arm64-msvc": "2.11.2", + "@tauri-apps/cli-win32-ia32-msvc": "2.11.2", + "@tauri-apps/cli-win32-x64-msvc": "2.11.2" + } + }, + "node_modules/@tauri-apps/cli-darwin-arm64": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.2.tgz", + "integrity": "sha512-+4UZzLt+eOAEQCwgd+TqKgyUJMrvx+BgdXLLaqJYmPqzP+nE6YZr/hY6CWLYGQb8jFn99jEkmC6uA3tNvamA1w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-darwin-x64": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.2.tgz", + "integrity": "sha512-VjYYtZUPqDMLutSfJEyxFE3Bz+DPi7c8wC3imckgvciLDZLq4qwKJxBicg0BXGhXjJsl8vKWgWRFNMPELQ+Xyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.2.tgz", + "integrity": "sha512-yMemD6f4i95AQriS8EazyOFzbE34yjnP16i3IOzpHGQvBoy2DjypFMFBq0NtPuITURv/cOGguRtHR5d79/9CSA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-gnu": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.2.tgz", + "integrity": "sha512-cgI91D2wL8GSgoWwZXDqt+DwnuZCP2/bz03QAE4TrhgAKIsrB4hX26W/H1EONPUUNkqrsgeCD0wU6pcNjV/5kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-musl": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.2.tgz", + "integrity": "sha512-X1rm0BERqAAggtYTESSgXrS3sz4Sb/OiPiz54UqISlXW+GkR3vNIGnsy/lejNmoXGVqri3Q53BCfQiclOIyRPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.2.tgz", + "integrity": "sha512-usbMLJbT3KtkOrBMDVeGYNM35aTHXx38SJSzTMSqqjeUIOQ+iVPjb2yAGNAE+KqmBbAx4FOFIyMeKXx2M/JKGQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-gnu": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.2.tgz", + "integrity": "sha512-Ru4gwJKPG0ctVGchRGpRup4Y4lW2SSfFnrbQcyHhCliKy4g8Qz97TrUgCur4CbWyAgKxvGh3SjrkA0LDYzDGiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-musl": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.2.tgz", + "integrity": "sha512-eUm7T6clN1MMmNSRQ9gaWsQdyehQx2Gmn5hht/QUlqZQI/qcP2OJK5dnaxqwFzCr2HdsEo9ydxaqcS1oJzMvUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-arm64-msvc": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.2.tgz", + "integrity": "sha512-HeeZW80jU+gVTOEX4X/hC6NVSAdDVXajwP5fxIZ/3z9WvUC7qrudX2GMTilYq6Dg0e0sk0XgsAJD1hZ5wPBXUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-ia32-msvc": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.2.tgz", + "integrity": "sha512-YhjQNZcXfbkCLyazSv1nPnJ9iRFE1wm6kc51FDbU10/Dk09io+6PAGMLjkxnX2GdM0qMnDmTjstY8mTDVvtKeA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-x64-msvc": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.2.tgz", + "integrity": "sha512-d2JchlFIpZevZVReyqhQOekJmb1UH3rhZ5VX6sH3ty9ETE0TKQavpihvoScUXfKKpW6HZC0MrFGRU0ZtD+w3gA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/plugin-opener": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz", + "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.11.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", + "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "dev": true, + "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/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "dev": true, + "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/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.366", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz", + "integrity": "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": 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/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.17.0.tgz", + "integrity": "sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz", + "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.61.0", + "@rollup/rollup-android-arm64": "4.61.0", + "@rollup/rollup-darwin-arm64": "4.61.0", + "@rollup/rollup-darwin-x64": "4.61.0", + "@rollup/rollup-freebsd-arm64": "4.61.0", + "@rollup/rollup-freebsd-x64": "4.61.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", + "@rollup/rollup-linux-arm-musleabihf": "4.61.0", + "@rollup/rollup-linux-arm64-gnu": "4.61.0", + "@rollup/rollup-linux-arm64-musl": "4.61.0", + "@rollup/rollup-linux-loong64-gnu": "4.61.0", + "@rollup/rollup-linux-loong64-musl": "4.61.0", + "@rollup/rollup-linux-ppc64-gnu": "4.61.0", + "@rollup/rollup-linux-ppc64-musl": "4.61.0", + "@rollup/rollup-linux-riscv64-gnu": "4.61.0", + "@rollup/rollup-linux-riscv64-musl": "4.61.0", + "@rollup/rollup-linux-s390x-gnu": "4.61.0", + "@rollup/rollup-linux-x64-gnu": "4.61.0", + "@rollup/rollup-linux-x64-musl": "4.61.0", + "@rollup/rollup-openbsd-x64": "4.61.0", + "@rollup/rollup-openharmony-arm64": "4.61.0", + "@rollup/rollup-win32-arm64-msvc": "4.61.0", + "@rollup/rollup-win32-ia32-msvc": "4.61.0", + "@rollup/rollup-win32-x64-gnu": "4.61.0", + "@rollup/rollup-win32-x64-msvc": "4.61.0", + "fsevents": "~2.3.2" + } + }, + "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==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "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/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==", + "dev": true, + "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/vite": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", + "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "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/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/app/frontend/package.json b/app/frontend/package.json new file mode 100644 index 0000000..b00cbe9 --- /dev/null +++ b/app/frontend/package.json @@ -0,0 +1,24 @@ +{ + "name": "tauri-app", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "tauri": "tauri" + }, + "dependencies": { + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-opener": "^2", + "lucide-react": "^1.17.0", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@tauri-apps/cli": "^2", + "@vitejs/plugin-react": "^4.6.0", + "vite": "^7.0.4" + } +} diff --git a/app/frontend/src/App.css b/app/frontend/src/App.css new file mode 100644 index 0000000..ea14b94 --- /dev/null +++ b/app/frontend/src/App.css @@ -0,0 +1,1283 @@ +/* Modern Minimalist & Glassmorphism Design System */ +:root { + font-family: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Animation and Shape Tokens */ + --md-shape-corner-small: 8px; + --md-shape-corner-medium: 12px; + --md-shape-corner-large: 16px; + --md-shape-corner-extra-large: 22px; + --md-shape-corner-full: 9999px; + --md-transition-duration: 0.25s; + --md-transition-easing: cubic-bezier(0.4, 0, 0.2, 1); + + /* Light Theme Variables (Default) */ + --md-sys-color-primary: #4f46e5; + --md-sys-color-on-primary: #ffffff; + --md-sys-color-primary-container: rgba(79, 70, 229, 0.06); + --md-sys-color-on-primary-container: #4338ca; + --md-sys-color-secondary: #0ea5e9; + --md-sys-color-on-secondary: #ffffff; + --md-sys-color-secondary-container: rgba(14, 165, 233, 0.06); + --md-sys-color-on-secondary-container: #0369a1; + --md-sys-color-tertiary: #d946ef; + --md-sys-color-on-tertiary: #ffffff; + --md-sys-color-background: #f8fafc; + --md-sys-color-on-background: #0f172a; + --md-sys-color-surface: rgba(255, 255, 255, 0.75); + --md-sys-color-on-surface: #0f172a; + --md-sys-color-surface-variant: rgba(241, 245, 249, 0.8); + --md-sys-color-on-surface-variant: #475569; + + /* Text description variables - HIGH CONTRAST for readability */ + --md-sys-color-outline: #64748b; /* Used for description texts in JSX */ + --md-sys-color-outline-variant: #94a3b8; /* Used for sub-description texts in JSX */ + + /* Border variables - SOFT TRANSLUCENT borders */ + --border-color: rgba(15, 23, 42, 0.08); + --border-color-muted: rgba(15, 23, 42, 0.05); + + --md-sys-color-error: #ef4444; + --md-sys-color-on-error: #ffffff; + --md-sys-color-success: #10b981; + --md-sys-color-on-success: #ffffff; + --md-sys-color-card-border: rgba(15, 23, 42, 0.06); + --glass-shadow: 0 8px 32px 0 rgba(15, 23, 42, 0.04); + --glass-blur: blur(16px); +} + +/* Dark Theme Variables */ +html[data-theme="dark"] { + --md-sys-color-primary: #6366f1; + --md-sys-color-on-primary: #ffffff; + --md-sys-color-primary-container: rgba(99, 102, 241, 0.12); + --md-sys-color-on-primary-container: #c7d2fe; + --md-sys-color-secondary: #38bdf8; + --md-sys-color-on-secondary: #0f172a; + --md-sys-color-secondary-container: rgba(56, 189, 248, 0.08); + --md-sys-color-on-secondary-container: #bae6fd; + --md-sys-color-tertiary: #f472b6; + --md-sys-color-on-tertiary: #0f172a; + --md-sys-color-background: #090a0f; + --md-sys-color-on-background: #f4f4f5; + --md-sys-color-surface: rgba(18, 20, 29, 0.65); + --md-sys-color-on-surface: #f4f4f5; + --md-sys-color-surface-variant: rgba(26, 29, 41, 0.55); + --md-sys-color-on-surface-variant: #a1a1aa; + + /* Text description variables - HIGH CONTRAST for readability */ + --md-sys-color-outline: #a1a1aa; /* Used for description texts in JSX */ + --md-sys-color-outline-variant: #71717a; /* Used for sub-description texts in JSX */ + + /* Border variables - SOFT TRANSLUCENT borders */ + --border-color: rgba(255, 255, 255, 0.09); + --border-color-muted: rgba(255, 255, 255, 0.05); + + --md-sys-color-error: #f87171; + --md-sys-color-on-error: #ffffff; + --md-sys-color-success: #34d399; + --md-sys-color-on-success: #090a0f; + --md-sys-color-card-border: rgba(255, 255, 255, 0.04); + --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3); + --glass-blur: blur(16px); +} + +/* Global Reset & Base Styles */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + background-color: var(--md-sys-color-background); + background-image: + radial-gradient(at 0% 0%, var(--md-sys-color-primary-container) 0px, transparent 50%), + radial-gradient(at 100% 0%, var(--md-sys-color-secondary-container) 0px, transparent 40%); + color: var(--md-sys-color-on-background); + overflow: hidden; + height: 100vh; + width: 100vw; + font-size: 16px; + transition: background-color var(--md-transition-duration) ease; +} + +/* Layout Framework */ +.app-container { + display: flex; + flex-direction: row; + height: 100vh; + width: 100vw; + overflow: hidden; +} + +/* Sidebar Styling */ +.sidebar { + width: 280px; + background-color: var(--md-sys-color-surface); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border-right: 1px solid var(--border-color); + display: flex; + flex-direction: column; + padding: 28px 18px; + justify-content: space-between; + box-shadow: var(--glass-shadow); + z-index: 11; + transition: all var(--md-transition-duration) var(--md-transition-easing); +} + +.sidebar-logo { + display: flex; + align-items: center; + gap: 12px; + padding: 0 12px 28px 12px; +} + +.sidebar-logo-icon { + color: var(--md-sys-color-primary); + width: 26px; + height: 26px; + filter: drop-shadow(0 2px 8px rgba(99, 102, 241, 0.3)); +} + +.sidebar-logo-text { + font-size: 1.15rem; + font-weight: 700; + letter-spacing: -0.02em; + color: var(--md-sys-color-on-background); +} + +.nav-list { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: auto; +} + +.nav-item { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 16px; + height: 48px; + border-radius: var(--md-shape-corner-medium); + color: var(--md-sys-color-on-surface-variant); + font-size: 0.9rem; + font-weight: 500; + cursor: pointer; + transition: all var(--md-transition-duration) var(--md-transition-easing); + user-select: none; + text-decoration: none; + position: relative; +} + +.nav-item:hover { + background-color: var(--md-sys-color-surface-variant); + color: var(--md-sys-color-primary); + transform: translateX(2px); +} + +.nav-item.active { + background-color: var(--md-sys-color-primary-container); + color: var(--md-sys-color-primary); + font-weight: 600; +} + +.nav-item.active::before { + content: ""; + position: absolute; + left: 0; + top: 14px; + bottom: 14px; + width: 4px; + background-color: var(--md-sys-color-primary); + border-radius: 0 4px 4px 0; +} + +.sidebar-footer { + padding: 18px 12px 0 12px; + border-top: 1px solid var(--border-color); + font-size: 0.78rem; + color: var(--md-sys-color-on-surface-variant); + display: flex; + flex-direction: column; + gap: 6px; + opacity: 0.95; +} + +/* Main Content Panel */ +.main-content { + flex: 1; + display: flex; + flex-direction: column; + background-color: transparent; + overflow: hidden; +} + +/* Persistent Top Status Bar */ +.top-status-bar { + height: 64px; + background-color: var(--md-sys-color-surface); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border-bottom: 1px solid var(--border-color); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 24px; + z-index: 10; + box-shadow: var(--glass-shadow); +} + +.current-model-info { + display: flex; + align-items: center; + gap: 10px; + font-size: 0.88rem; +} + +.status-indicator { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--md-sys-color-success); + box-shadow: 0 0 8px var(--md-sys-color-success); +} + +.status-indicator.busy { + background-color: var(--md-sys-color-primary); + box-shadow: 0 0 8px var(--md-sys-color-primary); + animation: pulse 1.8s infinite; +} + +.status-indicator.offline { + background-color: var(--md-sys-color-on-surface-variant); + box-shadow: none; + opacity: 0.6; +} + +.telemetry-group { + display: flex; + align-items: center; + gap: 8px; +} + +.telemetry-chip { + display: flex; + align-items: center; + gap: 6px; + background-color: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + border-radius: var(--md-shape-corner-medium); + padding: 6px 12px; + font-size: 0.8rem; + font-weight: 500; + color: var(--md-sys-color-on-surface-variant); + transition: all var(--md-transition-duration); +} + +.telemetry-chip-icon { + width: 14px; + height: 14px; +} + +.readiness-card { + margin: 0 0 18px 0; + border-left: 4px solid var(--md-sys-color-primary); +} + +.readiness-card-warning { + border-left-color: var(--md-sys-color-error); +} + +.readiness-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 14px; +} + +.readiness-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; + flex-wrap: wrap; +} + +.readiness-actions .m3-btn { + height: 34px; + padding: 0 14px; +} + +.readiness-issues, +.readiness-cleanup-list { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 12px; + font-size: 0.82rem; + color: var(--md-sys-color-on-surface-variant); +} + +.readiness-issues span { + color: var(--md-sys-color-error); +} + +/* Theme Toggle Button Style */ +.theme-toggle-btn { + background: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + color: var(--md-sys-color-on-surface-variant); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: var(--md-shape-corner-medium); + transition: all var(--md-transition-duration) var(--md-transition-easing); + margin-right: 6px; +} + +.theme-toggle-btn:hover { + color: var(--md-sys-color-primary); + border-color: var(--md-sys-color-primary); + background-color: var(--md-sys-color-primary-container); + transform: scale(1.05); +} + +/* Workspace Area */ +.workspace-area { + flex: 1; + overflow-y: auto; + padding: 28px; +} + +.workspace-title-section { + margin-bottom: 24px; +} + +.workspace-title { + font-size: 1.6rem; + font-weight: 700; + color: var(--md-sys-color-on-background); + letter-spacing: -0.02em; +} + +.workspace-subtitle { + font-size: 0.9rem; + color: var(--md-sys-color-on-surface-variant); + margin-top: 4px; + opacity: 0.8; +} + +/* Glassmorphic UI Cards */ +.m3-card { + background-color: var(--md-sys-color-surface); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border: 1px solid var(--md-sys-color-card-border); + border-radius: var(--md-shape-corner-large); + padding: 24px; + margin-bottom: 24px; + box-shadow: var(--glass-shadow); + transition: all var(--md-transition-duration) var(--md-transition-easing); +} + +.m3-card:hover { + border-color: rgba(99, 102, 241, 0.15); +} + +.m3-card-title { + font-size: 1.05rem; + font-weight: 600; + margin-bottom: 20px; + color: var(--md-sys-color-on-surface); + display: flex; + align-items: center; + gap: 8px; +} + +/* Buttons System */ +.m3-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + height: 38px; + padding: 0 20px; + border-radius: var(--md-shape-corner-medium); + font-size: 0.88rem; + font-weight: 550; + font-family: inherit; + border: none; + cursor: pointer; + transition: all var(--md-transition-duration) var(--md-transition-easing); + user-select: none; + line-height: 1; + white-space: nowrap; +} + +.m3-btn svg { + flex: 0 0 auto; +} + +.m3-btn .progress-spinner { + width: 14px; + height: 14px; + border-width: 2px; + border-color: currentColor; + border-right-color: transparent; + border-bottom-color: transparent; +} + +.m3-btn:disabled { + opacity: 0.45; + cursor: not-allowed; +} + +.m3-btn-filled { + background: linear-gradient(135deg, var(--md-sys-color-primary), #8b5cf6); + color: var(--md-sys-color-on-primary); + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2); +} + +.m3-btn-filled:hover:not(:disabled) { + box-shadow: 0 6px 20px rgba(99, 102, 241, 0.35); + transform: translateY(-1px); + filter: brightness(1.04); +} + +.m3-btn-tonal { + background-color: var(--md-sys-color-primary-container); + color: var(--md-sys-color-on-primary-container); +} + +.m3-btn-tonal:hover:not(:disabled) { + background-color: var(--md-sys-color-primary); + color: var(--md-sys-color-on-primary); + transform: translateY(-1px); +} + +.m3-btn-outlined { + background-color: transparent; + border: 1px solid var(--border-color); + color: var(--md-sys-color-on-surface); +} + +.m3-btn-outlined:hover:not(:disabled) { + background-color: var(--md-sys-color-surface-variant); + border-color: var(--md-sys-color-primary); + color: var(--md-sys-color-primary); +} + +.m3-btn-error { + background-color: rgba(244, 63, 94, 0.08); + border: 1px solid rgba(244, 63, 94, 0.18); + color: #e11d48; + box-shadow: 0 2px 8px rgba(244, 63, 94, 0.05); +} + +.m3-btn-error:hover:not(:disabled) { + background-color: rgba(244, 63, 94, 0.15); + border-color: rgba(244, 63, 94, 0.3); + transform: translateY(-1px); +} + +html[data-theme="dark"] .m3-btn-error { + background-color: rgba(251, 113, 133, 0.09); + border: 1px solid rgba(251, 113, 133, 0.22); + color: #fda4af; + box-shadow: 0 2px 8px rgba(251, 113, 133, 0.04); +} + +html[data-theme="dark"] .m3-btn-error:hover:not(:disabled) { + background-color: rgba(251, 113, 133, 0.16); + border-color: rgba(251, 113, 133, 0.35); +} + +/* Fields & Groups */ +.m3-field-group { + display: flex; + flex-direction: column; + gap: 18px; +} + +.m3-text-field { + display: flex; + flex-direction: column; + gap: 6px; +} + +.m3-text-field-label { + font-size: 0.82rem; + font-weight: 600; + letter-spacing: 0.01em; + color: var(--md-sys-color-on-surface-variant); +} + +.m3-input, .m3-textarea { + width: 100%; + background-color: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + border-radius: var(--md-shape-corner-medium); + padding: 10px 14px; + font-family: inherit; + font-size: 0.92rem; + color: var(--md-sys-color-on-surface); + transition: all var(--md-transition-duration) var(--md-transition-easing); + outline: none; +} + +.m3-input { + height: 42px; +} + +.m3-textarea { + min-height: 90px; + resize: vertical; +} + +.m3-input:focus, .m3-textarea:focus { + border-color: var(--md-sys-color-primary); + background-color: var(--md-sys-color-surface); + box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12); +} + +/* Custom Range Sliders */ +.m3-slider-group { + display: flex; + flex-direction: column; + gap: 4px; +} + +.m3-slider-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.m3-slider-label { + font-size: 0.82rem; + font-weight: 600; + color: var(--md-sys-color-on-surface-variant); +} + +.m3-slider-value { + font-size: 0.78rem; + font-weight: 700; + color: var(--md-sys-color-primary); + background-color: var(--md-sys-color-primary-container); + padding: 2px 8px; + border-radius: var(--md-shape-corner-full); +} + +.m3-slider { + -webkit-appearance: none; + appearance: none; + width: 100%; + height: 4px; + border-radius: var(--md-shape-corner-full); + background: var(--border-color); + outline: none; + margin: 12px 0; + transition: background 0.25s; +} + +.m3-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 16px; + height: 16px; + border-radius: 50%; + background: var(--md-sys-color-primary); + border: 2px solid var(--md-sys-color-surface); + box-shadow: 0 0 8px rgba(99, 102, 241, 0.35); + cursor: pointer; + transition: all var(--md-transition-duration) var(--md-transition-easing); +} + +.m3-slider::-webkit-slider-thumb:hover { + transform: scale(1.25); + box-shadow: 0 0 12px rgba(99, 102, 241, 0.6); +} + +/* Modern Switch Styles */ +.m3-switch-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; +} + +.m3-switch-info { + display: flex; + flex-direction: column; + gap: 2px; +} + +.m3-switch-title { + font-size: 0.9rem; + font-weight: 600; + color: var(--md-sys-color-on-surface); +} + +.m3-switch-description { + font-size: 0.78rem; + color: var(--md-sys-color-on-surface-variant); + opacity: 0.8; +} + +.m3-switch { + position: relative; + display: inline-block; + width: 46px; + height: 26px; +} + +.m3-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.m3-switch-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + border-radius: 26px; + transition: .25s; +} + +.m3-switch-slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: var(--md-sys-color-on-surface-variant); + border-radius: 50%; + transition: .25s; +} + +.m3-switch input:checked + .m3-switch-slider { + background-color: var(--md-sys-color-primary); + border-color: var(--md-sys-color-primary); +} + +.m3-switch input:checked + .m3-switch-slider:before { + transform: translateX(20px); + background-color: var(--md-sys-color-on-primary); +} + +/* Segmented Buttons */ +.m3-segmented-button { + display: flex; + background-color: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + border-radius: var(--md-shape-corner-medium); + padding: 3px; + overflow: hidden; + width: 100%; +} + +.m3-segment-item { + flex: 1; + text-align: center; + padding: 8px 0; + font-size: 0.82rem; + font-weight: 600; + cursor: pointer; + background-color: transparent; + color: var(--md-sys-color-on-surface-variant); + transition: all var(--md-transition-duration) var(--md-transition-easing); + border-radius: calc(var(--md-shape-corner-medium) - 2px); + user-select: none; + border: none; +} + +.m3-segment-item:hover:not(.active):not(.disabled) { + color: var(--md-sys-color-on-surface); + background-color: rgba(0, 0, 0, 0.03); +} + +html[data-theme="dark"] .m3-segment-item:hover:not(.active):not(.disabled) { + background-color: rgba(255, 255, 255, 0.04); +} + +.m3-segment-item.active { + background-color: var(--md-sys-color-primary); + color: var(--md-sys-color-on-primary); + box-shadow: 0 2px 8px rgba(99, 102, 241, 0.2); +} + +.m3-segment-item.disabled { + opacity: 0.45; + cursor: not-allowed; + text-decoration: line-through; +} + +/* Grid Layouts */ +.generator-layout { + display: grid; + grid-template-columns: 1fr; + gap: 24px; +} + +@media (min-width: 1000px) { + .generator-layout { + grid-template-columns: 1.15fr 0.85fr; + } +} + +.chips-container { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 8px; +} + +.status-chip { + display: inline-flex; + align-items: center; + gap: 6px; + background-color: var(--md-sys-color-surface-variant); + border: 1px solid var(--border-color); + color: var(--md-sys-color-on-surface-variant); + padding: 5px 12px; + border-radius: var(--md-shape-corner-full); + font-size: 0.78rem; + font-weight: 550; + cursor: pointer; + transition: all var(--md-transition-duration); +} + +.status-chip:hover { + background-color: var(--md-sys-color-primary-container); + border-color: var(--md-sys-color-primary); + color: var(--md-sys-color-primary); +} + +.prompt-actions { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 16px; +} + +.image-to-image-section { + margin-top: 12px; + border-top: 1px solid var(--border-color); + padding-top: 16px; +} + +/* Drag and Drop Zone */ +.image-dropzone { + border: 2.5px dashed var(--border-color); + border-radius: var(--md-shape-corner-large); + padding: 24px; + text-align: center; + cursor: pointer; + background-color: var(--md-sys-color-surface-variant); + color: var(--md-sys-color-on-surface-variant); + transition: all var(--md-transition-duration); + position: relative; + overflow: hidden; + min-height: 120px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 6px; +} + +.image-dropzone:hover { + background-color: var(--md-sys-color-primary-container); + border-color: var(--md-sys-color-primary); + color: var(--md-sys-color-primary); +} + +.dropped-image-preview { + max-width: 100%; + max-height: 160px; + border-radius: var(--md-shape-corner-medium); + object-fit: contain; + box-shadow: var(--glass-shadow); +} + +/* Aspect Ratio Buttons with Previews */ +.aspect-ratio-btn { + position: relative; + transition: all var(--md-transition-duration) var(--md-transition-easing); +} + +.aspect-ratio-btn.active { + background-color: var(--md-sys-color-primary-container) !important; + border-color: var(--md-sys-color-primary) !important; + color: var(--md-sys-color-primary) !important; + box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.15); +} + +.aspect-ratio-preview { + border: 1.5px solid currentColor; + border-radius: 2px; + opacity: 0.6; + background-color: transparent; + transition: all 0.2s ease; + margin-bottom: 6px; +} + +.aspect-ratio-btn:hover .aspect-ratio-preview, +.aspect-ratio-btn.active .aspect-ratio-preview { + opacity: 1; + background-color: rgba(99, 102, 241, 0.06); +} + +.ratio-1-1 { width: 16px; height: 16px; } +.ratio-4-3 { width: 20px; height: 15px; } +.ratio-16-9 { width: 24px; height: 13.5px; } +.ratio-9-16 { width: 13.5px; height: 24px; } + +/* Image Generation Output Area */ +.output-panel { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 380px; +} + +.output-image-container { + width: 100%; + aspect-ratio: 1; + background-color: var(--md-sys-color-surface-variant); + border-radius: var(--md-shape-corner-large); + border: 1px solid var(--border-color); + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + position: relative; + box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.output-image { + width: 100%; + height: 100%; + object-fit: contain; + transition: transform 0.3s; +} + +.output-image:hover { + transform: scale(1.015); +} + +/* Generation Progress Overlay */ +.progress-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(9, 10, 15, 0.85); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #ffffff; + gap: 14px; + padding: 24px; + z-index: 5; +} + +.progress-spinner { + width: 44px; + height: 44px; + border: 3px solid rgba(255, 255, 255, 0.15); + border-top-color: var(--md-sys-color-primary); + border-radius: 50%; + animation: spin 0.9s cubic-bezier(0.5, 0.1, 0.4, 0.9) infinite; + box-shadow: 0 0 12px rgba(99, 102, 241, 0.2); +} + +.loading-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--md-sys-color-primary); + opacity: 0.9; + animation: pulse 1.2s ease-in-out infinite; + box-shadow: 0 0 8px var(--md-sys-color-primary); +} + +.progress-text { + font-size: 1.05rem; + font-weight: 700; + letter-spacing: -0.01em; +} + +.progress-bar-container { + width: 80%; + height: 5px; + background-color: rgba(255, 255, 255, 0.12); + border-radius: var(--md-shape-corner-full); + overflow: hidden; + margin: 4px 0; +} + +.progress-bar-fill { + height: 100%; + background: linear-gradient(90deg, var(--md-sys-color-primary), #d946ef); + width: 0%; + transition: width 0.4s cubic-bezier(0.1, 0.8, 0.25, 1); + box-shadow: 0 0 8px rgba(99, 102, 241, 0.4); +} + +.output-placeholder-icon { + width: 48px; + height: 48px; + color: var(--md-sys-color-on-surface-variant); + opacity: 0.5; + filter: drop-shadow(0 2px 10px rgba(0,0,0,0.05)); +} + +.output-placeholder-text { + font-size: 0.88rem; + color: var(--md-sys-color-on-surface-variant); + margin-top: 12px; + text-align: center; + line-height: 1.5; + opacity: 0.8; +} + +.image-actions { + display: flex; + gap: 10px; + margin-top: 16px; + width: 100%; +} + +.image-actions button { + flex: 1; +} + +/* Models Grid and Lists */ +.models-grid { + display: grid; + grid-template-columns: 1fr; + gap: 20px; +} + +@media (min-width: 800px) { + .models-grid { + grid-template-columns: 1fr 1fr; + } +} + +.model-card { + display: flex; + flex-direction: column; + justify-content: space-between; + border: 1px solid var(--border-color-muted); +} + +.model-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 12px; +} + +.model-name { + font-size: 1.05rem; + font-weight: 600; +} + +.model-badge { + font-size: 0.72rem; + font-weight: 700; + padding: 3px 8px; + border-radius: var(--md-shape-corner-full); +} + +.model-badge-gguf { + background-color: rgba(245, 158, 11, 0.15); + color: #d97706; +} + +.model-badge-safetensors { + background-color: rgba(14, 165, 233, 0.15); + color: #0284c7; +} + +.model-description { + font-size: 0.82rem; + color: var(--md-sys-color-on-surface-variant); + margin-bottom: 16px; + line-height: 1.45; + opacity: 0.9; +} + +.model-status-info { + margin-top: auto; + padding-top: 12px; + border-top: 1px solid var(--border-color-muted); + display: flex; + align-items: center; + justify-content: space-between; +} + +.model-size { + font-size: 0.8rem; + font-weight: 550; + color: var(--md-sys-color-on-surface-variant); +} + +.model-progress-section { + width: 100%; + margin-top: 12px; +} + +.model-progress-label { + display: flex; + justify-content: space-between; + font-size: 0.78rem; + font-weight: 600; + margin-bottom: 4px; +} + +.model-progress-bar { + width: 100%; + height: 6px; + background-color: var(--border-color-muted); + border-radius: var(--md-shape-corner-full); + overflow: hidden; +} + +.model-progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--md-sys-color-primary), var(--md-sys-color-secondary)); + width: 0%; + transition: width 0.25s ease; +} + +/* Importer & Library */ +.import-box { + border: 2px dashed var(--border-color); + border-radius: var(--md-shape-corner-large); + padding: 32px; + text-align: center; + cursor: pointer; + transition: all var(--md-transition-duration); + background-color: var(--md-sys-color-surface); + color: var(--md-sys-color-on-surface-variant); + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; +} + +.import-box:hover { + background-color: var(--md-sys-color-primary-container); + border-color: var(--md-sys-color-primary); + color: var(--md-sys-color-primary); +} + +.import-icon { + width: 40px; + height: 40px; + color: var(--md-sys-color-primary); + filter: drop-shadow(0 2px 6px rgba(99, 102, 241, 0.15)); +} + +/* Gallery Section */ +.gallery-section { + margin-top: 36px; +} + +.gallery-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; +} + +.gallery-selection-actions { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.gallery-selection-actions .m3-btn { + height: 34px; + padding: 0 14px; +} + +.gallery-selection-count { + font-size: 0.82rem; + font-weight: 700; + color: var(--md-sys-color-primary); + padding: 7px 10px; + border-radius: var(--md-shape-corner-full); + background: var(--md-sys-color-primary-container); +} + +.gallery-hint { + margin-top: 8px; + font-size: 0.78rem; + color: var(--md-sys-color-outline); +} + +.gallery-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); + gap: 12px; + margin-top: 16px; +} + +.gallery-item { + aspect-ratio: 1; + border-radius: var(--md-shape-corner-medium); + overflow: hidden; + border: 1px solid var(--border-color-muted); + cursor: pointer; + position: relative; + contain: layout paint style; + transition: border-color var(--md-transition-duration), box-shadow var(--md-transition-duration), transform var(--md-transition-duration); +} + +.gallery-item.selected { + border-color: var(--md-sys-color-primary); + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.25); +} + +.gallery-thumb { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform var(--md-transition-duration) var(--md-transition-easing); +} + +.gallery-item:hover .gallery-thumb { + transform: scale(1.05); +} + +.gallery-select-badge { + position: absolute; + top: 8px; + right: 8px; + width: 26px; + height: 26px; + border-radius: 50%; + display: grid; + place-items: center; + color: var(--md-sys-color-on-primary); + background: var(--md-sys-color-primary); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28); +} + +.app-dialog-backdrop { + position: fixed; + inset: 0; + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + background: rgba(8, 12, 24, 0.64); + backdrop-filter: blur(4px) saturate(0.86); +} + +.app-dialog { + width: min(460px, 100%); + background: color-mix(in srgb, var(--md-sys-color-surface) 96%, white 4%); + color: var(--md-sys-color-on-surface); + border: 1px solid color-mix(in srgb, var(--md-sys-color-outline) 55%, transparent); + border-radius: var(--md-shape-corner-large); + box-shadow: + 0 22px 60px rgba(0, 0, 0, 0.42), + 0 0 0 1px rgba(255, 255, 255, 0.08) inset; + padding: 24px; +} + +.app-dialog-title { + font-size: 1.15rem; + font-weight: 800; + margin: 0 0 10px 0; +} + +.app-dialog-message { + font-size: 0.92rem; + line-height: 1.45; + color: var(--md-sys-color-on-surface-variant); + margin: 0; + white-space: pre-wrap; +} + +.app-dialog-actions { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-top: 22px; + flex-wrap: wrap; +} + +.gallery-empty { + text-align: center; + padding: 36px; + color: var(--md-sys-color-on-surface-variant); + font-size: 0.85rem; + opacity: 0.8; +} + +/* Animations */ +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.55; transform: scale(1.06); } +} + +/* Sidebar specs classes */ +.sidebar-specs-header { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 6px; + font-weight: 600; + color: var(--md-sys-color-on-background); +} + +.sidebar-specs-item { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + opacity: 0.85; + margin-bottom: 2px; + color: var(--md-sys-color-on-background); +} + +.sidebar-specs-os { + color: var(--md-sys-color-primary); + font-weight: 600; + margin-top: 4px; +} diff --git a/app/frontend/src/App.jsx b/app/frontend/src/App.jsx new file mode 100644 index 0000000..2a56654 --- /dev/null +++ b/app/frontend/src/App.jsx @@ -0,0 +1,516 @@ +import { useState, useEffect, useRef, useCallback, useMemo } from "react"; +import Sidebar from "./components/Sidebar"; +import TopStatusBar from "./components/TopStatusBar"; +import Generator from "./components/Generator"; +import ModelManager from "./components/ModelManager"; +import ImageConstraints from "./components/ImageConstraints"; +import { cleanupCandidates, formatBytes, getCleanupCandidates, getDiagnostics, getHardwareSpecs, getHealth, getTelemetry, getBackendOptions, getBackendStatus, listGeneratedOutputs, stopServer } from "./services/api"; +import "./App.css"; + +function App() { + const dialogResolverRef = useRef(null); + const [dialog, setDialog] = useState(null); + + const closeDialog = useCallback((value) => { + const resolver = dialogResolverRef.current; + dialogResolverRef.current = null; + setDialog(null); + if (resolver) resolver(value); + }, []); + + const showConfirm = useCallback(({ title = "Confirm Action", message, confirmLabel = "OK", cancelLabel = "Cancel", danger = false }) => { + return new Promise((resolve) => { + dialogResolverRef.current = resolve; + setDialog({ type: "confirm", title, message, confirmLabel, cancelLabel, danger }); + }); + }, []); + + const showAlert = useCallback(({ title = "Notice", message, confirmLabel = "OK", danger = false }) => { + return new Promise((resolve) => { + dialogResolverRef.current = resolve; + setDialog({ type: "alert", title, message, confirmLabel, danger }); + }); + }, []); + + // Theme State + const [theme, setTheme] = useState(() => { + const saved = localStorage.getItem("theme"); + if (saved) return saved; + return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; + }); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", theme); + localStorage.setItem("theme", theme); + }, [theme]); + + // Navigation + const [activeTab, setActiveTab] = useState("generator"); + + // Prompts + const [prompt, setPrompt] = useState(""); + const [negativePrompt, setNegativePrompt] = useState(""); + const [inputImage, setInputImage] = useState(null); // base64 for Image-to-Image + + // Model & Server Status + const [activeModel, setActiveModel] = useState(null); + const [serverRunning, setServerRunning] = useState(false); + const [isStoppingServer, setIsStoppingServer] = useState(false); + const [backendOptions, setBackendOptions] = useState({ + options: [{ id: "cpu", label: "CPU", available: true }], + cudaAvailable: false, + vulkanAvailable: false, + defaultBackendType: "cpu", + }); + const [health, setHealth] = useState(null); + const [cleanupItems, setCleanupItems] = useState([]); + const [isReadinessBusy, setIsReadinessBusy] = useState(false); + const [diagnosticsCopied, setDiagnosticsCopied] = useState(false); + + // Gallery History + const [generatedImages, setGeneratedImages] = useState([]); + + // Generation status + const [isGenerating, setIsGenerating] = useState(false); + const [generationProgress, setGenerationProgress] = useState(0); + + // System Specifications & Telemetry + const [specs, setSpecs] = useState({ + os_name: "Loading Specs...", + cpu_name: "Loading Specs...", + cpu_cores_physical: 4, + cpu_cores_logical: 8, + ram_total_gb: 0, + gpu_name: "Loading Specs...", + }); + + const [telemetry, setTelemetry] = useState({ + cpu_usage: 0, + ram_used_gb: 0, + ram_total_gb: 0, + gpu_name: "Detecting...", + vram_used_gb: 0, + vram_total_gb: 0, + }); + + // Default Image Constraints + const [constraints, setConstraints] = useState({ + width: 1024, + height: 1024, + steps: 4, // Recommended default steps for Flux.1 Schnell/Lightning + cfgScale: 1.0, // Recommended default CFG for Flux.1 Schnell + sampler: "euler_a", + seed: -1, + denoisingStrength: 0.7, + useGpu: true, + useTaesd: true, + useFlashAttn: true, + useTiling: false, + threads: 4, + backendType: "auto", + }); + + // Load hardware specifications on mount + useEffect(() => { + async function loadSpecs() { + try { + const hardware = await getHardwareSpecs(); + const backendInfo = await getBackendOptions(); + setBackendOptions(backendInfo); + setSpecs(hardware); + // Default CPU threads count to match physical cores + setConstraints((prev) => ({ + ...prev, + threads: hardware.cpu_cores_physical || 4, + backendType: prev.backendType === "auto" ? backendInfo.defaultBackendType || "cpu" : prev.backendType, + useGpu: (prev.backendType === "auto" ? backendInfo.defaultBackendType : prev.backendType) !== "cpu", + })); + } catch (err) { + console.error("Error fetching hardware specs:", err); + } + } + loadSpecs(); + }, []); + + const refreshReadiness = useCallback(async () => { + setIsReadinessBusy(true); + try { + const [healthInfo, candidates] = await Promise.all([ + getHealth(), + getCleanupCandidates().catch(() => []), + ]); + setHealth(healthInfo); + setCleanupItems(candidates); + } finally { + setIsReadinessBusy(false); + } + }, []); + + useEffect(() => { + refreshReadiness(); + }, [refreshReadiness]); + + const copyDiagnostics = useCallback(async () => { + try { + const diagnostics = await getDiagnostics(); + await navigator.clipboard.writeText(JSON.stringify(diagnostics, null, 2)); + setDiagnosticsCopied(true); + setTimeout(() => setDiagnosticsCopied(false), 1800); + } catch (err) { + showAlert({ title: "Diagnostics Failed", message: err.message || String(err), danger: true }); + } + }, [showAlert]); + + const cleanupSafeItems = useCallback(async () => { + if (cleanupItems.length === 0) return; + const totalBytes = cleanupItems.reduce((sum, item) => sum + Number(item.sizeBytes || 0), 0); + const ok = await showConfirm({ + title: "Clean Safe Files?", + message: `Delete ${cleanupItems.length} temporary/cache item${cleanupItems.length === 1 ? "" : "s"} and free about ${formatBytes(totalBytes)}?\n\nModels and generated outputs are not included.`, + confirmLabel: "Clean", + danger: true, + }); + if (!ok) return; + + setIsReadinessBusy(true); + try { + await cleanupCandidates(cleanupItems.map((item) => item.id)); + await refreshReadiness(); + } catch (err) { + showAlert({ title: "Cleanup Failed", message: err.message || String(err), danger: true }); + } finally { + setIsReadinessBusy(false); + } + }, [cleanupItems, refreshReadiness, showAlert, showConfirm]); + + useEffect(() => { + async function loadSavedOutputs() { + const outputs = await listGeneratedOutputs(); + setGeneratedImages(outputs); + } + loadSavedOutputs(); + }, []); + + // Save active model configuration to localStorage for persistence across reloads + useEffect(() => { + if (activeModel) { + localStorage.setItem("active-model", activeModel); + } else { + localStorage.removeItem("active-model"); + } + }, [activeModel]); + + // Check if server is already running on mount (handles page refresh and startup lag) + useEffect(() => { + let checkInterval = null; + + async function checkServerRunning() { + const status = await getBackendStatus(); + const isRunning = Boolean(status.ready); + if (isRunning) { + if (checkInterval) clearInterval(checkInterval); + + const savedModel = localStorage.getItem("active-model"); + if (savedModel) { + setActiveModel(savedModel); + setServerRunning(true); + } else { + // Query the active model from status if possible, otherwise use fallback + try { + if (status && status.settings && status.settings.model) { + const modelName = status.settings.model.split(/[\\/]/).pop(); + setActiveModel(modelName); + } + } catch (_) {} + setServerRunning(true); + } + } else { + // If server is not running, check if they had a simulated model active in browser mode + const isTauriDesktop = typeof window !== "undefined" && window.__TAURI_INTERNALS__ !== undefined; + if (!isTauriDesktop) { + const savedModel = localStorage.getItem("active-model"); + if (savedModel) { + setActiveModel(savedModel); + setServerRunning(false); + } + } + } + } + + checkServerRunning(); + // Poll every 2 seconds to auto-detect when the backend becomes ready + checkInterval = setInterval(checkServerRunning, 2000); + + return () => { + if (checkInterval) clearInterval(checkInterval); + }; + }, []); + + // Poll system telemetry usage statistics on interval + useEffect(() => { + async function updateTelemetry() { + try { + const stats = await getTelemetry(); + setTelemetry((prev) => ( + prev.cpu_usage === stats.cpu_usage && + prev.ram_used_gb === stats.ram_used_gb && + prev.ram_total_gb === stats.ram_total_gb && + prev.gpu_name === stats.gpu_name && + prev.vram_used_gb === stats.vram_used_gb && + prev.vram_total_gb === stats.vram_total_gb + ? prev + : stats + )); + } catch (err) { + // Telemetry errors ignored + } + } + + updateTelemetry(); + const interval = setInterval(updateTelemetry, 1500); // Poll every 1.5 seconds + + return () => clearInterval(interval); + }, []); + + // Sync active model settings default parameters + useEffect(() => { + if (activeModel) { + const name = activeModel.toLowerCase(); + if (name.includes("flux") || name.includes("schnell")) { + setConstraints((prev) => ({ + ...prev, + steps: 4, + cfgScale: 1.0, + width: 1024, + height: 1024, + })); + } else if (name.includes("lightning") || name.includes("turbo")) { + setConstraints((prev) => ({ + ...prev, + steps: 4, + cfgScale: 1.5, + width: 1024, + height: 1024, + })); + } else if (name.includes("sd15")) { + setConstraints((prev) => ({ + ...prev, + steps: 25, + cfgScale: 7.0, + width: 512, + height: 512, + })); + } else if (name.includes("sd35")) { + setConstraints((prev) => ({ + ...prev, + steps: 20, + cfgScale: 4.5, + width: 1024, + height: 1024, + })); + } else { + // Fallback for custom or SD 1.x models (like CyberRealistic or arbitrary safetensors) + setConstraints((prev) => ({ + ...prev, + steps: 20, + cfgScale: 7.0, + width: 512, + height: 512, + })); + } + } + }, [activeModel]); + + const activeTabContent = useMemo(() => { + switch (activeTab) { + case "generator": + return ( + + ); + case "models": + return ( + + ); + case "constraints": + return ( + + ); + default: + return null; + } + }, [ + activeTab, + prompt, + negativePrompt, + constraints, + activeModel, + generatedImages, + isGenerating, + generationProgress, + inputImage, + serverRunning, + specs, + backendOptions, + showAlert, + showConfirm, + ]); + + const sidebarContent = useMemo(() => ( + + ), [activeTab, specs]); + + const handleStopServer = useCallback(async () => { + if (!serverRunning || isStoppingServer) return; + setIsStoppingServer(true); + try { + await stopServer(); + setServerRunning(false); + setActiveModel(null); + } catch (err) { + console.error("Failed to stop server:", err); + showAlert({ title: "Stop Server Failed", message: err.message || String(err), danger: true }); + } finally { + setIsStoppingServer(false); + } + }, [serverRunning, isStoppingServer, showAlert]); + + const readinessIssues = [ + ...(health?.stale ? ["Restart Local AI Image Generator so the local server loads the latest API."] : []), + ...(health?.issues || []), + ]; + const cleanupBytes = cleanupItems.reduce((sum, item) => sum + Number(item.sizeBytes || 0), 0); + const showReadinessPanel = Boolean(health && (readinessIssues.length > 0 || cleanupItems.length > 0)); + + return ( +
+ {/* Sidebar with Navigation Rail & Specs */} + {sidebarContent} + + {/* Main Panel */} +
+ {/* Top telemetry specs chips bar */} + + + {showReadinessPanel && ( +
0 ? "readiness-card-warning" : ""}`}> +
+
+

+ {health?.stale ? "Restart Required" : readinessIssues.length > 0 ? "System Readiness" : "Safe Cleanup Available"} +

+

+ {health?.stale + ? `Running server build: ${health.build || "unknown"}` + : readinessIssues.length > 0 + ? "Local AI Image Generator found setup items that may need attention." + : `${cleanupItems.length} temporary item${cleanupItems.length === 1 ? "" : "s"} can be cleaned (${formatBytes(cleanupBytes)}).`} +

+
+
+ + + {cleanupItems.length > 0 && ( + + )} +
+
+ {readinessIssues.length > 0 && ( +
+ {readinessIssues.slice(0, 4).map((issue) => ( + {issue} + ))} +
+ )} + {cleanupItems.length > 0 && ( +
+ {cleanupItems.slice(0, 3).map((item) => ( + + {item.name} · {item.size} · {item.reason} + + ))} +
+ )} +
+ )} + + {/* Dynamic Workspace Container */} + {activeTabContent} +
+ + {dialog && ( +
+
+

{dialog.title}

+

{dialog.message}

+
+ {dialog.type === "confirm" && ( + + )} + +
+
+
+ )} +
+ ); +} + +export default App; diff --git a/app/frontend/src/components/Generator.jsx b/app/frontend/src/components/Generator.jsx new file mode 100644 index 0000000..042570d --- /dev/null +++ b/app/frontend/src/components/Generator.jsx @@ -0,0 +1,878 @@ +import React, { memo, useState, useRef, useCallback } from "react"; +import { Sparkles, Download, Copy, RefreshCw, ImagePlus, Check, Sliders, Layers, Trash2 } from "lucide-react"; +import { generateImage, isTauri, startServer, stopServer, waitForServerReady, getBackendStatus, getGenerationProgress, saveGeneratedOutput, deleteGeneratedOutputs } from "../services/api"; + +const GalleryItem = memo(({ img, idx, isSelected, onClick }) => { + const handleClick = (e) => { + onClick(idx, e); + }; + return ( +
+ Thumbnail + {isSelected && ( +
+ +
+ )} +
+ ); +}); + +function Generator({ + prompt, + setPrompt, + negativePrompt, + setNegativePrompt, + constraints, + setConstraints, + activeModel, + generatedImages, + setGeneratedImages, + isGenerating, + setIsGenerating, + generationProgress, + setGenerationProgress, + setActiveTab, + inputImage, + setInputImage, + showAlert = async ({ message }) => window.alert(message), + showConfirm = async ({ message }) => window.confirm(message), +}) { + const [outputImage, setOutputImage] = useState(null); + const [outputSeed, setOutputSeed] = useState(null); + const [genDuration, setGenDuration] = useState(null); + const [copySuccess, setCopySuccess] = useState(false); + const [elapsedTime, setElapsedTime] = useState(0); + const [estimatedLeftTime, setEstimatedLeftTime] = useState(0); + const [currentStep, setCurrentStep] = useState(0); + const [generationSpeed, setGenerationSpeed] = useState(""); + const [isCpuFallback, setIsCpuFallback] = useState(false); + const [isCancelling, setIsCancelling] = useState(false); + const [isRestartingBackend, setIsRestartingBackend] = useState(false); + const [restartLoadProgress, setRestartLoadProgress] = useState(null); + const [errorMsg, setErrorMsg] = useState(null); + const [selectedGalleryIndexes, setSelectedGalleryIndexes] = useState([]); + const timerRef = useRef(null); + const fileInputRef = useRef(null); + const abortControllerRef = useRef(null); + + // Trigger file dialog for Image-to-Image + const handleDropzoneClick = () => { + fileInputRef.current.click(); + }; + + // Convert uploaded image file to Base64 + const handleFileChange = (e) => { + const file = e.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = () => { + setInputImage(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + const clearInputImage = (e) => { + e.stopPropagation(); + setInputImage(null); + if (fileInputRef.current) fileInputRef.current.value = ""; + }; + + // Trigger main image generation process + const handleGenerate = async () => { + if (!prompt.trim()) return; + + setErrorMsg(null); + setIsRestartingBackend(true); + setRestartLoadProgress(null); + + let needsRestart = false; + try { + const status = await getBackendStatus(); + if (status && status.settings) { + const settings = status.settings; + const currentModelName = settings.model ? settings.model.split(/[\\/]/).pop() : null; + const targetModelName = activeModel ? activeModel.split(/[\\/]/).pop() : null; + + if (currentModelName !== targetModelName || + parseInt(settings.steps) !== parseInt(constraints.steps) || + Math.abs(parseFloat(settings.cfgScale) - parseFloat(constraints.cfgScale)) > 0.05 || + settings.sampler !== constraints.sampler || + parseInt(settings.threads) !== parseInt(constraints.threads) || + Boolean(settings.useGpu) !== (constraints.useGpu !== false) || + (settings.backendType || (settings.useGpu === false ? "cpu" : "auto")) !== (constraints.backendType || (constraints.useGpu === false ? "cpu" : "auto"))) { + needsRestart = true; + } + } else { + needsRestart = true; + } + } catch (e) { + needsRestart = true; + } + + if (needsRestart) { + try { + console.log("Settings out of sync, restarting backend..."); + await startServer(activeModel, constraints); + + let isReady = false; + let crashError = null; + for (let i = 0; i < 240; i++) { // Poll for up to 120 seconds (240 * 500ms) + const status = await getBackendStatus(); + if (status.loading) { + setRestartLoadProgress({ + progress: status.loading.progress || 0, + phase: status.loading.phase || "Loading model...", + speed: status.loading.speed || "", + current: status.loading.current || 0, + total: status.loading.total || 0, + backendMode: status.loading.backendMode || status.settings?.backendMode || "", + device: status.loading.device || status.settings?.backendDevice || "", + }); + } + if (status.ready) { + isReady = true; + break; + } + if (status.error) { + crashError = status.error; + break; + } + if (!status.running && i > 3) { + crashError = "The backend process terminated immediately on startup."; + break; + } + await new Promise((r) => setTimeout(r, 500)); + } + + if (!isReady) { + throw new Error(crashError || "Backend server failed to start after applying configuration changes."); + } + } catch (err) { + console.error("Failed to restart backend:", err); + setErrorMsg(err.message || "Failed to sync settings with backend."); + setIsRestartingBackend(false); + return; + } + } + setIsRestartingBackend(false); + setRestartLoadProgress(null); + + if (timerRef.current) clearInterval(timerRef.current); + setIsGenerating(true); + setGenerationProgress(0); + setElapsedTime(0); + setCurrentStep(0); + setGenerationSpeed(""); + setIsCpuFallback(false); + setGenDuration(null); + setOutputImage(null); + + // Calculate dynamic step estimation times + // CPU takes ~35s per step at 512px, ~140s at 1024px. GPU is ~0.04x of CPU time. + const baseGpuStepTime = (constraints.width >= 1024 ? 140 : 35) * 0.04; + const baseCpuStepTime = (constraints.width >= 1024 ? 140 : 35); + + const gpuSelected = (constraints.backendType || (constraints.useGpu === false ? "cpu" : "auto")) !== "cpu"; + let activeStepTime = gpuSelected ? baseGpuStepTime : baseCpuStepTime; + let cpuFallbackDetected = false; + let fallbackTime = 0; + let fallbackProgress = 0; + let elapsedSeconds = 0; + + setEstimatedLeftTime(Math.round(constraints.steps * activeStepTime)); + + timerRef.current = setInterval(async () => { + elapsedSeconds++; + setElapsedTime(elapsedSeconds); + + try { + const progress = await getGenerationProgress(); + if (progress && progress.active) { + const step = progress.step || 0; + const steps = progress.steps || constraints.steps || 20; + const speed = progress.speed || ""; + + setCurrentStep(step); + setGenerationSpeed(speed); + + // Calculate progress percentage + let progressPercent = 0; + if (steps > 0) { + progressPercent = Math.round((step / steps) * 100); + } + progressPercent = Math.min(99, progressPercent); + setGenerationProgress((prev) => Math.max(prev, progressPercent)); + + // Calculate remaining time + let remaining = 0; + const numericSpeed = parseFloat(speed); + if (!isNaN(numericSpeed) && numericSpeed > 0) { + const remainingSteps = Math.max(0, steps - step); + if (speed.includes("it/s")) { + remaining = remainingSteps / numericSpeed; + } else if (speed.includes("s/it")) { + remaining = remainingSteps * numericSpeed; + } + } else { + const activeStepTime = gpuSelected ? baseGpuStepTime : baseCpuStepTime; + remaining = Math.max(0, (steps - step) * activeStepTime); + } + + // Detect CPU fallback / slow generation if GPU was requested but it runs slow + if (gpuSelected && !cpuFallbackDetected) { + const isSlowItS = speed.includes("it/s") && numericSpeed < 0.2; + const isSlowSIt = speed.includes("s/it") && numericSpeed > 5.0; + if (isSlowItS || isSlowSIt) { + cpuFallbackDetected = true; + setIsCpuFallback(true); + } + } + + setEstimatedLeftTime(Math.round(remaining)); + } else { + // Creep up slowly while loading the model/preparing + setGenerationProgress((prev) => Math.min(15, prev + 1)); + setEstimatedLeftTime((prev) => Math.max(1, prev - 1)); + } + } catch (e) { + console.warn("Failed to get generation progress, running simulation fallback:", e); + + // Fallback simulation logic + if (gpuSelected && !cpuFallbackDetected && elapsedSeconds > constraints.steps * baseGpuStepTime * 1.3) { + cpuFallbackDetected = true; + setIsCpuFallback(true); + activeStepTime = baseCpuStepTime; + fallbackTime = elapsedSeconds; + fallbackProgress = Math.min(95, Math.round((elapsedSeconds / (constraints.steps * baseGpuStepTime)) * 100)); + } + + let step = Math.min(constraints.steps - 1, Math.floor(elapsedSeconds / activeStepTime)); + let expectedTotal = constraints.steps * activeStepTime; + if (elapsedSeconds >= expectedTotal) { + const computedStepTime = Math.ceil(elapsedSeconds / Math.max(0.5, step)); + activeStepTime = Math.max(activeStepTime + 15, computedStepTime + 15); + expectedTotal = constraints.steps * activeStepTime; + step = Math.min(constraints.steps - 1, Math.floor(elapsedSeconds / activeStepTime)); + } + setCurrentStep(step); + + const remaining = Math.max(1, expectedTotal - elapsedSeconds); + setEstimatedLeftTime(Math.round(remaining)); + + let progressPercent = 0; + if (cpuFallbackDetected) { + const remainingProgress = 99 - fallbackProgress; + const remainingTime = expectedTotal - fallbackTime; + if (remainingTime > 0) { + const ratio = Math.min(1.0, (elapsedSeconds - fallbackTime) / remainingTime); + if (ratio < 0.85) { + progressPercent = Math.round(fallbackProgress + ratio * remainingProgress); + } else { + const x = (elapsedSeconds - (fallbackTime + remainingTime * 0.85)) / (activeStepTime * 2); + const decay = 1 - Math.exp(-x); + progressPercent = Math.min(99, Math.round(fallbackProgress + 0.85 * remainingProgress + (0.14 * remainingProgress) * decay)); + } + } else { + progressPercent = 99; + } + } else { + if (elapsedSeconds < expectedTotal * 0.85) { + progressPercent = Math.round((elapsedSeconds / expectedTotal) * 100); + } else { + const x = (elapsedSeconds - expectedTotal * 0.85) / (activeStepTime * 2); + const decay = 1 - Math.exp(-x); + progressPercent = Math.min(99, Math.round(85 + 14 * decay)); + } + } + setGenerationProgress((p) => Math.max(p, progressPercent)); + } + }, 1000); + + try { + abortControllerRef.current = new AbortController(); + const result = await generateImage( + prompt, + negativePrompt, + constraints, + activeModel, + inputImage, // passes base64 if I2I + (prog) => setGenerationProgress((prev) => Math.max(prev, prog)), + abortControllerRef.current.signal + ); + + if (timerRef.current) clearInterval(timerRef.current); + setGenerationProgress(100); + setCurrentStep(constraints.steps); + setEstimatedLeftTime(0); + setGenerationSpeed(""); + + const metadata = { + prompt: prompt, + negativePrompt: negativePrompt, + seed: result.seed, + steps: constraints.steps, + cfgScale: constraints.cfgScale, + width: constraints.width, + height: constraints.height, + sampler: constraints.sampler, + model: activeModel, + duration_sec: result.duration_sec, + timestamp: new Date().toLocaleTimeString(), + inputImage: Boolean(inputImage), + }; + let savedOutput = null; + let savedUrl = null; + try { + savedOutput = await saveGeneratedOutput(result.image, metadata); + savedUrl = savedOutput.url; + if (!savedUrl) { + throw new Error("The local server saved the image but did not return a file URL."); + } + } catch (saveErr) { + console.error("Generated image could not be saved:", saveErr); + throw new Error(`Image generated but could not be saved to USB: ${saveErr.message || saveErr}`); + } + + setOutputImage(savedUrl); + setOutputSeed(result.seed); + setGenDuration(result.duration_sec); + + const historyItem = { + ...metadata, + ...(savedOutput || {}), + url: savedUrl, + }; + + setGeneratedImages((prev) => [historyItem, ...prev]); + } catch (e) { + if (e.name === "AbortError") { + console.log("Generation request was aborted by the user"); + } else { + console.error("Generation failed:", e); + setErrorMsg(e.message || "Generation failed. Please try again."); + } + if (timerRef.current) clearInterval(timerRef.current); + } finally { + setIsGenerating(false); + abortControllerRef.current = null; + } + }; + + // Stop/Cancel Generation Handler + const handleCancelGeneration = async () => { + if (await showConfirm({ + title: "Stop Generation?", + message: "The current image generation will be cancelled and the local model server may restart.", + confirmLabel: "Stop", + danger: true, + })) { + if (timerRef.current) clearInterval(timerRef.current); + + // Set cancelling state first to keep the progress overlay active in cancelling mode + setIsCancelling(true); + + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + } + + // In native desktop mode, restart the server process to immediately free CPU threads/memory + if (isTauri()) { + try { + console.log("Cancelling: Stopping server to kill generation threads..."); + await stopServer(); + if (activeModel) { + console.log("Cancelling: Restarting server for future generations..."); + await startServer(activeModel, constraints); + const ready = await waitForServerReady(); + if (!ready) { + console.warn("Server failed to restart properly."); + } + } + } catch (err) { + console.error("Failed to restart server on cancellation:", err); + } finally { + setIsCancelling(false); + setIsGenerating(false); + setGenerationProgress(0); + } + } else { + // Browser Mode + setIsCancelling(false); + setIsGenerating(false); + setGenerationProgress(0); + } + } + }; + + // Copy generated image to clipboard + const handleCopyImage = async () => { + if (!outputImage) return; + try { + if (outputImage.startsWith("data:image")) { + // base64 conversion for clipboard + const response = await fetch(outputImage); + const blob = await response.blob(); + await navigator.clipboard.write([ + new ClipboardItem({ [blob.type]: blob }) + ]); + } else { + // Remote Unsplash images fallback (draw on canvas then copy) + const img = new Image(); + img.crossOrigin = "anonymous"; + img.src = outputImage; + img.onload = async () => { + const canvas = document.createElement("canvas"); + canvas.width = img.width; + canvas.height = img.height; + const ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + canvas.toBlob(async (blob) => { + await navigator.clipboard.write([ + new ClipboardItem({ [blob.type]: blob }) + ]); + }, "image/png"); + }; + } + setCopySuccess(true); + setTimeout(() => setCopySuccess(false), 2000); + } catch (err) { + console.error("Failed to copy image:", err); + } + }; + + // Download generated image + const handleDownload = () => { + if (!outputImage) return; + const link = document.createElement("a"); + link.href = outputImage; + link.download = `diffusion-${outputSeed || Date.now()}.png`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + const downloadImageUrl = (url, filename = `diffusion-${Date.now()}.png`) => { + if (!url) return; + const link = document.createElement("a"); + link.href = url; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + // Reuse prompt settings from history + const loadHistoryItem = useCallback((item) => { + setPrompt(item.prompt); + setNegativePrompt(item.negativePrompt); + setConstraints((prev) => ({ + ...prev, + steps: item.steps, + cfgScale: item.cfgScale, + width: item.width, + height: item.height, + sampler: item.sampler, + seed: item.seed, + })); + setOutputImage(item.url); + setOutputSeed(item.seed); + setGenDuration(null); + }, [setPrompt, setNegativePrompt, setConstraints]); + + const toggleGallerySelection = useCallback((idx, event) => { + const multi = event.ctrlKey || event.metaKey || event.shiftKey; + setSelectedGalleryIndexes((prev) => { + if (!multi) return [idx]; + return prev.includes(idx) ? prev.filter((item) => item !== idx) : [...prev, idx]; + }); + if (generatedImages[idx]) { + loadHistoryItem(generatedImages[idx]); + } + }, [generatedImages, loadHistoryItem]); + + const selectedGalleryItems = selectedGalleryIndexes + .map((idx) => generatedImages[idx]) + .filter(Boolean); + + const clearGallerySelection = () => { + setSelectedGalleryIndexes([]); + }; + + const useSelectedGalleryItem = () => { + if (selectedGalleryItems[0]) { + loadHistoryItem(selectedGalleryItems[0]); + } + }; + + const downloadSelectedGalleryItems = () => { + selectedGalleryItems.forEach((item, index) => { + const seed = item.seed ?? Date.now(); + downloadImageUrl(item.url, `diffusion-${seed}-${index + 1}.png`); + }); + }; + + const deleteSelectedGalleryItems = async () => { + if (selectedGalleryItems.length === 0) return; + const count = selectedGalleryItems.length; + const confirmed = await showConfirm({ + title: "Delete Selected Outputs?", + message: `Delete ${count} selected output${count === 1 ? "" : "s"} from USB? This removes the image and metadata files.`, + confirmLabel: "Delete", + danger: true, + }); + if (!confirmed) return; + + try { + await deleteGeneratedOutputs(selectedGalleryItems); + const selectedSet = new Set(selectedGalleryIndexes); + setGeneratedImages((prev) => prev.filter((_, idx) => !selectedSet.has(idx))); + setSelectedGalleryIndexes([]); + + if (selectedGalleryItems.some((item) => item.url === outputImage)) { + setOutputImage(null); + setOutputSeed(null); + setGenDuration(null); + } + } catch (err) { + console.error("Failed to delete selected outputs:", err); + showAlert({ + title: "Delete Failed", + message: err.message || String(err), + danger: true, + }); + } + }; + + return ( +
+
+

Generator Dashboard

+

+ Create high-fidelity images completely locally on your external drive. +

+
+ +
+ {/* Left Side: Parameters & Input */} +
+
+

+ + Generation Workspace +

+ +
+ {/* Prompt Textarea */} +
+ +