diff --git a/.gitignore b/.gitignore index 44c0ca0..4db528c 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,8 @@ pkg/ # User config (not tracked — see contrib/config.example.json) config.json -# IDE / editor +# Node / Vite +ui/node_modules/ .vscode/ .idea/ *.swp diff --git a/PKGBUILD b/PKGBUILD index 53d4d9b..3bcbc02 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -11,6 +11,8 @@ depends=( 'python' 'python-pyserial' 'python-pulsectl' + 'python-fastapi' + 'python-uvicorn' 'pipewire-pulse' 'playerctl' ) @@ -37,9 +39,11 @@ package() { python -m installer --destdir="$pkgdir" dist/*.whl - # Systemd user service + # Systemd user services install -Dm644 contrib/turnupd.service \ "$pkgdir/usr/lib/systemd/user/turnupd.service" + install -Dm644 contrib/turnup-ui.service \ + "$pkgdir/usr/lib/systemd/user/turnup-ui.service" # License install -Dm644 LICENSE \ diff --git a/contrib/turnup-ui.service b/contrib/turnup-ui.service new file mode 100644 index 0000000..a75bc2c --- /dev/null +++ b/contrib/turnup-ui.service @@ -0,0 +1,18 @@ +[Unit] +Description=Turn Up web UI +Documentation=https://github.com/sean351/turn-up-arch +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/turnup-ui +Restart=on-failure +RestartSec=5 + +# Logging +StandardOutput=journal +StandardError=journal +SyslogIdentifier=turnup-ui + +[Install] +WantedBy=default.target diff --git a/pyproject.toml b/pyproject.toml index 7d32d75..90d4de1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,12 +17,14 @@ dependencies = [ [project.optional-dependencies] dev = ["pytest>=8.0"] +ui = ["fastapi>=0.110", "uvicorn>=0.29"] [tool.pytest.ini_options] testpaths = ["tests"] [project.scripts] -turnupd = "turnup.turnupd:main" +turnupd = "turnup.turnupd:main" +turnup-ui = "turnup.ui.server:main" [project.urls] Homepage = "https://github.com/sean351/turn-up-arch" diff --git a/src/turnup/turnupd.py b/src/turnup/turnupd.py index 5e6efc4..112aed1 100755 --- a/src/turnup/turnupd.py +++ b/src/turnup/turnupd.py @@ -397,7 +397,9 @@ def main() -> None: msg["id"], msg["action"], config, pulse ) elif msg["type"] == "heartbeat": - send_leds(ser, all_led_colors(config, knob_norms)) + new_colors = all_led_colors(config, knob_norms) + send_leds(ser, new_colors) + last_led_colors[:] = new_colors # Check for config changes every 2 s (serial read timeout = 0.1 s). now = time.monotonic() diff --git a/src/turnup/ui/__init__.py b/src/turnup/ui/__init__.py new file mode 100644 index 0000000..421bcce --- /dev/null +++ b/src/turnup/ui/__init__.py @@ -0,0 +1 @@ +# turnup.ui — web UI package diff --git a/src/turnup/ui/server.py b/src/turnup/ui/server.py new file mode 100644 index 0000000..fed2c6b --- /dev/null +++ b/src/turnup/ui/server.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +""" +ui/server.py — TurnUp web UI (FastAPI + uvicorn) + +Serves a PWA at http://127.0.0.1:5173 that lets you edit +~/.config/turnup/config.toml and manage named TOML presets. +""" + +from __future__ import annotations + +import logging +import re +from pathlib import Path +from typing import Any + +import uvicorn +from fastapi import FastAPI, HTTPException, Request +from fastapi.responses import FileResponse + +from ..config import DEFAULT_CONFIG_PATH, _XDG_CONFIG_DIR, load_config + +log = logging.getLogger("turnup-ui") + +PRESETS_DIR = Path(_XDG_CONFIG_DIR) / "presets" +STATIC_DIR = Path(__file__).parent / "static" + +# ── TOML serializer ──────────────────────────────────────────────────────────── +# tomllib (stdlib) is read-only; we write our own minimal serialiser so we +# don't need an extra runtime dep (tomli-w). + +_SAFE_NAME = re.compile(r"^[A-Za-z0-9 _\-\.]+$") + + +def _s(v: str) -> str: + """Quote a string value for TOML.""" + return '"' + v.replace("\\", "\\\\").replace('"', '\\"') + '"' + + +def _color(c: list[int]) -> str: + return f"[{int(c[0])}, {int(c[1])}, {int(c[2])}]" + + +def config_to_toml(cfg: dict) -> str: + lines: list[str] = [] + + lines.append(f'port = {_s(cfg.get("port", "/dev/ttyACM0"))}') + lines.append(f'baud = {int(cfg.get("baud", 115200))}') + lines.append("") + + leds = cfg.get("leds") or {} + lines.append("[leds]") + lines.append(f'mode = {_s(leds.get("mode", "volume"))}') + lines.append(f'low_color = {_color(leds.get("low_color", [255, 0, 0]))}') + lines.append(f'high_color = {_color(leds.get("high_color", [0, 255, 0]))}') + lines.append("") + + knobs = cfg.get("knobs") or {} + for i in range(5): + knob = knobs.get(str(i)) + if not knob: + continue + action = knob.get("action", "sink_volume") + lines.append(f"[knobs.{i}]") + lines.append(f'action = {_s(action)}') + if action == "group_volume": + tgts = knob.get("targets") or [] + lines.append(f'targets = [{", ".join(_s(t) for t in tgts)}]') + else: + lines.append(f'target = {_s(knob.get("target", "default"))}') + # Optional per-knob LED override (written as an inline table) + knob_led = knob.get("led") + if knob_led and isinstance(knob_led, dict): + parts: list[str] = [] + if "mode" in knob_led: + parts.append(f'mode = {_s(knob_led["mode"])}') + if "low_color" in knob_led: + parts.append(f'low_color = {_color(knob_led["low_color"])}') + if "high_color" in knob_led: + parts.append(f'high_color = {_color(knob_led["high_color"])}') + if parts: + lines.append(f'led = {{{", ".join(parts)}}}') + lines.append("") + + buttons = cfg.get("buttons") or {} + for i in range(5): + btn = buttons.get(str(i)) + if not btn: + continue + lines.append(f"[buttons.{i}]") + lines.append(f'action = {_s(btn.get("action", "mute_sink"))}') + lines.append(f'target = {_s(btn.get("target", "default"))}') + lines.append("") + + return "\n".join(lines) + + +# ── FastAPI app ──────────────────────────────────────────────────────────────── + +app = FastAPI(title="TurnUp UI", docs_url=None, redoc_url=None) + + +# ── Config API ───────────────────────────────────────────────────────────────── + +@app.get("/api/config") +def get_config() -> dict[str, Any]: + return load_config() + + +@app.post("/api/config") +async def save_config(request: Request) -> dict[str, bool]: + cfg = await request.json() + Path(DEFAULT_CONFIG_PATH).parent.mkdir(parents=True, exist_ok=True) + Path(DEFAULT_CONFIG_PATH).write_text(config_to_toml(cfg)) + return {"ok": True} + + +# ── Presets API ──────────────────────────────────────────────────────────────── + +def _preset_path(name: str) -> Path: + if not name or not _SAFE_NAME.match(name): + raise HTTPException(status_code=400, detail="Invalid preset name — use letters, numbers, spaces, hyphens, underscores, dots only") + return PRESETS_DIR / f"{name}.toml" + + +@app.get("/api/presets") +def list_presets() -> list[str]: + PRESETS_DIR.mkdir(parents=True, exist_ok=True) + return sorted(p.stem for p in PRESETS_DIR.glob("*.toml")) + + +@app.get("/api/presets/{name}") +def get_preset(name: str) -> dict[str, Any]: + path = _preset_path(name) + if not path.exists(): + raise HTTPException(status_code=404, detail="Preset not found") + return load_config(str(path)) + + +@app.post("/api/presets/{name}/save") +async def save_preset(name: str, request: Request) -> dict[str, bool]: + path = _preset_path(name) + PRESETS_DIR.mkdir(parents=True, exist_ok=True) + cfg = await request.json() + path.write_text(config_to_toml(cfg)) + return {"ok": True} + + +@app.post("/api/presets/{name}/apply") +def apply_preset(name: str) -> dict[str, bool]: + path = _preset_path(name) + if not path.exists(): + raise HTTPException(status_code=404, detail="Preset not found") + cfg = load_config(str(path)) + Path(DEFAULT_CONFIG_PATH).parent.mkdir(parents=True, exist_ok=True) + Path(DEFAULT_CONFIG_PATH).write_text(config_to_toml(cfg)) + return {"ok": True} + + +@app.delete("/api/presets/{name}") +def delete_preset(name: str) -> dict[str, bool]: + path = _preset_path(name) + if not path.exists(): + raise HTTPException(status_code=404, detail="Preset not found") + path.unlink() + return {"ok": True} + + +# ── Static files ─────────────────────────────────────────────────────────────── +# Must come AFTER all /api/* routes so the catch-all doesn't shadow them. +# Vite outputs hashed assets under assets/ and references them as /assets/… +# so we serve everything straight off STATIC_DIR at the URL root. + +@app.get("/") +def root() -> FileResponse: + return FileResponse(str(STATIC_DIR / "index.html")) + + +@app.get("/{filepath:path}") +def static_file(filepath: str) -> FileResponse: + path = (STATIC_DIR / filepath).resolve() + # Safety: disallow path traversal outside STATIC_DIR + try: + path.relative_to(STATIC_DIR.resolve()) + except ValueError: + raise HTTPException(status_code=403) + if not path.exists() or not path.is_file(): + # SPA fallback — return index.html for unknown paths + return FileResponse(str(STATIC_DIR / "index.html")) + return FileResponse(str(path)) + + +# ── Entry point ──────────────────────────────────────────────────────────────── + +def main() -> None: + logging.basicConfig( + level=logging.INFO, + format="%(levelname)s %(name)s %(message)s", + ) + log.info("TurnUp UI → http://127.0.0.1:5173") + uvicorn.run(app, host="127.0.0.1", port=5173, log_level="warning") + + +if __name__ == "__main__": + main() diff --git a/src/turnup/ui/static/assets/index-35WG7lRs.css b/src/turnup/ui/static/assets/index-35WG7lRs.css new file mode 100644 index 0000000..63ba356 --- /dev/null +++ b/src/turnup/ui/static/assets/index-35WG7lRs.css @@ -0,0 +1 @@ +:root{--bg: #0d1117;--surface: #161b22;--surface-2: #21262d;--border: #30363d;--text: #e6edf3;--text-muted: #8b949e;--accent: #58a6ff;--accent-dim: #1f3a5f;--success: #3fb950;--danger: #f85149;--warning: #d29922;--radius: 8px;--gap: 16px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}body{background:var(--bg);color:var(--text);font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:14px;line-height:1.6;min-height:100dvh}h2{font-size:13px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);margin-bottom:12px}label{display:block;font-size:12px;color:var(--text-muted);margin-bottom:4px}input[type=text],input[type=number],select,textarea{width:100%;background:var(--surface-2);color:var(--text);border:1px solid var(--border);border-radius:var(--radius);padding:7px 10px;font-size:13px;font-family:inherit;outline:none;transition:border-color .15s}input[type=text]:focus,input[type=number]:focus,select:focus,textarea:focus{border-color:var(--accent)}select{cursor:pointer}textarea{resize:vertical;min-height:60px}input[type=color]{width:36px;height:36px;padding:2px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);cursor:pointer;flex-shrink:0}button{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;font-size:13px;font-family:inherit;font-weight:500;border:1px solid transparent;border-radius:var(--radius);cursor:pointer;transition:background .15s,border-color .15s,opacity .15s;white-space:nowrap}button:active{opacity:.75}button:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:var(--accent);color:#000;border-color:var(--accent)}.btn-primary:hover:not(:disabled){background:#79b8ff;border-color:#79b8ff}.btn-secondary{background:var(--surface-2);color:var(--text);border-color:var(--border)}.btn-secondary:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}.btn-danger{background:transparent;color:var(--danger);border-color:var(--danger)}.btn-danger:hover:not(:disabled){background:var(--danger);color:#fff}.btn-sm{padding:4px 10px;font-size:12px}#app-header{position:sticky;top:0;z-index:100;display:flex;align-items:center;gap:var(--gap);padding:12px 24px;background:var(--surface);border-bottom:1px solid var(--border)}#app-header h1{font-size:16px;font-weight:700;letter-spacing:.04em;flex:1}#dirty-badge{font-size:11px;padding:2px 8px;border-radius:20px;background:var(--warning);color:#000;font-weight:600}main{max-width:1100px;margin:0 auto;padding:24px;display:flex;flex-direction:column;gap:28px}#loading{display:flex;align-items:center;justify-content:center;min-height:100dvh;color:var(--text-muted);font-size:14px}.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px}#connection .fields{display:flex;gap:var(--gap);flex-wrap:wrap}#connection .field{flex:1;min-width:160px}#global-leds .fields{display:flex;gap:var(--gap);align-items:flex-end;flex-wrap:wrap}#global-leds .field{flex:1;min-width:120px}.color-row{display:flex;align-items:center;gap:8px}.color-hex{font-size:12px;color:var(--text-muted);font-family:monospace}.led-preview{margin-top:12px;height:8px;border-radius:4px}.cards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:var(--gap)}.knob-card,.button-card{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:14px;display:flex;flex-direction:column;gap:10px}.knob-card .card-title,.button-card .card-title{font-size:13px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:8px}.card-index{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:var(--accent-dim);color:var(--accent);font-size:11px;font-weight:700}.led-override-toggle{font-size:11px;color:var(--text-muted);cursor:pointer;display:flex;align-items:center;gap:6px;-webkit-user-select:none;user-select:none;background:none;border:none;padding:0;font-family:inherit}.led-override-toggle:hover{color:var(--accent)}.led-override-panel{display:none;flex-direction:column;gap:8px;padding-top:8px;border-top:1px solid var(--border)}.led-override-panel.open{display:flex}.led-override-panel .color-row{flex-wrap:wrap;gap:6px}#presets .save-row{display:flex;gap:var(--gap);align-items:flex-end;flex-wrap:wrap;margin-bottom:16px}#presets .save-row .field{flex:1;min-width:180px}.preset-list{display:flex;flex-direction:column;gap:8px}.preset-item{display:flex;align-items:center;gap:10px;padding:10px 12px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius)}.preset-item .preset-name{flex:1;font-weight:500;font-size:13px}.preset-item .preset-actions{display:flex;gap:6px}#toast-container{position:fixed;bottom:24px;right:24px;display:flex;flex-direction:column;gap:8px;z-index:9999;pointer-events:none}.toast{padding:10px 16px;border-radius:var(--radius);font-size:13px;font-weight:500;color:#fff;animation:toast-in .2s ease,toast-out .3s ease 2.7s forwards;pointer-events:auto}.toast.success{background:var(--success);color:#000}.toast.error{background:var(--danger)}.toast.info{background:var(--accent);color:#000}@keyframes toast-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}@keyframes toast-out{0%{opacity:1}to{opacity:0}}.empty{text-align:center;padding:24px;color:var(--text-muted);font-size:13px}@media(max-width:540px){main{padding:16px}#app-header{padding:10px 16px}} diff --git a/src/turnup/ui/static/assets/index-Dcy9vL-q.js b/src/turnup/ui/static/assets/index-Dcy9vL-q.js new file mode 100644 index 0000000..4a27c50 --- /dev/null +++ b/src/turnup/ui/static/assets/index-Dcy9vL-q.js @@ -0,0 +1,9 @@ +(function(){const p=document.createElement("link").relList;if(p&&p.supports&&p.supports("modulepreload"))return;for(const U of document.querySelectorAll('link[rel="modulepreload"]'))v(U);new MutationObserver(U=>{for(const G of U)if(G.type==="childList")for(const J of G.addedNodes)J.tagName==="LINK"&&J.rel==="modulepreload"&&v(J)}).observe(document,{childList:!0,subtree:!0});function H(U){const G={};return U.integrity&&(G.integrity=U.integrity),U.referrerPolicy&&(G.referrerPolicy=U.referrerPolicy),U.crossOrigin==="use-credentials"?G.credentials="include":U.crossOrigin==="anonymous"?G.credentials="omit":G.credentials="same-origin",G}function v(U){if(U.ep)return;U.ep=!0;const G=H(U);fetch(U.href,G)}})();var fi={exports:{}},ze={};var Sv;function Im(){if(Sv)return ze;Sv=1;var g=Symbol.for("react.transitional.element"),p=Symbol.for("react.fragment");function H(v,U,G){var J=null;if(G!==void 0&&(J=""+G),U.key!==void 0&&(J=""+U.key),"key"in U){G={};for(var ml in U)ml!=="key"&&(G[ml]=U[ml])}else G=U;return U=G.ref,{$$typeof:g,type:v,key:J,ref:U!==void 0?U:null,props:G}}return ze.Fragment=p,ze.jsx=H,ze.jsxs=H,ze}var bv;function Pm(){return bv||(bv=1,fi.exports=Im()),fi.exports}var _=Pm(),ii={exports:{}},X={};var zv;function ly(){if(zv)return X;zv=1;var g=Symbol.for("react.transitional.element"),p=Symbol.for("react.portal"),H=Symbol.for("react.fragment"),v=Symbol.for("react.strict_mode"),U=Symbol.for("react.profiler"),G=Symbol.for("react.consumer"),J=Symbol.for("react.context"),ml=Symbol.for("react.forward_ref"),R=Symbol.for("react.suspense"),S=Symbol.for("react.memo"),Q=Symbol.for("react.lazy"),O=Symbol.for("react.activity"),Z=Symbol.iterator;function Gl(d){return d===null||typeof d!="object"?null:(d=Z&&d[Z]||d["@@iterator"],typeof d=="function"?d:null)}var Dl={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ol=Object.assign,zt={};function Xl(d,A,D){this.props=d,this.context=A,this.refs=zt,this.updater=D||Dl}Xl.prototype.isReactComponent={},Xl.prototype.setState=function(d,A){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,A,"setState")},Xl.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function st(){}st.prototype=Xl.prototype;function Y(d,A,D){this.props=d,this.context=A,this.refs=zt,this.updater=D||Dl}var vl=Y.prototype=new st;vl.constructor=Y,Ol(vl,Xl.prototype),vl.isPureReactComponent=!0;var Ul=Array.isArray;function xl(){}var I={H:null,A:null,T:null,S:null},Vl=Object.prototype.hasOwnProperty;function pt(d,A,D){var j=D.ref;return{$$typeof:g,type:d,key:A,ref:j!==void 0?j:null,props:D}}function Qa(d,A){return pt(d.type,A,d.props)}function Ot(d){return typeof d=="object"&&d!==null&&d.$$typeof===g}function Kl(d){var A={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(D){return A[D]})}var Ta=/\/+/g;function jt(d,A){return typeof d=="object"&&d!==null&&d.key!=null?Kl(""+d.key):A.toString(36)}function Tt(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(xl,xl):(d.status="pending",d.then(function(A){d.status==="pending"&&(d.status="fulfilled",d.value=A)},function(A){d.status==="pending"&&(d.status="rejected",d.reason=A)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function z(d,A,D,j,L){var w=typeof d;(w==="undefined"||w==="boolean")&&(d=null);var ul=!1;if(d===null)ul=!0;else switch(w){case"bigint":case"string":case"number":ul=!0;break;case"object":switch(d.$$typeof){case g:case p:ul=!0;break;case Q:return ul=d._init,z(ul(d._payload),A,D,j,L)}}if(ul)return L=L(d),ul=j===""?"."+jt(d,0):j,Ul(L)?(D="",ul!=null&&(D=ul.replace(Ta,"$&/")+"/"),z(L,A,D,"",function(Mu){return Mu})):L!=null&&(Ot(L)&&(L=Qa(L,D+(L.key==null||d&&d.key===L.key?"":(""+L.key).replace(Ta,"$&/")+"/")+ul)),A.push(L)),1;ul=0;var Ql=j===""?".":j+":";if(Ul(d))for(var bl=0;bl>>1,dl=z[cl];if(0>>1;clU(D,x))jU(L,D)?(z[cl]=L,z[j]=x,cl=j):(z[cl]=D,z[A]=x,cl=A);else if(jU(L,x))z[cl]=L,z[j]=x,cl=j;else break l}}return M}function U(z,M){var x=z.sortIndex-M.sortIndex;return x!==0?x:z.id-M.id}if(g.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var G=performance;g.unstable_now=function(){return G.now()}}else{var J=Date,ml=J.now();g.unstable_now=function(){return J.now()-ml}}var R=[],S=[],Q=1,O=null,Z=3,Gl=!1,Dl=!1,Ol=!1,zt=!1,Xl=typeof setTimeout=="function"?setTimeout:null,st=typeof clearTimeout=="function"?clearTimeout:null,Y=typeof setImmediate<"u"?setImmediate:null;function vl(z){for(var M=H(S);M!==null;){if(M.callback===null)v(S);else if(M.startTime<=z)v(S),M.sortIndex=M.expirationTime,p(R,M);else break;M=H(S)}}function Ul(z){if(Ol=!1,vl(z),!Dl)if(H(R)!==null)Dl=!0,xl||(xl=!0,Kl());else{var M=H(S);M!==null&&Tt(Ul,M.startTime-z)}}var xl=!1,I=-1,Vl=5,pt=-1;function Qa(){return zt?!0:!(g.unstable_now()-ptz&&Qa());){var cl=O.callback;if(typeof cl=="function"){O.callback=null,Z=O.priorityLevel;var dl=cl(O.expirationTime<=z);if(z=g.unstable_now(),typeof dl=="function"){O.callback=dl,vl(z),M=!0;break t}O===H(R)&&v(R),vl(z)}else v(R);O=H(R)}if(O!==null)M=!0;else{var d=H(S);d!==null&&Tt(Ul,d.startTime-z),M=!1}}break l}finally{O=null,Z=x,Gl=!1}M=void 0}}finally{M?Kl():xl=!1}}}var Kl;if(typeof Y=="function")Kl=function(){Y(Ot)};else if(typeof MessageChannel<"u"){var Ta=new MessageChannel,jt=Ta.port2;Ta.port1.onmessage=Ot,Kl=function(){jt.postMessage(null)}}else Kl=function(){Xl(Ot,0)};function Tt(z,M){I=Xl(function(){z(g.unstable_now())},M)}g.unstable_IdlePriority=5,g.unstable_ImmediatePriority=1,g.unstable_LowPriority=4,g.unstable_NormalPriority=3,g.unstable_Profiling=null,g.unstable_UserBlockingPriority=2,g.unstable_cancelCallback=function(z){z.callback=null},g.unstable_forceFrameRate=function(z){0>z||125cl?(z.sortIndex=x,p(S,z),H(R)===null&&z===H(S)&&(Ol?(st(I),I=-1):Ol=!0,Tt(Ul,x-cl))):(z.sortIndex=dl,p(R,z),Dl||Gl||(Dl=!0,xl||(xl=!0,Kl()))),z},g.unstable_shouldYield=Qa,g.unstable_wrapCallback=function(z){var M=Z;return function(){var x=Z;Z=M;try{return z.apply(this,arguments)}finally{Z=x}}}})(oi)),oi}var Av;function ay(){return Av||(Av=1,di.exports=ty()),di.exports}var vi={exports:{}},Yl={};var _v;function uy(){if(_v)return Yl;_v=1;var g=hi();function p(R){var S="https://react.dev/errors/"+R;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(g)}catch(p){console.error(p)}}return g(),vi.exports=uy(),vi.exports}var Ov;function ny(){if(Ov)return Te;Ov=1;var g=ay(),p=hi(),H=ey();function v(l){var t="https://react.dev/errors/"+l;if(1dl||(l.current=cl[dl],cl[dl]=null,dl--)}function D(l,t){dl++,cl[dl]=l.current,l.current=t}var j=d(null),L=d(null),w=d(null),ul=d(null);function Ql(l,t){switch(D(w,t),D(L,l),D(j,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Qo(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Qo(t),l=Zo(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}A(j),D(j,l)}function bl(){A(j),A(L),A(w)}function Mu(l){l.memoizedState!==null&&D(ul,l);var t=j.current,a=Zo(t,l.type);t!==a&&(D(L,l),D(j,a))}function Ee(l){L.current===l&&(A(j),A(L)),ul.current===l&&(A(ul),ge._currentValue=x)}var Zn,gi;function Ea(l){if(Zn===void 0)try{throw Error()}catch(a){var t=a.stack.trim().match(/\n( *(at )?)/);Zn=t&&t[1]||"",gi=-1)":-1e||i[u]!==y[e]){var b=` +`+i[u].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=u&&0<=e);break}}}finally{Ln=!1,Error.prepareStackTrace=a}return(a=l?l.displayName||l.name:"")?Ea(a):""}function Uv(l,t){switch(l.tag){case 26:case 27:case 5:return Ea(l.type);case 16:return Ea("Lazy");case 13:return l.child!==t&&t!==null?Ea("Suspense Fallback"):Ea("Suspense");case 19:return Ea("SuspenseList");case 0:case 15:return Vn(l.type,!1);case 11:return Vn(l.type.render,!1);case 1:return Vn(l.type,!0);case 31:return Ea("Activity");default:return""}}function ri(l){try{var t="",a=null;do t+=Uv(l,a),a=l,l=l.return;while(l);return t}catch(u){return` +Error generating stack: `+u.message+` +`+u.stack}}var Kn=Object.prototype.hasOwnProperty,Jn=g.unstable_scheduleCallback,wn=g.unstable_cancelCallback,Nv=g.unstable_shouldYield,jv=g.unstable_requestPaint,Pl=g.unstable_now,Cv=g.unstable_getCurrentPriorityLevel,Si=g.unstable_ImmediatePriority,bi=g.unstable_UserBlockingPriority,Ae=g.unstable_NormalPriority,Hv=g.unstable_LowPriority,zi=g.unstable_IdlePriority,Rv=g.log,qv=g.unstable_setDisableYieldValue,Du=null,lt=null;function Ft(l){if(typeof Rv=="function"&&qv(l),lt&&typeof lt.setStrictMode=="function")try{lt.setStrictMode(Du,l)}catch{}}var tt=Math.clz32?Math.clz32:Yv,Bv=Math.log,xv=Math.LN2;function Yv(l){return l>>>=0,l===0?32:31-(Bv(l)/xv|0)|0}var _e=256,pe=262144,Oe=4194304;function Aa(l){var t=l&42;if(t!==0)return t;switch(l&-l){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 l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Me(l,t,a){var u=l.pendingLanes;if(u===0)return 0;var e=0,n=l.suspendedLanes,c=l.pingedLanes;l=l.warmLanes;var f=u&134217727;return f!==0?(u=f&~n,u!==0?e=Aa(u):(c&=f,c!==0?e=Aa(c):a||(a=f&~l,a!==0&&(e=Aa(a))))):(f=u&~n,f!==0?e=Aa(f):c!==0?e=Aa(c):a||(a=u&~l,a!==0&&(e=Aa(a)))),e===0?0:t!==0&&t!==e&&(t&n)===0&&(n=e&-e,a=t&-t,n>=a||n===32&&(a&4194048)!==0)?t:e}function Uu(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Gv(l,t){switch(l){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 Ti(){var l=Oe;return Oe<<=1,(Oe&62914560)===0&&(Oe=4194304),l}function Wn(l){for(var t=[],a=0;31>a;a++)t.push(l);return t}function Nu(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Xv(l,t,a,u,e,n){var c=l.pendingLanes;l.pendingLanes=a,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=a,l.entangledLanes&=a,l.errorRecoveryDisabledLanes&=a,l.shellSuspendCounter=0;var f=l.entanglements,i=l.expirationTimes,y=l.hiddenUpdates;for(a=c&~a;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var Jv=/[\n"\\]/g;function ot(l){return l.replace(Jv,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function lc(l,t,a,u,e,n,c,f){l.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.type=c:l.removeAttribute("type"),t!=null?c==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+dt(t)):l.value!==""+dt(t)&&(l.value=""+dt(t)):c!=="submit"&&c!=="reset"||l.removeAttribute("value"),t!=null?tc(l,c,dt(t)):a!=null?tc(l,c,dt(a)):u!=null&&l.removeAttribute("value"),e==null&&n!=null&&(l.defaultChecked=!!n),e!=null&&(l.checked=e&&typeof e!="function"&&typeof e!="symbol"),f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?l.name=""+dt(f):l.removeAttribute("name")}function Ri(l,t,a,u,e,n,c,f){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),t!=null||a!=null){if(!(n!=="submit"&&n!=="reset"||t!=null)){Pn(l);return}a=a!=null?""+dt(a):"",t=t!=null?""+dt(t):a,f||t===l.value||(l.value=t),l.defaultValue=t}u=u??e,u=typeof u!="function"&&typeof u!="symbol"&&!!u,l.checked=f?l.checked:!!u,l.defaultChecked=!!u,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(l.name=c),Pn(l)}function tc(l,t,a){t==="number"&&Ne(l.ownerDocument)===l||l.defaultValue===""+a||(l.defaultValue=""+a)}function wa(l,t,a,u){if(l=l.options,t){t={};for(var e=0;e"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),cc=!1;if(Rt)try{var Ru={};Object.defineProperty(Ru,"passive",{get:function(){cc=!0}}),window.addEventListener("test",Ru,Ru),window.removeEventListener("test",Ru,Ru)}catch{cc=!1}var It=null,fc=null,Ce=null;function Qi(){if(Ce)return Ce;var l,t=fc,a=t.length,u,e="value"in It?It.value:It.textContent,n=e.length;for(l=0;l=xu),wi=" ",Wi=!1;function $i(l,t){switch(l){case"keyup":return z0.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Fi(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var ka=!1;function E0(l,t){switch(l){case"compositionend":return Fi(t);case"keypress":return t.which!==32?null:(Wi=!0,wi);case"textInput":return l=t.data,l===wi&&Wi?null:l;default:return null}}function A0(l,t){if(ka)return l==="compositionend"||!vc&&$i(l,t)?(l=Qi(),Ce=fc=It=null,ka=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:a,offset:t-l};l=u}l:{for(;a;){if(a.nextSibling){a=a.nextSibling;break l}a=a.parentNode}a=void 0}a=es(a)}}function cs(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?cs(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function fs(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Ne(l.document);t instanceof l.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)l=t.contentWindow;else break;t=Ne(l.document)}return t}function hc(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var j0=Rt&&"documentMode"in document&&11>=document.documentMode,Ia=null,gc=null,Qu=null,rc=!1;function is(l,t,a){var u=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;rc||Ia==null||Ia!==Ne(u)||(u=Ia,"selectionStart"in u&&hc(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),Qu&&Xu(Qu,u)||(Qu=u,u=On(gc,"onSelect"),0>=c,e-=c,Mt=1<<32-tt(t)+e|a<K?(k=C,C=null):k=C.sibling;var tl=h(o,C,m[K],T);if(tl===null){C===null&&(C=k);break}l&&C&&tl.alternate===null&&t(o,C),s=n(tl,s,K),ll===null?q=tl:ll.sibling=tl,ll=tl,C=k}if(K===m.length)return a(o,C),P&&Bt(o,K),q;if(C===null){for(;KK?(k=C,C=null):k=C.sibling;var za=h(o,C,tl.value,T);if(za===null){C===null&&(C=k);break}l&&C&&za.alternate===null&&t(o,C),s=n(za,s,K),ll===null?q=za:ll.sibling=za,ll=za,C=k}if(tl.done)return a(o,C),P&&Bt(o,K),q;if(C===null){for(;!tl.done;K++,tl=m.next())tl=E(o,tl.value,T),tl!==null&&(s=n(tl,s,K),ll===null?q=tl:ll.sibling=tl,ll=tl);return P&&Bt(o,K),q}for(C=u(C);!tl.done;K++,tl=m.next())tl=r(C,o,K,tl.value,T),tl!==null&&(l&&tl.alternate!==null&&C.delete(tl.key===null?K:tl.key),s=n(tl,s,K),ll===null?q=tl:ll.sibling=tl,ll=tl);return l&&C.forEach(function(km){return t(o,km)}),P&&Bt(o,K),q}function sl(o,s,m,T){if(typeof m=="object"&&m!==null&&m.type===Ol&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case Gl:l:{for(var q=m.key;s!==null;){if(s.key===q){if(q=m.type,q===Ol){if(s.tag===7){a(o,s.sibling),T=e(s,m.props.children),T.return=o,o=T;break l}}else if(s.elementType===q||typeof q=="object"&&q!==null&&q.$$typeof===Vl&&Ra(q)===s.type){a(o,s.sibling),T=e(s,m.props),wu(T,m),T.return=o,o=T;break l}a(o,s);break}else t(o,s);s=s.sibling}m.type===Ol?(T=Ua(m.props.children,o.mode,T,m.key),T.return=o,o=T):(T=Ze(m.type,m.key,m.props,null,o.mode,T),wu(T,m),T.return=o,o=T)}return c(o);case Dl:l:{for(q=m.key;s!==null;){if(s.key===q)if(s.tag===4&&s.stateNode.containerInfo===m.containerInfo&&s.stateNode.implementation===m.implementation){a(o,s.sibling),T=e(s,m.children||[]),T.return=o,o=T;break l}else{a(o,s);break}else t(o,s);s=s.sibling}T=_c(m,o.mode,T),T.return=o,o=T}return c(o);case Vl:return m=Ra(m),sl(o,s,m,T)}if(Tt(m))return N(o,s,m,T);if(Kl(m)){if(q=Kl(m),typeof q!="function")throw Error(v(150));return m=q.call(m),B(o,s,m,T)}if(typeof m.then=="function")return sl(o,s,$e(m),T);if(m.$$typeof===Y)return sl(o,s,Ke(o,m),T);Fe(o,m)}return typeof m=="string"&&m!==""||typeof m=="number"||typeof m=="bigint"?(m=""+m,s!==null&&s.tag===6?(a(o,s.sibling),T=e(s,m),T.return=o,o=T):(a(o,s),T=Ac(m,o.mode,T),T.return=o,o=T),c(o)):a(o,s)}return function(o,s,m,T){try{Ju=0;var q=sl(o,s,m,T);return su=null,q}catch(C){if(C===iu||C===we)throw C;var ll=ut(29,C,null,o.mode);return ll.lanes=T,ll.return=o,ll}}}var Ba=js(!0),Cs=js(!1),ua=!1;function Bc(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xc(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ea(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function na(l,t,a){var u=l.updateQueue;if(u===null)return null;if(u=u.shared,(al&2)!==0){var e=u.pending;return e===null?t.next=t:(t.next=e.next,e.next=t),u.pending=t,t=Qe(l),hs(l,null,a),t}return Xe(l,u,t,a),Qe(l)}function Wu(l,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194048)!==0)){var u=t.lanes;u&=l.pendingLanes,a|=u,t.lanes=a,Ai(l,a)}}function Yc(l,t){var a=l.updateQueue,u=l.alternate;if(u!==null&&(u=u.updateQueue,a===u)){var e=null,n=null;if(a=a.firstBaseUpdate,a!==null){do{var c={lane:a.lane,tag:a.tag,payload:a.payload,callback:null,next:null};n===null?e=n=c:n=n.next=c,a=a.next}while(a!==null);n===null?e=n=t:n=n.next=t}else e=n=t;a={baseState:u.baseState,firstBaseUpdate:e,lastBaseUpdate:n,shared:u.shared,callbacks:u.callbacks},l.updateQueue=a;return}l=a.lastBaseUpdate,l===null?a.firstBaseUpdate=t:l.next=t,a.lastBaseUpdate=t}var Gc=!1;function $u(){if(Gc){var l=fu;if(l!==null)throw l}}function Fu(l,t,a,u){Gc=!1;var e=l.updateQueue;ua=!1;var n=e.firstBaseUpdate,c=e.lastBaseUpdate,f=e.shared.pending;if(f!==null){e.shared.pending=null;var i=f,y=i.next;i.next=null,c===null?n=y:c.next=y,c=i;var b=l.alternate;b!==null&&(b=b.updateQueue,f=b.lastBaseUpdate,f!==c&&(f===null?b.firstBaseUpdate=y:f.next=y,b.lastBaseUpdate=i))}if(n!==null){var E=e.baseState;c=0,b=y=i=null,f=n;do{var h=f.lane&-536870913,r=h!==f.lane;if(r?(F&h)===h:(u&h)===h){h!==0&&h===cu&&(Gc=!0),b!==null&&(b=b.next={lane:0,tag:f.tag,payload:f.payload,callback:null,next:null});l:{var N=l,B=f;h=t;var sl=a;switch(B.tag){case 1:if(N=B.payload,typeof N=="function"){E=N.call(sl,E,h);break l}E=N;break l;case 3:N.flags=N.flags&-65537|128;case 0:if(N=B.payload,h=typeof N=="function"?N.call(sl,E,h):N,h==null)break l;E=O({},E,h);break l;case 2:ua=!0}}h=f.callback,h!==null&&(l.flags|=64,r&&(l.flags|=8192),r=e.callbacks,r===null?e.callbacks=[h]:r.push(h))}else r={lane:h,tag:f.tag,payload:f.payload,callback:f.callback,next:null},b===null?(y=b=r,i=E):b=b.next=r,c|=h;if(f=f.next,f===null){if(f=e.shared.pending,f===null)break;r=f,f=r.next,r.next=null,e.lastBaseUpdate=r,e.shared.pending=null}}while(!0);b===null&&(i=E),e.baseState=i,e.firstBaseUpdate=y,e.lastBaseUpdate=b,n===null&&(e.shared.lanes=0),da|=c,l.lanes=c,l.memoizedState=E}}function Hs(l,t){if(typeof l!="function")throw Error(v(191,l));l.call(t)}function Rs(l,t){var a=l.callbacks;if(a!==null)for(l.callbacks=null,l=0;ln?n:8;var c=z.T,f={};z.T=f,ef(l,!1,t,a);try{var i=e(),y=z.S;if(y!==null&&y(f,i),i!==null&&typeof i=="object"&&typeof i.then=="function"){var b=X0(i,u);Pu(l,t,b,it(l))}else Pu(l,t,u,it(l))}catch(E){Pu(l,t,{then:function(){},status:"rejected",reason:E},it())}finally{M.p=n,c!==null&&f.types!==null&&(c.types=f.types),z.T=c}}function J0(){}function af(l,t,a,u){if(l.tag!==5)throw Error(v(476));var e=vd(l).queue;od(l,e,t,x,a===null?J0:function(){return md(l),a(u)})}function vd(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:x,baseState:x,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Xt,lastRenderedState:x},next:null};var a={};return t.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Xt,lastRenderedState:a},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function md(l){var t=vd(l);t.next===null&&(t=l.alternate.memoizedState),Pu(l,t.next.queue,{},it())}function uf(){return Rl(ge)}function yd(){return Tl().memoizedState}function hd(){return Tl().memoizedState}function w0(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var a=it();l=ea(a);var u=na(t,l,a);u!==null&&(Il(u,t,a),Wu(u,t,a)),t={cache:Cc()},l.payload=t;return}t=t.return}}function W0(l,t,a){var u=it();a={lane:u,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},cn(l)?rd(t,a):(a=Tc(l,t,a,u),a!==null&&(Il(a,l,u),Sd(a,t,u)))}function gd(l,t,a){var u=it();Pu(l,t,a,u)}function Pu(l,t,a,u){var e={lane:u,revertLane:0,gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null};if(cn(l))rd(t,e);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=t.lastRenderedReducer,n!==null))try{var c=t.lastRenderedState,f=n(c,a);if(e.hasEagerState=!0,e.eagerState=f,at(f,c))return Xe(l,t,e,0),ol===null&&Ge(),!1}catch{}if(a=Tc(l,t,e,u),a!==null)return Il(a,l,u),Sd(a,t,u),!0}return!1}function ef(l,t,a,u){if(u={lane:2,revertLane:xf(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},cn(l)){if(t)throw Error(v(479))}else t=Tc(l,a,u,2),t!==null&&Il(t,l,2)}function cn(l){var t=l.alternate;return l===V||t!==null&&t===V}function rd(l,t){ou=Pe=!0;var a=l.pending;a===null?t.next=t:(t.next=a.next,a.next=t),l.pending=t}function Sd(l,t,a){if((a&4194048)!==0){var u=t.lanes;u&=l.pendingLanes,a|=u,t.lanes=a,Ai(l,a)}}var le={readContext:Rl,use:an,useCallback:rl,useContext:rl,useEffect:rl,useImperativeHandle:rl,useLayoutEffect:rl,useInsertionEffect:rl,useMemo:rl,useReducer:rl,useRef:rl,useState:rl,useDebugValue:rl,useDeferredValue:rl,useTransition:rl,useSyncExternalStore:rl,useId:rl,useHostTransitionStatus:rl,useFormState:rl,useActionState:rl,useOptimistic:rl,useMemoCache:rl,useCacheRefresh:rl};le.useEffectEvent=rl;var bd={readContext:Rl,use:an,useCallback:function(l,t){return Zl().memoizedState=[l,t===void 0?null:t],l},useContext:Rl,useEffect:ad,useImperativeHandle:function(l,t,a){a=a!=null?a.concat([l]):null,en(4194308,4,cd.bind(null,t,l),a)},useLayoutEffect:function(l,t){return en(4194308,4,l,t)},useInsertionEffect:function(l,t){en(4,2,l,t)},useMemo:function(l,t){var a=Zl();t=t===void 0?null:t;var u=l();if(xa){Ft(!0);try{l()}finally{Ft(!1)}}return a.memoizedState=[u,t],u},useReducer:function(l,t,a){var u=Zl();if(a!==void 0){var e=a(t);if(xa){Ft(!0);try{a(t)}finally{Ft(!1)}}}else e=t;return u.memoizedState=u.baseState=e,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:e},u.queue=l,l=l.dispatch=W0.bind(null,V,l),[u.memoizedState,l]},useRef:function(l){var t=Zl();return l={current:l},t.memoizedState=l},useState:function(l){l=kc(l);var t=l.queue,a=gd.bind(null,V,t);return t.dispatch=a,[l.memoizedState,a]},useDebugValue:lf,useDeferredValue:function(l,t){var a=Zl();return tf(a,l,t)},useTransition:function(){var l=kc(!1);return l=od.bind(null,V,l.queue,!0,!1),Zl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,a){var u=V,e=Zl();if(P){if(a===void 0)throw Error(v(407));a=a()}else{if(a=t(),ol===null)throw Error(v(349));(F&127)!==0||Xs(u,t,a)}e.memoizedState=a;var n={value:a,getSnapshot:t};return e.queue=n,ad(Zs.bind(null,u,n,l),[l]),u.flags|=2048,mu(9,{destroy:void 0},Qs.bind(null,u,n,a,t),null),a},useId:function(){var l=Zl(),t=ol.identifierPrefix;if(P){var a=Dt,u=Mt;a=(u&~(1<<32-tt(u)-1)).toString(32)+a,t="_"+t+"R_"+a,a=ln++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof u.is=="string"?c.createElement("select",{is:u.is}):c.createElement("select"),u.multiple?n.multiple=!0:u.size&&(n.size=u.size);break;default:n=typeof u.is=="string"?c.createElement(e,{is:u.is}):c.createElement(e)}}n[Cl]=t,n[Jl]=u;l:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)n.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break l;for(;c.sibling===null;){if(c.return===null||c.return===t)break l;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=n;l:switch(Bl(n,e,u),e){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break l;case"img":u=!0;break l;default:u=!1}u&&Zt(t)}}return hl(t),bf(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,a),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==u&&Zt(t);else{if(typeof u!="string"&&t.stateNode===null)throw Error(v(166));if(l=w.current,eu(t)){if(l=t.stateNode,a=t.memoizedProps,u=null,e=Hl,e!==null)switch(e.tag){case 27:case 5:u=e.memoizedProps}l[Cl]=t,l=!!(l.nodeValue===a||u!==null&&u.suppressHydrationWarning===!0||Go(l.nodeValue,a)),l||ta(t,!0)}else l=Mn(l).createTextNode(u),l[Cl]=t,t.stateNode=l}return hl(t),null;case 31:if(a=t.memoizedState,l===null||l.memoizedState!==null){if(u=eu(t),a!==null){if(l===null){if(!u)throw Error(v(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(v(557));l[Cl]=t}else Na(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;hl(t),l=!1}else a=Dc(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=a),l=!0;if(!l)return t.flags&256?(nt(t),t):(nt(t),null);if((t.flags&128)!==0)throw Error(v(558))}return hl(t),null;case 13:if(u=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(e=eu(t),u!==null&&u.dehydrated!==null){if(l===null){if(!e)throw Error(v(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(v(317));e[Cl]=t}else Na(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;hl(t),e=!1}else e=Dc(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),e=!0;if(!e)return t.flags&256?(nt(t),t):(nt(t),null)}return nt(t),(t.flags&128)!==0?(t.lanes=a,t):(a=u!==null,l=l!==null&&l.memoizedState!==null,a&&(u=t.child,e=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(e=u.alternate.memoizedState.cachePool.pool),n=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(n=u.memoizedState.cachePool.pool),n!==e&&(u.flags|=2048)),a!==l&&a&&(t.child.flags|=8192),vn(t,t.updateQueue),hl(t),null);case 4:return bl(),l===null&&Qf(t.stateNode.containerInfo),hl(t),null;case 10:return Yt(t.type),hl(t),null;case 19:if(A(zl),u=t.memoizedState,u===null)return hl(t),null;if(e=(t.flags&128)!==0,n=u.rendering,n===null)if(e)ae(u,!1);else{if(Sl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(n=Ie(l),n!==null){for(t.flags|=128,ae(u,!1),l=n.updateQueue,t.updateQueue=l,vn(t,l),t.subtreeFlags=0,l=a,a=t.child;a!==null;)gs(a,l),a=a.sibling;return D(zl,zl.current&1|2),P&&Bt(t,u.treeForkCount),t.child}l=l.sibling}u.tail!==null&&Pl()>rn&&(t.flags|=128,e=!0,ae(u,!1),t.lanes=4194304)}else{if(!e)if(l=Ie(n),l!==null){if(t.flags|=128,e=!0,l=l.updateQueue,t.updateQueue=l,vn(t,l),ae(u,!0),u.tail===null&&u.tailMode==="hidden"&&!n.alternate&&!P)return hl(t),null}else 2*Pl()-u.renderingStartTime>rn&&a!==536870912&&(t.flags|=128,e=!0,ae(u,!1),t.lanes=4194304);u.isBackwards?(n.sibling=t.child,t.child=n):(l=u.last,l!==null?l.sibling=n:t.child=n,u.last=n)}return u.tail!==null?(l=u.tail,u.rendering=l,u.tail=l.sibling,u.renderingStartTime=Pl(),l.sibling=null,a=zl.current,D(zl,e?a&1|2:a&1),P&&Bt(t,u.treeForkCount),l):(hl(t),null);case 22:case 23:return nt(t),Qc(),u=t.memoizedState!==null,l!==null?l.memoizedState!==null!==u&&(t.flags|=8192):u&&(t.flags|=8192),u?(a&536870912)!==0&&(t.flags&128)===0&&(hl(t),t.subtreeFlags&6&&(t.flags|=8192)):hl(t),a=t.updateQueue,a!==null&&vn(t,a.retryQueue),a=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(a=l.memoizedState.cachePool.pool),u=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(u=t.memoizedState.cachePool.pool),u!==a&&(t.flags|=2048),l!==null&&A(Ha),null;case 24:return a=null,l!==null&&(a=l.memoizedState.cache),t.memoizedState.cache!==a&&(t.flags|=2048),Yt(El),hl(t),null;case 25:return null;case 30:return null}throw Error(v(156,t.tag))}function P0(l,t){switch(Oc(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Yt(El),bl(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return Ee(t),null;case 31:if(t.memoizedState!==null){if(nt(t),t.alternate===null)throw Error(v(340));Na()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(nt(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(v(340));Na()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return A(zl),null;case 4:return bl(),null;case 10:return Yt(t.type),null;case 22:case 23:return nt(t),Qc(),l!==null&&A(Ha),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Yt(El),null;case 25:return null;default:return null}}function Ld(l,t){switch(Oc(t),t.tag){case 3:Yt(El),bl();break;case 26:case 27:case 5:Ee(t);break;case 4:bl();break;case 31:t.memoizedState!==null&&nt(t);break;case 13:nt(t);break;case 19:A(zl);break;case 10:Yt(t.type);break;case 22:case 23:nt(t),Qc(),l!==null&&A(Ha);break;case 24:Yt(El)}}function ue(l,t){try{var a=t.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var e=u.next;a=e;do{if((a.tag&l)===l){u=void 0;var n=a.create,c=a.inst;u=n(),c.destroy=u}a=a.next}while(a!==e)}}catch(f){nl(t,t.return,f)}}function ia(l,t,a){try{var u=t.updateQueue,e=u!==null?u.lastEffect:null;if(e!==null){var n=e.next;u=n;do{if((u.tag&l)===l){var c=u.inst,f=c.destroy;if(f!==void 0){c.destroy=void 0,e=t;var i=a,y=f;try{y()}catch(b){nl(e,i,b)}}}u=u.next}while(u!==n)}}catch(b){nl(t,t.return,b)}}function Vd(l){var t=l.updateQueue;if(t!==null){var a=l.stateNode;try{Rs(t,a)}catch(u){nl(l,l.return,u)}}}function Kd(l,t,a){a.props=Ya(l.type,l.memoizedProps),a.state=l.memoizedState;try{a.componentWillUnmount()}catch(u){nl(l,t,u)}}function ee(l,t){try{var a=l.ref;if(a!==null){switch(l.tag){case 26:case 27:case 5:var u=l.stateNode;break;case 30:u=l.stateNode;break;default:u=l.stateNode}typeof a=="function"?l.refCleanup=a(u):a.current=u}}catch(e){nl(l,t,e)}}function Ut(l,t){var a=l.ref,u=l.refCleanup;if(a!==null)if(typeof u=="function")try{u()}catch(e){nl(l,t,e)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof a=="function")try{a(null)}catch(e){nl(l,t,e)}else a.current=null}function Jd(l){var t=l.type,a=l.memoizedProps,u=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":a.autoFocus&&u.focus();break l;case"img":a.src?u.src=a.src:a.srcSet&&(u.srcset=a.srcSet)}}catch(e){nl(l,l.return,e)}}function zf(l,t,a){try{var u=l.stateNode;Tm(u,l.type,a,t),u[Jl]=t}catch(e){nl(l,l.return,e)}}function wd(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ha(l.type)||l.tag===4}function Tf(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||wd(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ha(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function Ef(l,t,a){var u=l.tag;if(u===5||u===6)l=l.stateNode,t?(a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a).insertBefore(l,t):(t=a.nodeType===9?a.body:a.nodeName==="HTML"?a.ownerDocument.body:a,t.appendChild(l),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=Ht));else if(u!==4&&(u===27&&ha(l.type)&&(a=l.stateNode,t=null),l=l.child,l!==null))for(Ef(l,t,a),l=l.sibling;l!==null;)Ef(l,t,a),l=l.sibling}function mn(l,t,a){var u=l.tag;if(u===5||u===6)l=l.stateNode,t?a.insertBefore(l,t):a.appendChild(l);else if(u!==4&&(u===27&&ha(l.type)&&(a=l.stateNode),l=l.child,l!==null))for(mn(l,t,a),l=l.sibling;l!==null;)mn(l,t,a),l=l.sibling}function Wd(l){var t=l.stateNode,a=l.memoizedProps;try{for(var u=l.type,e=t.attributes;e.length;)t.removeAttributeNode(e[0]);Bl(t,u,a),t[Cl]=l,t[Jl]=a}catch(n){nl(l,l.return,n)}}var Lt=!1,pl=!1,Af=!1,$d=typeof WeakSet=="function"?WeakSet:Set,jl=null;function lm(l,t){if(l=l.containerInfo,Vf=Rn,l=fs(l),hc(l)){if("selectionStart"in l)var a={start:l.selectionStart,end:l.selectionEnd};else l:{a=(a=l.ownerDocument)&&a.defaultView||window;var u=a.getSelection&&a.getSelection();if(u&&u.rangeCount!==0){a=u.anchorNode;var e=u.anchorOffset,n=u.focusNode;u=u.focusOffset;try{a.nodeType,n.nodeType}catch{a=null;break l}var c=0,f=-1,i=-1,y=0,b=0,E=l,h=null;t:for(;;){for(var r;E!==a||e!==0&&E.nodeType!==3||(f=c+e),E!==n||u!==0&&E.nodeType!==3||(i=c+u),E.nodeType===3&&(c+=E.nodeValue.length),(r=E.firstChild)!==null;)h=E,E=r;for(;;){if(E===l)break t;if(h===a&&++y===e&&(f=c),h===n&&++b===u&&(i=c),(r=E.nextSibling)!==null)break;E=h,h=E.parentNode}E=r}a=f===-1||i===-1?null:{start:f,end:i}}else a=null}a=a||{start:0,end:0}}else a=null;for(Kf={focusedElem:l,selectionRange:a},Rn=!1,jl=t;jl!==null;)if(t=jl,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,jl=l;else for(;jl!==null;){switch(t=jl,n=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(a=0;a title"))),Bl(n,u,a),n[Cl]=l,Nl(n),u=n;break l;case"link":var c=av("link","href",e).get(u+(a.href||""));if(c){for(var f=0;fsl&&(c=sl,sl=B,B=c);var o=ns(f,B),s=ns(f,sl);if(o&&s&&(r.rangeCount!==1||r.anchorNode!==o.node||r.anchorOffset!==o.offset||r.focusNode!==s.node||r.focusOffset!==s.offset)){var m=E.createRange();m.setStart(o.node,o.offset),r.removeAllRanges(),B>sl?(r.addRange(m),r.extend(s.node,s.offset)):(m.setEnd(s.node,s.offset),r.addRange(m))}}}}for(E=[],r=f;r=r.parentNode;)r.nodeType===1&&E.push({element:r,left:r.scrollLeft,top:r.scrollTop});for(typeof f.focus=="function"&&f.focus(),f=0;fa?32:a,z.T=null,a=Nf,Nf=null;var n=va,c=Wt;if(Ml=0,Su=va=null,Wt=0,(al&6)!==0)throw Error(v(331));var f=al;if(al|=4,co(n.current),uo(n,n.current,c,a),al=f,de(0,!1),lt&&typeof lt.onPostCommitFiberRoot=="function")try{lt.onPostCommitFiberRoot(Du,n)}catch{}return!0}finally{M.p=e,z.T=u,po(l,t)}}function Mo(l,t,a){t=mt(a,t),t=sf(l.stateNode,t,2),l=na(l,t,2),l!==null&&(Nu(l,2),Nt(l))}function nl(l,t,a){if(l.tag===3)Mo(l,l,a);else for(;t!==null;){if(t.tag===3){Mo(t,l,a);break}else if(t.tag===1){var u=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(oa===null||!oa.has(u))){l=mt(a,l),a=Md(2),u=na(t,a,2),u!==null&&(Dd(a,u,t,l),Nu(u,2),Nt(u));break}}t=t.return}}function Rf(l,t,a){var u=l.pingCache;if(u===null){u=l.pingCache=new um;var e=new Set;u.set(t,e)}else e=u.get(t),e===void 0&&(e=new Set,u.set(t,e));e.has(a)||(Of=!0,e.add(a),l=im.bind(null,l,t,a),t.then(l,l))}function im(l,t,a){var u=l.pingCache;u!==null&&u.delete(t),l.pingedLanes|=l.suspendedLanes&a,l.warmLanes&=~a,ol===l&&(F&a)===a&&(Sl===4||Sl===3&&(F&62914560)===F&&300>Pl()-gn?(al&2)===0&&bu(l,0):Mf|=a,ru===F&&(ru=0)),Nt(l)}function Do(l,t){t===0&&(t=Ti()),l=Da(l,t),l!==null&&(Nu(l,t),Nt(l))}function sm(l){var t=l.memoizedState,a=0;t!==null&&(a=t.retryLane),Do(l,a)}function dm(l,t){var a=0;switch(l.tag){case 31:case 13:var u=l.stateNode,e=l.memoizedState;e!==null&&(a=e.retryLane);break;case 19:u=l.stateNode;break;case 22:u=l.stateNode._retryCache;break;default:throw Error(v(314))}u!==null&&u.delete(t),Do(l,a)}function om(l,t){return Jn(l,t)}var An=null,Tu=null,qf=!1,_n=!1,Bf=!1,ya=0;function Nt(l){l!==Tu&&l.next===null&&(Tu===null?An=Tu=l:Tu=Tu.next=l),_n=!0,qf||(qf=!0,mm())}function de(l,t){if(!Bf&&_n){Bf=!0;do for(var a=!1,u=An;u!==null;){if(l!==0){var e=u.pendingLanes;if(e===0)var n=0;else{var c=u.suspendedLanes,f=u.pingedLanes;n=(1<<31-tt(42|l)+1)-1,n&=e&~(c&~f),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(a=!0,Co(u,n))}else n=F,n=Me(u,u===ol?n:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(n&3)===0||Uu(u,n)||(a=!0,Co(u,n));u=u.next}while(a);Bf=!1}}function vm(){Uo()}function Uo(){_n=qf=!1;var l=0;ya!==0&&Am()&&(l=ya);for(var t=Pl(),a=null,u=An;u!==null;){var e=u.next,n=No(u,t);n===0?(u.next=null,a===null?An=e:a.next=e,e===null&&(Tu=a)):(a=u,(l!==0||(n&3)!==0)&&(_n=!0)),u=e}Ml!==0&&Ml!==5||de(l),ya!==0&&(ya=0)}function No(l,t){for(var a=l.suspendedLanes,u=l.pingedLanes,e=l.expirationTimes,n=l.pendingLanes&-62914561;0f)break;var b=i.transferSize,E=i.initiatorType;b&&Xo(E)&&(i=i.responseEnd,c+=b*(i"u"?null:document;function Io(l,t,a){var u=Eu;if(u&&typeof t=="string"&&t){var e=ot(t);e='link[rel="'+l+'"][href="'+e+'"]',typeof a=="string"&&(e+='[crossorigin="'+a+'"]'),ko.has(e)||(ko.add(e),l={rel:l,crossOrigin:a,href:t},u.querySelector(e)===null&&(t=u.createElement("link"),Bl(t,"link",l),Nl(t),u.head.appendChild(t)))}}function Cm(l){$t.D(l),Io("dns-prefetch",l,null)}function Hm(l,t){$t.C(l,t),Io("preconnect",l,t)}function Rm(l,t,a){$t.L(l,t,a);var u=Eu;if(u&&l&&t){var e='link[rel="preload"][as="'+ot(t)+'"]';t==="image"&&a&&a.imageSrcSet?(e+='[imagesrcset="'+ot(a.imageSrcSet)+'"]',typeof a.imageSizes=="string"&&(e+='[imagesizes="'+ot(a.imageSizes)+'"]')):e+='[href="'+ot(l)+'"]';var n=e;switch(t){case"style":n=Au(l);break;case"script":n=_u(l)}bt.has(n)||(l=O({rel:"preload",href:t==="image"&&a&&a.imageSrcSet?void 0:l,as:t},a),bt.set(n,l),u.querySelector(e)!==null||t==="style"&&u.querySelector(ye(n))||t==="script"&&u.querySelector(he(n))||(t=u.createElement("link"),Bl(t,"link",l),Nl(t),u.head.appendChild(t)))}}function qm(l,t){$t.m(l,t);var a=Eu;if(a&&l){var u=t&&typeof t.as=="string"?t.as:"script",e='link[rel="modulepreload"][as="'+ot(u)+'"][href="'+ot(l)+'"]',n=e;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=_u(l)}if(!bt.has(n)&&(l=O({rel:"modulepreload",href:l},t),bt.set(n,l),a.querySelector(e)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(a.querySelector(he(n)))return}u=a.createElement("link"),Bl(u,"link",l),Nl(u),a.head.appendChild(u)}}}function Bm(l,t,a){$t.S(l,t,a);var u=Eu;if(u&&l){var e=Ka(u).hoistableStyles,n=Au(l);t=t||"default";var c=e.get(n);if(!c){var f={loading:0,preload:null};if(c=u.querySelector(ye(n)))f.loading=5;else{l=O({rel:"stylesheet",href:l,"data-precedence":t},a),(a=bt.get(n))&&If(l,a);var i=c=u.createElement("link");Nl(i),Bl(i,"link",l),i._p=new Promise(function(y,b){i.onload=y,i.onerror=b}),i.addEventListener("load",function(){f.loading|=1}),i.addEventListener("error",function(){f.loading|=2}),f.loading|=4,Un(c,t,u)}c={type:"stylesheet",instance:c,count:1,state:f},e.set(n,c)}}}function xm(l,t){$t.X(l,t);var a=Eu;if(a&&l){var u=Ka(a).hoistableScripts,e=_u(l),n=u.get(e);n||(n=a.querySelector(he(e)),n||(l=O({src:l,async:!0},t),(t=bt.get(e))&&Pf(l,t),n=a.createElement("script"),Nl(n),Bl(n,"link",l),a.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},u.set(e,n))}}function Ym(l,t){$t.M(l,t);var a=Eu;if(a&&l){var u=Ka(a).hoistableScripts,e=_u(l),n=u.get(e);n||(n=a.querySelector(he(e)),n||(l=O({src:l,async:!0,type:"module"},t),(t=bt.get(e))&&Pf(l,t),n=a.createElement("script"),Nl(n),Bl(n,"link",l),a.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},u.set(e,n))}}function Po(l,t,a,u){var e=(e=w.current)?Dn(e):null;if(!e)throw Error(v(446));switch(l){case"meta":case"title":return null;case"style":return typeof a.precedence=="string"&&typeof a.href=="string"?(t=Au(a.href),a=Ka(e).hoistableStyles,u=a.get(t),u||(u={type:"style",instance:null,count:0,state:null},a.set(t,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(a.rel==="stylesheet"&&typeof a.href=="string"&&typeof a.precedence=="string"){l=Au(a.href);var n=Ka(e).hoistableStyles,c=n.get(l);if(c||(e=e.ownerDocument||e,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(l,c),(n=e.querySelector(ye(l)))&&!n._p&&(c.instance=n,c.state.loading=5),bt.has(l)||(a={rel:"preload",as:"style",href:a.href,crossOrigin:a.crossOrigin,integrity:a.integrity,media:a.media,hrefLang:a.hrefLang,referrerPolicy:a.referrerPolicy},bt.set(l,a),n||Gm(e,l,a,c.state))),t&&u===null)throw Error(v(528,""));return c}if(t&&u!==null)throw Error(v(529,""));return null;case"script":return t=a.async,a=a.src,typeof a=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=_u(a),a=Ka(e).hoistableScripts,u=a.get(t),u||(u={type:"script",instance:null,count:0,state:null},a.set(t,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(v(444,l))}}function Au(l){return'href="'+ot(l)+'"'}function ye(l){return'link[rel="stylesheet"]['+l+"]"}function lv(l){return O({},l,{"data-precedence":l.precedence,precedence:null})}function Gm(l,t,a,u){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?u.loading=1:(t=l.createElement("link"),u.preload=t,t.addEventListener("load",function(){return u.loading|=1}),t.addEventListener("error",function(){return u.loading|=2}),Bl(t,"link",a),Nl(t),l.head.appendChild(t))}function _u(l){return'[src="'+ot(l)+'"]'}function he(l){return"script[async]"+l}function tv(l,t,a){if(t.count++,t.instance===null)switch(t.type){case"style":var u=l.querySelector('style[data-href~="'+ot(a.href)+'"]');if(u)return t.instance=u,Nl(u),u;var e=O({},a,{"data-href":a.href,"data-precedence":a.precedence,href:null,precedence:null});return u=(l.ownerDocument||l).createElement("style"),Nl(u),Bl(u,"style",e),Un(u,a.precedence,l),t.instance=u;case"stylesheet":e=Au(a.href);var n=l.querySelector(ye(e));if(n)return t.state.loading|=4,t.instance=n,Nl(n),n;u=lv(a),(e=bt.get(e))&&If(u,e),n=(l.ownerDocument||l).createElement("link"),Nl(n);var c=n;return c._p=new Promise(function(f,i){c.onload=f,c.onerror=i}),Bl(n,"link",u),t.state.loading|=4,Un(n,a.precedence,l),t.instance=n;case"script":return n=_u(a.src),(e=l.querySelector(he(n)))?(t.instance=e,Nl(e),e):(u=a,(e=bt.get(n))&&(u=O({},a),Pf(u,e)),l=l.ownerDocument||l,e=l.createElement("script"),Nl(e),Bl(e,"link",u),l.head.appendChild(e),t.instance=e);case"void":return null;default:throw Error(v(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(u=t.instance,t.state.loading|=4,Un(u,a.precedence,l));return t.instance}function Un(l,t,a){for(var u=a.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),e=u.length?u[u.length-1]:null,n=e,c=0;c title"):null)}function Xm(l,t,a){if(a===1||t.itemProp!=null)return!1;switch(l){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"?(l=t.disabled,typeof t.precedence=="string"&&l==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 ev(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function Qm(l,t,a,u){if(a.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(a.state.loading&4)===0){if(a.instance===null){var e=Au(u.href),n=t.querySelector(ye(e));if(n){t=n._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=jn.bind(l),t.then(l,l)),a.state.loading|=4,a.instance=n,Nl(n);return}n=t.ownerDocument||t,u=lv(u),(e=bt.get(e))&&If(u,e),n=n.createElement("link"),Nl(n);var c=n;c._p=new Promise(function(f,i){c.onload=f,c.onerror=i}),Bl(n,"link",u),a.instance=n}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(a,t),(t=a.state.preload)&&(a.state.loading&3)===0&&(l.count++,a=jn.bind(l),t.addEventListener("load",a),t.addEventListener("error",a))}}var li=0;function Zm(l,t){return l.stylesheets&&l.count===0&&Hn(l,l.stylesheets),0li?50:800)+t);return l.unsuspend=a,function(){l.unsuspend=null,clearTimeout(u),clearTimeout(e)}}:null}function jn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Hn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Cn=null;function Hn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Cn=new Map,t.forEach(Lm,l),Cn=null,jn.call(l))}function Lm(l,t){if(!(t.state.loading&4)){var a=Cn.get(l);if(a)var u=a.get(null);else{a=new Map,Cn.set(l,a);for(var e=l.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(g)}catch(p){console.error(p)}}return g(),si.exports=ny(),si.exports}var fy=cy();async function Ou(g){if(!g.ok){const p=await g.json().catch(()=>null);throw new Error(p?.detail??`${g.status} ${g.statusText}`)}}async function Dv(){const g=await fetch("/api/config");return await Ou(g),g.json()}async function iy(g){const p=await fetch("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(g)});await Ou(p)}async function sy(){const g=await fetch("/api/presets");return g.ok?g.json():[]}async function dy(g){const p=await fetch(`/api/presets/${encodeURIComponent(g)}`);return await Ou(p),p.json()}async function oy(g,p){const H=await fetch(`/api/presets/${encodeURIComponent(g)}/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(p)});await Ou(H)}async function vy(g){const p=await fetch(`/api/presets/${encodeURIComponent(g)}/apply`,{method:"POST"});await Ou(p)}async function my(g){const p=await fetch(`/api/presets/${encodeURIComponent(g)}`,{method:"DELETE"});await Ou(p)}function yy({toasts:g,onRemove:p}){return _.jsx("div",{id:"toast-container",children:g.map(H=>_.jsx(hy,{toast:H,onRemove:p},H.id))})}function hy({toast:g,onRemove:p}){return Ll.useEffect(()=>{const H=setTimeout(()=>p(g.id),3100);return()=>clearTimeout(H)},[g.id,p]),_.jsx("div",{className:`toast ${g.type}`,children:g.message})}function gy({config:g,onChange:p}){return _.jsxs("section",{className:"card",id:"connection",children:[_.jsx("h2",{children:"Connection"}),_.jsxs("div",{className:"fields",children:[_.jsxs("div",{className:"field",children:[_.jsx("label",{htmlFor:"port",children:"Serial port"}),_.jsx("input",{type:"text",id:"port",value:g.port,placeholder:"/dev/ttyACM0",onChange:H=>p({port:H.target.value})})]}),_.jsxs("div",{className:"field",children:[_.jsx("label",{htmlFor:"baud",children:"Baud rate"}),_.jsx("input",{type:"number",id:"baud",value:g.baud,onChange:H=>p({baud:parseInt(H.target.value,10)||115200})})]})]})]})}function yi([g,p,H]){return"#"+[g,p,H].map(v=>Math.max(0,Math.min(255,v)).toString(16).padStart(2,"0")).join("")}function ry(g){const p=parseInt(g.replace("#",""),16);return[p>>16&255,p>>8&255,p&255]}function Qn({id:g,label:p,value:H,onChange:v}){const U=yi(H);return _.jsxs("div",{children:[_.jsx("label",{htmlFor:g,children:p}),_.jsxs("div",{className:"color-row",children:[_.jsx("input",{type:"color",id:g,value:U,onChange:G=>v(ry(G.target.value))}),_.jsx("span",{className:"color-hex",children:U})]})]})}function Sy({leds:g,onChange:p}){const H=J=>p({...g,...J}),v=yi(g.low_color),U=yi(g.high_color),G=g.mode==="off"?"#000":g.mode==="static"?U:`linear-gradient(to right, ${v}, ${U})`;return _.jsxs("section",{className:"card",id:"global-leds",children:[_.jsx("h2",{children:"Global LEDs"}),_.jsxs("div",{className:"fields",children:[_.jsxs("div",{className:"field",children:[_.jsx("label",{htmlFor:"led-mode",children:"Mode"}),_.jsxs("select",{id:"led-mode",value:g.mode,onChange:J=>H({mode:J.target.value}),children:[_.jsx("option",{value:"volume",children:"volume — fade low → high"}),_.jsx("option",{value:"static",children:"static — always high color"}),_.jsx("option",{value:"off",children:"off — LEDs disabled"})]})]}),_.jsx("div",{className:"field",style:{opacity:g.mode==="volume"?1:.4},children:_.jsx(Qn,{id:"led-low-color",label:"Low color (0 %)",value:g.low_color,onChange:J=>H({low_color:J})})}),_.jsx("div",{className:"field",children:_.jsx(Qn,{id:"led-high-color",label:"High color (100 %)",value:g.high_color,onChange:J=>H({high_color:J})})})]}),_.jsx("div",{className:"led-preview",style:{background:G}})]})}const by=[{value:"sink_volume",label:"sink_volume — output device"},{value:"source_volume",label:"source_volume — microphone"},{value:"app_volume",label:"app_volume — single app"},{value:"group_volume",label:"group_volume — multiple apps"}],mi={mode:"volume",low_color:[255,0,0],high_color:[0,255,0]};function zy({index:g,knob:p,onChange:H}){const[v,U]=Ll.useState(!!p.led),G=S=>H({...p,...S}),J={mode:p.led?.mode??mi.mode,low_color:p.led?.low_color??mi.low_color,high_color:p.led?.high_color??mi.high_color},ml=S=>G({led:{...J,...S}}),R=()=>{const S=!v;if(U(S),!S){const{led:Q,...O}=p;H(O)}};return _.jsxs("div",{className:"knob-card",children:[_.jsxs("div",{className:"card-title",children:[_.jsx("span",{className:"card-index",children:g}),"Knob ",g]}),_.jsxs("div",{children:[_.jsx("label",{htmlFor:`knob-${g}-action`,children:"Action"}),_.jsx("select",{id:`knob-${g}-action`,value:p.action,onChange:S=>{const Q=S.target.value;G(Q==="group_volume"?{action:Q,targets:p.targets??[],target:void 0}:{action:Q,target:p.target??"default",targets:void 0})},children:by.map(S=>_.jsx("option",{value:S.value,children:S.label},S.value))})]}),p.action==="group_volume"?_.jsxs("div",{children:[_.jsx("label",{htmlFor:`knob-${g}-targets`,children:"Targets (comma-separated)"}),_.jsx("textarea",{id:`knob-${g}-targets`,value:(p.targets??[]).join(", "),placeholder:"spotify, vlc, brave",onChange:S=>G({targets:S.target.value.split(",").map(Q=>Q.trim()).filter(Boolean)})})]}):_.jsxs("div",{children:[_.jsx("label",{htmlFor:`knob-${g}-target`,children:"Target"}),_.jsx("input",{type:"text",id:`knob-${g}-target`,value:p.target??"default",placeholder:"default",onChange:S=>G({target:S.target.value})})]}),_.jsxs("button",{className:"led-override-toggle",onClick:R,children:[_.jsx("span",{children:v?"▾":"▸"}),"LED override"]}),v&&_.jsxs("div",{className:"led-override-panel open",children:[_.jsxs("div",{children:[_.jsx("label",{htmlFor:`knob-${g}-led-mode`,children:"Mode"}),_.jsxs("select",{id:`knob-${g}-led-mode`,value:J.mode,onChange:S=>ml({mode:S.target.value}),children:[_.jsx("option",{value:"volume",children:"volume"}),_.jsx("option",{value:"static",children:"static"}),_.jsx("option",{value:"off",children:"off"})]})]}),_.jsx(Qn,{id:`knob-${g}-led-low`,label:"Low color",value:J.low_color,onChange:S=>ml({low_color:S})}),_.jsx(Qn,{id:`knob-${g}-led-high`,label:"High color",value:J.high_color,onChange:S=>ml({high_color:S})})]})]})}const Ty=[{value:"mute_sink",label:"mute_sink — toggle output mute"},{value:"mute_source",label:"mute_source — toggle mic mute"},{value:"command",label:"command — run shell command"}];function Ey({index:g,btn:p,onChange:H}){const v=p.action==="command";return _.jsxs("div",{className:"button-card",children:[_.jsxs("div",{className:"card-title",children:[_.jsx("span",{className:"card-index",children:g}),"Button ",g]}),_.jsxs("div",{children:[_.jsx("label",{htmlFor:`btn-${g}-action`,children:"Action"}),_.jsx("select",{id:`btn-${g}-action`,value:p.action,onChange:U=>H({...p,action:U.target.value}),children:Ty.map(U=>_.jsx("option",{value:U.value,children:U.label},U.value))})]}),_.jsxs("div",{children:[_.jsx("label",{htmlFor:`btn-${g}-target`,children:v?"Command":"Target"}),_.jsx("input",{type:"text",id:`btn-${g}-target`,value:p.target,placeholder:v?"playerctl play-pause":"default",onChange:U=>H({...p,target:U.target.value})})]})]})}function Ay({presets:g,config:p,onLoad:H,onRefresh:v,onToast:U}){const[G,J]=Ll.useState(""),ml=async()=>{const O=G.trim();if(!O){U("Enter a preset name first","info");return}try{await oy(O,p),U(`Preset "${O}" saved`),J(""),v()}catch(Z){U(`Save preset failed: ${Z.message}`,"error")}},R=async O=>{try{const Z=await dy(O);H(Z),U(`Preset "${O}" loaded — click Save Config to write to disk`,"info")}catch(Z){U(`Load failed: ${Z.message}`,"error")}},S=async O=>{try{await vy(O);const Z=await Dv();H(Z),U(`Preset "${O}" applied — daemon will reload automatically`)}catch(Z){U(`Apply failed: ${Z.message}`,"error")}},Q=async O=>{if(confirm(`Delete preset "${O}"?`))try{await my(O),U(`Preset "${O}" deleted`),v()}catch(Z){U(`Delete failed: ${Z.message}`,"error")}};return _.jsxs("section",{className:"card",id:"presets",children:[_.jsx("h2",{children:"Presets"}),_.jsxs("div",{className:"save-row",children:[_.jsxs("div",{className:"field",children:[_.jsx("label",{htmlFor:"preset-name",children:"Preset name"}),_.jsx("input",{type:"text",id:"preset-name",value:G,placeholder:"my-setup",onChange:O=>J(O.target.value),onKeyDown:O=>O.key==="Enter"&&void ml()})]}),_.jsx("button",{className:"btn-secondary",onClick:()=>{ml()},children:"Save current as preset"})]}),_.jsx("div",{className:"preset-list",children:g.length===0?_.jsx("p",{className:"empty",children:"No presets saved yet."}):g.map(O=>_.jsxs("div",{className:"preset-item",children:[_.jsx("span",{className:"preset-name",children:O}),_.jsxs("div",{className:"preset-actions",children:[_.jsx("button",{className:"btn-secondary btn-sm",onClick:()=>{R(O)},children:"Load"}),_.jsx("button",{className:"btn-primary btn-sm",onClick:()=>{S(O)},children:"Apply"}),_.jsx("button",{className:"btn-danger btn-sm",onClick:()=>{Q(O)},children:"Delete"})]})]},O))})]})}const _y=["0","1","2","3","4"],py=["0","1","2","3","4"];let Oy=0;function My(){const[g,p]=Ll.useState(null),[H,v]=Ll.useState(null),[U,G]=Ll.useState([]),[J,ml]=Ll.useState([]),[R,S]=Ll.useState(!0),[Q,O]=Ll.useState(!1),Z=Ll.useCallback((Y,vl="success")=>{const Ul=++Oy;ml(xl=>[...xl,{id:Ul,message:Y,type:vl}])},[]),Gl=Ll.useCallback(Y=>{ml(vl=>vl.filter(Ul=>Ul.id!==Y))},[]),Dl=Ll.useCallback(async()=>{try{const Y=await sy();G(Y)}catch{}},[]);Ll.useEffect(()=>{(async()=>{try{const Y=await Dv();p(Y),v(Y)}catch(Y){Z(`Failed to load config: ${Y.message}`,"error")}finally{S(!1)}await Dl()})()},[Z,Dl]);const Ol=g!==null&&JSON.stringify(g)!==JSON.stringify(H),zt=async()=>{if(g){O(!0);try{await iy(g),v(g),Z("Config saved — daemon will reload automatically")}catch(Y){Z(`Save failed: ${Y.message}`,"error")}finally{O(!1)}}},Xl=()=>{H&&p(H)},st=Ll.useCallback((Y,vl)=>{p(Ul=>Ul&&{...Ul,[Y]:vl})},[]);return R?_.jsx("div",{id:"loading",children:_.jsx("p",{children:"Connecting to daemon…"})}):g?_.jsxs(_.Fragment,{children:[_.jsxs("header",{id:"app-header",children:[_.jsx("h1",{children:"TurnUp"}),Ol&&_.jsx("span",{id:"dirty-badge",className:"visible",children:"unsaved changes"}),_.jsx("button",{className:"btn-secondary",onClick:Xl,disabled:!Ol,children:"Revert"}),_.jsx("button",{className:"btn-primary",onClick:()=>{zt()},disabled:!Ol||Q,children:Q?"Saving…":"Save Config"})]}),_.jsxs("main",{children:[_.jsx(gy,{config:g,onChange:Y=>p(vl=>vl&&{...vl,...Y})}),_.jsx(Sy,{leds:g.leds,onChange:Y=>st("leds",Y)}),_.jsxs("section",{className:"card",id:"knobs",children:[_.jsx("h2",{children:"Knobs"}),_.jsx("div",{className:"cards-grid",children:_y.map(Y=>_.jsx(zy,{index:Number(Y),knob:g.knobs[Y]??{action:"sink_volume",target:"default"},onChange:vl=>st("knobs",{...g.knobs,[Y]:vl})},Y))})]}),_.jsxs("section",{className:"card",id:"buttons",children:[_.jsx("h2",{children:"Buttons"}),_.jsx("div",{className:"cards-grid",children:py.map(Y=>_.jsx(Ey,{index:Number(Y),btn:g.buttons[Y]??{action:"mute_sink",target:"default"},onChange:vl=>st("buttons",{...g.buttons,[Y]:vl})},Y))})]}),_.jsx(Ay,{presets:U,config:g,onLoad:Y=>p(Y),onRefresh:Dl,onToast:Z})]}),_.jsx(yy,{toasts:J,onRemove:Gl})]}):_.jsx("div",{id:"loading",children:_.jsxs("p",{children:["Could not reach the API server. Is ",_.jsx("code",{children:"turnup-ui"})," running?"]})})}"serviceWorker"in navigator&&window.addEventListener("load",()=>{navigator.serviceWorker.register("/sw.js").catch(()=>{})});fy.createRoot(document.getElementById("root")).render(_.jsx(Ll.StrictMode,{children:_.jsx(My,{})})); diff --git a/src/turnup/ui/static/icon.svg b/src/turnup/ui/static/icon.svg new file mode 100644 index 0000000..ab7f10b --- /dev/null +++ b/src/turnup/ui/static/icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/turnup/ui/static/index.html b/src/turnup/ui/static/index.html new file mode 100644 index 0000000..8688328 --- /dev/null +++ b/src/turnup/ui/static/index.html @@ -0,0 +1,16 @@ + + + + + + + + + TurnUp + + + + +
+ + diff --git a/src/turnup/ui/static/manifest.json b/src/turnup/ui/static/manifest.json new file mode 100644 index 0000000..32d26cf --- /dev/null +++ b/src/turnup/ui/static/manifest.json @@ -0,0 +1,17 @@ +{ + "name": "TurnUp", + "short_name": "TurnUp", + "description": "Configure your TurnUp knob/button mixer", + "start_url": "/", + "display": "standalone", + "background_color": "#0d1117", + "theme_color": "#0d1117", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/src/turnup/ui/static/sw.js b/src/turnup/ui/static/sw.js new file mode 100644 index 0000000..4f33cb0 --- /dev/null +++ b/src/turnup/ui/static/sw.js @@ -0,0 +1,31 @@ +// Network-first SW: static assets are cached after first fetch; +// API calls always go to the network. +const CACHE = 'turnup-v1'; + +self.addEventListener('install', () => { + self.skipWaiting(); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keys) => + Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))) + ) + ); + self.clients.claim(); +}); + +self.addEventListener('fetch', (e) => { + // Always go network-first for API calls so the UI never serves stale data + if (e.request.url.includes('/api/')) return; + + e.respondWith( + fetch(e.request) + .then((response) => { + const clone = response.clone(); + caches.open(CACHE).then((c) => c.put(e.request, clone)); + return response; + }) + .catch(() => caches.match(e.request)) + ); +}); diff --git a/src/turnup/ui/static/vite.svg b/src/turnup/ui/static/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/src/turnup/ui/static/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/turnupd.install b/turnupd.install index d054017..dee404a 100644 --- a/turnupd.install +++ b/turnupd.install @@ -1,25 +1,32 @@ post_install() { systemctl --global enable turnupd.service - echo "turnupd: service enabled for all users — it will start on next login." - echo "To start it now: systemctl --user start turnupd.service" + systemctl --global enable turnup-ui.service + echo "turnupd + turnup-ui: services enabled for all users — they will start on next login." + echo "To start them now:" + echo " systemctl --user start turnupd.service" + echo " systemctl --user start turnup-ui.service" + echo "UI will be available at http://127.0.0.1:5173" } post_upgrade() { systemctl --global reenable turnupd.service + systemctl --global reenable turnup-ui.service # Restart for all currently logged-in users while read -r uid _; do - systemctl -M "${uid}@.host" --user restart turnupd.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user restart turnupd.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user restart turnup-ui.service 2>/dev/null || true done < <(loginctl list-users --no-legend 2>/dev/null) } pre_remove() { # Stop and disable for all currently logged-in users while read -r uid _; do - systemctl -M "${uid}@.host" --user stop turnupd.service 2>/dev/null || true - systemctl -M "${uid}@.host" --user disable turnupd.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user stop turnupd.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user disable turnupd.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user stop turnup-ui.service 2>/dev/null || true + systemctl -M "${uid}@.host" --user disable turnup-ui.service 2>/dev/null || true done < <(loginctl list-users --no-legend 2>/dev/null) - # Remove the global enable symlink - # (/etc/systemd/user/default.target.wants/turnupd.service) - systemctl --global disable turnupd.service 2>/dev/null || true + systemctl --global disable turnupd.service 2>/dev/null || true + systemctl --global disable turnup-ui.service 2>/dev/null || true } diff --git a/ui/.gitignore b/ui/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/ui/.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/ui/README.md b/ui/README.md new file mode 100644 index 0000000..d2e7761 --- /dev/null +++ b/ui/README.md @@ -0,0 +1,73 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/ui/eslint.config.js b/ui/eslint.config.js new file mode 100644 index 0000000..5e6b472 --- /dev/null +++ b/ui/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..2ed656f --- /dev/null +++ b/ui/index.html @@ -0,0 +1,15 @@ + + + + + + + + + TurnUp + + +
+ + + diff --git a/ui/package-lock.json b/ui/package-lock.json new file mode 100644 index 0000000..f3a5a51 --- /dev/null +++ b/ui/package-lock.json @@ -0,0 +1,3286 @@ +{ + "name": "turnup-ui", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "turnup-ui", + "version": "0.0.0", + "dependencies": { + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "typescript": "~5.9.3", + "typescript-eslint": "^8.48.0", + "vite": "^7.3.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.3", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", + "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "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-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "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.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.15.tgz", + "integrity": "sha512-BgjLoRuSr0MTI5wA6gMw9Xy0sFudAaUuvrnjgGx9wZ522fYYLA5SYJ+1Y30vTcJEG+DRCyDHx/gzQVfofYzSdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", + "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/type-utils": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", + "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", + "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", + "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.56.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "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.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001774", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz", + "integrity": "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==", + "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/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "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/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "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/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "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/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", + "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.3", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "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/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "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/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "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/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "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/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.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/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz", + "integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/utils": "8.56.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "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/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "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/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 0000000..b7575f5 --- /dev/null +++ b/ui/package.json @@ -0,0 +1,30 @@ +{ + "name": "turnup-ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "typescript": "~5.9.3", + "typescript-eslint": "^8.48.0", + "vite": "^7.3.1" + } +} diff --git a/ui/public/icon.svg b/ui/public/icon.svg new file mode 100644 index 0000000..ab7f10b --- /dev/null +++ b/ui/public/icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/ui/public/manifest.json b/ui/public/manifest.json new file mode 100644 index 0000000..32d26cf --- /dev/null +++ b/ui/public/manifest.json @@ -0,0 +1,17 @@ +{ + "name": "TurnUp", + "short_name": "TurnUp", + "description": "Configure your TurnUp knob/button mixer", + "start_url": "/", + "display": "standalone", + "background_color": "#0d1117", + "theme_color": "#0d1117", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any maskable" + } + ] +} diff --git a/ui/public/sw.js b/ui/public/sw.js new file mode 100644 index 0000000..4f33cb0 --- /dev/null +++ b/ui/public/sw.js @@ -0,0 +1,31 @@ +// Network-first SW: static assets are cached after first fetch; +// API calls always go to the network. +const CACHE = 'turnup-v1'; + +self.addEventListener('install', () => { + self.skipWaiting(); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keys) => + Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))) + ) + ); + self.clients.claim(); +}); + +self.addEventListener('fetch', (e) => { + // Always go network-first for API calls so the UI never serves stale data + if (e.request.url.includes('/api/')) return; + + e.respondWith( + fetch(e.request) + .then((response) => { + const clone = response.clone(); + caches.open(CACHE).then((c) => c.put(e.request, clone)); + return response; + }) + .catch(() => caches.match(e.request)) + ); +}); diff --git a/ui/public/vite.svg b/ui/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/ui/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/App.tsx b/ui/src/App.tsx new file mode 100644 index 0000000..d6e191c --- /dev/null +++ b/ui/src/App.tsx @@ -0,0 +1,174 @@ +import { useState, useEffect, useCallback } from 'react'; +import type { Config, ToastItem } from './types'; +import * as api from './api'; +import { ToastContainer } from './components/Toast'; +import { Connection } from './components/Connection'; +import { GlobalLeds } from './components/GlobalLeds'; +import { KnobCard } from './components/KnobCard'; +import { ButtonCard } from './components/ButtonCard'; +import { Presets } from './components/Presets'; + +const KNOB_INDICES = ['0', '1', '2', '3', '4'] as const; +const BTN_INDICES = ['0', '1', '2', '3', '4'] as const; + +let toastSeq = 0; + +export default function App() { + const [config, setConfig] = useState(null); + const [saved, setSaved] = useState(null); + const [presets, setPresets] = useState([]); + const [toasts, setToasts] = useState([]); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + + const addToast = useCallback((message: string, type: ToastItem['type'] = 'success') => { + const id = ++toastSeq; + setToasts((prev) => [...prev, { id, message, type }]); + }, []); + + const removeToast = useCallback((id: number) => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + }, []); + + const loadPresets = useCallback(async () => { + try { + const names = await api.listPresets(); + setPresets(names); + } catch { + // Non-fatal — presets dir may not exist yet + } + }, []); + + // Initial load + useEffect(() => { + void (async () => { + try { + const cfg = await api.fetchConfig(); + setConfig(cfg); + setSaved(cfg); + } catch (err) { + addToast(`Failed to load config: ${(err as Error).message}`, 'error'); + } finally { + setLoading(false); + } + await loadPresets(); + })(); + }, [addToast, loadPresets]); + + const isDirty = config !== null && JSON.stringify(config) !== JSON.stringify(saved); + + const handleSave = async () => { + if (!config) return; + setSaving(true); + try { + await api.saveConfig(config); + setSaved(config); + addToast('Config saved — daemon will reload automatically'); + } catch (err) { + addToast(`Save failed: ${(err as Error).message}`, 'error'); + } finally { + setSaving(false); + } + }; + + const handleRevert = () => { + if (saved) setConfig(saved); + }; + + const patchConfig = useCallback((key: K, value: Config[K]) => { + setConfig((prev) => prev ? { ...prev, [key]: value } : prev); + }, []); + + if (loading) { + return ( +
+

Connecting to daemon…

+
+ ); + } + + if (!config) { + return ( +
+

Could not reach the API server. Is turnup-ui running?

+
+ ); + } + + return ( + <> +
+

TurnUp

+ {isDirty && unsaved changes} + + +
+ +
+ setConfig((prev) => prev ? { ...prev, ...patch } : prev)} + /> + + patchConfig('leds', leds)} + /> + +
+

