feat(auth): replace browser Basic Auth popup with custom Shadcn SSO AuthGateModal and .hl-input system
This commit is contained in:
1 parent
ba3cf726b4
commit
cbc47336d6
13 files changed
+805
-209
No files matched your search
@@ -10,7 +10,6 @@ status.961504.xyz:443 {
|
||||
}
|
||||
|
||||
# 2. 家庭统一导航总入口免端口 443 访问 -> https://nav.961504.xyz
|
||||
# (通过 Tailscale 加密专线回源至家里 Mac mini 的 Sun-Panel)
|
||||
nav.961504.xyz:443 {
|
||||
encode zstd gzip
|
||||
reverse_proxy 100.108.205.40:3002
|
||||
@@ -23,10 +22,11 @@ wx.961504.xyz:443 {
|
||||
}
|
||||
|
||||
# 4. AGY 24小时云端 Web 工作台 (443 免端口访问) -> https://agy.961504.xyz
|
||||
# 使用 forward_auth 对接 HomeLab SSO 2.0 自定义登录卡片,彻底告别浏览器原生丑陋弹窗!
|
||||
agy.961504.xyz:443 {
|
||||
encode zstd gzip
|
||||
basicauth /* {
|
||||
ixvii0iv $2a$14$VaaNvgIjsCJFzXCpIxjcOerKUIdkN7GhVWAlGh3/ZZjBOADY9lg..
|
||||
forward_auth 100.108.205.40:3002 {
|
||||
uri /api/auth/verify
|
||||
}
|
||||
reverse_proxy 100.108.205.40:7681
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
auto_https disable_redirects
|
||||
}
|
||||
|
||||
# 0. 家庭统一导航总入口 Sun-Panel (https://home.961504.xyz:10443)
|
||||
# 0. 家庭统一导航总入口 HomeLab Console V3 (https://home.961504.xyz:10443)
|
||||
home.961504.xyz:10443, nav.home.961504.xyz:10443 {
|
||||
tls /Users/ixvii0iv/homelab/stacks/gateway/certs/fullchain.pem /Users/ixvii0iv/homelab/stacks/gateway/certs/privkey.pem
|
||||
encode zstd gzip
|
||||
@@ -22,12 +22,12 @@ nas.home.961504.xyz:10443, z4.home.961504.xyz:10443 {
|
||||
reverse_proxy 192.168.31.185:5055
|
||||
}
|
||||
|
||||
# 2. 路由器 Mihomo / Clash 面板 (已开启 HTTP Basic Auth 密码锁保护: ixvii0iv / Mac mini密码)
|
||||
# 2. 路由器 Mihomo / Clash 面板 (通过 HomeLab SSO 2.0 自定义登录卡片保护)
|
||||
clash.home.961504.xyz:10443 {
|
||||
tls /Users/ixvii0iv/homelab/stacks/gateway/certs/fullchain.pem /Users/ixvii0iv/homelab/stacks/gateway/certs/privkey.pem
|
||||
encode zstd gzip
|
||||
basic_auth {
|
||||
ixvii0iv $2a$14$VaaNvgIjsCJFzXCpIxjcOerKUIdkN7GhVWAlGh3/ZZjBOADY9lg..
|
||||
forward_auth 127.0.0.1:3002 {
|
||||
uri /api/auth/verify
|
||||
}
|
||||
reverse_proxy 192.168.31.1:9999
|
||||
}
|
||||
@@ -36,8 +36,8 @@ clash.home.961504.xyz:10443 {
|
||||
router.home.961504.xyz:10443 {
|
||||
tls /Users/ixvii0iv/homelab/stacks/gateway/certs/fullchain.pem /Users/ixvii0iv/homelab/stacks/gateway/certs/privkey.pem
|
||||
encode zstd gzip
|
||||
basic_auth {
|
||||
ixvii0iv $2a$14$VaaNvgIjsCJFzXCpIxjcOerKUIdkN7GhVWAlGh3/ZZjBOADY9lg..
|
||||
forward_auth 127.0.0.1:3002 {
|
||||
uri /api/auth/verify
|
||||
}
|
||||
reverse_proxy 192.168.31.1:80
|
||||
}
|
||||
@@ -50,11 +50,12 @@ lucky.home.961504.xyz:10443 {
|
||||
}
|
||||
|
||||
# 5. AGY 24小时云端 Web 工作台 (https://agy.home.961504.xyz:10443)
|
||||
# 使用 forward_auth 对接 HomeLab SSO 2.0 自定义登录卡片,彻底告别浏览器原生丑陋弹窗!
|
||||
agy.home.961504.xyz:10443 {
|
||||
tls /Users/ixvii0iv/homelab/stacks/gateway/certs/fullchain.pem /Users/ixvii0iv/homelab/stacks/gateway/certs/privkey.pem
|
||||
encode zstd gzip
|
||||
basic_auth {
|
||||
ixvii0iv $2a$14$VaaNvgIjsCJFzXCpIxjcOerKUIdkN7GhVWAlGh3/ZZjBOADY9lg..
|
||||
forward_auth 127.0.0.1:3002 {
|
||||
uri /api/auth/verify
|
||||
}
|
||||
reverse_proxy 127.0.0.1:7681
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/*! tailwindcss v4.3.5 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:block))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-divide-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--spacing:.25rem;--container-md:28rem;--container-xl:36rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--blur-sm:8px;--blur-md:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-Line truncated
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
(function(){const O=document.createElement("link").relList;if(O&&O.supports&&O.supports("modulepreload"))return;for(const E of document.querySelectorAll('link[rel="modulepreload"]'))d(E);new MutationObserver(E=>{for(const H of E)if(H.type==="childList")for(const J of H.addedNodes)J.tagName==="LINK"&&J.rel==="modulepreload"&&d(J)}).observe(document,{childList:!0,subtree:!0});function T(E){const H={};return E.integrity&&(H.integrity=E.integrity),E.referrerPolicy&&(H.referrerPolicy=E.referrerPolicy),E.crossOrigin==="use-credentials"?H.credentials="include":E.crossOrigin==="anonymous"?H.credentials="omit":H.credentials="same-origin",H}function d(E){if(E.ep)return;E.ep=!0;const H=T(E);fetch(E.href,H)}})();function g0(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x.default:x}var Ts={exports:{}},nn={};/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var u0;function pv(){if(u0)return nn;u0=1;var x=Symbol.for("react.transitional.element"),O=Symbol.for("react.fragment");function T(d,E,H){var J=null;if(H!==void 0&&(J=""+H),E.key!==void 0&&(J=""+E.key),"key"in E){H={};for(var K in E)K!=="key"&&(H[K]=E[K])}else H=E;return E=H.ref,{$$typeof:x,type:d,key:J,ref:E!==void 0?E:null,props:H}}return nn.Fragment=O,nn.jsx=T,nn.jsxs=T,nn}var n0;function Nv(){return n0||(n0=1,Ts.exports=pv()),Ts.exports}var f=Nv(),_s={exports:{}},V={};/**
|
||||
* @license React
|
||||
* react.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var c0;function Tv(){if(c0)return V;c0=1;var x=Symbol.for("react.transitional.element"),O=Symbol.for("react.portal"),T=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),H=Symbol.for("react.consumer"),J=Symbol.for("react.context"),K=Symbol.for("react.forward_ref"),Q=Symbol.for("react.suspense"),W=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),S=Symbol.for("react.activity"),D=Symbol.for("react.view_transition"),w=Symbol.iterator;function U(r){return r===null||typeof r!="object"?null:(r=w&&r[w]||r["@@iterator"],typeof r=="function"?r:null)}var vl={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},P=Object.assign,jl={};function Bl(r,_,B){this.props=r,this.context=_,this.refs=jl,this.updater=B||vl}Bl.prototype.isReactComponent={},Bl.prototype.setState=function(r,_){if(typeof r!="object"&&typeof r!="function"&&r!=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,r,_,"setState")},Bl.prototype.forceUpdate=function(r){this.updater.enqueueForceUpdate(this,r,"forceUpdate")};function I(){}I.prototype=Bl.prototype;function il(r,_,B){this.props=r,this.context=_,this.refs=jl,this.updater=B||vl}var Il=il.prototype=new I;Il.constructor=il,P(Il,Bl.prototype),Il.isPureReactComponent=!0;var Pl=Array.isArray;function ll(){}var ol={H:null,A:null,T:null,S:null},Qt=Object.prototype.hasOwnProperty;function Tt(r,_,B){var q=B.ref;return{$$typeof:x,type:r,key:_,ref:q!==void 0?q:null,props:B}}function _t(r,_){return Tt(r.type,_,r.props)}function rt(r){return typeof r=="object"&&r!==null&&r.$$typeof===x}function be(r){var _={"=":"=0",":":"=2"};return"$"+r.replace(/[=:]/g,function(B){return _[B]})}var $e=/\/+/g;function ql(r,_){return typeof r=="object"&&r!==null&&r.key!=null?be(""+r.key):_.toString(36)}function j(r){switch(r.status){case"fulfilled":return r.value;case"rejected":throw r.reason;default:switch(typeof r.status=="string"?r.then(ll,ll):(r.status="pending",r.then(function(_){r.status==="pending"&&(r.status="fulfilled",r.value=_)},function(_){r.status==="pending"&&(r.status="rejected",r.reason=_)})),r.status){case"fulfilled":return r.value;case"rejected":throw r.reason}}throw r}function X(r,_,B,q,cl){var fl=typeof r;(fl==="undefined"||fl==="boolean")&&(r=null);var rl=!1;if(r===null)rl=!0;else switch(fl){case"bigint":case"string":case"number":rl=!0;break;case"object":switch(r.$$typeof){case x:case O:rl=!0;break;case A:return rl=r._init,X(rl(r._payload),_,B,q,cl)}}if(rl)return cl=cl(r),rl=q===""?"."+ql(r,0):q,Pl(cl)?(B="",rl!=null&&(B=rl.replace($e,"$&/")+"/"),X(cl,_,B,"",function(ee){return ee})):cl!=null&&(rt(cl)&&(cl=_t(cl,B+(cl.key==null||r&&r.key===cl.key?"":(""+cl.key).replace($e,"$&/")+"/")+rl)),_.push(cl)),1;rl=0;var R=q===""?".":q+":";if(Pl(r))for(var Z=0;Z<r.length;Z++)q=r[Z],fl=R+ql(q,Z),rl+=X(q,_,B,fl,cl);else if(Z=U(r),typeof Z=="function")for(r=Z.call(r),Z=0;!(q=r.next()).done;)q=q.value,fl=R+ql(q,Z++),rl+=X(q,_,B,fl,cl);else if(fl==="object"){if(typeof r.then=="function")return X(j(r),_,B,q,cl);throw _=String(r),Error("Objects are not valid as a React child (found: "+(_==="[object Object]"?"object with keys {"+Object.keys(r).join(", ")+"}":_)+"). If you meant to render a collection of children, use an array instead.")}return rl}function L(r,_,B){if(r==null)return r;var q=[],cl=0;return X(r,q,"","",function(fl){return _.call(B,fl,cl++)}),q}function pl(r){if(r._status===-1){var _=r._result,B=_();B.then(function(q){(r._status===0||r._status===-1)&&(r._status=1,r._result=q,B.status===void 0&&(B.status="fulfilled",B.value=q))},function(q){(r._status===0||r._status===-1)&&(r._status=2,r._result=q,B.status===void 0&&(B.status="rejected",B.reason=q))}),r._status===-1&&(r._status=0,r._result=B)}if(r._status===1)return r._result.default;throw r._result}var ml=typeof reportError=="function"?reportError:function(r){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var _=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof r=="object"&&r!==null&&typeof r.message=="string"?String(r.message):String(r),error:r});if(!window.dispatchEvent(_))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",r);return}console.error(r)};function Rt(r){var _=ol.T,B={};B.types=_!==null?_.types:null,ol.T=B;try{var q=r(),cl=ol.S;cl!==null&&cl(B,q),typeof q=="object"&&q!==null&&typeof q.then=="function"&&q.then(ll,ml)}catch(fl){ml(fl)}finally{_!==null&&B.types!==null&&(_.types=B.types),ol.T=_}}function te(r){var _=ol.T;if(_!==null){var B=_.types;B===null?_.types=[r]:B.indexOf(r)===-1&&B.push(r)}else Rt(te.bind(null,r))}var We={map:L,forEach:function(r,_,B){L(r,function(){_.apply(this,arguments)},B)},count:function(r){var _=0;return L(r,function(){_++}),_},toArray:function(r){return L(r,function(_){return _})||[]},only:function(r){if(!rLine truncated
|
||||
* @license React
|
||||
* scheduler.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var f0;function _v(){return f0||(f0=1,(function(x){function O(j,X){var L=j.length;j.push(X);l:for(;0<L;){var pl=L-1>>>1,ml=j[pl];if(0<E(ml,X))j[pl]=X,j[L]=ml,L=pl;else break l}}function T(j){return j.length===0?null:j[0]}function d(j){if(j.length===0)return null;var X=j[0],L=j.pop();if(L!==X){j[0]=L;l:for(var pl=0,ml=j.length,Rt=ml>>>1;pl<Rt;){var te=2*(pl+1)-1,We=j[te],r=te+1,_=j[r];if(0>E(We,L))r<ml&&0>E(_,We)?(j[pl]=_,j[r]=L,pl=r):(j[pl]=We,j[te]=L,pl=te);else if(r<ml&&0>E(_,L))j[pl]=_,j[r]=L,pl=r;else break l}}return X}function E(j,X){var L=j.sortIndex-X.sortIndex;return L!==0?L:j.id-X.id}if(x.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var H=performance;x.unstable_now=function(){return H.now()}}else{var J=Date,K=J.now();x.unstable_now=function(){return J.now()-K}}var Q=[],W=[],A=1,S=null,D=3,w=!1,U=!1,vl=!1,P=!1,jl=typeof setTimeout=="function"?setTimeout:null,Bl=typeof clearTimeout=="function"?clearTimeout:null,I=typeof setImmediate<"u"?setImmediate:null;function il(j){for(var X=T(W);X!==null;){if(X.callback===null)d(W);else if(X.startTime<=j)d(W),X.sortIndex=X.expirationTime,O(Q,X);else break;X=T(W)}}function Il(j){if(vl=!1,il(j),!U)if(T(Q)!==null)U=!0,Pl||(Pl=!0,rt());else{var X=T(W);X!==null&&ql(Il,X.startTime-j)}}var Pl=!1,ll=-1,ol=5,Qt=-1;function Tt(){return P?!0:!(x.unstable_now()-Qt<ol)}function _t(){if(P=!1,Pl){var j=x.unstable_now();Qt=j;var X=!0;try{l:{U=!1,vl&&(vl=!1,Bl(ll),ll=-1),w=!0;var L=D;try{t:{for(il(j),S=T(Q);S!==null&&!(S.expirationTime>j&&Tt());){var pl=S.callback;if(typeof pl=="function"){S.callback=null,D=S.priorityLevel;var ml=pl(S.expirationTime<=j);if(j=x.unstable_now(),typeof ml=="function"){S.callback=ml,il(j),X=!0;break t}S===T(Q)&&d(Q),il(j)}else d(Q);S=T(Q)}if(S!==null)X=!0;else{var Rt=T(W);Rt!==null&&ql(Il,Rt.startTime-j),X=!1}}break l}finally{S=null,D=L,w=!1}X=void 0}}finally{X?rt():Pl=!1}}}var rt;if(typeof I=="function")rt=function(){I(_t)};else if(typeof MessageChannel<"u"){var be=new MessageChannel,$e=be.port2;be.port1.onmessage=_t,rt=function(){$e.postMessage(null)}}else rt=function(){jl(_t,0)};function ql(j,X){ll=jl(function(){j(x.unstable_now())},X)}x.unstable_IdlePriority=5,x.unstable_ImmediatePriority=1,x.unstable_LowPriority=4,x.unstable_NormalPriority=3,x.unstable_Profiling=null,x.unstable_UserBlockingPriority=2,x.unstable_cancelCallback=function(j){j.callback=null},x.unstable_forceFrameRate=function(j){0>j||125<j?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):ol=0<j?Math.floor(1e3/j):5},x.unstable_getCurrentPriorityLevel=function(){return D},x.unstable_next=function(j){switch(D){case 1:case 2:case 3:var X=3;break;default:X=D}var L=D;D=X;try{return j()}finally{D=L}},x.unstable_requestPaint=function(){P=!0},x.unstable_runWithPriority=function(j,X){switch(j){case 1:case 2:case 3:case 4:case 5:break;default:j=3}var L=D;D=j;try{return X()}finally{D=L}},x.unstable_scheduleCallback=function(j,X,L){var pl=x.unstable_now();switch(typeof L=="object"&&L!==null?(L=L.delay,L=typeof L=="number"&&0<L?pl+L:pl):L=pl,j){case 1:var ml=-1;break;case 2:ml=250;break;case 5:ml=1073741823;break;case 4:ml=1e4;break;default:ml=5e3}return ml=L+ml,j={id:A++,callback:X,priorityLevel:j,startTime:L,expirationTime:ml,sortIndex:-1},L>pl?(j.sortIndex=L,O(W,j),T(Q)===null&&j===T(W)&&(vl?(Bl(ll),ll=-1):vl=!0,ql(Il,L-pl))):(j.sortIndex=ml,O(Q,j),U||w||(U=!0,Pl||(Pl=!0,rt()))),j},x.unstable_shouldYield=Tt,x.unstable_wrapCallback=function(j){var X=D;return function(){var L=D;D=X;try{return j.apply(this,arguments)}finally{D=L}}}})(Os)),Os}var s0;function Ev(){return s0||(s0=1,zs.exports=_v()),zs.exports}var js={exports:{}},Wl={};/**
|
||||
* @license React
|
||||
* react-dom.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var o0;function zv(){if(o0)return Wl;o0=1;var x=As();function O(A){var S="https://react.dev/errors/"+A;if(1<arguments.length){S+="?args[]="+encodeURIComponent(arguments[1]);for(var D=2;D<arguments.length;D++)S+="&args[]="+encodeURIComponent(arguments[D])}return"Minified React error #"+A+"; visit "+S+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function T(){}var d={d:{f:T,r:function(){throw Error(O(522))},D:T,C:T,L:T,m:T,X:T,S:T,M:T},p:0,findDOMNode:null},E=Symbol.for("react.portal"),H=Symbol.for("react.recoverable"),J=Symbol.for("react.optimistic_key");function K(A,S,D){var w=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:E,key:w==null?null:w===J?J:""+w,children:A,containerInfo:S,implementation:D}}var Q=x.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function W(A,S){if(A==="font")return"";if(typeof S=="string")return S==="use-credentials"?S:""}return Wl.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=d,Wl.browser=function(A){return{$$typeof:H,_reason:A}},Wl.createPortal=function(A,S){var D=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!S||S.nodeType!==1&&S.nodeType!==9&&S.nodeType!==11)throw Error(O(299));return K(A,S,null,D)},Wl.flushSync=function(A){var S=Q.T,D=d.p;try{if(Q.T=null,d.p=2,A)return A()}finally{Q.T=S,d.p=D,d.d.f()}},Wl.preconnect=function(A,S){typeof A=="string"&&(S?(S=S.crossOrigin,S=typeof S=="string"?S==="use-credentials"?S:"":void 0):S=null,d.d.C(A,S))},Wl.prefetchDNS=function(A){typeof A=="string"&&d.d.D(A)},Wl.preinit=function(A,S){if(typeof A=="string"&&S&&typeof S.as=="string"){var D=S.as,w=W(D,S.crossOrigin),U=typeof S.integrity=="string"?S.integrity:void 0,vl=typeof S.fetchPriority=="string"?S.fetchPriority:void 0;D==="style"?d.d.S(A,typeof S.precedence=="string"?S.precedence:void 0,{crossOrigin:w,integrity:U,fetchPriority:vl}):D==="script"&&d.d.X(A,{crossOrigin:w,integrity:U,fetchPriority:vl,nonce:typeof S.nonce=="string"?S.nonce:void 0})}},Wl.preinitModule=function(A,S){if(typeof A=="string")if(typeof S=="object"&&S!==null){if(S.as==null||S.as==="script"){var D=W(S.as,S.crossOrigin);d.d.M(A,{crossOrigin:D,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0})}}else S==null&&d.d.M(A)},Wl.preload=function(A,S){if(typeof A=="string"&&typeof S=="object"&&S!==null&&typeof S.as=="string"){var D=S.as,w=W(D,S.crossOrigin);d.d.L(A,D,{crossOrigin:w,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,type:typeof S.type=="string"?S.type:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0,referrerPolicy:typeof S.referrerPolicy=="string"?S.referrerPolicy:void 0,imageSrcSet:typeof S.imageSrcSet=="string"?S.imageSrcSet:void 0,imageSizes:typeof S.imageSizes=="string"?S.imageSizes:void 0,media:typeof S.media=="string"?S.media:void 0})}},Wl.preloadModule=function(A,S){if(typeof A=="string")if(S){var D=W(S.as,S.crossOrigin);d.d.m(A,{as:typeof S.as=="string"&&S.as!=="script"?S.as:void 0,crossOrigin:D,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0})}else d.d.m(A)},Wl.requestFormReset=function(A){d.d.r(A)},Wl.unstable_batchedUpdates=function(A,S){return A(S)},Wl.useFormState=function(A,S,D){return Q.H.useFormState(A,S,D)},Wl.useFormStatus=function(){return Q.H.useHostTransitionStatus()},Wl.version="19.3.1",Wl}var r0;function Ov(){if(r0)return js.exports;r0=1;function x(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(x)}catch(O){console.error(O)}}return x(),js.exports=zv(),js.exports}/**
|
||||
* @license React
|
||||
* react-dom-client.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var d0;function jv(){if(d0)return cn;d0=1;var x=Ev(),O=As(),T=Ov();function d(l){var t="https://react.dev/errors/"+l;if(1<arguments.length){t+="?args[]="+encodeURIComponent(arguments[1]);for(var e=2;e<arguments.length;e++)t+="&args[]="+encodeURIComponent(arguments[e])}return"Minified React error #"+l+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function E(l){return!(!l||l.nodeType!==1&&l.nodeType!==9&&l.nodeType!==11)}function H(l){for(var t=l,e=t;e&&!e.alternate;)t=e,(t.flags&4098)!==0&&(l=t.return),e=t.return;for(;t.return;)t=t.return;return t.tag===3?l:null}function J(l){if(l.tag===13){var t=l.memoizedState;if(t===null&&(l=l.alternate,l!==null&&(t=l.memoizedState)),t!==null)return t.dehydrated}return null}function K(l){if(l.tag===31){var t=l.memoizedState;if(t===null&&(l=l.alternate,l!==null&&(t=l.memoizedState)),t!==null)return t.dehydrated}return null}function Q(l){if(H(l)!==l)throw Error(d(188))}function W(l){var t=l.alternate;if(!t){if(t=H(l),t===null)throw Error(d(188));return t!==l?null:l}for(var e=l,a=t;;){var u=e.return;if(u===null)break;var n=u.alternate;if(n===null){if(a=u.return,a!==null){e=a;continue}break}if(u.child===n.child){for(n=u.child;n;){if(n===e)return Q(u),l;if(n===a)return Q(u),t;n=n.sibling}throw Error(d(188))}if(e.return!==a.return)e=u,a=n;else{for(var c=!1,i=u.child;i;){if(i===e){c=!0,e=u,a=n;break}if(i===a){c=!0,a=u,e=n;break}i=i.sibling}if(!c){for(i=n.child;i;){if(i===e){c=!0,e=n,a=u;break}if(i===a){c=!0,a=n,e=u;break}i=i.sibling}if(!c)throw Error(d(189))}}if(e.alternate!==a)throw Error(d(190))}if(e.tag!==3)throw Error(d(188));return e.stateNode.current===e?l:t}function A(l){var t=l.tag;if(t===5||t===26||t===27||t===6)return l;for(l=l.child;l!==null;){if(t=A(l),t!==null)return t;l=l.sibling}return null}function S(l,t,e,a,u,n){for(;l!==null;){if((l.tag===5||l.tag===27||l.tag===6)&&e(l,a,u,n)||(l.tag!==22||l.memoizedState===null)&&(t||l.tag!==5&&l.tag!==27)&&S(l.child,t,e,a,u,n))return!0;l=l.sibling}return!1}function D(l){for(l=l.return;l!==null;){if(l.tag===3||l.tag===5||l.tag===27)return l;l=l.return}return null}function w(l){var t=!1;for(l=l.return;l!==null&&(l.tag===4&&(t=!0),!(l.tag===3||l.tag===5||l.tag===27));)l=l.return;return t}function U(l){var t=[null,null],e=D(l);return e===null||vl(t,l,e.child,{foundSelf:!1}),t}function vl(l,t,e,a){for(;e!==null;){if(e===t)a.foundSelf=!0;else if(e.tag===5||e.tag===27||e.tag===6){if(a.foundSelf)return l[1]=e,!0;l[0]=e}else if((e.tag!==22||e.memoizedState===null)&&vl(l,t,e.child,a))return!0;e=e.sibling}return!1}function P(l){switch(l.tag){case 5:case 27:case 6:return l.stateNode;case 3:return l.stateNode.containerInfo;default:throw Error(d(559))}}var jl=null,Bl=null;function I(l,t,e){return l===e?!0:l===t?(jl=l,!0):!1}function il(l,t,e){return l===e?(Bl=l,!1):l===t?(Bl!==null&&(jl=l),!0):!1}function Il(l){if(l===null)return null;do l=l===null?null:l.return;while(l&&l.tag!==5&&l.tag!==27&&l.tag!==3);return l||null}function Pl(l,t,e){for(var a=0,u=l;u;u=e(u))a++;u=0;for(var n=t;n;n=e(n))u++;for(;0<a-u;)l=e(l),a--;for(;0<u-a;)t=e(t),u--;for(;a--;){if(l===t||t!==null&&l===t.alternate)return l;l=e(l),t=e(t)}return null}var ll=Object.assign,ol=Symbol.for("react.element"),Qt=Symbol.for("react.transitional.element"),Tt=Symbol.for("react.portal"),_t=Symbol.for("react.fragment"),rt=Symbol.for("react.strict_mode"),be=Symbol.for("react.profiler"),$e=Symbol.for("react.consumer"),ql=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),X=Symbol.for("react.suspense"),L=Symbol.for("react.suspense_list"),pl=Symbol.for("react.memo"),ml=Symbol.for("react.lazy"),Rt=Symbol.for("react.activity"),te=Symbol.for("react.legacy_hidden"),We=Symbol.for("react.memo_cache_sentinel"),r=Symbol.for("react.view_transition"),_=Symbol.for("react.recoverable"),B=Symbol.iterator;function q(l){return l===null||typeof l!="object"?null:(l=B&&l[B]||l["@@iterator"],typeof l=="function"?l:null)}var cl=Symbol.for("react.client.reference");function fl(l){if(l==null)return null;if(typeof l=="function")return l.$$typeof===cl?null:l.displayName||l.name||null;if(typeof l=="string")return l;switch(l){case _t:return"Fragment";case be:return"Profiler";case rt:return"StrictMode";case X:return"Suspense";case L:return"SuspenseList";case Rt:return"Activity";case r:return"ViewTransition"}if(typeof l=="object")switch(l.$$typeof){case Tt:return"Portal";case ql:return l.displayName||"Context";case $e:return(l._context.displayName||"Context")+".Consumer";case j:var t=l.render;return l=l.displayName,l||(l=t.displayName||t.name||"",l=l!==""?"ForwardRef("+l+")":"ForwardRef"),l;case pl:return t=l.displayName||null,t!==null?t:fl(l.type)||"Memo";case ml:t=l._payload,l=l._init;try{return fl(l(t))}catch{}}return null}var rl=Array.isArray,R=O.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Z=T.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ee={pending:!1,data:null,method:null,action:nLine truncated
|
||||
at`)?" (<anonymous>)":-1<e.stack.indexOf("@")?"@unknown:0:0":""}return`
|
||||
`+Lc+l+Us}var Zc=!1;function Vc(l,t){if(!l||Zc)return"";Zc=!0;var e=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var a={DetermineComponentFrameRoot:function(){try{if(t){var N=function(){throw Error()};if(Object.defineProperty(N.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(N,[])}catch(z){var m=z}Reflect.construct(l,[],N)}else{try{N.call()}catch(z){m=z}N=!1;try{var g=Object.getOwnPropertyDescriptor(l.prototype,"props");Object.defineProperty(l.prototype,"props",{configurable:!0,set:function(){throw Error()}}),N=!0,new l}finally{N&&(g!==void 0?Object.defineProperty(l.prototype,"props",g):delete l.prototype.props)}}}else{try{throw Error()}catch(z){m=z}(N=l())&&typeof N.catch=="function"&&N.catch(function(){})}}catch(z){if(z&&m&&typeof z.stack=="string")return[z.stack,m.stack]}return[null,null]}};a.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var u=Object.getOwnPropertyDescriptor(a.DetermineComponentFrameRoot,"name");u&&u.configurable&&Object.defineProperty(a.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var n=a.DetermineComponentFrameRoot(),c=n[0],i=n[1];if(c&&i){var s=c.split(`
|
||||
`),v=i.split(`
|
||||
`);for(u=a=0;a<s.length&&!s[a].includes("DetermineComponentFrameRoot");)a++;for(;u<v.length&&!v[u].includes("DetermineComponentFrameRoot");)u++;if(a===s.length||u===v.length)for(a=s.length-1,u=v.length-1;1<=a&&0<=u&&s[a]!==v[u];)u--;for(;1<=a&&0<=u;a--,u--)if(s[a]!==v[u]){if(a!==1||u!==1)do if(a--,u--,0>u||s[a]!==v[u]){var b=`
|
||||
`+s[a].replace(" at new "," at ");return l.displayName&&b.includes("<anonymous>")&&(b=b.replace("<anonymous>",l.displayName)),b}while(1<=a&&0<=u);break}}}finally{Zc=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Se(e):""}function E0(l,t){switch(l.tag){case 26:case 27:case 5:return Se(l.type);case 16:return Se("Lazy");case 13:return l.child!==t&&t!==null?Se("Suspense Fallback"):Se("Suspense");case 19:return Se("SuspenseList");case 0:case 15:return Vc(l.type,!1);case 11:return Vc(l.type.render,!1);case 1:return Vc(l.type,!0);case 31:return Se("Activity");case 30:return Se("ViewTransition");default:return""}}function Rs(l){try{var t="",e=null;do t+=E0(l,e),e=l,l=l.return;while(l);return t}catch(a){return`
|
||||
Error generating stack: `+a.message+`
|
||||
`+a.stack}}var Kc=Object.prototype.hasOwnProperty,Jc=x.unstable_scheduleCallback,kc=x.unstable_cancelCallback,z0=x.unstable_shouldYield,O0=x.unstable_requestPaint,dt=x.unstable_now,j0=x.unstable_getCurrentPriorityLevel,Hs=x.unstable_ImmediatePriority,Ys=x.unstable_UserBlockingPriority,rn=x.unstable_NormalPriority,A0=x.unstable_LowPriority,Bs=x.unstable_IdlePriority,C0=x.log,M0=x.unstable_setDisableYieldValue,du=null,mt=null;function pe(l){if(typeof C0=="function"&&M0(l),mt&&typeof mt.setStrictMode=="function")try{mt.setStrictMode(du,l)}catch{}}var ht=Math.clz32?Math.clz32:R0,D0=Math.log,U0=Math.LN2;function R0(l){return l>>>=0,l===0?32:31-(D0(l)/U0|0)|0}var dn=256,mn=262144,hn=4194304;function Fe(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&-l;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 vn(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var u=0,n=l.suspendedLanes,c=l.pingedLanes;l=l.warmLanes;var i=a&134217727;return i!==0?(a=i&~n,a!==0?u=Fe(a):(c&=i,c!==0?u=Fe(c):e||(e=i&~l,e!==0&&(u=Fe(e))))):(i=a&~n,i!==0?u=Fe(i):c!==0?u=Fe(c):e||(e=a&~l,e!==0&&(u=Fe(e)))),u===0?0:t!==0&&t!==u&&(t&n)===0&&(n=u&-u,e=t&-t,n>=e||n===32&&(e&4194048)!==0)?t:u}function mu(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function qs(l,t){(t&8)!==0&&(t|=t&32);var e=l.entangledLanes;if(e!==0)for(l=l.entanglements,e&=t;0<e;){var a=31-ht(e),u=1<<a;t|=l[a],e&=~u}return t}function H0(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 ws(){var l=hn;return hn<<=1,(hn&62914560)===0&&(hn=4194304),l}function $c(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function hu(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Y0(l,t,e,a,u,n){var c=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var i=l.entanglements,s=l.expirationTimes,v=l.hiddenUpdates;for(e=c&~e;0<e;){var b=31-ht(e),N=1<<b;i[b]=0,s[b]=-1;var m=v[b];if(m!==null)for(v[b]=null,b=0;b<m.length;b++){var g=m[b];g!==null&&(g.lane&=-536870913)}e&=~N}a!==0&&Gs(l,a,0),n!==0&&u===0&&l.tag!==0&&(l.suspendedLanes|=n&~(c&~t))}function Gs(l,t,e){l.pendingLanes|=t,l.suspendedLanes&=~t;var a=31-ht(t);l.entangledLanes|=t,l.entanglements[a]=l.entanglements[a]|1073741824|e&261930}function Qs(l,t){var e=l.entangledLanes|=t;for(l=l.entanglements;e;){var a=31-ht(e),u=1<<a;u&t|l[a]&t&&(l[a]|=t),e&=~u}}function Xs(l,t){var e=t&-t;return e=(e&42)!==0?1:Wc(e),(e&(l.suspendedLanes|t))!==0?0:e}function Wc(l){switch(l){case 2:l=1;break;case 8:l=4;break;case 32:l=16;break;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:case 4194304:case 8388608:case 16777216:case 33554432:l=128;break;case 268435456:l=134217728;break;default:l=0}return l}function Fc(l){return l&=-l,2<l?8<l?(l&134217727)!==0?32:268435456:8:2}function Ls(){var l=Z.p;return l!==0?l:(l=window.event,l===void 0?32:Fm(l.type))}function Zs(l,t){var e=Z.p;try{return Z.p=l,t()}finally{Z.p=e}}var ae=Math.random().toString(36).slice(2),Zl="__reactFiber$"+ae,nt="__reactProps$"+ae,Na="__reactContainer$"+ae,Vs="__reactEvents$"+ae,B0="__reactListeners$"+ae,q0="__reactHandles$"+ae,Ks="__reactResources$"+ae,vu="__reactMarker$"+ae,yn="__reactLoad$"+ae;function gn(l){delete l[Zl],delete l[nt],delete l[B0],delete l[q0]}function Ie(l){var t;if(t=l[Zl])return t;for(var e=l.parentNode;e;){if(t=e[Na]||e[Zl]){if(e=t.alternate,t.child!==null||e!==null&&e.child!==null)for(l=Mm(l);l!==null;){if(e=l[Zl])return e;l=Mm(l)}return t}l=e,e=l.parentNode}return null}function Ta(l){if(l=l[Zl]||l[Na]){var t=l.tag;if(t===5||t===6||t===13||t===31||t===26||t===27||t===3)return l}return null}function yu(l){var t=l.tag;if(t===5||t===26||t===27||t===6)return l.stateNode;throw Error(d(33))}function _a(l){var t=l[Ks];return t||(t=l[Ks]={hoistableStyles:new Map,hoistableScripts:new Map}),t}function wl(l){l[vu]=!0}function Js(l){l[yn]=void 0}var ks=new Set,$s={};function Pe(l,t){Ea(l,t),Ea(l+"Capture",t)}function
Line truncated
|
||||
`).replace(E1,"")}function rm(l,t){return t=om(t),om(l)===t}function bl(l,t,e,a,u,n){switch(e){case"children":if(typeof a=="string")t==="body"||t==="textarea"&&a===""||Oa(l,a);else if(typeof a=="number"||typeof a=="bigint")t!=="body"&&Oa(l,""+a);else return;break;case"className":xn(l,"class",a);break;case"tabIndex":xn(l,"tabindex",a);break;case"dir":case"role":case"viewBox":case"width":case"height":xn(l,e,a);break;case"style":no(l,a,n);return;case"data":if(t!=="object"){xn(l,"data",a);break}case"src":case"href":if(a===""&&(t!=="a"||e!=="href")){l.removeAttribute(e);break}if(a==null||typeof a=="function"||typeof a=="symbol"||typeof a=="boolean"){l.removeAttribute(e);break}a=Sn(a),l.setAttribute(e,a);break;case"action":case"formAction":if(typeof a=="function"){l.setAttribute(e,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof n=="function"&&(e==="formAction"?(t!=="input"&&bl(l,t,"name",u.name,u,null),bl(l,t,"formEncType",u.formEncType,u,null),bl(l,t,"formMethod",u.formMethod,u,null),bl(l,t,"formTarget",u.formTarget,u,null)):(bl(l,t,"encType",u.encType,u,null),bl(l,t,"method",u.method,u,null),bl(l,t,"target",u.target,u,null)));if(a==null||typeof a=="symbol"||typeof a=="boolean"){l.removeAttribute(e);break}a=Sn(a),l.setAttribute(e,a);break;case"onClick":a!=null&&(l.onclick=Zt);return;case"onScroll":a!=null&&el("scroll",l);return;case"onScrollEnd":a!=null&&el("scrollend",l);return;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(d(61));if(e=a.__html,e!=null){if(u.children!=null)throw Error(d(60));(n!=null?n.__html:void 0)!==e&&(l.innerHTML=e)}}break;case"multiple":l.multiple=a&&typeof a!="function"&&typeof a!="symbol";break;case"muted":l.muted=a&&typeof a!="function"&&typeof a!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(a==null||typeof a=="function"||typeof a=="boolean"||typeof a=="symbol"){l.removeAttribute("xlink:href");break}e=Sn(a),l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",e);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":a!=null&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,a):l.removeAttribute(e);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"credentialless":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":a&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,""):l.removeAttribute(e);break;case"capture":case"download":a===!0?l.setAttribute(e,""):a!==!1&&a!=null&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,a):l.removeAttribute(e);break;case"cols":case"rows":case"size":case"span":a!=null&&typeof a!="function"&&typeof a!="symbol"&&!isNaN(a)&&1<=a?l.setAttribute(e,a):l.removeAttribute(e);break;case"rowSpan":case"start":a==null||typeof a=="function"||typeof a=="symbol"||isNaN(a)?l.removeAttribute(e):l.setAttribute(e,a);break;case"popover":el("beforetoggle",l),el("toggle",l),bn(l,"popover",a);break;case"xlinkActuate":ue(l,"http://www.w3.org/1999/xlink","xlink:actuate",a);break;case"xlinkArcrole":ue(l,"http://www.w3.org/1999/xlink","xlink:arcrole",a);break;case"xlinkRole":ue(l,"http://www.w3.org/1999/xlink","xlink:role",a);break;case"xlinkShow":ue(l,"http://www.w3.org/1999/xlink","xlink:show",a);break;case"xlinkTitle":ue(l,"http://www.w3.org/1999/xlink","xlink:title",a);break;case"xlinkType":ue(l,"http://www.w3.org/1999/xlink","xlink:type",a);break;case"xmlBase":ue(l,"http://www.w3.org/XML/1998/namespace","xml:base",a);break;case"xmlLang":ue(l,"http://www.w3.org/XML/1998/namespace","xml:lang",a);break;case"xmlSpace":ue(l,"http://www.w3.org/XML/1998/namespace","xml:space",a);break;case"is":bn(l,"is",a);break;case"innerText":case"textContent":return;default:if(!(2<e.length)||e[0]!=="o"&&e[0]!=="O"||e[1]!=="n"&&e[1]!=="N")e=Z0.get(e)||e,bn(l,e,a);else return}sl=!0}function ls(l,t,e,a,u,n){switch(e){case"style":no(l,a,n);return;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(d(61));if(e=a.__html,e!=null){if(u.children!=null)throw Error(d(60));(n!=null?n.__html:void 0)!==e&&(l.innerHTML=e)}}break;case"children":if(typeof a=="string")Oa(l,a);else if(typeof a=="number"||typeof a=="bigint")Oa(l,""+a);else return;break;case"onScroll":a!=null&&el("scroll",l);return;case"onScrollEnd":a!=null&&el("scro
Line truncated
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Qv=x=>x.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),S0=(...x)=>x.filter((O,T,d)=>!!O&&O.trim()!==""&&d.indexOf(O)===T).join(" ").trim();/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/var Xv={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Lv=xl.forwardRef(({color:x="currentColor",size:O=24,strokeWidth:T=2,absoluteStrokeWidth:d,className:E="",children:H,iconNode:J,...K},Q)=>xl.createElement("svg",{ref:Q,...Xv,width:O,height:O,stroke:x,strokeWidth:d?Number(T)*24/Number(O):T,className:S0("lucide",E),...K},[...J.map(([W,A])=>xl.createElement(W,A)),...Array.isArray(H)?H:[H]]));/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Fl=(x,O)=>{const T=xl.forwardRef(({className:d,...E},H)=>xl.createElement(Lv,{ref:H,iconNode:O,className:S0(`lucide-${Qv(x)}`,d),...E}));return T.displayName=`${x}`,T};/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Zv=[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]],p0=Fl("BookOpen",Zv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Vv=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],N0=Fl("Check",Vv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Kv=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],Jv=Fl("EyeOff",Kv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const kv=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],$v=Fl("Eye",kv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Wv=[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]],y0=Fl("KeyRound",Wv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Fv=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],Iv=Fl("Layers",Fv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Pv=[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1",key:"1g98yp"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1",key:"6d4xhi"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1",key:"nxv5o0"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1",key:"1bb6yr"}]],ly=Fl("LayoutGrid",Pv);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ty=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],ey=Fl("Lock",ty);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ay=[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z",key:"a7tn18"}]],uy=Fl("Moon",ay);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ny=[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z",key:"12rzf8"}]],cy=Fl("Palette",ny);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const iy=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M9 21V9",key:"1oto5p"}]],fy=Fl("PanelsTopLeft",iy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const sy=[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]],Cs=Fl("Search",sy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const oy=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],ry=Fl("ShieldCheck",oy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const dy=[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",key:"4pj2yx"}],["path",{d:"M20 3v4",key:"1olli1"}],["path",{d:"M22 5h-4",key:"1gvqau"}],["path",{d:"M4 17v2",key:"vumght"}],["path",{d:"M5 18H3",key:"zchphs"}]],my=Fl("Sparkles",dy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const hy=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],vy=Fl("Sun",hy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const yy=[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]],Ms=Fl("Terminal",yy);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const gy=[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]],by=Fl("User",gy),xy=[{id:"auto",label:"智能路由"},{id:"edge443",label:"443 免端口"},{id:"home10443",label:"10443 家宽"},{id:"lan",label:"LAN 局域网"}],Sy=()=>{const{theme:x,resolvedTheme:O,routeMode:T,viewMode:d,telemetry:E,setTheme:H,toggleTheme:J,setRouteMode:K,setViewMode:Q,setShowAgyModal:W,setShowCmdPalette:A}=ke();return f.jsxs(f.Fragment,{children:[f.jsx("header",{className:"border-b hl-border sticky top-0 z-30 backdrop-blur-md",style:{backgroundColor:"color-mix(in srgb, var(--bg-card) 88%, transparent)"},children:f.jsxs("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-14 flex items-center justify-between gap-4",children:[f.jsxs("div",{className:"flex items-center gap-4 shrink-0",children:[f.jsxs("div",{onClick:()=>Q("dashboard"),className:"flex items-center gap-2.5 cursor-pointer",children:[f.jsx("img",{src:"https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/apple.png",alt:"Mac mini",className:"w-6 h-6 rounded"}),f.jsx("span",{className:"font-semibold text-sm tracking-tight",children:"HomeLab"}),f.jsx("span",{className:"w-2 h-2 rounded-full",style:{backgroundColor:"var(--success)"},title:"全屋 4 节点在线"})]}),f.jsx("div",{className:"h-4 w-[1px] hl-muted"}),f.jsxs("nav",{className:"flex items-center gap-1 text-xs",children:[f.jsxs("button",{onClick:()=>Q("dashboard"),className:"px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer",style:d==="dashboard"?{backgroundColor:"var(--bg-muted)",color:"var(--text-main)"}:{color:"var(--text-muted)"},children:[f.jsx(ly,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"中控台"})]}),f.jsxs("button",{onClick:()=>Q("storybook"),className:"px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer",style:d==="storybook"?{backgroundColor:"var(--bg-muted)",color:"var(--text-main)"}:{color:"var(--text-muted)"},children:[f.jsx(p0,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"Storybook 设计规范"})]})]})]}),f.jsxs("div",{className:"flex items-center gap-2.5 shrink-0 ml-auto",children:[f.jsxs("button",{onClick:()=>A(!0),className:"hl-btn-outline px-3 py-1.5 text-xs flex items-center gap-3 cursor-pointer",title:"按 Cmd+K 唤起全局命令面板",children:[f.jsxs("span",{className:"flex items-center gap-1.5",style:{color:"var(--text-muted)"},children:[f.jsx(Cs,{className:"w-3.5 h-3.5"}),f.jsx("span",{className:"hidden sm:inline",children:"搜索服务或指令..."})]}),f.jsx("kbd",{className:"px-1.5 py-0.5 text-[10px] font-mono-num rounded hl-muted",style:{color:"var(--text-muted)"},children:"⌘K"})]}),f.jsxs("button",{onClick:()=>W(!0),className:"hl-btn-primary px-3 py-1.5 text-xs flex items-center gap-1.5 cursor-pointer",children:[f.jsx(Ms,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"AGY 终端"})]}),f.jsxs("div",{className:"flex items-center p-0.5 rounded-lg hl-muted border hl-border text-xs",children:[f.jsx("button",{onClick:J,className:"px-2.5 py-1 rounded-md font-medium transition-all flex items-center gap-1.5 cursor-pointer",style:{backgroundColor:"var(--bg-card)",color:"var(--text-main)",boxShadow:"0 1px 2px rgba(0,0,0,0.08)"},title:"点击切换深色 / 浅色主题(默认跟随系统)",children:O==="dark"?f.jsxs(f.Fragment,{children:[f.jsx(uy,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"深色"})]}):f.jsxs(f.Fragment,{children:[f.jsx(vy,{className:"w-3.5 h-3.5"}),f.jsx("span",{children:"浅色"})]})}),x!=="system"&&f.jsx("button",{onClick:()=>H("system"),className:"px-2 py-1 rounded-md text-[11px] transition-all cursor-pointer",style:{color:"var(--text-muted)"},title:"恢复跟随设备系统深浅色自动切换",children:"自动"})]})]})]})}),d==="dashboard"&&f.jsx("div",{className:"border-b hl-border",style:{backgroundColor:"var(--bg-card)"},children:f.jsxs("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex flex-wrap items-center justify-between gap-3",children:[f.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs font-mono-num",children:[f.jsxs("div",{className:"hl-pill px-2.5 py-1 flex items-center gap-2",children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"M6 CPU"}),f.jsx("div",{className:"w-12 h-1.5 rounded-full hl-muted overflow-hidden",children:f.jsx("div",{className:"h-full hl-bar-fill",style:{width:`${Math.max(5,E.mini.cpu_pct)}%`}})}),f.jsxs("span",{className:"font-medium",children:[E.mini.cpu_pct,"%"]})]}),f.jsxs("div",{className:"hl-pill px-2.5 py-1 flex items-center gap-2",children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"RAM"}),f.jsx("div",{className:"w-12 h-1.5 rounded-full hl-muted overflow-hidden",children:f.jsx("div",{className:"h-full hl-bar-fill",style:{width:`${Math.max(5,E.mini.mem_pct)}%`}})}),f.jsxs("span",{className:"font-medium",children:[E.mini.mem_used_gb,"G"]})]}),f.jsxs("div",{className:"hl-pill px-2.Line truncated
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
(function(){const A=document.createElement("link").relList;if(A&&A.supports&&A.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))d(O);new MutationObserver(O=>{for(const q of O)if(q.type==="childList")for(const al of q.addedNodes)al.tagName==="LINK"&&al.rel==="modulepreload"&&d(al)}).observe(document,{childList:!0,subtree:!0});function N(O){const q={};return O.integrity&&(q.integrity=O.integrity),O.referrerPolicy&&(q.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?q.credentials="include":O.crossOrigin==="anonymous"?q.credentials="omit":q.credentials="same-origin",q}function d(O){if(O.ep)return;O.ep=!0;const q=N(O);fetch(O.href,q)}})();function m0(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x.default:x}var Ns={exports:{}},nn={};/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var t0;function b1(){if(t0)return nn;t0=1;var x=Symbol.for("react.transitional.element"),A=Symbol.for("react.fragment");function N(d,O,q){var al=null;if(q!==void 0&&(al=""+q),O.key!==void 0&&(al=""+O.key),"key"in O){q={};for(var W in O)W!=="key"&&(q[W]=O[W])}else q=O;return O=q.ref,{$$typeof:x,type:d,key:al,ref:O!==void 0?O:null,props:q}}return nn.Fragment=A,nn.jsx=N,nn.jsxs=N,nn}var e0;function S1(){return e0||(e0=1,Ns.exports=b1()),Ns.exports}var s=S1(),Es={exports:{}},V={};/**
|
||||
* @license React
|
||||
* react.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var a0;function x1(){if(a0)return V;a0=1;var x=Symbol.for("react.transitional.element"),A=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),q=Symbol.for("react.consumer"),al=Symbol.for("react.context"),W=Symbol.for("react.forward_ref"),k=Symbol.for("react.suspense"),F=Symbol.for("react.memo"),D=Symbol.for("react.lazy"),S=Symbol.for("react.activity"),_=Symbol.for("react.view_transition"),B=Symbol.iterator;function G(r){return r===null||typeof r!="object"?null:(r=B&&r[B]||r["@@iterator"],typeof r=="function"?r:null)}var $={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},ul=Object.assign,Bl={};function nt(r,E,H){this.props=r,this.context=E,this.refs=Bl,this.updater=H||$}nt.prototype.isReactComponent={},nt.prototype.setState=function(r,E){if(typeof r!="object"&&typeof r!="function"&&r!=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,r,E,"setState")},nt.prototype.forceUpdate=function(r){this.updater.enqueueForceUpdate(this,r,"forceUpdate")};function ke(){}ke.prototype=nt.prototype;function Bt(r,E,H){this.props=r,this.context=E,this.refs=Bl,this.updater=H||$}var Gt=Bt.prototype=new ke;Gt.constructor=Bt,ul(Gt,nt.prototype),Gt.isPureReactComponent=!0;var ct=Array.isArray;function I(){}var sl={H:null,A:null,T:null,S:null},wt=Object.prototype.hasOwnProperty;function St(r,E,H){var Y=H.ref;return{$$typeof:x,type:r,key:E,ref:Y!==void 0?Y:null,props:H}}function xt(r,E){return St(r.type,E,r.props)}function it(r){return typeof r=="object"&&r!==null&&r.$$typeof===x}function ge(r){var E={"=":"=0",":":"=2"};return"$"+r.replace(/[=:]/g,function(H){return E[H]})}var $e=/\/+/g;function Ul(r,E){return typeof r=="object"&&r!==null&&r.key!=null?ge(""+r.key):E.toString(36)}function M(r){switch(r.status){case"fulfilled":return r.value;case"rejected":throw r.reason;default:switch(typeof r.status=="string"?r.then(I,I):(r.status="pending",r.then(function(E){r.status==="pending"&&(r.status="fulfilled",r.value=E)},function(E){r.status==="pending"&&(r.status="rejected",r.reason=E)})),r.status){case"fulfilled":return r.value;case"rejected":throw r.reason}}throw r}function Q(r,E,H,Y,cl){var il=typeof r;(il==="undefined"||il==="boolean")&&(r=null);var ol=!1;if(r===null)ol=!0;else switch(il){case"bigint":case"string":case"number":ol=!0;break;case"object":switch(r.$$typeof){case x:case A:ol=!0;break;case D:return ol=r._init,Q(ol(r._payload),E,H,Y,cl)}}if(ol)return cl=cl(r),ol=Y===""?"."+Ul(r,0):Y,ct(cl)?(H="",ol!=null&&(H=ol.replace($e,"$&/")+"/"),Q(cl,E,H,"",function(te){return te})):cl!=null&&(it(cl)&&(cl=xt(cl,H+(cl.key==null||r&&r.key===cl.key?"":(""+cl.key).replace($e,"$&/")+"/")+ol)),E.push(cl)),1;ol=0;var U=Y===""?".":Y+":";if(ct(r))for(var Z=0;Z<r.length;Z++)Y=r[Z],il=U+Ul(Y,Z),ol+=Q(Y,E,H,il,cl);else if(Z=G(r),typeof Z=="function")for(r=Z.call(r),Z=0;!(Y=r.next()).done;)Y=Y.value,il=U+Ul(Y,Z++),ol+=Q(Y,E,H,il,cl);else if(il==="object"){if(typeof r.then=="function")return Q(M(r),E,H,Y,cl);throw E=String(r),Error("Objects are not valid as a React child (found: "+(E==="[object Object]"?"object with keys {"+Object.keys(r).join(", ")+"}":E)+"). If you meant to render a collection of children, use an array instead.")}return ol}function X(r,E,H){if(r==null)return r;var Y=[],cl=0;return Q(r,Y,"","",function(il){return E.call(H,il,cl++)}),Y}function bl(r){if(r._status===-1){var E=r._result,H=E();H.then(function(Y){(r._status===0||r._status===-1)&&(r._status=1,r._result=Y,H.status===void 0&&(H.status="fulfilled",H.value=Y))},function(Y){(r._status===0||r._status===-1)&&(r._status=2,r._result=Y,H.status===void 0&&(H.status="rejected",H.reason=Y))}),r._status===-1&&(r._status=0,r._result=H)}if(r._status===1)return r._result.default;throw r._result}var dl=typeof reportError=="function"?reportError:function(r){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var E=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof r=="object"&&r!==null&&typeof r.message=="string"?String(r.message):String(r),error:r});if(!window.dispatchEvent(E))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",r);return}console.error(r)};function jt(r){var E=sl.T,H={};H.types=E!==null?E.types:null,sl.T=H;try{var Y=r(),cl=sl.S;cl!==null&&cl(H,Y),typeof Y=="object"&&Y!==null&&typeof Y.then=="function"&&Y.then(I,dl)}catch(il){dl(il)}finally{E!==null&&H.types!==null&&(E.types=H.types),sl.T=E}}function le(r){var E=sl.T;if(E!==null){var H=E.types;H===null?E.types=[r]:H.indexOf(r)===-1&&H.push(r)}else jt(le.bind(null,r))}var We={map:X,forEach:function(r,E,H){X(r,function(){E.apply(this,arguments)},H)},count:function(r){var E=0;return X(r,function(){E++}),E},toArray:function(r){return X(r,function(E){return E})||[]},only:function(r){if(!itLine truncated
|
||||
* @license React
|
||||
* scheduler.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var n0;function p1(){return n0||(n0=1,(function(x){function A(M,Q){var X=M.length;M.push(Q);l:for(;0<X;){var bl=X-1>>>1,dl=M[bl];if(0<O(dl,Q))M[bl]=Q,M[X]=dl,X=bl;else break l}}function N(M){return M.length===0?null:M[0]}function d(M){if(M.length===0)return null;var Q=M[0],X=M.pop();if(X!==Q){M[0]=X;l:for(var bl=0,dl=M.length,jt=dl>>>1;bl<jt;){var le=2*(bl+1)-1,We=M[le],r=le+1,E=M[r];if(0>O(We,X))r<dl&&0>O(E,We)?(M[bl]=E,M[r]=X,bl=r):(M[bl]=We,M[le]=X,bl=le);else if(r<dl&&0>O(E,X))M[bl]=E,M[r]=X,bl=r;else break l}}return Q}function O(M,Q){var X=M.sortIndex-Q.sortIndex;return X!==0?X:M.id-Q.id}if(x.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var q=performance;x.unstable_now=function(){return q.now()}}else{var al=Date,W=al.now();x.unstable_now=function(){return al.now()-W}}var k=[],F=[],D=1,S=null,_=3,B=!1,G=!1,$=!1,ul=!1,Bl=typeof setTimeout=="function"?setTimeout:null,nt=typeof clearTimeout=="function"?clearTimeout:null,ke=typeof setImmediate<"u"?setImmediate:null;function Bt(M){for(var Q=N(F);Q!==null;){if(Q.callback===null)d(F);else if(Q.startTime<=M)d(F),Q.sortIndex=Q.expirationTime,A(k,Q);else break;Q=N(F)}}function Gt(M){if($=!1,Bt(M),!G)if(N(k)!==null)G=!0,ct||(ct=!0,it());else{var Q=N(F);Q!==null&&Ul(Gt,Q.startTime-M)}}var ct=!1,I=-1,sl=5,wt=-1;function St(){return ul?!0:!(x.unstable_now()-wt<sl)}function xt(){if(ul=!1,ct){var M=x.unstable_now();wt=M;var Q=!0;try{l:{G=!1,$&&($=!1,nt(I),I=-1),B=!0;var X=_;try{t:{for(Bt(M),S=N(k);S!==null&&!(S.expirationTime>M&&St());){var bl=S.callback;if(typeof bl=="function"){S.callback=null,_=S.priorityLevel;var dl=bl(S.expirationTime<=M);if(M=x.unstable_now(),typeof dl=="function"){S.callback=dl,Bt(M),Q=!0;break t}S===N(k)&&d(k),Bt(M)}else d(k);S=N(k)}if(S!==null)Q=!0;else{var jt=N(F);jt!==null&&Ul(Gt,jt.startTime-M),Q=!1}}break l}finally{S=null,_=X,B=!1}Q=void 0}}finally{Q?it():ct=!1}}}var it;if(typeof ke=="function")it=function(){ke(xt)};else if(typeof MessageChannel<"u"){var ge=new MessageChannel,$e=ge.port2;ge.port1.onmessage=xt,it=function(){$e.postMessage(null)}}else it=function(){Bl(xt,0)};function Ul(M,Q){I=Bl(function(){M(x.unstable_now())},Q)}x.unstable_IdlePriority=5,x.unstable_ImmediatePriority=1,x.unstable_LowPriority=4,x.unstable_NormalPriority=3,x.unstable_Profiling=null,x.unstable_UserBlockingPriority=2,x.unstable_cancelCallback=function(M){M.callback=null},x.unstable_forceFrameRate=function(M){0>M||125<M?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):sl=0<M?Math.floor(1e3/M):5},x.unstable_getCurrentPriorityLevel=function(){return _},x.unstable_next=function(M){switch(_){case 1:case 2:case 3:var Q=3;break;default:Q=_}var X=_;_=Q;try{return M()}finally{_=X}},x.unstable_requestPaint=function(){ul=!0},x.unstable_runWithPriority=function(M,Q){switch(M){case 1:case 2:case 3:case 4:case 5:break;default:M=3}var X=_;_=M;try{return Q()}finally{_=X}},x.unstable_scheduleCallback=function(M,Q,X){var bl=x.unstable_now();switch(typeof X=="object"&&X!==null?(X=X.delay,X=typeof X=="number"&&0<X?bl+X:bl):X=bl,M){case 1:var dl=-1;break;case 2:dl=250;break;case 5:dl=1073741823;break;case 4:dl=1e4;break;default:dl=5e3}return dl=X+dl,M={id:D++,callback:Q,priorityLevel:M,startTime:X,expirationTime:dl,sortIndex:-1},X>bl?(M.sortIndex=X,A(F,M),N(k)===null&&M===N(F)&&($?(nt(I),I=-1):$=!0,Ul(Gt,X-bl))):(M.sortIndex=dl,A(k,M),G||B||(G=!0,ct||(ct=!0,it()))),M},x.unstable_shouldYield=St,x.unstable_wrapCallback=function(M){var Q=_;return function(){var X=_;_=Q;try{return M.apply(this,arguments)}finally{_=X}}}})(Os)),Os}var c0;function T1(){return c0||(c0=1,zs.exports=p1()),zs.exports}var As={exports:{}},Kl={};/**
|
||||
* @license React
|
||||
* react-dom.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var i0;function N1(){if(i0)return Kl;i0=1;var x=Ms();function A(D){var S="https://react.dev/errors/"+D;if(1<arguments.length){S+="?args[]="+encodeURIComponent(arguments[1]);for(var _=2;_<arguments.length;_++)S+="&args[]="+encodeURIComponent(arguments[_])}return"Minified React error #"+D+"; visit "+S+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function N(){}var d={d:{f:N,r:function(){throw Error(A(522))},D:N,C:N,L:N,m:N,X:N,S:N,M:N},p:0,findDOMNode:null},O=Symbol.for("react.portal"),q=Symbol.for("react.recoverable"),al=Symbol.for("react.optimistic_key");function W(D,S,_){var B=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:O,key:B==null?null:B===al?al:""+B,children:D,containerInfo:S,implementation:_}}var k=x.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function F(D,S){if(D==="font")return"";if(typeof S=="string")return S==="use-credentials"?S:""}return Kl.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=d,Kl.browser=function(D){return{$$typeof:q,_reason:D}},Kl.createPortal=function(D,S){var _=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!S||S.nodeType!==1&&S.nodeType!==9&&S.nodeType!==11)throw Error(A(299));return W(D,S,null,_)},Kl.flushSync=function(D){var S=k.T,_=d.p;try{if(k.T=null,d.p=2,D)return D()}finally{k.T=S,d.p=_,d.d.f()}},Kl.preconnect=function(D,S){typeof D=="string"&&(S?(S=S.crossOrigin,S=typeof S=="string"?S==="use-credentials"?S:"":void 0):S=null,d.d.C(D,S))},Kl.prefetchDNS=function(D){typeof D=="string"&&d.d.D(D)},Kl.preinit=function(D,S){if(typeof D=="string"&&S&&typeof S.as=="string"){var _=S.as,B=F(_,S.crossOrigin),G=typeof S.integrity=="string"?S.integrity:void 0,$=typeof S.fetchPriority=="string"?S.fetchPriority:void 0;_==="style"?d.d.S(D,typeof S.precedence=="string"?S.precedence:void 0,{crossOrigin:B,integrity:G,fetchPriority:$}):_==="script"&&d.d.X(D,{crossOrigin:B,integrity:G,fetchPriority:$,nonce:typeof S.nonce=="string"?S.nonce:void 0})}},Kl.preinitModule=function(D,S){if(typeof D=="string")if(typeof S=="object"&&S!==null){if(S.as==null||S.as==="script"){var _=F(S.as,S.crossOrigin);d.d.M(D,{crossOrigin:_,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0})}}else S==null&&d.d.M(D)},Kl.preload=function(D,S){if(typeof D=="string"&&typeof S=="object"&&S!==null&&typeof S.as=="string"){var _=S.as,B=F(_,S.crossOrigin);d.d.L(D,_,{crossOrigin:B,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,type:typeof S.type=="string"?S.type:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0,referrerPolicy:typeof S.referrerPolicy=="string"?S.referrerPolicy:void 0,imageSrcSet:typeof S.imageSrcSet=="string"?S.imageSrcSet:void 0,imageSizes:typeof S.imageSizes=="string"?S.imageSizes:void 0,media:typeof S.media=="string"?S.media:void 0})}},Kl.preloadModule=function(D,S){if(typeof D=="string")if(S){var _=F(S.as,S.crossOrigin);d.d.m(D,{as:typeof S.as=="string"&&S.as!=="script"?S.as:void 0,crossOrigin:_,integrity:typeof S.integrity=="string"?S.integrity:void 0,nonce:typeof S.nonce=="string"?S.nonce:void 0,fetchPriority:typeof S.fetchPriority=="string"?S.fetchPriority:void 0})}else d.d.m(D)},Kl.requestFormReset=function(D){d.d.r(D)},Kl.unstable_batchedUpdates=function(D,S){return D(S)},Kl.useFormState=function(D,S,_){return k.H.useFormState(D,S,_)},Kl.useFormStatus=function(){return k.H.useHostTransitionStatus()},Kl.version="19.3.1",Kl}var f0;function E1(){if(f0)return As.exports;f0=1;function x(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(x)}catch(A){console.error(A)}}return x(),As.exports=N1(),As.exports}/**
|
||||
* @license React
|
||||
* react-dom-client.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var s0;function _1(){if(s0)return cn;s0=1;var x=T1(),A=Ms(),N=E1();function d(l){var t="https://react.dev/errors/"+l;if(1<arguments.length){t+="?args[]="+encodeURIComponent(arguments[1]);for(var e=2;e<arguments.length;e++)t+="&args[]="+encodeURIComponent(arguments[e])}return"Minified React error #"+l+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function O(l){return!(!l||l.nodeType!==1&&l.nodeType!==9&&l.nodeType!==11)}function q(l){for(var t=l,e=t;e&&!e.alternate;)t=e,(t.flags&4098)!==0&&(l=t.return),e=t.return;for(;t.return;)t=t.return;return t.tag===3?l:null}function al(l){if(l.tag===13){var t=l.memoizedState;if(t===null&&(l=l.alternate,l!==null&&(t=l.memoizedState)),t!==null)return t.dehydrated}return null}function W(l){if(l.tag===31){var t=l.memoizedState;if(t===null&&(l=l.alternate,l!==null&&(t=l.memoizedState)),t!==null)return t.dehydrated}return null}function k(l){if(q(l)!==l)throw Error(d(188))}function F(l){var t=l.alternate;if(!t){if(t=q(l),t===null)throw Error(d(188));return t!==l?null:l}for(var e=l,a=t;;){var u=e.return;if(u===null)break;var n=u.alternate;if(n===null){if(a=u.return,a!==null){e=a;continue}break}if(u.child===n.child){for(n=u.child;n;){if(n===e)return k(u),l;if(n===a)return k(u),t;n=n.sibling}throw Error(d(188))}if(e.return!==a.return)e=u,a=n;else{for(var c=!1,i=u.child;i;){if(i===e){c=!0,e=u,a=n;break}if(i===a){c=!0,a=u,e=n;break}i=i.sibling}if(!c){for(i=n.child;i;){if(i===e){c=!0,e=n,a=u;break}if(i===a){c=!0,a=n,e=u;break}i=i.sibling}if(!c)throw Error(d(189))}}if(e.alternate!==a)throw Error(d(190))}if(e.tag!==3)throw Error(d(188));return e.stateNode.current===e?l:t}function D(l){var t=l.tag;if(t===5||t===26||t===27||t===6)return l;for(l=l.child;l!==null;){if(t=D(l),t!==null)return t;l=l.sibling}return null}function S(l,t,e,a,u,n){for(;l!==null;){if((l.tag===5||l.tag===27||l.tag===6)&&e(l,a,u,n)||(l.tag!==22||l.memoizedState===null)&&(t||l.tag!==5&&l.tag!==27)&&S(l.child,t,e,a,u,n))return!0;l=l.sibling}return!1}function _(l){for(l=l.return;l!==null;){if(l.tag===3||l.tag===5||l.tag===27)return l;l=l.return}return null}function B(l){var t=!1;for(l=l.return;l!==null&&(l.tag===4&&(t=!0),!(l.tag===3||l.tag===5||l.tag===27));)l=l.return;return t}function G(l){var t=[null,null],e=_(l);return e===null||$(t,l,e.child,{foundSelf:!1}),t}function $(l,t,e,a){for(;e!==null;){if(e===t)a.foundSelf=!0;else if(e.tag===5||e.tag===27||e.tag===6){if(a.foundSelf)return l[1]=e,!0;l[0]=e}else if((e.tag!==22||e.memoizedState===null)&&$(l,t,e.child,a))return!0;e=e.sibling}return!1}function ul(l){switch(l.tag){case 5:case 27:case 6:return l.stateNode;case 3:return l.stateNode.containerInfo;default:throw Error(d(559))}}var Bl=null,nt=null;function ke(l,t,e){return l===e?!0:l===t?(Bl=l,!0):!1}function Bt(l,t,e){return l===e?(nt=l,!1):l===t?(nt!==null&&(Bl=l),!0):!1}function Gt(l){if(l===null)return null;do l=l===null?null:l.return;while(l&&l.tag!==5&&l.tag!==27&&l.tag!==3);return l||null}function ct(l,t,e){for(var a=0,u=l;u;u=e(u))a++;u=0;for(var n=t;n;n=e(n))u++;for(;0<a-u;)l=e(l),a--;for(;0<u-a;)t=e(t),u--;for(;a--;){if(l===t||t!==null&&l===t.alternate)return l;l=e(l),t=e(t)}return null}var I=Object.assign,sl=Symbol.for("react.element"),wt=Symbol.for("react.transitional.element"),St=Symbol.for("react.portal"),xt=Symbol.for("react.fragment"),it=Symbol.for("react.strict_mode"),ge=Symbol.for("react.profiler"),$e=Symbol.for("react.consumer"),Ul=Symbol.for("react.context"),M=Symbol.for("react.forward_ref"),Q=Symbol.for("react.suspense"),X=Symbol.for("react.suspense_list"),bl=Symbol.for("react.memo"),dl=Symbol.for("react.lazy"),jt=Symbol.for("react.activity"),le=Symbol.for("react.legacy_hidden"),We=Symbol.for("react.memo_cache_sentinel"),r=Symbol.for("react.view_transition"),E=Symbol.for("react.recoverable"),H=Symbol.iterator;function Y(l){return l===null||typeof l!="object"?null:(l=H&&l[H]||l["@@iterator"],typeof l=="function"?l:null)}var cl=Symbol.for("react.client.reference");function il(l){if(l==null)return null;if(typeof l=="function")return l.$$typeof===cl?null:l.displayName||l.name||null;if(typeof l=="string")return l;switch(l){case xt:return"Fragment";case ge:return"Profiler";case it:return"StrictMode";case Q:return"Suspense";case X:return"SuspenseList";case jt:return"Activity";case r:return"ViewTransition"}if(typeof l=="object")switch(l.$$typeof){case St:return"Portal";case Ul:return l.displayName||"Context";case $e:return(l._context.displayName||"Context")+".Consumer";case M:var t=l.render;return l=l.displayName,l||(l=t.displayName||t.name||"",l=l!==""?"ForwardRef("+l+")":"ForwardRef"),l;case bl:return t=l.displayName||null,t!==null?t:il(l.type)||"Memo";case dl:t=l._payload,l=l._init;try{return il(l(t))}catch{}}return null}var ol=Array.isArray,U=A.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Z=N.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,te={pending:!1,data:null,method:null,action:nuLine truncated
|
||||
at`)?" (<anonymous>)":-1<e.stack.indexOf("@")?"@unknown:0:0":""}return`
|
||||
`+Zc+l+js}var Vc=!1;function Lc(l,t){if(!l||Vc)return"";Vc=!0;var e=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var a={DetermineComponentFrameRoot:function(){try{if(t){var T=function(){throw Error()};if(Object.defineProperty(T.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(T,[])}catch(z){var m=z}Reflect.construct(l,[],T)}else{try{T.call()}catch(z){m=z}T=!1;try{var g=Object.getOwnPropertyDescriptor(l.prototype,"props");Object.defineProperty(l.prototype,"props",{configurable:!0,set:function(){throw Error()}}),T=!0,new l}finally{T&&(g!==void 0?Object.defineProperty(l.prototype,"props",g):delete l.prototype.props)}}}else{try{throw Error()}catch(z){m=z}(T=l())&&typeof T.catch=="function"&&T.catch(function(){})}}catch(z){if(z&&m&&typeof z.stack=="string")return[z.stack,m.stack]}return[null,null]}};a.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var u=Object.getOwnPropertyDescriptor(a.DetermineComponentFrameRoot,"name");u&&u.configurable&&Object.defineProperty(a.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var n=a.DetermineComponentFrameRoot(),c=n[0],i=n[1];if(c&&i){var f=c.split(`
|
||||
`),v=i.split(`
|
||||
`);for(u=a=0;a<f.length&&!f[a].includes("DetermineComponentFrameRoot");)a++;for(;u<v.length&&!v[u].includes("DetermineComponentFrameRoot");)u++;if(a===f.length||u===v.length)for(a=f.length-1,u=v.length-1;1<=a&&0<=u&&f[a]!==v[u];)u--;for(;1<=a&&0<=u;a--,u--)if(f[a]!==v[u]){if(a!==1||u!==1)do if(a--,u--,0>u||f[a]!==v[u]){var b=`
|
||||
`+f[a].replace(" at new "," at ");return l.displayName&&b.includes("<anonymous>")&&(b=b.replace("<anonymous>",l.displayName)),b}while(1<=a&&0<=u);break}}}finally{Vc=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Se(e):""}function T0(l,t){switch(l.tag){case 26:case 27:case 5:return Se(l.type);case 16:return Se("Lazy");case 13:return l.child!==t&&t!==null?Se("Suspense Fallback"):Se("Suspense");case 19:return Se("SuspenseList");case 0:case 15:return Lc(l.type,!1);case 11:return Lc(l.type.render,!1);case 1:return Lc(l.type,!0);case 31:return Se("Activity");case 30:return Se("ViewTransition");default:return""}}function Cs(l){try{var t="",e=null;do t+=T0(l,e),e=l,l=l.return;while(l);return t}catch(a){return`
|
||||
Error generating stack: `+a.message+`
|
||||
`+a.stack}}var Kc=Object.prototype.hasOwnProperty,Jc=x.unstable_scheduleCallback,kc=x.unstable_cancelCallback,N0=x.unstable_shouldYield,E0=x.unstable_requestPaint,ft=x.unstable_now,_0=x.unstable_getCurrentPriorityLevel,Ds=x.unstable_ImmediatePriority,Us=x.unstable_UserBlockingPriority,rn=x.unstable_NormalPriority,z0=x.unstable_LowPriority,Rs=x.unstable_IdlePriority,O0=x.log,A0=x.unstable_setDisableYieldValue,du=null,st=null;function xe(l){if(typeof O0=="function"&&A0(l),st&&typeof st.setStrictMode=="function")try{st.setStrictMode(du,l)}catch{}}var ot=Math.clz32?Math.clz32:C0,M0=Math.log,j0=Math.LN2;function C0(l){return l>>>=0,l===0?32:31-(M0(l)/j0|0)|0}var dn=256,mn=262144,hn=4194304;function Fe(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&-l;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 vn(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var u=0,n=l.suspendedLanes,c=l.pingedLanes;l=l.warmLanes;var i=a&134217727;return i!==0?(a=i&~n,a!==0?u=Fe(a):(c&=i,c!==0?u=Fe(c):e||(e=i&~l,e!==0&&(u=Fe(e))))):(i=a&~n,i!==0?u=Fe(i):c!==0?u=Fe(c):e||(e=a&~l,e!==0&&(u=Fe(e)))),u===0?0:t!==0&&t!==u&&(t&n)===0&&(n=u&-u,e=t&-t,n>=e||n===32&&(e&4194048)!==0)?t:u}function mu(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Hs(l,t){(t&8)!==0&&(t|=t&32);var e=l.entangledLanes;if(e!==0)for(l=l.entanglements,e&=t;0<e;){var a=31-ot(e),u=1<<a;t|=l[a],e&=~u}return t}function D0(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 Ys(){var l=hn;return hn<<=1,(hn&62914560)===0&&(hn=4194304),l}function $c(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function hu(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function U0(l,t,e,a,u,n){var c=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var i=l.entanglements,f=l.expirationTimes,v=l.hiddenUpdates;for(e=c&~e;0<e;){var b=31-ot(e),T=1<<b;i[b]=0,f[b]=-1;var m=v[b];if(m!==null)for(v[b]=null,b=0;b<m.length;b++){var g=m[b];g!==null&&(g.lane&=-536870913)}e&=~T}a!==0&&qs(l,a,0),n!==0&&u===0&&l.tag!==0&&(l.suspendedLanes|=n&~(c&~t))}function qs(l,t,e){l.pendingLanes|=t,l.suspendedLanes&=~t;var a=31-ot(t);l.entangledLanes|=t,l.entanglements[a]=l.entanglements[a]|1073741824|e&261930}function Bs(l,t){var e=l.entangledLanes|=t;for(l=l.entanglements;e;){var a=31-ot(e),u=1<<a;u&t|l[a]&t&&(l[a]|=t),e&=~u}}function Gs(l,t){var e=t&-t;return e=(e&42)!==0?1:Wc(e),(e&(l.suspendedLanes|t))!==0?0:e}function Wc(l){switch(l){case 2:l=1;break;case 8:l=4;break;case 32:l=16;break;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:case 4194304:case 8388608:case 16777216:case 33554432:l=128;break;case 268435456:l=134217728;break;default:l=0}return l}function Fc(l){return l&=-l,2<l?8<l?(l&134217727)!==0?32:268435456:8:2}function ws(){var l=Z.p;return l!==0?l:(l=window.event,l===void 0?32:km(l.type))}function Qs(l,t){var e=Z.p;try{return Z.p=l,t()}finally{Z.p=e}}var ee=Math.random().toString(36).slice(2),wl="__reactFiber$"+ee,Pl="__reactProps$"+ee,Ta="__reactContainer$"+ee,Xs="__reactEvents$"+ee,R0="__reactListeners$"+ee,H0="__reactHandles$"+ee,Zs="__reactResources$"+ee,vu="__reactMarker$"+ee,yn="__reactLoad$"+ee;function gn(l){delete l[wl],delete l[Pl],delete l[R0],delete l[H0]}function Ie(l){var t;if(t=l[wl])return t;for(var e=l.parentNode;e;){if(t=e[Ta]||e[wl]){if(e=t.alternate,t.child!==null||e!==null&&e.child!==null)for(l=Am(l);l!==null;){if(e=l[wl])return e;l=Am(l)}return t}l=e,e=l.parentNode}return null}function Na(l){if(l=l[wl]||l[Ta]){var t=l.tag;if(t===5||t===6||t===13||t===31||t===26||t===27||t===3)return l}return null}function yu(l){var t=l.tag;if(t===5||t===26||t===27||t===6)return l.stateNode;throw Error(d(33))}function Ea(l){var t=l[Zs];return t||(t=l[Zs]={hoistableStyles:new Map,hoistableScripts:new Map}),t}function Rl(l){l[vu]=!0}function Vs(l){l[yn]=void 0}var Ls=new Set,Ks={};function Pe(l,t){_a(l,t),_a(l+"Capture",t)}function
Line truncated
|
||||
`).replace(Tv,"")}function fm(l,t){return t=im(t),im(l)===t}function yl(l,t,e,a,u,n){switch(e){case"children":if(typeof a=="string")t==="body"||t==="textarea"&&a===""||Oa(l,a);else if(typeof a=="number"||typeof a=="bigint")t!=="body"&&Oa(l,""+a);else return;break;case"className":Sn(l,"class",a);break;case"tabIndex":Sn(l,"tabindex",a);break;case"dir":case"role":case"viewBox":case"width":case"height":Sn(l,e,a);break;case"style":eo(l,a,n);return;case"data":if(t!=="object"){Sn(l,"data",a);break}case"src":case"href":if(a===""&&(t!=="a"||e!=="href")){l.removeAttribute(e);break}if(a==null||typeof a=="function"||typeof a=="symbol"||typeof a=="boolean"){l.removeAttribute(e);break}a=xn(a),l.setAttribute(e,a);break;case"action":case"formAction":if(typeof a=="function"){l.setAttribute(e,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof n=="function"&&(e==="formAction"?(t!=="input"&&yl(l,t,"name",u.name,u,null),yl(l,t,"formEncType",u.formEncType,u,null),yl(l,t,"formMethod",u.formMethod,u,null),yl(l,t,"formTarget",u.formTarget,u,null)):(yl(l,t,"encType",u.encType,u,null),yl(l,t,"method",u.method,u,null),yl(l,t,"target",u.target,u,null)));if(a==null||typeof a=="symbol"||typeof a=="boolean"){l.removeAttribute(e);break}a=xn(a),l.setAttribute(e,a);break;case"onClick":a!=null&&(l.onclick=Zt);return;case"onScroll":a!=null&&ll("scroll",l);return;case"onScrollEnd":a!=null&&ll("scrollend",l);return;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(d(61));if(e=a.__html,e!=null){if(u.children!=null)throw Error(d(60));(n!=null?n.__html:void 0)!==e&&(l.innerHTML=e)}}break;case"multiple":l.multiple=a&&typeof a!="function"&&typeof a!="symbol";break;case"muted":l.muted=a&&typeof a!="function"&&typeof a!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(a==null||typeof a=="function"||typeof a=="boolean"||typeof a=="symbol"){l.removeAttribute("xlink:href");break}e=xn(a),l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",e);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":a!=null&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,a):l.removeAttribute(e);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"credentialless":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":a&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,""):l.removeAttribute(e);break;case"capture":case"download":a===!0?l.setAttribute(e,""):a!==!1&&a!=null&&typeof a!="function"&&typeof a!="symbol"?l.setAttribute(e,a):l.removeAttribute(e);break;case"cols":case"rows":case"size":case"span":a!=null&&typeof a!="function"&&typeof a!="symbol"&&!isNaN(a)&&1<=a?l.setAttribute(e,a):l.removeAttribute(e);break;case"rowSpan":case"start":a==null||typeof a=="function"||typeof a=="symbol"||isNaN(a)?l.removeAttribute(e):l.setAttribute(e,a);break;case"popover":ll("beforetoggle",l),ll("toggle",l),bn(l,"popover",a);break;case"xlinkActuate":ae(l,"http://www.w3.org/1999/xlink","xlink:actuate",a);break;case"xlinkArcrole":ae(l,"http://www.w3.org/1999/xlink","xlink:arcrole",a);break;case"xlinkRole":ae(l,"http://www.w3.org/1999/xlink","xlink:role",a);break;case"xlinkShow":ae(l,"http://www.w3.org/1999/xlink","xlink:show",a);break;case"xlinkTitle":ae(l,"http://www.w3.org/1999/xlink","xlink:title",a);break;case"xlinkType":ae(l,"http://www.w3.org/1999/xlink","xlink:type",a);break;case"xmlBase":ae(l,"http://www.w3.org/XML/1998/namespace","xml:base",a);break;case"xmlLang":ae(l,"http://www.w3.org/XML/1998/namespace","xml:lang",a);break;case"xmlSpace":ae(l,"http://www.w3.org/XML/1998/namespace","xml:space",a);break;case"is":bn(l,"is",a);break;case"innerText":case"textContent":return;default:if(!(2<e.length)||e[0]!=="o"&&e[0]!=="O"||e[1]!=="n"&&e[1]!=="N")e=Q0.get(e)||e,bn(l,e,a);else return}fl=!0}function ls(l,t,e,a,u,n){switch(e){case"style":eo(l,a,n);return;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(d(61));if(e=a.__html,e!=null){if(u.children!=null)throw Error(d(60));(n!=null?n.__html:void 0)!==e&&(l.innerHTML=e)}}break;case"children":if(typeof a=="string")Oa(l,a);else if(typeof a=="number"||typeof a=="bigint")Oa(l,""+a);else return;break;case"onScroll":a!=null&&ll("scroll",l);return;case"onScrollEnd":a!=null&&ll("scro
Line truncated
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const B1=x=>x.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),y0=(...x)=>x.filter((A,N,d)=>!!A&&A.trim()!==""&&d.indexOf(A)===N).join(" ").trim();/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/var G1={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const w1=Jl.forwardRef(({color:x="currentColor",size:A=24,strokeWidth:N=2,absoluteStrokeWidth:d,className:O="",children:q,iconNode:al,...W},k)=>Jl.createElement("svg",{ref:k,...G1,width:A,height:A,stroke:x,strokeWidth:d?Number(N)*24/Number(A):N,className:y0("lucide",O),...W},[...al.map(([F,D])=>Jl.createElement(F,D)),...Array.isArray(q)?q:[q]]));/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const qt=(x,A)=>{const N=Jl.forwardRef(({className:d,...O},q)=>Jl.createElement(w1,{ref:q,iconNode:A,className:y0(`lucide-${B1(x)}`,d),...O}));return N.displayName=`${x}`,N};/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const Q1=[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]],g0=qt("BookOpen",Q1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const X1=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],Z1=qt("Check",X1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const V1=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],L1=qt("Layers",V1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const K1=[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1",key:"1g98yp"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1",key:"6d4xhi"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1",key:"nxv5o0"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1",key:"1bb6yr"}]],J1=qt("LayoutGrid",K1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const k1=[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z",key:"a7tn18"}]],$1=qt("Moon",k1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const W1=[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z",key:"12rzf8"}]],F1=qt("Palette",W1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const I1=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M9 21V9",key:"1oto5p"}]],P1=qt("PanelsTopLeft",I1);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ly=[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]],b0=qt("Search",ly);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ty=[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",key:"4pj2yx"}],["path",{d:"M20 3v4",key:"1olli1"}],["path",{d:"M22 5h-4",key:"1gvqau"}],["path",{d:"M4 17v2",key:"vumght"}],["path",{d:"M5 18H3",key:"zchphs"}]],ey=qt("Sparkles",ty);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ay=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],uy=qt("Sun",ay);/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/const ny=[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]],S0=qt("Terminal",ny),cy=[{id:"auto",label:"智能路由"},{id:"edge443",label:"443 免端口"},{id:"home10443",label:"10443 家宽"},{id:"lan",label:"LAN 局域网"}],iy=()=>{const{theme:x,resolvedTheme:A,routeMode:N,viewMode:d,telemetry:O,setTheme:q,toggleTheme:al,setRouteMode:W,setViewMode:k,setShowAgyModal:F,setShowCmdPalette:D}=Je();return s.jsxs(s.Fragment,{children:[s.jsx("header",{className:"border-b hl-border sticky top-0 z-30 backdrop-blur-md",style:{backgroundColor:"color-mix(in srgb, var(--bg-card) 88%, transparent)"},children:s.jsxs("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-14 flex items-center justify-between gap-4",children:[s.jsxs("div",{className:"flex items-center gap-4 shrink-0",children:[s.jsxs("div",{onClick:()=>k("dashboard"),className:"flex items-center gap-2.5 cursor-pointer",children:[s.jsx("img",{src:"https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/apple.png",alt:"Mac mini",className:"w-6 h-6 rounded"}),s.jsx("span",{className:"font-semibold text-sm tracking-tight",children:"HomeLab"}),s.jsx("span",{className:"w-2 h-2 rounded-full",style:{backgroundColor:"var(--success)"},title:"全屋 4 节点在线"})]}),s.jsx("div",{className:"h-4 w-[1px] hl-muted"}),s.jsxs("nav",{className:"flex items-center gap-1 text-xs",children:[s.jsxs("button",{onClick:()=>k("dashboard"),className:"px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer",style:d==="dashboard"?{backgroundColor:"var(--bg-muted)",color:"var(--text-main)"}:{color:"var(--text-muted)"},children:[s.jsx(J1,{className:"w-3.5 h-3.5"}),s.jsx("span",{children:"中控台"})]}),s.jsxs("button",{onClick:()=>k("storybook"),className:"px-2.5 py-1.5 rounded-md font-medium flex items-center gap-1.5 transition-all cursor-pointer",style:d==="storybook"?{backgroundColor:"var(--bg-muted)",color:"var(--text-main)"}:{color:"var(--text-muted)"},children:[s.jsx(g0,{className:"w-3.5 h-3.5"}),s.jsx("span",{children:"Storybook 设计规范"})]})]})]}),s.jsxs("div",{className:"flex items-center gap-2.5 shrink-0 ml-auto",children:[s.jsxs("button",{onClick:()=>D(!0),className:"hl-btn-outline px-3 py-1.5 text-xs flex items-center gap-3 cursor-pointer",title:"按 Cmd+K 唤起全局命令面板",children:[s.jsxs("span",{className:"flex items-center gap-1.5",style:{color:"var(--text-muted)"},children:[s.jsx(b0,{className:"w-3.5 h-3.5"}),s.jsx("span",{className:"hidden sm:inline",children:"搜索服务或指令..."})]}),s.jsx("kbd",{className:"px-1.5 py-0.5 text-[10px] font-mono-num rounded hl-muted",style:{color:"var(--text-muted)"},children:"⌘K"})]}),s.jsxs("button",{onClick:()=>F(!0),className:"hl-btn-primary px-3 py-1.5 text-xs flex items-center gap-1.5 cursor-pointer",children:[s.jsx(S0,{className:"w-3.5 h-3.5"}),s.jsx("span",{children:"AGY 终端"})]}),s.jsxs("div",{className:"flex items-center p-0.5 rounded-lg hl-muted border hl-border text-xs",children:[s.jsx("button",{onClick:al,className:"px-2.5 py-1 rounded-md font-medium transition-all flex items-center gap-1.5 cursor-pointer",style:{backgroundColor:"var(--bg-card)",color:"var(--text-main)",boxShadow:"0 1px 2px rgba(0,0,0,0.08)"},title:"点击切换深色 / 浅色主题(默认跟随系统)",children:A==="dark"?s.jsxs(s.Fragment,{children:[s.jsx($1,{className:"w-3.5 h-3.5"}),s.jsx("span",{children:"深色"})]}):s.jsxs(s.Fragment,{children:[s.jsx(uy,{className:"w-3.5 h-3.5"}),s.jsx("span",{children:"浅色"})]})}),x!=="system"&&s.jsx("button",{onClick:()=>q("system"),className:"px-2 py-1 rounded-md text-[11px] transition-all cursor-pointer",style:{color:"var(--text-muted)"},title:"恢复跟随设备系统深浅色自动切换",children:"自动"})]})]})]})}),d==="dashboard"&&s.jsx("div",{className:"border-b hl-border",style:{backgroundColor:"var(--bg-card)"},children:s.jsxs("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex flex-wrap items-center justify-between gap-3",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs font-mono-num",children:[s.jsxs("div",{className:"hl-pill px-2.5 py-1 flex items-center gap-2",children:[s.jsx("span",{style:{color:"var(--text-muted)"},children:"M6 CPU"}),s.jsx("div",{className:"w-12 h-1.5 rounded-full hl-muted overflow-hidden",children:s.jsx("div",{className:"h-full hl-bar-fill",style:{width:`${Math.max(5,O.mini.cpu_pct)}%`}})}),s.jsxs("span",{className:"font-medium",children:[O.mini.cpu_pct,"%"]})]}),s.jsxs("div",{className:"hl-pill px-2.5 py-1 flex items-center gap-2",children:[s.jsx("span",{style:{color:"var(--text-muted)"},children:"RAM"}),s.jsx("div",{className:"w-12 h-1.5 rounded-full hl-muted overflow-hidden",children:s.jsx("div",{className:"h-full hl-bar-fill",style:{width:`${Math.max(5,O.mini.mem_pct)}%`}})}),s.jsxs("span",{className:"font-medium",children:[O.mini.mem_used_gb,"G"]})]}),s.jsxs("div",{className:"hl-pill px-2.5 pLine truncated
|
||||
@@ -0,0 +1 @@
|
||||
/*! tailwindcss v4.3.5 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:block))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-divide-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--spacing:.25rem;--container-md:28rem;--container-xl:36rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--blur-sm:8px;--blur-md:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-Line truncated
|
||||
Vendored
+2
-2
@@ -11,8 +11,8 @@
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<script type="module" crossorigin src="/assets/index-D9ftMUDG.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B_rkFolS.css">
|
||||
<script type="module" crossorigin src="/assets/index-CC6K5dbV.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-R7AnvXyQ.css">
|
||||
</head>
|
||||
<body class="min-h-screen">
|
||||
<div id="root"></div>
|
||||
|
||||
+148
-7
@@ -1,18 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
# ==============================================================================
|
||||
# HomeLab All-in-One 专属中控台后端服务 (Port 3002)
|
||||
# 提供 Apple/Shadcn 风格单页应用与全屋设备实时遥测 API (/api/telemetry, /api/action)
|
||||
# HomeLab All-in-One 专属中控台后端服务 (Port 3002 & 3004)
|
||||
# 提供:
|
||||
# 1. Apple/Shadcn 风格单页应用静态资源
|
||||
# 2. 全屋设备实时遥测 API (/api/telemetry, /api/action/*)
|
||||
# 3. 统一自定义 SSO 认证网关 (/api/auth/verify, /api/auth/login, /api/auth/status)
|
||||
# 彻底替代浏览器原生丑陋的 HTTP Basic Auth 弹窗!
|
||||
# ==============================================================================
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import mimetypes
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from http.cookies import SimpleCookie
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
@@ -21,10 +29,40 @@ BASE_DIR = Path(__file__).resolve().parent
|
||||
DIST_DIR = BASE_DIR / "dist"
|
||||
INDEX_FILE = BASE_DIR / "index.html"
|
||||
|
||||
# Unified SSO Credentials & HMAC Secret
|
||||
AUTH_USER = os.environ.get("HOMELAB_USER", "ixvii0iv")
|
||||
AUTH_PASS = os.environ.get("HOMELAB_PASS", "k10y15ZXC.")
|
||||
AUTH_SECRET = os.environ.get("HOMELAB_SECRET", "hl-m6-macmini-sso-secret-2026-961504xyz").encode("utf-8")
|
||||
COOKIE_NAME = "hl_sso"
|
||||
COOKIE_MAX_AGE = 30 * 86400 # 30 Days
|
||||
|
||||
_cache = {"data": None, "ts": 0.0}
|
||||
_cache_lock = threading.Lock()
|
||||
|
||||
|
||||
def create_sso_token(username: str) -> str:
|
||||
exp = int(time.time()) + COOKIE_MAX_AGE
|
||||
payload = f"{username}:{exp}"
|
||||
sig = hmac.new(AUTH_SECRET, payload.encode("utf-8"), hashlib.sha256).hexdigest()
|
||||
return f"{payload}:{sig}"
|
||||
|
||||
|
||||
def verify_sso_token(token: str) -> tuple[bool, str]:
|
||||
if not token or token.count(":") != 2:
|
||||
return False, ""
|
||||
try:
|
||||
username, exp_str, sig = token.split(":", 2)
|
||||
if int(exp_str) < int(time.time()):
|
||||
return False, ""
|
||||
payload = f"{username}:{exp_str}"
|
||||
expected = hmac.new(AUTH_SECRET, payload.encode("utf-8"), hashlib.sha256).hexdigest()
|
||||
if hmac.compare_digest(sig, expected):
|
||||
return True, username
|
||||
except Exception:
|
||||
pass
|
||||
return False, ""
|
||||
|
||||
|
||||
def run_cmd(cmd: str, timeout: float = 2.0) -> str:
|
||||
try:
|
||||
env = os.environ.copy()
|
||||
@@ -50,7 +88,6 @@ def check_tcp(host: str, port: int, timeout: float = 0.8) -> tuple[bool, int]:
|
||||
def get_mac_mini_stats() -> dict:
|
||||
# 1. CPU Load & Core count
|
||||
load_str = run_cmd("sysctl -n vm.loadavg")
|
||||
# Format: "{ 1.42 1.18 1.05 }"
|
||||
loads = [float(x) for x in re.findall(r"[0-9]+\.[0-9]+", load_str)] or [0.0, 0.0, 0.0]
|
||||
cores = int(run_cmd("sysctl -n hw.ncpu") or "12")
|
||||
cpu_pct = min(100, round((loads[0] / max(1, cores)) * 100, 1))
|
||||
@@ -273,21 +310,80 @@ class PortalHandler(BaseHTTPRequestHandler):
|
||||
def log_message(self, fmt, *args):
|
||||
pass
|
||||
|
||||
def _send_json(self, obj: dict, status: int = 200):
|
||||
def _get_cookie_token(self) -> str:
|
||||
raw_cookie = self.headers.get("Cookie", "")
|
||||
if not raw_cookie:
|
||||
return ""
|
||||
c = SimpleCookie()
|
||||
try:
|
||||
c.load(raw_cookie)
|
||||
if COOKIE_NAME in c:
|
||||
return c[COOKIE_NAME].value
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback regex parse
|
||||
m = re.search(rf"{COOKIE_NAME}=([^;\s]+)", raw_cookie)
|
||||
return m.group(1) if m else ""
|
||||
|
||||
def _is_authenticated(self) -> tuple[bool, str]:
|
||||
token = self._get_cookie_token()
|
||||
return verify_sso_token(token)
|
||||
|
||||
def _send_json(self, obj: dict, status: int = 200, extra_headers=None):
|
||||
body = json.dumps(obj, ensure_ascii=False).encode("utf-8")
|
||||
self.send_response(status)
|
||||
self.send_header("Content-Type", "application/json; charset=utf-8")
|
||||
self.send_header("Cache-Control", "no-store")
|
||||
if extra_headers:
|
||||
for k, v in extra_headers:
|
||||
self.send_header(k, v)
|
||||
self.send_header("Content-Length", str(len(body)))
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
|
||||
def do_GET(self):
|
||||
# 1. Caddy forward_auth verification endpoint (/api/auth/verify)
|
||||
if self.path.startswith("/api/auth/verify"):
|
||||
ok, username = self._is_authenticated()
|
||||
if ok:
|
||||
self.send_response(200)
|
||||
self.send_header("X-Auth-User", username)
|
||||
self.send_header("Content-Length", "2")
|
||||
self.end_headers()
|
||||
self.wfile.write(b"OK")
|
||||
return
|
||||
|
||||
# Not authenticated -> Redirect to our custom-styled HomeLab Console Login Modal!
|
||||
fwd_proto = self.headers.get("X-Forwarded-Proto", "https")
|
||||
fwd_host = self.headers.get("X-Forwarded-Host") or self.headers.get("Host", "agy.961504.xyz")
|
||||
fwd_uri = self.headers.get("X-Forwarded-Uri", "/")
|
||||
target_url = f"{fwd_proto}://{fwd_host}{fwd_uri}"
|
||||
encoded_target = urllib.parse.quote(target_url, safe="")
|
||||
|
||||
if ".home.961504.xyz" in fwd_host or ":10443" in fwd_host:
|
||||
login_portal = f"https://home.961504.xyz:10443/?auth_redirect={encoded_target}"
|
||||
else:
|
||||
login_portal = f"https://nav.961504.xyz/?auth_redirect={encoded_target}"
|
||||
|
||||
self.send_response(302)
|
||||
self.send_header("Location", login_portal)
|
||||
self.send_header("Cache-Control", "no-store")
|
||||
self.send_header("Content-Length", "0")
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
# 2. Check current SSO status (/api/auth/status)
|
||||
if self.path.startswith("/api/auth/status"):
|
||||
ok, username = self._is_authenticated()
|
||||
self._send_json({"authenticated": ok, "username": username if ok else None})
|
||||
return
|
||||
|
||||
# 3. Telemetry endpoint (/api/telemetry)
|
||||
if self.path.startswith("/api/telemetry"):
|
||||
self._send_json(collect_telemetry())
|
||||
return
|
||||
|
||||
# Serve static assets from Vite build output (dist/) if available
|
||||
# 4. Serve static assets from Vite build output (dist/) if available
|
||||
clean_path = self.path.split("?", 1)[0].lstrip("/")
|
||||
if clean_path and DIST_DIR.exists():
|
||||
asset_file = (DIST_DIR / clean_path).resolve()
|
||||
@@ -302,7 +398,7 @@ class PortalHandler(BaseHTTPRequestHandler):
|
||||
self.wfile.write(body)
|
||||
return
|
||||
|
||||
# Serve SPA index.html from dist/index.html (React+Vite build) or fallback index.html
|
||||
# 5. Serve SPA index.html from dist/index.html
|
||||
spa_index = (DIST_DIR / "index.html") if (DIST_DIR / "index.html").exists() else INDEX_FILE
|
||||
if spa_index.exists():
|
||||
body = spa_index.read_bytes()
|
||||
@@ -316,6 +412,51 @@ class PortalHandler(BaseHTTPRequestHandler):
|
||||
self.send_error(404, "index.html not found")
|
||||
|
||||
def do_POST(self):
|
||||
# 1. Unified Custom Login Endpoint (/api/auth/login)
|
||||
if self.path == "/api/auth/login":
|
||||
length = int(self.headers.get("Content-Length", "0"))
|
||||
raw = self.rfile.read(length).decode("utf-8") if length > 0 else "{}"
|
||||
try:
|
||||
body = json.loads(raw)
|
||||
except Exception:
|
||||
body = {}
|
||||
username = str(body.get("username", "")).strip()
|
||||
password = str(body.get("password", ""))
|
||||
|
||||
if username == AUTH_USER and password == AUTH_PASS:
|
||||
token = create_sso_token(username)
|
||||
host = self.headers.get("Host", "")
|
||||
headers = []
|
||||
# Set cross-subdomain cookie for *.961504.xyz (works for both nav.961504.xyz, agy.961504.xyz, *.home.961504.xyz)
|
||||
if "961504.xyz" in host:
|
||||
headers.append(
|
||||
(
|
||||
"Set-Cookie",
|
||||
f"{COOKIE_NAME}={token}; Domain=.961504.xyz; Path=/; Max-Age={COOKIE_MAX_AGE}; HttpOnly; Secure; SameSite=Lax",
|
||||
)
|
||||
)
|
||||
else:
|
||||
headers.append(
|
||||
(
|
||||
"Set-Cookie",
|
||||
f"{COOKIE_NAME}={token}; Path=/; Max-Age={COOKIE_MAX_AGE}; HttpOnly; SameSite=Lax",
|
||||
)
|
||||
)
|
||||
self._send_json({"ok": True, "username": username}, status=200, extra_headers=headers)
|
||||
else:
|
||||
self._send_json({"ok": False, "message": "用户名或访问密码不正确"}, status=401)
|
||||
return
|
||||
|
||||
# 2. Logout Endpoint (/api/auth/logout)
|
||||
if self.path == "/api/auth/logout":
|
||||
headers = [
|
||||
("Set-Cookie", f"{COOKIE_NAME}=; Domain=.961504.xyz; Path=/; Max-Age=0; HttpOnly; Secure; SameSite=Lax"),
|
||||
("Set-Cookie", f"{COOKIE_NAME}=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax"),
|
||||
]
|
||||
self._send_json({"ok": True}, status=200, extra_headers=headers)
|
||||
return
|
||||
|
||||
# 3. Operations Actions
|
||||
if self.path == "/api/action/backup_nas":
|
||||
out = run_cmd("/Users/ixvii0iv/homelab/scripts/backup-to-nas.sh", timeout=15.0)
|
||||
with _cache_lock:
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { usePortalStore } from './store/usePortalStore';
|
||||
import { TopRibbon } from './components/TopRibbon';
|
||||
import { ServiceCard } from './components/ServiceCard';
|
||||
import { SshShelf } from './components/SshShelf';
|
||||
import { CommandPalette } from './components/CommandPalette';
|
||||
import { AgyTerminalModal } from './components/AgyTerminalModal';
|
||||
import { AuthGateCard } from './components/AuthGateModal';
|
||||
import { StorybookWorkbench } from './components/StorybookWorkbench';
|
||||
import { LAYOUT_PRESETS } from './design-system/tokens';
|
||||
import type { ServiceGroup } from './types/telemetry';
|
||||
@@ -21,6 +22,12 @@ export const App: React.FC = () => {
|
||||
routeMode,
|
||||
} = usePortalStore();
|
||||
|
||||
const [authRedirect, setAuthRedirect] = useState<string | null>(() => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
return params.get('auth_redirect');
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fetchTelemetry();
|
||||
const timer = setInterval(fetchTelemetry, 3000);
|
||||
@@ -45,7 +52,8 @@ export const App: React.FC = () => {
|
||||
return '443 免端口 HTTPS 直达 (*.961504.xyz)';
|
||||
}, [getEffectiveMode, routeMode]);
|
||||
|
||||
const gridClass = LAYOUT_PRESETS[layoutPreset]?.gridClass || LAYOUT_PRESETS['homepage-3col'].gridClass;
|
||||
const gridClass =
|
||||
LAYOUT_PRESETS[layoutPreset]?.gridClass || LAYOUT_PRESETS['homepage-3col'].gridClass;
|
||||
|
||||
const serviceGroups = useMemo<ServiceGroup[]>(() => {
|
||||
const t = telemetry;
|
||||
@@ -235,6 +243,22 @@ export const App: React.FC = () => {
|
||||
|
||||
{/* 5. Embedded AGY Cloud Terminal Modal */}
|
||||
<AgyTerminalModal />
|
||||
|
||||
{/* 6. Custom SSO Auth Gate Modal (Replaces Browser Native Basic Auth Popup!) */}
|
||||
{authRedirect && (
|
||||
<div className="fixed inset-0 z-50 bg-black/75 backdrop-blur-sm flex items-center justify-center p-4">
|
||||
<AuthGateCard
|
||||
targetUrl={authRedirect}
|
||||
onSuccess={() => {
|
||||
window.location.href = authRedirect;
|
||||
}}
|
||||
onCancel={() => {
|
||||
setAuthRedirect(null);
|
||||
window.history.replaceState({}, '', '/');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { usePortalStore } from '../store/usePortalStore';
|
||||
import { AuthGateCard } from './AuthGateModal';
|
||||
|
||||
export const AgyTerminalModal: React.FC = () => {
|
||||
const { showAgyModal, setShowAgyModal, getEffectiveMode } = usePortalStore();
|
||||
|
||||
if (!showAgyModal) return null;
|
||||
const [authChecked, setAuthChecked] = useState(false);
|
||||
const [authenticated, setAuthenticated] = useState(false);
|
||||
|
||||
const mode = getEffectiveMode();
|
||||
const url =
|
||||
@@ -14,6 +15,28 @@ export const AgyTerminalModal: React.FC = () => {
|
||||
? 'https://agy.home.961504.xyz:10443'
|
||||
: 'https://agy.961504.xyz';
|
||||
|
||||
useEffect(() => {
|
||||
if (!showAgyModal) return;
|
||||
if (mode === 'lan') {
|
||||
setAuthenticated(true);
|
||||
setAuthChecked(true);
|
||||
return;
|
||||
}
|
||||
setAuthChecked(false);
|
||||
fetch('/api/auth/status', { credentials: 'include' })
|
||||
.then((r) => r.json())
|
||||
.then((d) => {
|
||||
setAuthenticated(Boolean(d.authenticated));
|
||||
setAuthChecked(true);
|
||||
})
|
||||
.catch(() => {
|
||||
setAuthenticated(false);
|
||||
setAuthChecked(true);
|
||||
});
|
||||
}, [showAgyModal, mode]);
|
||||
|
||||
if (!showAgyModal) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 bg-black/75 backdrop-blur-sm flex items-center justify-center p-3 sm:p-6">
|
||||
<div className="w-full h-full max-w-6xl hl-card flex flex-col overflow-hidden shadow-2xl">
|
||||
@@ -45,7 +68,22 @@ export const AgyTerminalModal: React.FC = () => {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<iframe src={url} title="AGY Cloud Workbench" className="w-full flex-1 bg-black border-0" />
|
||||
|
||||
{!authChecked ? (
|
||||
<div className="flex-1 flex items-center justify-center text-xs font-mono-num" style={{ color: 'var(--text-muted)' }}>
|
||||
正在校验 HomeLab SSO 通行证...
|
||||
</div>
|
||||
) : !authenticated ? (
|
||||
<div className="flex-1 flex items-center justify-center p-4" style={{ backgroundColor: 'var(--bg-page)' }}>
|
||||
<AuthGateCard
|
||||
targetUrl={url}
|
||||
onSuccess={() => setAuthenticated(true)}
|
||||
onCancel={() => setShowAgyModal(false)}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<iframe src={url} title="AGY Cloud Workbench" className="w-full flex-1 bg-black border-0" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Check, Eye, EyeOff, Lock, ShieldCheck, Terminal, User } from 'lucide-react';
|
||||
|
||||
interface AuthGateCardProps {
|
||||
targetUrl?: string;
|
||||
onSuccess?: () => void;
|
||||
onCancel?: () => void;
|
||||
embedded?: boolean;
|
||||
}
|
||||
|
||||
export const AuthGateCard: React.FC<AuthGateCardProps> = ({
|
||||
targetUrl = 'https://agy.961504.xyz',
|
||||
onSuccess,
|
||||
onCancel,
|
||||
embedded = false,
|
||||
}) => {
|
||||
const [username, setUsername] = useState('ixvii0iv');
|
||||
const [password, setPassword] = useState('');
|
||||
const [showPass, setShowPass] = useState(false);
|
||||
const [rememberMe, setRememberMe] = useState(true);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!username.trim() || !password) {
|
||||
setErrorMsg('请输入用户名与访问密钥');
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
setErrorMsg(null);
|
||||
try {
|
||||
const res = await fetch('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ username: username.trim(), password, remember: rememberMe }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (res.ok && data.ok) {
|
||||
onSuccess?.();
|
||||
} else {
|
||||
setErrorMsg(data.message || '认证未通过,请检查密码');
|
||||
}
|
||||
} catch {
|
||||
setErrorMsg('网络请求异常,请稍后重试');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full max-w-md hl-card p-6 space-y-5 ${
|
||||
embedded ? '' : 'shadow-2xl'
|
||||
}`}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-start justify-between gap-3 border-b hl-border pb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div
|
||||
className="w-10 h-10 rounded-xl flex items-center justify-center border hl-border shrink-0"
|
||||
style={{ backgroundColor: 'var(--accent-soft)', color: 'var(--accent)' }}
|
||||
>
|
||||
<ShieldCheck className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-sm font-bold tracking-tight">HomeLab 统一安全通行证</h3>
|
||||
<span
|
||||
className="text-[10px] font-mono-num px-1.5 py-0.5 rounded font-semibold"
|
||||
style={{ backgroundColor: 'var(--success-soft)', color: 'var(--success)' }}
|
||||
>
|
||||
SSO 2.0
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs font-mono-num mt-0.5 truncate max-w-[260px]" style={{ color: 'var(--text-muted)' }}>
|
||||
{targetUrl}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-semibold" style={{ color: 'var(--text-muted)' }}>
|
||||
管理员账号 (Username)
|
||||
</label>
|
||||
<div className="hl-input-group">
|
||||
<User className="w-4 h-4 shrink-0" style={{ color: 'var(--text-subtle)' }} />
|
||||
<input
|
||||
type="text"
|
||||
autoComplete="username"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
placeholder="输入管理员账号 (如 ixvii0iv)"
|
||||
className="font-mono-num"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<label className="block text-xs font-semibold" style={{ color: 'var(--text-muted)' }}>
|
||||
访问通行密钥 (Access Key)
|
||||
</label>
|
||||
<span className="text-[10px] font-mono-num" style={{ color: 'var(--text-subtle)' }}>
|
||||
与 Mac mini 密码一致
|
||||
</span>
|
||||
</div>
|
||||
<div className="hl-input-group">
|
||||
<Lock className="w-4 h-4 shrink-0" style={{ color: 'var(--text-subtle)' }} />
|
||||
<input
|
||||
type={showPass ? 'text' : 'password'}
|
||||
autoComplete="current-password"
|
||||
autoFocus
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="输入访问密钥..."
|
||||
className="font-mono-num"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPass(!showPass)}
|
||||
className="p-1 rounded hover:opacity-80 cursor-pointer"
|
||||
style={{ color: 'var(--text-muted)' }}
|
||||
title={showPass ? '隐藏密码' : '显示密码'}
|
||||
>
|
||||
{showPass ? <EyeOff className="w-3.5 h-3.5" /> : <Eye className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Custom Checkbox */}
|
||||
<div className="flex items-center justify-between pt-0.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRememberMe(!rememberMe)}
|
||||
className="flex items-center gap-2 text-xs cursor-pointer select-none"
|
||||
style={{ color: 'var(--text-muted)' }}
|
||||
>
|
||||
<span
|
||||
className="w-4 h-4 rounded flex items-center justify-center border transition-colors"
|
||||
style={
|
||||
rememberMe
|
||||
? {
|
||||
backgroundColor: 'var(--accent)',
|
||||
borderColor: 'var(--accent)',
|
||||
color: '#ffffff',
|
||||
}
|
||||
: {
|
||||
backgroundColor: 'var(--bg-muted)',
|
||||
borderColor: 'var(--border-color)',
|
||||
}
|
||||
}
|
||||
>
|
||||
{rememberMe && <Check className="w-3 h-3" />}
|
||||
</span>
|
||||
<span>在此设备保持 30 天免密通行 (*.961504.xyz)</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{errorMsg && (
|
||||
<div
|
||||
className="px-3 py-2 rounded-lg text-xs font-medium border"
|
||||
style={{
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
||||
borderColor: 'rgba(239, 68, 68, 0.3)',
|
||||
color: '#ef4444',
|
||||
}}
|
||||
>
|
||||
{errorMsg}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center justify-end gap-2.5 pt-2">
|
||||
{onCancel && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="hl-btn-outline px-4 py-2 text-xs font-medium cursor-pointer"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="hl-btn-primary px-5 py-2 text-xs font-semibold flex items-center gap-2 cursor-pointer"
|
||||
>
|
||||
<Terminal className="w-3.5 h-3.5" />
|
||||
<span>{loading ? '正在验证签名...' : '解锁并进入工作台'}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,14 +1,30 @@
|
||||
import React, { useState } from 'react';
|
||||
import { BookOpen, Check, Layers, Layout, Palette, Sparkles, Terminal } from 'lucide-react';
|
||||
import {
|
||||
BookOpen,
|
||||
Check,
|
||||
KeyRound,
|
||||
Layers,
|
||||
Layout,
|
||||
Palette,
|
||||
Search,
|
||||
Sparkles,
|
||||
Terminal,
|
||||
} from 'lucide-react';
|
||||
import { LAYOUT_PRESETS, THEME_PALETTES, type LayoutPresetId } from '../design-system/tokens';
|
||||
import { usePortalStore } from '../store/usePortalStore';
|
||||
import { AuthGateCard } from './AuthGateModal';
|
||||
import { ServiceCard } from './ServiceCard';
|
||||
import { SshShelf } from './SshShelf';
|
||||
|
||||
type StoryId = 'layout-architecture' | 'theme-tokens' | 'service-card' | 'ssh-shelf';
|
||||
type StoryId =
|
||||
| 'layout-architecture'
|
||||
| 'theme-tokens'
|
||||
| 'form-inputs'
|
||||
| 'service-card'
|
||||
| 'ssh-shelf';
|
||||
|
||||
export const StorybookWorkbench: React.FC = () => {
|
||||
const [activeStory, setActiveStory] = useState<StoryId>('layout-architecture');
|
||||
const [activeStory, setActiveStory] = useState<StoryId>('form-inputs');
|
||||
const {
|
||||
theme,
|
||||
resolvedTheme,
|
||||
@@ -17,12 +33,17 @@ export const StorybookWorkbench: React.FC = () => {
|
||||
setLayoutPreset,
|
||||
setViewMode,
|
||||
telemetry,
|
||||
showToast,
|
||||
} = usePortalStore();
|
||||
|
||||
// Interactive Playground Props for ServiceCard story
|
||||
const [demoOnline, setDemoOnline] = useState(true);
|
||||
const [demoAction, setDemoAction] = useState<'drawer' | 'backup' | undefined>('drawer');
|
||||
|
||||
// Interactive Playground Props for Form Inputs story
|
||||
const [demoSearch, setDemoSearch] = useState('');
|
||||
const [demoHost, setDemoHost] = useState('192.168.31.164');
|
||||
|
||||
const stories: Array<{ id: StoryId; group: string; title: string; icon: React.ReactNode }> = [
|
||||
{
|
||||
id: 'layout-architecture',
|
||||
@@ -36,16 +57,22 @@ export const StorybookWorkbench: React.FC = () => {
|
||||
title: '02. 双主题色板与自动切换规范',
|
||||
icon: <Palette className="w-3.5 h-3.5" />,
|
||||
},
|
||||
{
|
||||
id: 'form-inputs',
|
||||
group: 'COMPONENTS / 核心组件',
|
||||
title: '03. Input & AuthGate 输入框与登录弹窗',
|
||||
icon: <KeyRound className="w-3.5 h-3.5" />,
|
||||
},
|
||||
{
|
||||
id: 'service-card',
|
||||
group: 'COMPONENTS / 核心组件',
|
||||
title: '03. ServiceCard 内联遥测卡片',
|
||||
title: '04. ServiceCard 内联遥测卡片',
|
||||
icon: <Layers className="w-3.5 h-3.5" />,
|
||||
},
|
||||
{
|
||||
id: 'ssh-shelf',
|
||||
group: 'COMPONENTS / 核心组件',
|
||||
title: '04. SshShelf 快捷指令栏',
|
||||
title: '05. SshShelf 快捷指令栏',
|
||||
icon: <Terminal className="w-3.5 h-3.5" />,
|
||||
},
|
||||
];
|
||||
@@ -60,7 +87,7 @@ export const StorybookWorkbench: React.FC = () => {
|
||||
<BookOpen className="w-4 h-4" style={{ color: 'var(--accent)' }} />
|
||||
<span className="text-xs font-bold uppercase tracking-wider">Storybook 组件库</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-mono-num px-1.5 py-0.5 rounded hl-muted">v3.1</span>
|
||||
<span className="text-[10px] font-mono-num px-1.5 py-0.5 rounded hl-muted">v3.2</span>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
@@ -295,7 +322,93 @@ export const StorybookWorkbench: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* STORY 3: ServiceCard Interactive Playground */}
|
||||
{/* STORY 3: Custom Form Inputs & AuthGate Card */}
|
||||
{activeStory === 'form-inputs' && (
|
||||
<div className="hl-card p-6 space-y-6">
|
||||
<div className="border-b hl-border pb-4 flex items-center justify-between">
|
||||
<div>
|
||||
<span
|
||||
className="text-[11px] font-mono-num uppercase tracking-wider"
|
||||
style={{ color: 'var(--accent)' }}
|
||||
>
|
||||
Components / Form Controls & SSO Auth Gate
|
||||
</span>
|
||||
<h2 className="text-lg font-bold mt-0.5">
|
||||
统一自定义输入框 (`.hl-input`) 与 SSO 认证卡片(彻底禁用浏览器原生弹窗)
|
||||
</h2>
|
||||
</div>
|
||||
<KeyRound className="w-4 h-4" style={{ color: 'var(--accent)' }} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
|
||||
{/* Left: Input Primitives Showcase */}
|
||||
<div className="p-5 rounded-xl hl-muted border hl-border space-y-4">
|
||||
<div className="text-xs font-bold uppercase tracking-wider" style={{ color: 'var(--text-muted)' }}>
|
||||
1. 基础表单输入组件规范 (`.hl-input` / `.hl-input-group`)
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium" style={{ color: 'var(--text-muted)' }}>
|
||||
带前缀图标与快捷键提示的搜索框
|
||||
</label>
|
||||
<div className="hl-input-group">
|
||||
<Search className="w-4 h-4 shrink-0" style={{ color: 'var(--text-subtle)' }} />
|
||||
<input
|
||||
type="text"
|
||||
value={demoSearch}
|
||||
onChange={(e) => setDemoSearch(e.target.value)}
|
||||
placeholder="搜索服务、SSH 指令或节点..."
|
||||
/>
|
||||
<kbd
|
||||
className="px-1.5 py-0.5 text-[10px] font-mono-num rounded hl-card border hl-border"
|
||||
style={{ color: 'var(--text-muted)' }}
|
||||
>
|
||||
⌘K
|
||||
</kbd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium" style={{ color: 'var(--text-muted)' }}>
|
||||
等宽字体 IP / 域名输入框 (`.hl-input .font-mono-num`)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={demoHost}
|
||||
onChange={(e) => setDemoHost(e.target.value)}
|
||||
className="hl-input font-mono-num"
|
||||
placeholder="192.168.31.164"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-3 rounded-lg hl-card text-[11px] leading-relaxed space-y-1" style={{ color: 'var(--text-muted)' }}>
|
||||
<div className="font-semibold" style={{ color: 'var(--text-main)' }}>
|
||||
为什么不再出现浏览器默认输入框和弹窗?
|
||||
</div>
|
||||
<p>
|
||||
1. 全局 CSS 已设置 <code>appearance: none</code> 与自定义聚焦光环{' '}
|
||||
<code>box-shadow: 0 0 0 3px var(--accent-soft)</code>,并覆盖了 Chrome 自动填充的黄色背景。
|
||||
</p>
|
||||
<p>
|
||||
2. Caddy 网关已移除 <code>basicauth</code>,改用 <code>forward_auth</code> 对接右侧的{' '}
|
||||
<strong>HomeLab SSO 2.0 统一认证卡片</strong>,一次登录全域名 30 天免密通行。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Live AuthGateCard Preview */}
|
||||
<div className="flex flex-col items-center">
|
||||
<AuthGateCard
|
||||
embedded
|
||||
targetUrl="https://agy.961504.xyz"
|
||||
onSuccess={() => showToast('SSO 认证成功!已签发 30 天全域名通行 Cookie')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* STORY 4: ServiceCard Interactive Playground */}
|
||||
{activeStory === 'service-card' && (
|
||||
<div className="hl-card p-6 space-y-6">
|
||||
<div className="border-b hl-border pb-4 flex items-center justify-between">
|
||||
@@ -366,7 +479,7 @@ export const StorybookWorkbench: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* STORY 4: SshShelf */}
|
||||
{/* STORY 5: SshShelf */}
|
||||
{activeStory === 'ssh-shelf' && (
|
||||
<div className="hl-card p-6 space-y-6">
|
||||
<div className="border-b hl-border pb-4">
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
/* =========================================================================
|
||||
HomeLab Console V3 (React + Vite + TypeScript + Zustand + Tailwind v4)
|
||||
Architecture: gethomepage.dev (Top Ribbon + 3-Col Rows + Inline Widgets)
|
||||
Design System: shadcn/ui + Raycast Command Palette + 4 Official Themes
|
||||
Architecture: gethomepage.dev (Two-Tier AppShell + 3-Col Rows + Inline Widgets)
|
||||
Design System: shadcn/ui + Catppuccin/Linear + Custom Form Controls & Auth Gate
|
||||
========================================================================= */
|
||||
:root,
|
||||
[data-theme="zinc-dark"] {
|
||||
[data-theme="dark"] {
|
||||
--bg-page: #09090b;
|
||||
--bg-card: #121215;
|
||||
--bg-widget: #16161a;
|
||||
@@ -21,13 +21,13 @@
|
||||
--primary: #fafafa;
|
||||
--primary-fg: #09090b;
|
||||
--accent: #3b82f6;
|
||||
--accent-soft: rgba(59, 130, 246, 0.14);
|
||||
--accent-soft: rgba(59, 130, 246, 0.16);
|
||||
--success: #10b981;
|
||||
--success-soft: rgba(16, 185, 129, 0.14);
|
||||
--card-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.5);
|
||||
--card-shadow: 0 4px 16px -4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
[data-theme="zinc-light"] {
|
||||
[data-theme="light"] {
|
||||
--bg-page: #f8fafc;
|
||||
--bg-card: #ffffff;
|
||||
--bg-widget: #f8fafc;
|
||||
@@ -42,54 +42,12 @@
|
||||
--primary: #0f172a;
|
||||
--primary-fg: #ffffff;
|
||||
--accent: #2563eb;
|
||||
--accent-soft: rgba(37, 99, 235, 0.08);
|
||||
--accent-soft: rgba(37, 99, 235, 0.12);
|
||||
--success: #10b981;
|
||||
--success-soft: rgba(16, 185, 129, 0.1);
|
||||
--card-shadow: 0 1px 3px 0 rgba(15, 23, 42, 0.04), 0 1px 2px -1px rgba(15, 23, 42, 0.03);
|
||||
}
|
||||
|
||||
[data-theme="catppuccin"] {
|
||||
--bg-page: #11111b;
|
||||
--bg-card: #1e1e2e;
|
||||
--bg-widget: #181825;
|
||||
--bg-muted: #313244;
|
||||
--bg-hover: #242438;
|
||||
--text-main: #cdd6f4;
|
||||
--text-muted: #a6adc8;
|
||||
--text-subtle: #6c7086;
|
||||
--border-color: #313244;
|
||||
--border-subtle: rgba(205, 214, 244, 0.06);
|
||||
--border-hover: #45475a;
|
||||
--primary: #cba6f7;
|
||||
--primary-fg: #11111b;
|
||||
--accent: #89b4fa;
|
||||
--accent-soft: rgba(137, 180, 250, 0.15);
|
||||
--success: #a6e3a1;
|
||||
--success-soft: rgba(166, 227, 161, 0.15);
|
||||
--card-shadow: 0 4px 16px -4px rgba(17, 17, 27, 0.6);
|
||||
}
|
||||
|
||||
[data-theme="nord"] {
|
||||
--bg-page: #242933;
|
||||
--bg-card: #2e3440;
|
||||
--bg-widget: #292e39;
|
||||
--bg-muted: #3b4252;
|
||||
--bg-hover: #353c4a;
|
||||
--text-main: #eceff4;
|
||||
--text-muted: #d8dee9;
|
||||
--text-subtle: #81a1c1;
|
||||
--border-color: #3b4252;
|
||||
--border-subtle: rgba(236, 239, 244, 0.06);
|
||||
--border-hover: #4c566a;
|
||||
--primary: #88c0d0;
|
||||
--primary-fg: #2e3440;
|
||||
--accent: #88c0d0;
|
||||
--accent-soft: rgba(136, 192, 208, 0.15);
|
||||
--success: #a3be8c;
|
||||
--success-soft: rgba(163, 190, 140, 0.15);
|
||||
--card-shadow: 0 4px 12px -2px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background-color: var(--bg-page);
|
||||
@@ -98,6 +56,94 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
Global Browser Default Input Reset & Custom Input System (.hl-input)
|
||||
彻底禁用浏览器原生丑陋的 input 边框、外发光与黄色自动填充背景
|
||||
========================================================================= */
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
input:-webkit-autofill,
|
||||
input:-webkit-autofill:hover,
|
||||
input:-webkit-autofill:focus,
|
||||
textarea:-webkit-autofill {
|
||||
-webkit-text-fill-color: var(--text-main) !important;
|
||||
-webkit-box-shadow: 0 0 0px 1000px var(--bg-muted) inset !important;
|
||||
transition: background-color 5000s ease-in-out 0s;
|
||||
}
|
||||
|
||||
.hl-input {
|
||||
width: 100%;
|
||||
background-color: var(--bg-muted);
|
||||
color: var(--text-main);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.625rem;
|
||||
padding: 0.55rem 0.75rem;
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.25rem;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.hl-input::placeholder {
|
||||
color: var(--text-subtle);
|
||||
}
|
||||
|
||||
.hl-input:hover {
|
||||
border-color: var(--border-hover);
|
||||
}
|
||||
|
||||
.hl-input:focus,
|
||||
.hl-input:focus-visible {
|
||||
background-color: var(--bg-card);
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px var(--accent-soft);
|
||||
}
|
||||
|
||||
.hl-input-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
background-color: var(--bg-muted);
|
||||
color: var(--text-main);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.625rem;
|
||||
padding: 0 0.75rem;
|
||||
height: 2.375rem;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.hl-input-group:hover {
|
||||
border-color: var(--border-hover);
|
||||
}
|
||||
|
||||
.hl-input-group:focus-within {
|
||||
background-color: var(--bg-card);
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px var(--accent-soft);
|
||||
}
|
||||
|
||||
.hl-input-group input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: var(--text-main);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.hl-input-group input::placeholder {
|
||||
color: var(--text-subtle);
|
||||
}
|
||||
|
||||
.font-mono-num {
|
||||
font-family: "JetBrains Mono", "SF Mono", Menlo, monospace;
|
||||
font-variant-numeric: tabular-nums;
|
||||
@@ -141,11 +187,14 @@ body {
|
||||
color: var(--primary-fg);
|
||||
font-weight: 500;
|
||||
border-radius: 0.5rem;
|
||||
transition: opacity 0.15s ease;
|
||||
transition: opacity 0.15s ease, transform 0.1s ease;
|
||||
}
|
||||
.hl-btn-primary:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.hl-btn-primary:active {
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
.hl-btn-outline {
|
||||
background-color: var(--bg-card);
|
||||
|
||||
Reference in new issue
Block a user