Knobs

+
+ {KNOB_INDICES.map((i) => ( + + patchConfig('knobs', { ...config.knobs, [i]: knob }) + } + /> + ))} +
+
+ +
+

Buttons

+
+ {BTN_INDICES.map((i) => ( + + patchConfig('buttons', { ...config.buttons, [i]: btn }) + } + /> + ))} +
+
+ + setConfig(cfg)} + onRefresh={loadPresets} + onToast={addToast} + /> +
+ + + + ); +} diff --git a/ui/src/api.ts b/ui/src/api.ts new file mode 100644 index 0000000..b378005 --- /dev/null +++ b/ui/src/api.ts @@ -0,0 +1,58 @@ +import type { Config } from './types'; + +async function checkResponse(r: Response): Promise { + if (!r.ok) { + const body = await r.json().catch(() => null); + throw new Error(body?.detail ?? `${r.status} ${r.statusText}`); + } +} + +export async function fetchConfig(): Promise { + const r = await fetch('/api/config'); + await checkResponse(r); + return r.json(); +} + +export async function saveConfig(cfg: Config): Promise { + const r = await fetch('/api/config', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(cfg), + }); + await checkResponse(r); +} + +export async function listPresets(): Promise { + const r = await fetch('/api/presets'); + if (!r.ok) return []; + return r.json(); +} + +export async function fetchPreset(name: string): Promise { + const r = await fetch(`/api/presets/${encodeURIComponent(name)}`); + await checkResponse(r); + return r.json(); +} + +export async function savePreset(name: string, cfg: Config): Promise { + const r = await fetch(`/api/presets/${encodeURIComponent(name)}/save`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(cfg), + }); + await checkResponse(r); +} + +export async function applyPreset(name: string): Promise { + const r = await fetch(`/api/presets/${encodeURIComponent(name)}/apply`, { + method: 'POST', + }); + await checkResponse(r); +} + +export async function deletePreset(name: string): Promise { + const r = await fetch(`/api/presets/${encodeURIComponent(name)}`, { + method: 'DELETE', + }); + await checkResponse(r); +} diff --git a/ui/src/components/ButtonCard.tsx b/ui/src/components/ButtonCard.tsx new file mode 100644 index 0000000..47da979 --- /dev/null +++ b/ui/src/components/ButtonCard.tsx @@ -0,0 +1,52 @@ +import type { ButtonConfig, ButtonAction } from '../types'; + +const ACTIONS: { value: ButtonAction; label: string }[] = [ + { value: 'mute_sink', label: 'mute_sink — toggle output mute' }, + { value: 'mute_source', label: 'mute_source — toggle mic mute' }, + { value: 'command', label: 'command — run shell command' }, +]; + +interface Props { + index: number; + btn: ButtonConfig; + onChange: (btn: ButtonConfig) => void; +} + +export function ButtonCard({ index, btn, onChange }: Props) { + const isCmd = btn.action === 'command'; + + return ( +
+
+ {index} + Button {index} +
+ +
+ + +
+ +
+ + onChange({ ...btn, target: e.target.value })} + /> +
+
+ ); +} diff --git a/ui/src/components/ColorPicker.tsx b/ui/src/components/ColorPicker.tsx new file mode 100644 index 0000000..7e5cdbb --- /dev/null +++ b/ui/src/components/ColorPicker.tsx @@ -0,0 +1,26 @@ +import { hexToRgb, rgbToHex } from '../utils'; + +interface Props { + id: string; + label: string; + value: [number, number, number]; + onChange: (rgb: [number, number, number]) => void; +} + +export function ColorPicker({ id, label, value, onChange }: Props) { + const hex = rgbToHex(value); + return ( +
+ +
+ onChange(hexToRgb(e.target.value))} + /> + {hex} +
+
+ ); +} diff --git a/ui/src/components/Connection.tsx b/ui/src/components/Connection.tsx new file mode 100644 index 0000000..b8e0032 --- /dev/null +++ b/ui/src/components/Connection.tsx @@ -0,0 +1,37 @@ +import type { Config } from '../types'; + +interface Props { + config: Config; + onChange: (patch: Partial>) => void; +} + +export function Connection({ config, onChange }: Props) { + return ( +
+

Connection

+
+
+ + onChange({ port: e.target.value })} + /> +
+
+ + + onChange({ baud: parseInt(e.target.value, 10) || 115200 }) + } + /> +
+
+
+ ); +} diff --git a/ui/src/components/GlobalLeds.tsx b/ui/src/components/GlobalLeds.tsx new file mode 100644 index 0000000..85c1f0b --- /dev/null +++ b/ui/src/components/GlobalLeds.tsx @@ -0,0 +1,59 @@ +import type { LedConfig, LedMode } from '../types'; +import { ColorPicker } from './ColorPicker'; +import { rgbToHex } from '../utils'; + +interface Props { + leds: LedConfig; + onChange: (leds: LedConfig) => void; +} + +export function GlobalLeds({ leds, onChange }: Props) { + const update = (patch: Partial) => onChange({ ...leds, ...patch }); + const lowHex = rgbToHex(leds.low_color); + const highHex = rgbToHex(leds.high_color); + + const previewBg = + leds.mode === 'off' ? '#000' : + leds.mode === 'static' ? highHex : + `linear-gradient(to right, ${lowHex}, ${highHex})`; + + return ( +
+

Global LEDs

+
+
+ + +
+ +
+ update({ low_color })} + /> +
+ +
+ update({ high_color })} + /> +
+
+ +
+
+ ); +} diff --git a/ui/src/components/KnobCard.tsx b/ui/src/components/KnobCard.tsx new file mode 100644 index 0000000..fa52ff1 --- /dev/null +++ b/ui/src/components/KnobCard.tsx @@ -0,0 +1,141 @@ +import { useState } from 'react'; +import type { KnobConfig, KnobAction, LedConfig, LedMode } from '../types'; +import { ColorPicker } from './ColorPicker'; + +const ACTIONS: { value: KnobAction; label: string }[] = [ + { value: 'sink_volume', label: 'sink_volume — output device' }, + { value: 'source_volume', label: 'source_volume — microphone' }, + { value: 'app_volume', label: 'app_volume — single app' }, + { value: 'group_volume', label: 'group_volume — multiple apps' }, +]; + +const DEFAULT_LED: LedConfig = { + mode: 'volume', + low_color: [255, 0, 0], + high_color: [0, 255, 0], +}; + +interface Props { + index: number; + knob: KnobConfig; + onChange: (knob: KnobConfig) => void; +} + +export function KnobCard({ index, knob, onChange }: Props) { + const [ledOpen, setLedOpen] = useState(!!knob.led); + + const update = (patch: Partial) => onChange({ ...knob, ...patch }); + + const ledCfg: LedConfig = { + mode: knob.led?.mode ?? DEFAULT_LED.mode, + low_color: knob.led?.low_color ?? DEFAULT_LED.low_color, + high_color: knob.led?.high_color ?? DEFAULT_LED.high_color, + }; + + const updateLed = (patch: Partial) => + update({ led: { ...ledCfg, ...patch } }); + + const toggleLed = () => { + const next = !ledOpen; + setLedOpen(next); + if (!next) { + // Drop the led key entirely when panel is closed + const { led: _dropped, ...rest } = knob; + onChange(rest as KnobConfig); + } + }; + + return ( +
+
+ {index} + Knob {index} +
+ + {/* Action */} +
+ + +
+ + {/* Target / Targets */} + {knob.action === 'group_volume' ? ( +
+ +