diff --git a/server/public/assets/index-BqgbVRB7.js b/server/public/assets/index-BqgbVRB7.js deleted file mode 100644 index 8423e4dc..00000000 --- a/server/public/assets/index-BqgbVRB7.js +++ /dev/null @@ -1,11 +0,0 @@ -(function(){const i=document.createElement("link").relList;if(i&&i.supports&&i.supports("modulepreload"))return;for(const f of document.querySelectorAll('link[rel="modulepreload"]'))r(f);new MutationObserver(f=>{for(const d of f)if(d.type==="childList")for(const m of d.addedNodes)m.tagName==="LINK"&&m.rel==="modulepreload"&&r(m)}).observe(document,{childList:!0,subtree:!0});function c(f){const d={};return f.integrity&&(d.integrity=f.integrity),f.referrerPolicy&&(d.referrerPolicy=f.referrerPolicy),f.crossOrigin==="use-credentials"?d.credentials="include":f.crossOrigin==="anonymous"?d.credentials="omit":d.credentials="same-origin",d}function r(f){if(f.ep)return;f.ep=!0;const d=c(f);fetch(f.href,d)}})();var Vc={exports:{}},qa={};var Ad;function Ip(){if(Ad)return qa;Ad=1;var s=Symbol.for("react.transitional.element"),i=Symbol.for("react.fragment");function c(r,f,d){var m=null;if(d!==void 0&&(m=""+d),f.key!==void 0&&(m=""+f.key),"key"in f){d={};for(var b in f)b!=="key"&&(d[b]=f[b])}else d=f;return f=d.ref,{$$typeof:s,type:r,key:m,ref:f!==void 0?f:null,props:d}}return qa.Fragment=i,qa.jsx=c,qa.jsxs=c,qa}var Rd;function e0(){return Rd||(Rd=1,Vc.exports=Ip()),Vc.exports}var x=e0(),Zc={exports:{}},F={};var Nd;function t0(){if(Nd)return F;Nd=1;var s=Symbol.for("react.transitional.element"),i=Symbol.for("react.portal"),c=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),d=Symbol.for("react.consumer"),m=Symbol.for("react.context"),b=Symbol.for("react.forward_ref"),y=Symbol.for("react.suspense"),v=Symbol.for("react.memo"),C=Symbol.for("react.lazy"),N=Symbol.for("react.activity"),j=Symbol.iterator;function w(S){return S===null||typeof S!="object"?null:(S=j&&S[j]||S["@@iterator"],typeof S=="function"?S:null)}var H={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Y=Object.assign,G={};function X(S,B,L){this.props=S,this.context=B,this.refs=G,this.updater=L||H}X.prototype.isReactComponent={},X.prototype.setState=function(S,B){if(typeof S!="object"&&typeof S!="function"&&S!=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,S,B,"setState")},X.prototype.forceUpdate=function(S){this.updater.enqueueForceUpdate(this,S,"forceUpdate")};function V(){}V.prototype=X.prototype;function J(S,B,L){this.props=S,this.context=B,this.refs=G,this.updater=L||H}var de=J.prototype=new V;de.constructor=J,Y(de,X.prototype),de.isPureReactComponent=!0;var Te=Array.isArray;function qe(){}var ee={H:null,A:null,T:null,S:null},Le=Object.prototype.hasOwnProperty;function Ne(S,B,L){var Z=L.ref;return{$$typeof:s,type:S,key:B,ref:Z!==void 0?Z:null,props:L}}function it(S,B){return Ne(S.type,B,S.props)}function ut(S){return typeof S=="object"&&S!==null&&S.$$typeof===s}function Fe(S){var B={"=":"=0",":":"=2"};return"$"+S.replace(/[=:]/g,function(L){return B[L]})}var jl=/\/+/g;function Gt(S,B){return typeof S=="object"&&S!==null&&S.key!=null?Fe(""+S.key):B.toString(36)}function Ct(S){switch(S.status){case"fulfilled":return S.value;case"rejected":throw S.reason;default:switch(typeof S.status=="string"?S.then(qe,qe):(S.status="pending",S.then(function(B){S.status==="pending"&&(S.status="fulfilled",S.value=B)},function(B){S.status==="pending"&&(S.status="rejected",S.reason=B)})),S.status){case"fulfilled":return S.value;case"rejected":throw S.reason}}throw S}function M(S,B,L,Z,P){var le=typeof S;(le==="undefined"||le==="boolean")&&(S=null);var he=!1;if(S===null)he=!0;else switch(le){case"bigint":case"string":case"number":he=!0;break;case"object":switch(S.$$typeof){case s:case i:he=!0;break;case C:return he=S._init,M(he(S._payload),B,L,Z,P)}}if(he)return P=P(S),he=Z===""?"."+Gt(S,0):Z,Te(P)?(L="",he!=null&&(L=he.replace(jl,"$&/")+"/"),M(P,B,L,"",function(Zn){return Zn})):P!=null&&(ut(P)&&(P=it(P,L+(P.key==null||S&&S.key===P.key?"":(""+P.key).replace(jl,"$&/")+"/")+he)),B.push(P)),1;he=0;var $e=Z===""?".":Z+":";if(Te(S))for(var ze=0;ze>>1,Se=M[pe];if(0>>1;pef(L,W))Zf(P,L)?(M[pe]=P,M[Z]=W,pe=Z):(M[pe]=L,M[B]=W,pe=B);else if(Zf(P,W))M[pe]=P,M[Z]=W,pe=Z;else break e}}return q}function f(M,q){var W=M.sortIndex-q.sortIndex;return W!==0?W:M.id-q.id}if(s.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var d=performance;s.unstable_now=function(){return d.now()}}else{var m=Date,b=m.now();s.unstable_now=function(){return m.now()-b}}var y=[],v=[],C=1,N=null,j=3,w=!1,H=!1,Y=!1,G=!1,X=typeof setTimeout=="function"?setTimeout:null,V=typeof clearTimeout=="function"?clearTimeout:null,J=typeof setImmediate<"u"?setImmediate:null;function de(M){for(var q=c(v);q!==null;){if(q.callback===null)r(v);else if(q.startTime<=M)r(v),q.sortIndex=q.expirationTime,i(y,q);else break;q=c(v)}}function Te(M){if(Y=!1,de(M),!H)if(c(y)!==null)H=!0,qe||(qe=!0,Fe());else{var q=c(v);q!==null&&Ct(Te,q.startTime-M)}}var qe=!1,ee=-1,Le=5,Ne=-1;function it(){return G?!0:!(s.unstable_now()-NeM&&it());){var pe=N.callback;if(typeof pe=="function"){N.callback=null,j=N.priorityLevel;var Se=pe(N.expirationTime<=M);if(M=s.unstable_now(),typeof Se=="function"){N.callback=Se,de(M),q=!0;break t}N===c(y)&&r(y),de(M)}else r(y);N=c(y)}if(N!==null)q=!0;else{var S=c(v);S!==null&&Ct(Te,S.startTime-M),q=!1}}break e}finally{N=null,j=W,w=!1}q=void 0}}finally{q?Fe():qe=!1}}}var Fe;if(typeof J=="function")Fe=function(){J(ut)};else if(typeof MessageChannel<"u"){var jl=new MessageChannel,Gt=jl.port2;jl.port1.onmessage=ut,Fe=function(){Gt.postMessage(null)}}else Fe=function(){X(ut,0)};function Ct(M,q){ee=X(function(){M(s.unstable_now())},q)}s.unstable_IdlePriority=5,s.unstable_ImmediatePriority=1,s.unstable_LowPriority=4,s.unstable_NormalPriority=3,s.unstable_Profiling=null,s.unstable_UserBlockingPriority=2,s.unstable_cancelCallback=function(M){M.callback=null},s.unstable_forceFrameRate=function(M){0>M||125pe?(M.sortIndex=W,i(v,M),c(y)===null&&M===c(v)&&(Y?(V(ee),ee=-1):Y=!0,Ct(Te,W-pe))):(M.sortIndex=Se,i(y,M),H||w||(H=!0,qe||(qe=!0,Fe()))),M},s.unstable_shouldYield=it,s.unstable_wrapCallback=function(M){var q=j;return function(){var W=j;j=q;try{return M.apply(this,arguments)}finally{j=W}}}})(Jc)),Jc}var zd;function n0(){return zd||(zd=1,kc.exports=l0()),kc.exports}var $c={exports:{}},Je={};var Md;function a0(){if(Md)return Je;Md=1;var s=or();function i(y){var v="https://react.dev/errors/"+y;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(i){console.error(i)}}return s(),$c.exports=a0(),$c.exports}var Ud;function u0(){if(Ud)return La;Ud=1;var s=n0(),i=or(),c=i0();function r(e){var t="https://react.dev/errors/"+e;if(1Se||(e.current=pe[Se],pe[Se]=null,Se--)}function L(e,t){Se++,pe[Se]=e.current,e.current=t}var Z=S(null),P=S(null),le=S(null),he=S(null);function $e(e,t){switch(L(le,t),L(P,e),L(Z,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Jh(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Jh(t),e=$h(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}B(Z),L(Z,e)}function ze(){B(Z),B(P),B(le)}function Zn(e){e.memoizedState!==null&&L(he,e);var t=Z.current,l=$h(t,e.type);t!==l&&(L(P,e),L(Z,l))}function ka(e){P.current===e&&(B(Z),B(P)),he.current===e&&(B(he),wa._currentValue=W)}var Ru,Er;function Hl(e){if(Ru===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);Ru=t&&t[1]||"",Er=-1)":-1a||p[n]!==A[a]){var z=` -`+p[n].replace(" at new "," at ");return e.displayName&&z.includes("")&&(z=z.replace("",e.displayName)),z}while(1<=n&&0<=a);break}}}finally{Nu=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Hl(l):""}function zm(e,t){switch(e.tag){case 26:case 27:case 5:return Hl(e.type);case 16:return Hl("Lazy");case 13:return e.child!==t&&t!==null?Hl("Suspense Fallback"):Hl("Suspense");case 19:return Hl("SuspenseList");case 0:case 15:return Ou(e.type,!1);case 11:return Ou(e.type.render,!1);case 1:return Ou(e.type,!0);case 31:return Hl("Activity");default:return""}}function _r(e){try{var t="",l=null;do t+=zm(e,l),l=e,e=e.return;while(e);return t}catch(n){return` -Error generating stack: `+n.message+` -`+n.stack}}var Cu=Object.prototype.hasOwnProperty,zu=s.unstable_scheduleCallback,Mu=s.unstable_cancelCallback,Mm=s.unstable_shouldYield,Dm=s.unstable_requestPaint,st=s.unstable_now,Um=s.unstable_getCurrentPriorityLevel,Tr=s.unstable_ImmediatePriority,Ar=s.unstable_UserBlockingPriority,Ja=s.unstable_NormalPriority,wm=s.unstable_LowPriority,Rr=s.unstable_IdlePriority,Bm=s.log,jm=s.unstable_setDisableYieldValue,Kn=null,ct=null;function ol(e){if(typeof Bm=="function"&&jm(e),ct&&typeof ct.setStrictMode=="function")try{ct.setStrictMode(Kn,e)}catch{}}var rt=Math.clz32?Math.clz32:Lm,Hm=Math.log,qm=Math.LN2;function Lm(e){return e>>>=0,e===0?32:31-(Hm(e)/qm|0)|0}var $a=256,Wa=262144,Fa=4194304;function ql(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Pa(e,t,l){var n=e.pendingLanes;if(n===0)return 0;var a=0,u=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var h=n&134217727;return h!==0?(n=h&~u,n!==0?a=ql(n):(o&=h,o!==0?a=ql(o):l||(l=h&~e,l!==0&&(a=ql(l))))):(h=n&~u,h!==0?a=ql(h):o!==0?a=ql(o):l||(l=n&~e,l!==0&&(a=ql(l)))),a===0?0:t!==0&&t!==a&&(t&u)===0&&(u=a&-a,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:a}function kn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Ym(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Nr(){var e=Fa;return Fa<<=1,(Fa&62914560)===0&&(Fa=4194304),e}function Du(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Jn(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Xm(e,t,l,n,a,u){var o=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var h=e.entanglements,p=e.expirationTimes,A=e.hiddenUpdates;for(l=o&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var km=/[\n"\\]/g;function bt(e){return e.replace(km,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function qu(e,t,l,n,a,u,o,h){e.name="",o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.type=o:e.removeAttribute("type"),t!=null?o==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+gt(t)):e.value!==""+gt(t)&&(e.value=""+gt(t)):o!=="submit"&&o!=="reset"||e.removeAttribute("value"),t!=null?Lu(e,o,gt(t)):l!=null?Lu(e,o,gt(l)):n!=null&&e.removeAttribute("value"),a==null&&u!=null&&(e.defaultChecked=!!u),a!=null&&(e.checked=a&&typeof a!="function"&&typeof a!="symbol"),h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"?e.name=""+gt(h):e.removeAttribute("name")}function Yr(e,t,l,n,a,u,o,h){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){Hu(e);return}l=l!=null?""+gt(l):"",t=t!=null?""+gt(t):l,h||t===e.value||(e.value=t),e.defaultValue=t}n=n??a,n=typeof n!="function"&&typeof n!="symbol"&&!!n,e.checked=h?e.checked:!!n,e.defaultChecked=!!n,o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"&&(e.name=o),Hu(e)}function Lu(e,t,l){t==="number"&&ti(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function rn(e,t,l,n){if(e=e.options,t){t={};for(var a=0;a"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Vu=!1;if(Zt)try{var Pn={};Object.defineProperty(Pn,"passive",{get:function(){Vu=!0}}),window.addEventListener("test",Pn,Pn),window.removeEventListener("test",Pn,Pn)}catch{Vu=!1}var hl=null,Zu=null,ni=null;function kr(){if(ni)return ni;var e,t=Zu,l=t.length,n,a="value"in hl?hl.value:hl.textContent,u=a.length;for(e=0;e=ta),Ir=" ",eo=!1;function to(e,t){switch(e){case"keyup":return xy.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function lo(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var dn=!1;function _y(e,t){switch(e){case"compositionend":return lo(t);case"keypress":return t.which!==32?null:(eo=!0,Ir);case"textInput":return e=t.data,e===Ir&&eo?null:e;default:return null}}function Ty(e,t){if(dn)return e==="compositionend"||!Wu&&to(e,t)?(e=kr(),ni=Zu=hl=null,dn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=n}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=oo(l)}}function ho(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?ho(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function mo(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=ti(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=ti(e.document)}return t}function Iu(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Dy=Zt&&"documentMode"in document&&11>=document.documentMode,mn=null,es=null,ia=null,ts=!1;function yo(e,t,l){var n=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;ts||mn==null||mn!==ti(n)||(n=mn,"selectionStart"in n&&Iu(n)?n={start:n.selectionStart,end:n.selectionEnd}:(n=(n.ownerDocument&&n.ownerDocument.defaultView||window).getSelection(),n={anchorNode:n.anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset}),ia&&aa(ia,n)||(ia=n,n=Wi(es,"onSelect"),0>=o,a-=o,Bt=1<<32-rt(t)+a|l<te?(ue=K,K=null):ue=K.sibling;var oe=R(E,K,T[te],D);if(oe===null){K===null&&(K=ue);break}e&&K&&oe.alternate===null&&t(E,K),g=u(oe,g,te),re===null?k=oe:re.sibling=oe,re=oe,K=ue}if(te===T.length)return l(E,K),se&&kt(E,te),k;if(K===null){for(;tete?(ue=K,K=null):ue=K.sibling;var wl=R(E,K,oe.value,D);if(wl===null){K===null&&(K=ue);break}e&&K&&wl.alternate===null&&t(E,K),g=u(wl,g,te),re===null?k=wl:re.sibling=wl,re=wl,K=ue}if(oe.done)return l(E,K),se&&kt(E,te),k;if(K===null){for(;!oe.done;te++,oe=T.next())oe=U(E,oe.value,D),oe!==null&&(g=u(oe,g,te),re===null?k=oe:re.sibling=oe,re=oe);return se&&kt(E,te),k}for(K=n(K);!oe.done;te++,oe=T.next())oe=O(K,E,te,oe.value,D),oe!==null&&(e&&oe.alternate!==null&&K.delete(oe.key===null?te:oe.key),g=u(oe,g,te),re===null?k=oe:re.sibling=oe,re=oe);return e&&K.forEach(function(Pp){return t(E,Pp)}),se&&kt(E,te),k}function be(E,g,T,D){if(typeof T=="object"&&T!==null&&T.type===Y&&T.key===null&&(T=T.props.children),typeof T=="object"&&T!==null){switch(T.$$typeof){case w:e:{for(var k=T.key;g!==null;){if(g.key===k){if(k=T.type,k===Y){if(g.tag===7){l(E,g.sibling),D=a(g,T.props.children),D.return=E,E=D;break e}}else if(g.elementType===k||typeof k=="object"&&k!==null&&k.$$typeof===Le&&$l(k)===g.type){l(E,g.sibling),D=a(g,T.props),fa(D,T),D.return=E,E=D;break e}l(E,g);break}else t(E,g);g=g.sibling}T.type===Y?(D=Vl(T.props.children,E.mode,D,T.key),D.return=E,E=D):(D=di(T.type,T.key,T.props,null,E.mode,D),fa(D,T),D.return=E,E=D)}return o(E);case H:e:{for(k=T.key;g!==null;){if(g.key===k)if(g.tag===4&&g.stateNode.containerInfo===T.containerInfo&&g.stateNode.implementation===T.implementation){l(E,g.sibling),D=a(g,T.children||[]),D.return=E,E=D;break e}else{l(E,g);break}else t(E,g);g=g.sibling}D=cs(T,E.mode,D),D.return=E,E=D}return o(E);case Le:return T=$l(T),be(E,g,T,D)}if(Ct(T))return Q(E,g,T,D);if(Fe(T)){if(k=Fe(T),typeof k!="function")throw Error(r(150));return T=k.call(T),$(E,g,T,D)}if(typeof T.then=="function")return be(E,g,Si(T),D);if(T.$$typeof===J)return be(E,g,pi(E,T),D);xi(E,T)}return typeof T=="string"&&T!==""||typeof T=="number"||typeof T=="bigint"?(T=""+T,g!==null&&g.tag===6?(l(E,g.sibling),D=a(g,T),D.return=E,E=D):(l(E,g),D=ss(T,E.mode,D),D.return=E,E=D),o(E)):l(E,g)}return function(E,g,T,D){try{oa=0;var k=be(E,g,T,D);return An=null,k}catch(K){if(K===Tn||K===gi)throw K;var re=ft(29,K,null,E.mode);return re.lanes=D,re.return=E,re}finally{}}}var Fl=qo(!0),Lo=qo(!1),vl=!1;function Ss(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function xs(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function gl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function bl(e,t,l){var n=e.updateQueue;if(n===null)return null;if(n=n.shared,(fe&2)!==0){var a=n.pending;return a===null?t.next=t:(t.next=a.next,a.next=t),n.pending=t,t=hi(e),Eo(e,null,l),t}return fi(e,n,t,l),hi(e)}function ha(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var n=t.lanes;n&=e.pendingLanes,l|=n,t.lanes=l,Cr(e,l)}}function Es(e,t){var l=e.updateQueue,n=e.alternate;if(n!==null&&(n=n.updateQueue,l===n)){var a=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var o={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?a=u=o:u=u.next=o,l=l.next}while(l!==null);u===null?a=u=t:u=u.next=t}else a=u=t;l={baseState:n.baseState,firstBaseUpdate:a,lastBaseUpdate:u,shared:n.shared,callbacks:n.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var _s=!1;function da(){if(_s){var e=_n;if(e!==null)throw e}}function ma(e,t,l,n){_s=!1;var a=e.updateQueue;vl=!1;var u=a.firstBaseUpdate,o=a.lastBaseUpdate,h=a.shared.pending;if(h!==null){a.shared.pending=null;var p=h,A=p.next;p.next=null,o===null?u=A:o.next=A,o=p;var z=e.alternate;z!==null&&(z=z.updateQueue,h=z.lastBaseUpdate,h!==o&&(h===null?z.firstBaseUpdate=A:h.next=A,z.lastBaseUpdate=p))}if(u!==null){var U=a.baseState;o=0,z=A=p=null,h=u;do{var R=h.lane&-536870913,O=R!==h.lane;if(O?(ie&R)===R:(n&R)===R){R!==0&&R===En&&(_s=!0),z!==null&&(z=z.next={lane:0,tag:h.tag,payload:h.payload,callback:null,next:null});e:{var Q=e,$=h;R=t;var be=l;switch($.tag){case 1:if(Q=$.payload,typeof Q=="function"){U=Q.call(be,U,R);break e}U=Q;break e;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=$.payload,R=typeof Q=="function"?Q.call(be,U,R):Q,R==null)break e;U=N({},U,R);break e;case 2:vl=!0}}R=h.callback,R!==null&&(e.flags|=64,O&&(e.flags|=8192),O=a.callbacks,O===null?a.callbacks=[R]:O.push(R))}else O={lane:R,tag:h.tag,payload:h.payload,callback:h.callback,next:null},z===null?(A=z=O,p=U):z=z.next=O,o|=R;if(h=h.next,h===null){if(h=a.shared.pending,h===null)break;O=h,h=O.next,O.next=null,a.lastBaseUpdate=O,a.shared.pending=null}}while(!0);z===null&&(p=U),a.baseState=p,a.firstBaseUpdate=A,a.lastBaseUpdate=z,u===null&&(a.shared.lanes=0),Tl|=o,e.lanes=o,e.memoizedState=U}}function Yo(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function Xo(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var o=M.T,h={};M.T=h,Gs(e,!1,t,l);try{var p=a(),A=M.S;if(A!==null&&A(h,p),p!==null&&typeof p=="object"&&typeof p.then=="function"){var z=Xy(p,n);va(e,t,z,pt(e))}else va(e,t,n,pt(e))}catch(U){va(e,t,{then:function(){},status:"rejected",reason:U},pt())}finally{q.p=u,o!==null&&h.types!==null&&(o.types=h.types),M.T=o}}function ky(){}function Ys(e,t,l,n){if(e.tag!==5)throw Error(r(476));var a=Sf(e).queue;bf(e,a,t,W,l===null?ky:function(){return xf(e),l(n)})}function Sf(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:W,baseState:W,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ft,lastRenderedState:W},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ft,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function xf(e){var t=Sf(e);t.next===null&&(t=e.alternate.memoizedState),va(e,t.next.queue,{},pt())}function Xs(){return Ze(wa)}function Ef(){return De().memoizedState}function _f(){return De().memoizedState}function Jy(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=pt();e=gl(l);var n=bl(t,e,l);n!==null&&(at(n,t,l),ha(n,t,l)),t={cache:ps()},e.payload=t;return}t=t.return}}function $y(e,t,l){var n=pt();l={lane:n,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Mi(e)?Af(t,l):(l=is(e,t,l,n),l!==null&&(at(l,e,n),Rf(l,t,n)))}function Tf(e,t,l){var n=pt();va(e,t,l,n)}function va(e,t,l,n){var a={lane:n,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Mi(e))Af(t,a);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var o=t.lastRenderedState,h=u(o,l);if(a.hasEagerState=!0,a.eagerState=h,ot(h,o))return fi(e,t,a,0),xe===null&&oi(),!1}catch{}finally{}if(l=is(e,t,a,n),l!==null)return at(l,e,n),Rf(l,t,n),!0}return!1}function Gs(e,t,l,n){if(n={lane:2,revertLane:Sc(),gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Mi(e)){if(t)throw Error(r(479))}else t=is(e,l,n,2),t!==null&&at(t,e,2)}function Mi(e){var t=e.alternate;return e===I||t!==null&&t===I}function Af(e,t){Nn=Ti=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Rf(e,t,l){if((l&4194048)!==0){var n=t.lanes;n&=e.pendingLanes,l|=n,t.lanes=l,Cr(e,l)}}var ga={readContext:Ze,use:Ni,useCallback:Oe,useContext:Oe,useEffect:Oe,useImperativeHandle:Oe,useLayoutEffect:Oe,useInsertionEffect:Oe,useMemo:Oe,useReducer:Oe,useRef:Oe,useState:Oe,useDebugValue:Oe,useDeferredValue:Oe,useTransition:Oe,useSyncExternalStore:Oe,useId:Oe,useHostTransitionStatus:Oe,useFormState:Oe,useActionState:Oe,useOptimistic:Oe,useMemoCache:Oe,useCacheRefresh:Oe};ga.useEffectEvent=Oe;var Nf={readContext:Ze,use:Ni,useCallback:function(e,t){return We().memoizedState=[e,t===void 0?null:t],e},useContext:Ze,useEffect:of,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,Ci(4194308,4,mf.bind(null,t,e),l)},useLayoutEffect:function(e,t){return Ci(4194308,4,e,t)},useInsertionEffect:function(e,t){Ci(4,2,e,t)},useMemo:function(e,t){var l=We();t=t===void 0?null:t;var n=e();if(Pl){ol(!0);try{e()}finally{ol(!1)}}return l.memoizedState=[n,t],n},useReducer:function(e,t,l){var n=We();if(l!==void 0){var a=l(t);if(Pl){ol(!0);try{l(t)}finally{ol(!1)}}}else a=t;return n.memoizedState=n.baseState=a,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:a},n.queue=e,e=e.dispatch=$y.bind(null,I,e),[n.memoizedState,e]},useRef:function(e){var t=We();return e={current:e},t.memoizedState=e},useState:function(e){e=Bs(e);var t=e.queue,l=Tf.bind(null,I,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:qs,useDeferredValue:function(e,t){var l=We();return Ls(l,e,t)},useTransition:function(){var e=Bs(!1);return e=bf.bind(null,I,e.queue,!0,!1),We().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var n=I,a=We();if(se){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),xe===null)throw Error(r(349));(ie&127)!==0||ko(n,t,l)}a.memoizedState=l;var u={value:l,getSnapshot:t};return a.queue=u,of($o.bind(null,n,u,e),[e]),n.flags|=2048,Cn(9,{destroy:void 0},Jo.bind(null,n,u,l,t),null),l},useId:function(){var e=We(),t=xe.identifierPrefix;if(se){var l=jt,n=Bt;l=(n&~(1<<32-rt(n)-1)).toString(32)+l,t="_"+t+"R_"+l,l=Ai++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof n.is=="string"?o.createElement("select",{is:n.is}):o.createElement("select"),n.multiple?u.multiple=!0:n.size&&(u.size=n.size);break;default:u=typeof n.is=="string"?o.createElement(a,{is:n.is}):o.createElement(a)}}u[Qe]=t,u[Pe]=n;e:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)u.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break e;for(;o.sibling===null;){if(o.return===null||o.return===t)break e;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=u;e:switch(ke(u,a,n),a){case"button":case"input":case"select":case"textarea":n=!!n.autoFocus;break e;case"img":n=!0;break e;default:n=!1}n&&It(t)}}return _e(t),lc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==n&&It(t);else{if(typeof n!="string"&&t.stateNode===null)throw Error(r(166));if(e=le.current,Sn(t)){if(e=t.stateNode,l=t.memoizedProps,n=null,a=Ve,a!==null)switch(a.tag){case 27:case 5:n=a.memoizedProps}e[Qe]=t,e=!!(e.nodeValue===l||n!==null&&n.suppressHydrationWarning===!0||Kh(e.nodeValue,l)),e||yl(t,!0)}else e=Fi(e).createTextNode(n),e[Qe]=t,t.stateNode=e}return _e(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(n=Sn(t),l!==null){if(e===null){if(!n)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[Qe]=t}else Zl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;_e(t),e=!1}else l=hs(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(dt(t),t):(dt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return _e(t),null;case 13:if(n=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Sn(t),n!==null&&n.dehydrated!==null){if(e===null){if(!a)throw Error(r(318));if(a=t.memoizedState,a=a!==null?a.dehydrated:null,!a)throw Error(r(317));a[Qe]=t}else Zl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;_e(t),a=!1}else a=hs(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(dt(t),t):(dt(t),null)}return dt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=n!==null,e=e!==null&&e.memoizedState!==null,l&&(n=t.child,a=null,n.alternate!==null&&n.alternate.memoizedState!==null&&n.alternate.memoizedState.cachePool!==null&&(a=n.alternate.memoizedState.cachePool.pool),u=null,n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(u=n.memoizedState.cachePool.pool),u!==a&&(n.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),ji(t,t.updateQueue),_e(t),null);case 4:return ze(),e===null&&Tc(t.stateNode.containerInfo),_e(t),null;case 10:return $t(t.type),_e(t),null;case 19:if(B(Me),n=t.memoizedState,n===null)return _e(t),null;if(a=(t.flags&128)!==0,u=n.rendering,u===null)if(a)Sa(n,!1);else{if(Ce!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=_i(e),u!==null){for(t.flags|=128,Sa(n,!1),e=u.updateQueue,t.updateQueue=e,ji(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)_o(l,e),l=l.sibling;return L(Me,Me.current&1|2),se&&kt(t,n.treeForkCount),t.child}e=e.sibling}n.tail!==null&&st()>Xi&&(t.flags|=128,a=!0,Sa(n,!1),t.lanes=4194304)}else{if(!a)if(e=_i(u),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,ji(t,e),Sa(n,!0),n.tail===null&&n.tailMode==="hidden"&&!u.alternate&&!se)return _e(t),null}else 2*st()-n.renderingStartTime>Xi&&l!==536870912&&(t.flags|=128,a=!0,Sa(n,!1),t.lanes=4194304);n.isBackwards?(u.sibling=t.child,t.child=u):(e=n.last,e!==null?e.sibling=u:t.child=u,n.last=u)}return n.tail!==null?(e=n.tail,n.rendering=e,n.tail=e.sibling,n.renderingStartTime=st(),e.sibling=null,l=Me.current,L(Me,a?l&1|2:l&1),se&&kt(t,n.treeForkCount),e):(_e(t),null);case 22:case 23:return dt(t),As(),n=t.memoizedState!==null,e!==null?e.memoizedState!==null!==n&&(t.flags|=8192):n&&(t.flags|=8192),n?(l&536870912)!==0&&(t.flags&128)===0&&(_e(t),t.subtreeFlags&6&&(t.flags|=8192)):_e(t),l=t.updateQueue,l!==null&&ji(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),n=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(n=t.memoizedState.cachePool.pool),n!==l&&(t.flags|=2048),e!==null&&B(Jl),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),$t(Ue),_e(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function ep(e,t){switch(os(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return $t(Ue),ze(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return ka(t),null;case 31:if(t.memoizedState!==null){if(dt(t),t.alternate===null)throw Error(r(340));Zl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(dt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Zl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return B(Me),null;case 4:return ze(),null;case 10:return $t(t.type),null;case 22:case 23:return dt(t),As(),e!==null&&B(Jl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return $t(Ue),null;case 25:return null;default:return null}}function Ff(e,t){switch(os(t),t.tag){case 3:$t(Ue),ze();break;case 26:case 27:case 5:ka(t);break;case 4:ze();break;case 31:t.memoizedState!==null&&dt(t);break;case 13:dt(t);break;case 19:B(Me);break;case 10:$t(t.type);break;case 22:case 23:dt(t),As(),e!==null&&B(Jl);break;case 24:$t(Ue)}}function xa(e,t){try{var l=t.updateQueue,n=l!==null?l.lastEffect:null;if(n!==null){var a=n.next;l=a;do{if((l.tag&e)===e){n=void 0;var u=l.create,o=l.inst;n=u(),o.destroy=n}l=l.next}while(l!==a)}}catch(h){ye(t,t.return,h)}}function El(e,t,l){try{var n=t.updateQueue,a=n!==null?n.lastEffect:null;if(a!==null){var u=a.next;n=u;do{if((n.tag&e)===e){var o=n.inst,h=o.destroy;if(h!==void 0){o.destroy=void 0,a=t;var p=l,A=h;try{A()}catch(z){ye(a,p,z)}}}n=n.next}while(n!==u)}}catch(z){ye(t,t.return,z)}}function Pf(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{Xo(t,l)}catch(n){ye(e,e.return,n)}}}function If(e,t,l){l.props=Il(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(n){ye(e,t,n)}}function Ea(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var n=e.stateNode;break;case 30:n=e.stateNode;break;default:n=e.stateNode}typeof l=="function"?e.refCleanup=l(n):l.current=n}}catch(a){ye(e,t,a)}}function Ht(e,t){var l=e.ref,n=e.refCleanup;if(l!==null)if(typeof n=="function")try{n()}catch(a){ye(e,t,a)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(a){ye(e,t,a)}else l.current=null}function eh(e){var t=e.type,l=e.memoizedProps,n=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&n.focus();break e;case"img":l.src?n.src=l.src:l.srcSet&&(n.srcset=l.srcSet)}}catch(a){ye(e,e.return,a)}}function nc(e,t,l){try{var n=e.stateNode;Ep(n,e.type,l,t),n[Pe]=t}catch(a){ye(e,e.return,a)}}function th(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Cl(e.type)||e.tag===4}function ac(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||th(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Cl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function ic(e,t,l){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=Vt));else if(n!==4&&(n===27&&Cl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(ic(e,t,l),e=e.sibling;e!==null;)ic(e,t,l),e=e.sibling}function Hi(e,t,l){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(n!==4&&(n===27&&Cl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Hi(e,t,l),e=e.sibling;e!==null;)Hi(e,t,l),e=e.sibling}function lh(e){var t=e.stateNode,l=e.memoizedProps;try{for(var n=e.type,a=t.attributes;a.length;)t.removeAttributeNode(a[0]);ke(t,n,l),t[Qe]=e,t[Pe]=l}catch(u){ye(e,e.return,u)}}var el=!1,je=!1,uc=!1,nh=typeof WeakSet=="function"?WeakSet:Set,Ge=null;function tp(e,t){if(e=e.containerInfo,Nc=au,e=mo(e),Iu(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var n=l.getSelection&&l.getSelection();if(n&&n.rangeCount!==0){l=n.anchorNode;var a=n.anchorOffset,u=n.focusNode;n=n.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var o=0,h=-1,p=-1,A=0,z=0,U=e,R=null;t:for(;;){for(var O;U!==l||a!==0&&U.nodeType!==3||(h=o+a),U!==u||n!==0&&U.nodeType!==3||(p=o+n),U.nodeType===3&&(o+=U.nodeValue.length),(O=U.firstChild)!==null;)R=U,U=O;for(;;){if(U===e)break t;if(R===l&&++A===a&&(h=o),R===u&&++z===n&&(p=o),(O=U.nextSibling)!==null)break;U=R,R=U.parentNode}U=O}l=h===-1||p===-1?null:{start:h,end:p}}else l=null}l=l||{start:0,end:0}}else l=null;for(Oc={focusedElem:e,selectionRange:l},au=!1,Ge=t;Ge!==null;)if(t=Ge,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Ge=e;else for(;Ge!==null;){switch(t=Ge,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),ke(u,n,l),u[Qe]=e,Xe(u),n=u;break e;case"link":var o=rd("link","href",a).get(n+(l.href||""));if(o){for(var h=0;hbe&&(o=be,be=$,$=o);var E=fo(h,$),g=fo(h,be);if(E&&g&&(O.rangeCount!==1||O.anchorNode!==E.node||O.anchorOffset!==E.offset||O.focusNode!==g.node||O.focusOffset!==g.offset)){var T=U.createRange();T.setStart(E.node,E.offset),O.removeAllRanges(),$>be?(O.addRange(T),O.extend(g.node,g.offset)):(T.setEnd(g.node,g.offset),O.addRange(T))}}}}for(U=[],O=h;O=O.parentNode;)O.nodeType===1&&U.push({element:O,left:O.scrollLeft,top:O.scrollTop});for(typeof h.focus=="function"&&h.focus(),h=0;hl?32:l,M.T=null,l=dc,dc=null;var u=Rl,o=il;if(Ye=0,wn=Rl=null,il=0,(fe&6)!==0)throw Error(r(331));var h=fe;if(fe|=4,mh(u.current),fh(u,u.current,o,l),fe=h,Oa(0,!1),ct&&typeof ct.onPostCommitFiberRoot=="function")try{ct.onPostCommitFiberRoot(Kn,u)}catch{}return!0}finally{q.p=a,M.T=n,Dh(e,t)}}function wh(e,t,l){t=xt(l,t),t=Ks(e.stateNode,t,2),e=bl(e,t,2),e!==null&&(Jn(e,2),qt(e))}function ye(e,t,l){if(e.tag===3)wh(e,e,l);else for(;t!==null;){if(t.tag===3){wh(t,e,l);break}else if(t.tag===1){var n=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof n.componentDidCatch=="function"&&(Al===null||!Al.has(n))){e=xt(l,e),l=Bf(2),n=bl(t,l,2),n!==null&&(jf(l,n,t,e),Jn(n,2),qt(n));break}}t=t.return}}function vc(e,t,l){var n=e.pingCache;if(n===null){n=e.pingCache=new ap;var a=new Set;n.set(t,a)}else a=n.get(t),a===void 0&&(a=new Set,n.set(t,a));a.has(l)||(rc=!0,a.add(l),e=rp.bind(null,e,t,l),t.then(e,e))}function rp(e,t,l){var n=e.pingCache;n!==null&&n.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,xe===e&&(ie&l)===l&&(Ce===4||Ce===3&&(ie&62914560)===ie&&300>st()-Yi?(fe&2)===0&&Bn(e,0):oc|=l,Un===ie&&(Un=0)),qt(e)}function Bh(e,t){t===0&&(t=Nr()),e=Ql(e,t),e!==null&&(Jn(e,t),qt(e))}function op(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),Bh(e,l)}function fp(e,t){var l=0;switch(e.tag){case 31:case 13:var n=e.stateNode,a=e.memoizedState;a!==null&&(l=a.retryLane);break;case 19:n=e.stateNode;break;case 22:n=e.stateNode._retryCache;break;default:throw Error(r(314))}n!==null&&n.delete(t),Bh(e,l)}function hp(e,t){return zu(e,t)}var ki=null,Hn=null,gc=!1,Ji=!1,bc=!1,Ol=0;function qt(e){e!==Hn&&e.next===null&&(Hn===null?ki=Hn=e:Hn=Hn.next=e),Ji=!0,gc||(gc=!0,mp())}function Oa(e,t){if(!bc&&Ji){bc=!0;do for(var l=!1,n=ki;n!==null;){if(e!==0){var a=n.pendingLanes;if(a===0)var u=0;else{var o=n.suspendedLanes,h=n.pingedLanes;u=(1<<31-rt(42|e)+1)-1,u&=a&~(o&~h),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,Lh(n,u))}else u=ie,u=Pa(n,n===xe?u:0,n.cancelPendingCommit!==null||n.timeoutHandle!==-1),(u&3)===0||kn(n,u)||(l=!0,Lh(n,u));n=n.next}while(l);bc=!1}}function dp(){jh()}function jh(){Ji=gc=!1;var e=0;Ol!==0&&Tp()&&(e=Ol);for(var t=st(),l=null,n=ki;n!==null;){var a=n.next,u=Hh(n,t);u===0?(n.next=null,l===null?ki=a:l.next=a,a===null&&(Hn=l)):(l=n,(e!==0||(u&3)!==0)&&(Ji=!0)),n=a}Ye!==0&&Ye!==5||Oa(e),Ol!==0&&(Ol=0)}function Hh(e,t){for(var l=e.suspendedLanes,n=e.pingedLanes,a=e.expirationTimes,u=e.pendingLanes&-62914561;0h)break;var z=p.transferSize,U=p.initiatorType;z&&kh(U)&&(p=p.responseEnd,o+=z*(p"u"?null:document;function id(e,t,l){var n=qn;if(n&&typeof t=="string"&&t){var a=bt(t);a='link[rel="'+e+'"][href="'+a+'"]',typeof l=="string"&&(a+='[crossorigin="'+l+'"]'),ad.has(a)||(ad.add(a),e={rel:e,crossOrigin:l,href:t},n.querySelector(a)===null&&(t=n.createElement("link"),ke(t,"link",e),Xe(t),n.head.appendChild(t)))}}function Up(e){ul.D(e),id("dns-prefetch",e,null)}function wp(e,t){ul.C(e,t),id("preconnect",e,t)}function Bp(e,t,l){ul.L(e,t,l);var n=qn;if(n&&e&&t){var a='link[rel="preload"][as="'+bt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(a+='[imagesrcset="'+bt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(a+='[imagesizes="'+bt(l.imageSizes)+'"]')):a+='[href="'+bt(e)+'"]';var u=a;switch(t){case"style":u=Ln(e);break;case"script":u=Yn(e)}Nt.has(u)||(e=N({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Nt.set(u,e),n.querySelector(a)!==null||t==="style"&&n.querySelector(Da(u))||t==="script"&&n.querySelector(Ua(u))||(t=n.createElement("link"),ke(t,"link",e),Xe(t),n.head.appendChild(t)))}}function jp(e,t){ul.m(e,t);var l=qn;if(l&&e){var n=t&&typeof t.as=="string"?t.as:"script",a='link[rel="modulepreload"][as="'+bt(n)+'"][href="'+bt(e)+'"]',u=a;switch(n){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Yn(e)}if(!Nt.has(u)&&(e=N({rel:"modulepreload",href:e},t),Nt.set(u,e),l.querySelector(a)===null)){switch(n){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Ua(u)))return}n=l.createElement("link"),ke(n,"link",e),Xe(n),l.head.appendChild(n)}}}function Hp(e,t,l){ul.S(e,t,l);var n=qn;if(n&&e){var a=sn(n).hoistableStyles,u=Ln(e);t=t||"default";var o=a.get(u);if(!o){var h={loading:0,preload:null};if(o=n.querySelector(Da(u)))h.loading=5;else{e=N({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Nt.get(u))&&Bc(e,l);var p=o=n.createElement("link");Xe(p),ke(p,"link",e),p._p=new Promise(function(A,z){p.onload=A,p.onerror=z}),p.addEventListener("load",function(){h.loading|=1}),p.addEventListener("error",function(){h.loading|=2}),h.loading|=4,Ii(o,t,n)}o={type:"stylesheet",instance:o,count:1,state:h},a.set(u,o)}}}function qp(e,t){ul.X(e,t);var l=qn;if(l&&e){var n=sn(l).hoistableScripts,a=Yn(e),u=n.get(a);u||(u=l.querySelector(Ua(a)),u||(e=N({src:e,async:!0},t),(t=Nt.get(a))&&jc(e,t),u=l.createElement("script"),Xe(u),ke(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},n.set(a,u))}}function Lp(e,t){ul.M(e,t);var l=qn;if(l&&e){var n=sn(l).hoistableScripts,a=Yn(e),u=n.get(a);u||(u=l.querySelector(Ua(a)),u||(e=N({src:e,async:!0,type:"module"},t),(t=Nt.get(a))&&jc(e,t),u=l.createElement("script"),Xe(u),ke(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},n.set(a,u))}}function ud(e,t,l,n){var a=(a=le.current)?Pi(a):null;if(!a)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Ln(l.href),l=sn(a).hoistableStyles,n=l.get(t),n||(n={type:"style",instance:null,count:0,state:null},l.set(t,n)),n):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Ln(l.href);var u=sn(a).hoistableStyles,o=u.get(e);if(o||(a=a.ownerDocument||a,o={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,o),(u=a.querySelector(Da(e)))&&!u._p&&(o.instance=u,o.state.loading=5),Nt.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Nt.set(e,l),u||Yp(a,e,l,o.state))),t&&n===null)throw Error(r(528,""));return o}if(t&&n!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Yn(l),l=sn(a).hoistableScripts,n=l.get(t),n||(n={type:"script",instance:null,count:0,state:null},l.set(t,n)),n):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function Ln(e){return'href="'+bt(e)+'"'}function Da(e){return'link[rel="stylesheet"]['+e+"]"}function sd(e){return N({},e,{"data-precedence":e.precedence,precedence:null})}function Yp(e,t,l,n){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?n.loading=1:(t=e.createElement("link"),n.preload=t,t.addEventListener("load",function(){return n.loading|=1}),t.addEventListener("error",function(){return n.loading|=2}),ke(t,"link",l),Xe(t),e.head.appendChild(t))}function Yn(e){return'[src="'+bt(e)+'"]'}function Ua(e){return"script[async]"+e}function cd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var n=e.querySelector('style[data-href~="'+bt(l.href)+'"]');if(n)return t.instance=n,Xe(n),n;var a=N({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return n=(e.ownerDocument||e).createElement("style"),Xe(n),ke(n,"style",a),Ii(n,l.precedence,e),t.instance=n;case"stylesheet":a=Ln(l.href);var u=e.querySelector(Da(a));if(u)return t.state.loading|=4,t.instance=u,Xe(u),u;n=sd(l),(a=Nt.get(a))&&Bc(n,a),u=(e.ownerDocument||e).createElement("link"),Xe(u);var o=u;return o._p=new Promise(function(h,p){o.onload=h,o.onerror=p}),ke(u,"link",n),t.state.loading|=4,Ii(u,l.precedence,e),t.instance=u;case"script":return u=Yn(l.src),(a=e.querySelector(Ua(u)))?(t.instance=a,Xe(a),a):(n=l,(a=Nt.get(u))&&(n=N({},l),jc(n,a)),e=e.ownerDocument||e,a=e.createElement("script"),Xe(a),ke(a,"link",n),e.head.appendChild(a),t.instance=a);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(n=t.instance,t.state.loading|=4,Ii(n,l.precedence,e));return t.instance}function Ii(e,t,l){for(var n=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),a=n.length?n[n.length-1]:null,u=a,o=0;o title"):null)}function Xp(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function fd(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function Gp(e,t,l,n){if(l.type==="stylesheet"&&(typeof n.media!="string"||matchMedia(n.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var a=Ln(n.href),u=t.querySelector(Da(a));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=tu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Xe(u);return}u=t.ownerDocument||t,n=sd(n),(a=Nt.get(a))&&Bc(n,a),u=u.createElement("link"),Xe(u);var o=u;o._p=new Promise(function(h,p){o.onload=h,o.onerror=p}),ke(u,"link",n),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=tu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var Hc=0;function Qp(e,t){return e.stylesheets&&e.count===0&&nu(e,e.stylesheets),0Hc?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(n),clearTimeout(a)}}:null}function tu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)nu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var lu=null;function nu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,lu=new Map,t.forEach(Vp,e),lu=null,tu.call(e))}function Vp(e,t){if(!(t.state.loading&4)){var l=lu.get(e);if(l)var n=l.get(null);else{l=new Map,lu.set(e,l);for(var a=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(s)}catch(i){console.error(i)}}return s(),Kc.exports=u0(),Kc.exports}var c0=s0();var Bd="popstate";function r0(s={}){function i(r,f){let{pathname:d,search:m,hash:b}=r.location;return tr("",{pathname:d,search:m,hash:b},f.state&&f.state.usr||null,f.state&&f.state.key||"default")}function c(r,f){return typeof f=="string"?f:Qa(f)}return f0(i,c,null,s)}function Re(s,i){if(s===!1||s===null||typeof s>"u")throw new Error(i)}function wt(s,i){if(!s){typeof console<"u"&&console.warn(i);try{throw new Error(i)}catch{}}}function o0(){return Math.random().toString(36).substring(2,10)}function jd(s,i){return{usr:s.state,key:s.key,idx:i}}function tr(s,i,c=null,r){return{pathname:typeof s=="string"?s:s.pathname,search:"",hash:"",...typeof i=="string"?Gn(i):i,state:c,key:i&&i.key||r||o0()}}function Qa({pathname:s="/",search:i="",hash:c=""}){return i&&i!=="?"&&(s+=i.charAt(0)==="?"?i:"?"+i),c&&c!=="#"&&(s+=c.charAt(0)==="#"?c:"#"+c),s}function Gn(s){let i={};if(s){let c=s.indexOf("#");c>=0&&(i.hash=s.substring(c),s=s.substring(0,c));let r=s.indexOf("?");r>=0&&(i.search=s.substring(r),s=s.substring(0,r)),s&&(i.pathname=s)}return i}function f0(s,i,c,r={}){let{window:f=document.defaultView,v5Compat:d=!1}=r,m=f.history,b="POP",y=null,v=C();v==null&&(v=0,m.replaceState({...m.state,idx:v},""));function C(){return(m.state||{idx:null}).idx}function N(){b="POP";let G=C(),X=G==null?null:G-v;v=G,y&&y({action:b,location:Y.location,delta:X})}function j(G,X){b="PUSH";let V=tr(Y.location,G,X);v=C()+1;let J=jd(V,v),de=Y.createHref(V);try{m.pushState(J,"",de)}catch(Te){if(Te instanceof DOMException&&Te.name==="DataCloneError")throw Te;f.location.assign(de)}d&&y&&y({action:b,location:Y.location,delta:1})}function w(G,X){b="REPLACE";let V=tr(Y.location,G,X);v=C();let J=jd(V,v),de=Y.createHref(V);m.replaceState(J,"",de),d&&y&&y({action:b,location:Y.location,delta:0})}function H(G){return h0(G)}let Y={get action(){return b},get location(){return s(f,m)},listen(G){if(y)throw new Error("A history only accepts one active listener");return f.addEventListener(Bd,N),y=G,()=>{f.removeEventListener(Bd,N),y=null}},createHref(G){return i(f,G)},createURL:H,encodeLocation(G){let X=H(G);return{pathname:X.pathname,search:X.search,hash:X.hash}},push:j,replace:w,go(G){return m.go(G)}};return Y}function h0(s,i=!1){let c="http://localhost";typeof window<"u"&&(c=window.location.origin!=="null"?window.location.origin:window.location.href),Re(c,"No window.location.(origin|href) available to create URL");let r=typeof s=="string"?s:Qa(s);return r=r.replace(/ $/,"%20"),!i&&r.startsWith("//")&&(r=c+r),new URL(r,c)}function kd(s,i,c="/"){return d0(s,i,c,!1)}function d0(s,i,c,r){let f=typeof i=="string"?Gn(i):i,d=cl(f.pathname||"/",c);if(d==null)return null;let m=Jd(s);m0(m);let b=null;for(let y=0;b==null&&y{let C={relativePath:v===void 0?m.path||"":v,caseSensitive:m.caseSensitive===!0,childrenIndex:b,route:m};if(C.relativePath.startsWith("/")){if(!C.relativePath.startsWith(r)&&y)return;Re(C.relativePath.startsWith(r),`Absolute route path "${C.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),C.relativePath=C.relativePath.slice(r.length)}let N=sl([r,C.relativePath]),j=c.concat(C);m.children&&m.children.length>0&&(Re(m.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${N}".`),Jd(m.children,i,j,N,y)),!(m.path==null&&!m.index)&&i.push({path:N,score:x0(N,m.index),routesMeta:j})};return s.forEach((m,b)=>{if(m.path===""||!m.path?.includes("?"))d(m,b);else for(let y of $d(m.path))d(m,b,!0,y)}),i}function $d(s){let i=s.split("/");if(i.length===0)return[];let[c,...r]=i,f=c.endsWith("?"),d=c.replace(/\?$/,"");if(r.length===0)return f?[d,""]:[d];let m=$d(r.join("/")),b=[];return b.push(...m.map(y=>y===""?d:[d,y].join("/"))),f&&b.push(...m),b.map(y=>s.startsWith("/")&&y===""?"/":y)}function m0(s){s.sort((i,c)=>i.score!==c.score?c.score-i.score:E0(i.routesMeta.map(r=>r.childrenIndex),c.routesMeta.map(r=>r.childrenIndex)))}var y0=/^:[\w-]+$/,p0=3,v0=2,g0=1,b0=10,S0=-2,Hd=s=>s==="*";function x0(s,i){let c=s.split("/"),r=c.length;return c.some(Hd)&&(r+=S0),i&&(r+=v0),c.filter(f=>!Hd(f)).reduce((f,d)=>f+(y0.test(d)?p0:d===""?g0:b0),r)}function E0(s,i){return s.length===i.length&&s.slice(0,-1).every((r,f)=>r===i[f])?s[s.length-1]-i[i.length-1]:0}function _0(s,i,c=!1){let{routesMeta:r}=s,f={},d="/",m=[];for(let b=0;b{if(C==="*"){let H=b[j]||"";m=d.slice(0,d.length-H.length).replace(/(.)\/+$/,"$1")}const w=b[j];return N&&!w?v[C]=void 0:v[C]=(w||"").replace(/%2F/g,"/"),v},{}),pathname:d,pathnameBase:m,pattern:s}}function T0(s,i=!1,c=!0){wt(s==="*"||!s.endsWith("*")||s.endsWith("/*"),`Route path "${s}" will be treated as if it were "${s.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${s.replace(/\*$/,"/*")}".`);let r=[],f="^"+s.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(m,b,y)=>(r.push({paramName:b,isOptional:y!=null}),y?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return s.endsWith("*")?(r.push({paramName:"*"}),f+=s==="*"||s==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):c?f+="\\/*$":s!==""&&s!=="/"&&(f+="(?:(?=\\/|$))"),[new RegExp(f,i?void 0:"i"),r]}function A0(s){try{return s.split("/").map(i=>decodeURIComponent(i).replace(/\//g,"%2F")).join("/")}catch(i){return wt(!1,`The URL path "${s}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${i}).`),s}}function cl(s,i){if(i==="/")return s;if(!s.toLowerCase().startsWith(i.toLowerCase()))return null;let c=i.endsWith("/")?i.length-1:i.length,r=s.charAt(c);return r&&r!=="/"?null:s.slice(c)||"/"}var R0=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,N0=s=>R0.test(s);function O0(s,i="/"){let{pathname:c,search:r="",hash:f=""}=typeof s=="string"?Gn(s):s,d;if(c)if(N0(c))d=c;else{if(c.includes("//")){let m=c;c=c.replace(/\/\/+/g,"/"),wt(!1,`Pathnames cannot have embedded double slashes - normalizing ${m} -> ${c}`)}c.startsWith("/")?d=qd(c.substring(1),"/"):d=qd(c,i)}else d=i;return{pathname:d,search:M0(r),hash:D0(f)}}function qd(s,i){let c=i.replace(/\/+$/,"").split("/");return s.split("/").forEach(f=>{f===".."?c.length>1&&c.pop():f!=="."&&c.push(f)}),c.length>1?c.join("/"):"/"}function Wc(s,i,c,r){return`Cannot include a '${s}' character in a manually specified \`to.${i}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${c}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function C0(s){return s.filter((i,c)=>c===0||i.route.path&&i.route.path.length>0)}function Wd(s){let i=C0(s);return i.map((c,r)=>r===i.length-1?c.pathname:c.pathnameBase)}function Fd(s,i,c,r=!1){let f;typeof s=="string"?f=Gn(s):(f={...s},Re(!f.pathname||!f.pathname.includes("?"),Wc("?","pathname","search",f)),Re(!f.pathname||!f.pathname.includes("#"),Wc("#","pathname","hash",f)),Re(!f.search||!f.search.includes("#"),Wc("#","search","hash",f)));let d=s===""||f.pathname==="",m=d?"/":f.pathname,b;if(m==null)b=c;else{let N=i.length-1;if(!r&&m.startsWith("..")){let j=m.split("/");for(;j[0]==="..";)j.shift(),N-=1;f.pathname=j.join("/")}b=N>=0?i[N]:"/"}let y=O0(f,b),v=m&&m!=="/"&&m.endsWith("/"),C=(d||m===".")&&c.endsWith("/");return!y.pathname.endsWith("/")&&(v||C)&&(y.pathname+="/"),y}var sl=s=>s.join("/").replace(/\/\/+/g,"/"),z0=s=>s.replace(/\/+$/,"").replace(/^\/*/,"/"),M0=s=>!s||s==="?"?"":s.startsWith("?")?s:"?"+s,D0=s=>!s||s==="#"?"":s.startsWith("#")?s:"#"+s;function U0(s){return s!=null&&typeof s.status=="number"&&typeof s.statusText=="string"&&typeof s.internal=="boolean"&&"data"in s}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Pd=["POST","PUT","PATCH","DELETE"];new Set(Pd);var w0=["GET",...Pd];new Set(w0);var Qn=_.createContext(null);Qn.displayName="DataRouter";var xu=_.createContext(null);xu.displayName="DataRouterState";_.createContext(!1);var Id=_.createContext({isTransitioning:!1});Id.displayName="ViewTransition";var B0=_.createContext(new Map);B0.displayName="Fetchers";var j0=_.createContext(null);j0.displayName="Await";var Xt=_.createContext(null);Xt.displayName="Navigation";var Va=_.createContext(null);Va.displayName="Location";var rl=_.createContext({outlet:null,matches:[],isDataRoute:!1});rl.displayName="Route";var fr=_.createContext(null);fr.displayName="RouteError";function H0(s,{relative:i}={}){Re(Za(),"useHref() may be used only in the context of a component.");let{basename:c,navigator:r}=_.useContext(Xt),{hash:f,pathname:d,search:m}=Ka(s,{relative:i}),b=d;return c!=="/"&&(b=d==="/"?c:sl([c,d])),r.createHref({pathname:b,search:m,hash:f})}function Za(){return _.useContext(Va)!=null}function ln(){return Re(Za(),"useLocation() may be used only in the context of a component."),_.useContext(Va).location}var em="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function tm(s){_.useContext(Xt).static||_.useLayoutEffect(s)}function q0(){let{isDataRoute:s}=_.useContext(rl);return s?F0():L0()}function L0(){Re(Za(),"useNavigate() may be used only in the context of a component.");let s=_.useContext(Qn),{basename:i,navigator:c}=_.useContext(Xt),{matches:r}=_.useContext(rl),{pathname:f}=ln(),d=JSON.stringify(Wd(r)),m=_.useRef(!1);return tm(()=>{m.current=!0}),_.useCallback((y,v={})=>{if(wt(m.current,em),!m.current)return;if(typeof y=="number"){c.go(y);return}let C=Fd(y,JSON.parse(d),f,v.relative==="path");s==null&&i!=="/"&&(C.pathname=C.pathname==="/"?i:sl([i,C.pathname])),(v.replace?c.replace:c.push)(C,v.state,v)},[i,c,d,f,s])}_.createContext(null);function Ka(s,{relative:i}={}){let{matches:c}=_.useContext(rl),{pathname:r}=ln(),f=JSON.stringify(Wd(c));return _.useMemo(()=>Fd(s,JSON.parse(f),r,i==="path"),[s,f,r,i])}function Y0(s,i){return lm(s,i)}function lm(s,i,c,r,f){Re(Za(),"useRoutes() may be used only in the context of a component.");let{navigator:d}=_.useContext(Xt),{matches:m}=_.useContext(rl),b=m[m.length-1],y=b?b.params:{},v=b?b.pathname:"/",C=b?b.pathnameBase:"/",N=b&&b.route;{let V=N&&N.path||"";nm(v,!N||V.endsWith("*")||V.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${v}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. - -Please change the parent to .`)}let j=ln(),w;if(i){let V=typeof i=="string"?Gn(i):i;Re(C==="/"||V.pathname?.startsWith(C),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${C}" but pathname "${V.pathname}" was given in the \`location\` prop.`),w=V}else w=j;let H=w.pathname||"/",Y=H;if(C!=="/"){let V=C.replace(/^\//,"").split("/");Y="/"+H.replace(/^\//,"").split("/").slice(V.length).join("/")}let G=kd(s,{pathname:Y});wt(N||G!=null,`No routes matched location "${w.pathname}${w.search}${w.hash}" `),wt(G==null||G[G.length-1].route.element!==void 0||G[G.length-1].route.Component!==void 0||G[G.length-1].route.lazy!==void 0,`Matched leaf route at location "${w.pathname}${w.search}${w.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let X=Z0(G&&G.map(V=>Object.assign({},V,{params:Object.assign({},y,V.params),pathname:sl([C,d.encodeLocation?d.encodeLocation(V.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:V.pathname]),pathnameBase:V.pathnameBase==="/"?C:sl([C,d.encodeLocation?d.encodeLocation(V.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:V.pathnameBase])})),m,c,r,f);return i&&X?_.createElement(Va.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...w},navigationType:"POP"}},X):X}function X0(){let s=W0(),i=U0(s)?`${s.status} ${s.statusText}`:s instanceof Error?s.message:JSON.stringify(s),c=s instanceof Error?s.stack:null,r="rgba(200,200,200, 0.5)",f={padding:"0.5rem",backgroundColor:r},d={padding:"2px 4px",backgroundColor:r},m=null;return console.error("Error handled by React Router default ErrorBoundary:",s),m=_.createElement(_.Fragment,null,_.createElement("p",null,"💿 Hey developer 👋"),_.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",_.createElement("code",{style:d},"ErrorBoundary")," or"," ",_.createElement("code",{style:d},"errorElement")," prop on your route.")),_.createElement(_.Fragment,null,_.createElement("h2",null,"Unexpected Application Error!"),_.createElement("h3",{style:{fontStyle:"italic"}},i),c?_.createElement("pre",{style:f},c):null,m)}var G0=_.createElement(X0,null),Q0=class extends _.Component{constructor(s){super(s),this.state={location:s.location,revalidation:s.revalidation,error:s.error}}static getDerivedStateFromError(s){return{error:s}}static getDerivedStateFromProps(s,i){return i.location!==s.location||i.revalidation!=="idle"&&s.revalidation==="idle"?{error:s.error,location:s.location,revalidation:s.revalidation}:{error:s.error!==void 0?s.error:i.error,location:i.location,revalidation:s.revalidation||i.revalidation}}componentDidCatch(s,i){this.props.onError?this.props.onError(s,i):console.error("React Router caught the following error during render",s)}render(){return this.state.error!==void 0?_.createElement(rl.Provider,{value:this.props.routeContext},_.createElement(fr.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function V0({routeContext:s,match:i,children:c}){let r=_.useContext(Qn);return r&&r.static&&r.staticContext&&(i.route.errorElement||i.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=i.route.id),_.createElement(rl.Provider,{value:s},c)}function Z0(s,i=[],c=null,r=null,f=null){if(s==null){if(!c)return null;if(c.errors)s=c.matches;else if(i.length===0&&!c.initialized&&c.matches.length>0)s=c.matches;else return null}let d=s,m=c?.errors;if(m!=null){let C=d.findIndex(N=>N.route.id&&m?.[N.route.id]!==void 0);Re(C>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(m).join(",")}`),d=d.slice(0,Math.min(d.length,C+1))}let b=!1,y=-1;if(c)for(let C=0;C=0?d=d.slice(0,y+1):d=[d[0]];break}}}let v=c&&r?(C,N)=>{r(C,{location:c.location,params:c.matches?.[0]?.params??{},errorInfo:N})}:void 0;return d.reduceRight((C,N,j)=>{let w,H=!1,Y=null,G=null;c&&(w=m&&N.route.id?m[N.route.id]:void 0,Y=N.route.errorElement||G0,b&&(y<0&&j===0?(nm("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),H=!0,G=null):y===j&&(H=!0,G=N.route.hydrateFallbackElement||null)));let X=i.concat(d.slice(0,j+1)),V=()=>{let J;return w?J=Y:H?J=G:N.route.Component?J=_.createElement(N.route.Component,null):N.route.element?J=N.route.element:J=C,_.createElement(V0,{match:N,routeContext:{outlet:C,matches:X,isDataRoute:c!=null},children:J})};return c&&(N.route.ErrorBoundary||N.route.errorElement||j===0)?_.createElement(Q0,{location:c.location,revalidation:c.revalidation,component:Y,error:w,children:V(),routeContext:{outlet:null,matches:X,isDataRoute:!0},onError:v}):V()},null)}function hr(s){return`${s} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function K0(s){let i=_.useContext(Qn);return Re(i,hr(s)),i}function k0(s){let i=_.useContext(xu);return Re(i,hr(s)),i}function J0(s){let i=_.useContext(rl);return Re(i,hr(s)),i}function dr(s){let i=J0(s),c=i.matches[i.matches.length-1];return Re(c.route.id,`${s} can only be used on routes that contain a unique "id"`),c.route.id}function $0(){return dr("useRouteId")}function W0(){let s=_.useContext(fr),i=k0("useRouteError"),c=dr("useRouteError");return s!==void 0?s:i.errors?.[c]}function F0(){let{router:s}=K0("useNavigate"),i=dr("useNavigate"),c=_.useRef(!1);return tm(()=>{c.current=!0}),_.useCallback(async(f,d={})=>{wt(c.current,em),c.current&&(typeof f=="number"?s.navigate(f):await s.navigate(f,{fromRouteId:i,...d}))},[s,i])}var Ld={};function nm(s,i,c){!i&&!Ld[s]&&(Ld[s]=!0,wt(!1,c))}_.memo(P0);function P0({routes:s,future:i,state:c,unstable_onError:r}){return lm(s,void 0,c,r,i)}function lr(s){Re(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function I0({basename:s="/",children:i=null,location:c,navigationType:r="POP",navigator:f,static:d=!1}){Re(!Za(),"You cannot render a inside another . You should never have more than one in your app.");let m=s.replace(/^\/*/,"/"),b=_.useMemo(()=>({basename:m,navigator:f,static:d,future:{}}),[m,f,d]);typeof c=="string"&&(c=Gn(c));let{pathname:y="/",search:v="",hash:C="",state:N=null,key:j="default"}=c,w=_.useMemo(()=>{let H=cl(y,m);return H==null?null:{location:{pathname:H,search:v,hash:C,state:N,key:j},navigationType:r}},[m,y,v,C,N,j,r]);return wt(w!=null,` is not able to match the URL "${y}${v}${C}" because it does not start with the basename, so the won't render anything.`),w==null?null:_.createElement(Xt.Provider,{value:b},_.createElement(Va.Provider,{children:i,value:w}))}function ev({children:s,location:i}){return Y0(nr(s),i)}function nr(s,i=[]){let c=[];return _.Children.forEach(s,(r,f)=>{if(!_.isValidElement(r))return;let d=[...i,f];if(r.type===_.Fragment){c.push.apply(c,nr(r.props.children,d));return}Re(r.type===lr,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),Re(!r.props.index||!r.props.children,"An index route cannot have child routes.");let m={id:r.props.id||d.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,middleware:r.props.middleware,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(m.children=nr(r.props.children,d)),c.push(m)}),c}var mu="get",yu="application/x-www-form-urlencoded";function Eu(s){return s!=null&&typeof s.tagName=="string"}function tv(s){return Eu(s)&&s.tagName.toLowerCase()==="button"}function lv(s){return Eu(s)&&s.tagName.toLowerCase()==="form"}function nv(s){return Eu(s)&&s.tagName.toLowerCase()==="input"}function av(s){return!!(s.metaKey||s.altKey||s.ctrlKey||s.shiftKey)}function iv(s,i){return s.button===0&&(!i||i==="_self")&&!av(s)}var fu=null;function uv(){if(fu===null)try{new FormData(document.createElement("form"),0),fu=!1}catch{fu=!0}return fu}var sv=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Fc(s){return s!=null&&!sv.has(s)?(wt(!1,`"${s}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${yu}"`),null):s}function cv(s,i){let c,r,f,d,m;if(lv(s)){let b=s.getAttribute("action");r=b?cl(b,i):null,c=s.getAttribute("method")||mu,f=Fc(s.getAttribute("enctype"))||yu,d=new FormData(s)}else if(tv(s)||nv(s)&&(s.type==="submit"||s.type==="image")){let b=s.form;if(b==null)throw new Error('Cannot submit a +

Runs Start → Dock → Full commands to ready the rover.

+
+ + {updated && Updated {updated}} +
+ +
+ +

+ Point the rover straight at the dock, about one foot away, before triggering. +

+
+ + +
+
+ +
+

Manual OI

+
+ {manualOiButtons.map((btn) => ( + + ))} +
+
+
+ +
+ +

Sensor streaming auto-starts after each OI change.

+ + ); +} + +function SpeedRow({ left, right }) { + return ( +
-

Left

-

{left}

+

Left

+

{left}

-

Right

-

{right}

+

Right

+

{right}

); } -export default function DrivePanel() { - const { roverId, speeds, stopMotors, sendOiCommand } = useDriveControls(); - +function StatusPill({ label, active }) { return ( -
-
-
-

Drive Controls

-

- {roverId ? `Driving rover ${roverId}` : 'No rover assigned'} -

-
-
- W/A/S/D: move - Shift: boost -
-
- - - -
- -
- -
-

OI Modes

-
- {oiButtons.map((btn) => ( - - ))} -
-
- -

- Sensor streaming starts automatically after each OI change. Keep this tab focused while driving. -

-
+ + {label} + ); } diff --git a/webui/src/components/MobileControls.jsx b/webui/src/components/MobileControls.jsx new file mode 100644 index 00000000..3182b7d4 --- /dev/null +++ b/webui/src/components/MobileControls.jsx @@ -0,0 +1,128 @@ +import { useCallback } from 'react'; +import { Joystick } from 'react-joystick-component'; +import { useDriveControl } from '../context/DriveControlContext.jsx'; + +function clampUnit(value = 0) { + if (typeof value !== 'number' || Number.isNaN(value)) return 0; + return Math.max(-1, Math.min(1, value)); +} + +function MobileJoystick() { + const { roverId, driveWithVector, stopMotors } = useDriveControl(); + const disabled = !roverId; + + const handleMove = useCallback( + (event = {}) => { + if (disabled) return; + const x = clampUnit(event.x ?? 0); + const y = clampUnit(event.y ?? 0); + driveWithVector({ x, y }); + }, + [disabled, driveWithVector], + ); + + const handleStop = useCallback(() => { + if (disabled) return; + driveWithVector({ x: 0, y: 0 }); + }, [disabled, driveWithVector]); + + return ( +
+
Joystick
+
+ +
+

+ Drag to drive. Release to stop sending drive commands. +

+ +
+ ); +} + +function AuxMotorControls() { + const { roverId, setAuxMotors } = useDriveControl(); + const disabled = !roverId; + + const runAllForward = () => { + if (disabled) return; + setAuxMotors({ main: 127, side: 127, vacuum: 127 }); + }; + + const stopAll = () => { + if (disabled) return; + setAuxMotors({ main: 0, side: 0, vacuum: 0 }); + }; + + const auxButtons = [ + { label: 'Main +', values: { main: 127 } }, + { label: 'Main -', values: { main: -127 } }, + { label: 'Side +', values: { side: 127 } }, + { label: 'Side -', values: { side: -127 } }, + { label: 'Vacuum Max', values: { vacuum: 127 } }, + { label: 'Vacuum Off', values: { vacuum: 0 } }, + ]; + + return ( +
+
Aux Motors
+
+ + +
+
+ {auxButtons.map((btn) => ( + + ))} +
+
+ ); +} + +export default function MobileControlsStack() { + return ( +
+ + +
+ ); +} + +export { MobileJoystick, AuxMotorControls }; diff --git a/webui/src/components/TelemetryPanel.jsx b/webui/src/components/TelemetryPanel.jsx index af75fdbd..298a1443 100644 --- a/webui/src/components/TelemetryPanel.jsx +++ b/webui/src/components/TelemetryPanel.jsx @@ -1,56 +1,56 @@ -import { useMemo } from 'react'; import { useSession } from '../context/SessionContext.jsx'; import { useTelemetryFrame } from '../context/TelemetryContext.jsx'; -function formatEntries(sensors = {}) { - return Object.entries(sensors).map(([key, value]) => ({ - key, - value: typeof value === 'object' ? JSON.stringify(value) : value, - })); +function formatMetric(value, fallback = '--') { + if (value == null || value === '') return fallback; + return value; } export default function TelemetryPanel() { const { session } = useSession(); const roverId = session?.assignment?.roverId; const frame = useTelemetryFrame(roverId); - - const entries = useMemo(() => formatEntries(frame?.sensors), [frame?.sensors]); + const sensors = frame?.sensors || {}; + const voltage = sensors.voltageMv != null ? (sensors.voltageMv / 1000).toFixed(2) : null; + const current = sensors.currentMa != null ? (sensors.currentMa / 1000).toFixed(2) : null; + const charge = sensors.batteryChargeMah; + const capacity = sensors.batteryCapacityMah; + const updated = frame?.receivedAt ? new Date(frame.receivedAt).toLocaleTimeString() : null; + const rawSnippet = frame?.raw ? (frame.raw.length > 80 ? `${frame.raw.slice(0, 80)}…` : frame.raw) : null; return ( -
-
-
-

Telemetry

-

- {roverId ? `Rover ${roverId}` : 'No rover assigned'} -

-
-

- {frame?.receivedAt ? `Updated ${new Date(frame.receivedAt).toLocaleTimeString()}` : 'Waiting…'} -

-
- {entries.length === 0 ? ( -

- {roverId ? 'No sensor frames yet.' : 'Assignment required to view sensors.'} -

+
+
+ Telemetry + {updated ? `Updated ${updated}` : 'waiting'} +
+ {!roverId ? ( +

Assignment required to view sensors.

+ ) : !frame ? ( +

No sensor frames yet.

) : ( -
- {entries.map(({ key, value }) => ( -
-
{key}
-
{value}
-
- ))} -
- )} - {frame?.raw && ( -
-

Raw frame

-
-            {frame.raw}
-          
+
+ + + + +
)} + {rawSnippet && ( +
+          {rawSnippet}
+        
+ )}
); } + +function Metric({ label, value }) { + return ( +
+ {label} + {value} +
+ ); +} diff --git a/webui/src/components/VideoTile.jsx b/webui/src/components/VideoTile.jsx index 9035c543..8558a4be 100644 --- a/webui/src/components/VideoTile.jsx +++ b/webui/src/components/VideoTile.jsx @@ -4,7 +4,7 @@ import { WhepPlayer } from '../lib/whepPlayer.js'; const RESTART_DELAY_MS = 2000; const UNMUTE_RETRY_MS = 3000; -export default function VideoTile({ sessionInfo, label, forceMute = false }) { +export default function VideoTile({ sessionInfo, label, forceMute = false, telemetryFrame, batteryConfig }) { const videoRef = useRef(null); const restartTimer = useRef(null); const unmuteTimer = useRef(null); @@ -12,6 +12,13 @@ export default function VideoTile({ sessionInfo, label, forceMute = false }) { const [detail, setDetail] = useState(null); const [restartToken, setRestartToken] = useState(0); const [muted, setMuted] = useState(true); + const sensors = telemetryFrame?.sensors; + const batteryCharge = sensors?.batteryChargeMah ?? null; + const batteryCapacity = sensors?.batteryCapacityMah ?? null; + const wheelOvercurrents = sensors?.wheelOvercurrents || null; + const overcurrentActive = Boolean( + wheelOvercurrents && Object.values(wheelOvercurrents).some((value) => Boolean(value)), + ); const scheduleRestart = useCallback(() => { clearTimeout(restartTimer.current); @@ -22,19 +29,31 @@ export default function VideoTile({ sessionInfo, label, forceMute = false }) { (delay = 0) => { if (forceMute) return; clearTimeout(unmuteTimer.current); - unmuteTimer.current = setTimeout(async () => { + + const scheduleRetry = () => { + clearTimeout(unmuteTimer.current); + unmuteTimer.current = setTimeout(() => { + if (!forceMute) { + tryPlay(); + } + }, UNMUTE_RETRY_MS); + }; + + const tryPlay = async () => { const video = videoRef.current; if (!video) return; try { video.muted = false; await video.play(); setMuted(false); - } catch (err) { + } catch { video.muted = true; setMuted(true); - attemptUnmute(UNMUTE_RETRY_MS); + scheduleRetry(); } - }, delay); + }; + + unmuteTimer.current = setTimeout(tryPlay, delay); }, [forceMute], ); @@ -55,13 +74,11 @@ export default function VideoTile({ sessionInfo, label, forceMute = false }) { useEffect(() => { if (!sessionInfo?.url || !videoRef.current) { - setStatus('waiting'); - setDetail(null); return undefined; } let active = true; let player; - setMuted(true); + const resetMuteId = setTimeout(() => setMuted(true), 0); const handleStatus = (nextStatus, info) => { if (!active) return; setStatus(nextStatus); @@ -87,6 +104,7 @@ export default function VideoTile({ sessionInfo, label, forceMute = false }) { return () => { active = false; + clearTimeout(resetMuteId); player?.stop(); }; }, [sessionInfo?.url, sessionInfo?.token, restartToken, scheduleRestart]); @@ -97,16 +115,17 @@ export default function VideoTile({ sessionInfo, label, forceMute = false }) { } }, [status, sessionInfo?.url, scheduleRestart]); - const renderedStatus = - status === 'error' - ? `Error: ${detail || 'unknown'}` - : detail - ? `${status} (${detail})` - : status; + const renderedStatus = !sessionInfo?.url + ? 'waiting' + : status === 'error' + ? `Error: ${detail || 'unknown'}` + : detail + ? `${status} (${detail})` + : status; return ( -
-
+
+
-
- {label}{' '} - {renderedStatus} + +
+ {label} · {renderedStatus} +
+
+ ); +} + +function BatteryBar({ charge, capacity, config }) { + if (charge == null || !config?.full || config.warn == null) { + return null; + } + const span = config.full - config.warn; + if (span <= 0) return null; + const normalized = (charge - config.warn) / span; + const percent = Math.min(1, Math.max(0, normalized)); + const percentDisplay = Math.round(percent * 100); + const depleted = normalized <= 0; + const urgent = config.urgent != null && charge <= config.urgent; + const barClass = depleted + ? 'bg-red-500 animate-pulse' + : urgent + ? 'bg-amber-400' + : 'bg-emerald-500'; + const capText = capacity ? `${charge}/${capacity}` : `${charge}`; + return ( +
+
+ Battery + {capText} mAh +
+
+
+
+
+ ); +} + +function HudOverlay({ frame }) { + const sensors = frame?.sensors; + const bumps = sensors?.bumpsAndWheelDrops || {}; + const [now, setNow] = useState(() => Date.now()); + + useEffect(() => { + const interval = setInterval(() => setNow(Date.now()), 150); + return () => clearInterval(interval); + }, []); + + const pulse = frame?.receivedAt ? now - frame.receivedAt < 200 : false; + + const bumperBadges = [ + { label: 'B-L', active: bumps.bumpLeft }, + { label: 'B-R', active: bumps.bumpRight }, + ]; + const wheelBadges = [ + { label: 'DROP L', active: bumps.wheelDropLeft }, + { label: 'DROP R', active: bumps.wheelDropRight }, + ]; + + return ( +
+
+
+ + SENSORS +
+
+ {bumperBadges.map((badge) => ( + + ))} +
+
+
+ {wheelBadges.map((badge) => ( + + ))} +
+
+ ); +} + +function HudBadge({ label, active }) { + return ( + + {label} + + ); +} + +function OvercurrentOverlay({ active }) { + if (!active) return null; + return ( +
+
+ Overcurrent
); diff --git a/webui/src/context/DriveControlContext.jsx b/webui/src/context/DriveControlContext.jsx new file mode 100644 index 00000000..121d63ba --- /dev/null +++ b/webui/src/context/DriveControlContext.jsx @@ -0,0 +1,19 @@ +import { createContext, useContext } from 'react'; +import { useDriveControls as useDriveControlsHook } from '../hooks/useDriveControls.js'; + +/* eslint-disable react-refresh/only-export-components */ + +const DriveControlContext = createContext(null); + +export function DriveControlProvider({ children }) { + const controls = useDriveControlsHook(); + return {children}; +} + +export function useDriveControl() { + const context = useContext(DriveControlContext); + if (!context) { + throw new Error('useDriveControl must be used within DriveControlProvider'); + } + return context; +} diff --git a/webui/src/context/SessionContext.jsx b/webui/src/context/SessionContext.jsx index 6dec238f..8027f6eb 100644 --- a/webui/src/context/SessionContext.jsx +++ b/webui/src/context/SessionContext.jsx @@ -1,3 +1,5 @@ +/* eslint-disable react-refresh/only-export-components */ + import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useSocket } from './SocketContext.jsx'; @@ -61,7 +63,13 @@ export function SessionProvider({ children }) { socket.on('log:init', handleLogInit); socket.on('log:entry', handleLogEntry); socket.on('alert:new', (payload = {}) => { - setAlerts((prev) => [...prev.slice(-49), payload]); + setAlerts((prev) => [ + ...prev.slice(-49), + { + ...payload, + receivedAt: Date.now(), + }, + ]); }); return () => { socket.off('session:sync', handleSession); diff --git a/webui/src/context/SocketContext.jsx b/webui/src/context/SocketContext.jsx index c464e304..fd96a846 100644 --- a/webui/src/context/SocketContext.jsx +++ b/webui/src/context/SocketContext.jsx @@ -1,3 +1,5 @@ +/* eslint-disable react-refresh/only-export-components */ + // src/context/SocketContext.jsx import { createContext, useContext } from "react"; import { socket } from "../lib/socket"; diff --git a/webui/src/context/TelemetryContext.jsx b/webui/src/context/TelemetryContext.jsx index 03d97a45..0a37f312 100644 --- a/webui/src/context/TelemetryContext.jsx +++ b/webui/src/context/TelemetryContext.jsx @@ -1,3 +1,5 @@ +/* eslint-disable react-refresh/only-export-components */ + import { createContext, useContext, useMemo, useState, useEffect } from 'react'; import { useSocket } from './SocketContext.jsx'; diff --git a/webui/src/hooks/useDriveControls.js b/webui/src/hooks/useDriveControls.js index ea43164c..79a578ef 100644 --- a/webui/src/hooks/useDriveControls.js +++ b/webui/src/hooks/useDriveControls.js @@ -1,3 +1,5 @@ +/* global Buffer */ + import { useCallback, useEffect, useRef, useState } from 'react'; import { useSocket } from '../context/SocketContext.jsx'; import { useSession } from '../context/SessionContext.jsx'; @@ -10,6 +12,16 @@ const OI_COMMANDS = { dock: [143], }; +const AUX_LIMITS = { + main: [-127, 127], + side: [-127, 127], + vacuum: [0, 127], +}; + +const COMMAND_DELAY_MS = 200; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } @@ -51,6 +63,11 @@ function computeSpeeds(keys) { }; } +function clampUnit(value) { + if (typeof value !== 'number' || Number.isNaN(value)) return 0; + return Math.max(-1, Math.min(1, value)); +} + function shouldIgnoreEvent(event) { const target = event.target; if (!target) return false; @@ -66,7 +83,10 @@ function shouldIgnoreEvent(event) { function bytesToBase64(bytes) { const binary = String.fromCharCode(...bytes); if (typeof btoa === 'function') return btoa(binary); - return Buffer.from(bytes).toString('base64'); + if (typeof Buffer !== 'undefined') { + return Buffer.from(bytes).toString('base64'); + } + throw new Error('No base64 encoder available'); } export function useDriveControls() { @@ -75,7 +95,7 @@ export function useDriveControls() { const roverId = session?.assignment?.roverId; const keysRef = useRef(new Set()); const lastSpeedsRef = useRef({ left: 0, right: 0 }); - const [currentSpeeds, setCurrentSpeeds] = useState(lastSpeedsRef.current); + const [currentSpeeds, setCurrentSpeeds] = useState(() => ({ left: 0, right: 0 })); const emitCommand = useCallback( (payload, cb) => { @@ -106,16 +126,49 @@ export function useDriveControls() { }); }, [emitCommand, roverId]); + const driveWithVector = useCallback( + ({ x = 0, y = 0, boost = false } = {}) => { + if (!roverId) return; + const base = boost ? 400 : 250; + const forward = clampUnit(y) * base; + const turn = clampUnit(x) * base; + const speeds = { + left: clamp(Math.round(forward + turn), -500, 500), + right: clamp(Math.round(forward - turn), -500, 500), + }; + lastSpeedsRef.current = speeds; + setCurrentSpeeds(speeds); + emitCommand({ + type: 'drive', + data: { driveDirect: speeds }, + }); + }, + [emitCommand, roverId], + ); + + const sendMotorPwm = useCallback( + ({ main = 0, side = 0, vacuum = 0 } = {}) => { + if (!roverId) return; + const payload = { + main: clamp(main, AUX_LIMITS.main[0], AUX_LIMITS.main[1]), + side: clamp(side, AUX_LIMITS.side[0], AUX_LIMITS.side[1]), + vacuum: clamp(vacuum, AUX_LIMITS.vacuum[0], AUX_LIMITS.vacuum[1]), + }; + emitCommand({ + type: 'motors', + data: { motorPwm: payload }, + }); + }, + [emitCommand, roverId], + ); + const stopMotors = useCallback(() => { if (!roverId) return; keysRef.current.clear(); lastSpeedsRef.current = { left: 0, right: 0 }; setCurrentSpeeds(lastSpeedsRef.current); - emitCommand({ - type: 'motors', - data: { motorPwm: { main: 0, side: 0, vacuum: 0 } }, - }); - }, [emitCommand, roverId]); + sendMotorPwm({ main: 0, side: 0, vacuum: 0 }); + }, [roverId, sendMotorPwm]); const sendOiCommand = useCallback( (key) => { @@ -131,6 +184,27 @@ export function useDriveControls() { [emitCommand, enableSensorStream, roverId], ); + const runStartDockFull = useCallback(async () => { + if (!roverId) return; + for (const key of ['start', 'dock', 'full']) { + sendOiCommand(key); + // brief pause so the commands aren't collapsed by the rover + await sleep(COMMAND_DELAY_MS); + } + }, [roverId, sendOiCommand]); + + const seekDock = useCallback(() => { + sendOiCommand('dock'); + }, [sendOiCommand]); + + const setAuxMotors = useCallback( + (values) => { + if (!roverId) return; + sendMotorPwm(values); + }, + [roverId, sendMotorPwm], + ); + useEffect(() => { if (!roverId) { keysRef.current.clear(); @@ -171,5 +245,9 @@ export function useDriveControls() { speeds: currentSpeeds, stopMotors, sendOiCommand, + runStartDockFull, + seekDock, + setAuxMotors, + driveWithVector, }; } diff --git a/webui/src/hooks/useVideoRequests.js b/webui/src/hooks/useVideoRequests.js index 474f080e..34a31c9b 100644 --- a/webui/src/hooks/useVideoRequests.js +++ b/webui/src/hooks/useVideoRequests.js @@ -1,24 +1,17 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { useSocket } from '../context/SocketContext.jsx'; export function useVideoRequests(roverIds = []) { const socket = useSocket(); const [sources, setSources] = useState({}); + const ids = useMemo(() => Array.from(new Set(roverIds.filter(Boolean))), [roverIds]); + const idsKey = ids.join('|'); useEffect(() => { - const ids = Array.from(new Set(roverIds.filter(Boolean))); if (!ids.length) { - setSources({}); - return; + return undefined; } let cancelled = false; - setSources((prev) => { - const next = {}; - ids.forEach((id) => { - if (prev[id]) next[id] = prev[id]; - }); - return next; - }); ids.forEach((roverId) => { socket.emit('video:request', { roverId }, (resp = {}) => { if (cancelled) return; @@ -32,7 +25,17 @@ export function useVideoRequests(roverIds = []) { return () => { cancelled = true; }; - }, [socket, roverIds.join('|')]); + }, [socket, idsKey, ids]); + const filtered = useMemo(() => { + if (!ids.length) return {}; + const next = {}; + ids.forEach((id) => { + if (sources[id]) { + next[id] = sources[id]; + } + }); + return next; + }, [ids, sources]); - return sources; + return filtered; } diff --git a/webui/src/lib/whepPlayer.js b/webui/src/lib/whepPlayer.js index 110cab98..69121798 100644 --- a/webui/src/lib/whepPlayer.js +++ b/webui/src/lib/whepPlayer.js @@ -1,3 +1,5 @@ +/* global Buffer */ + const RTC_CONFIG = { iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, @@ -8,11 +10,20 @@ const RTC_CONFIG = { }; +function encodeBase64(value) { + if (typeof btoa === 'function') { + return btoa(value); + } + if (typeof Buffer !== 'undefined') { + return Buffer.from(value).toString('base64'); + } + throw new Error('No base64 encoder available'); +} + function buildAuthHeader(token) { if (!token) return {}; const credential = `${token}:${token}`; - const encoded = - typeof btoa === 'function' ? btoa(credential) : Buffer.from(credential).toString('base64'); + const encoded = encodeBase64(credential); return { Authorization: `Basic ${encoded}` }; } @@ -54,9 +65,9 @@ export class WhepPlayer { this.pc = pc; const stream = new MediaStream(); pc.ontrack = (event) => { - event.streams[0]?.getTracks().forEach((track) => stream.addTrack(track)); + event.streams[0]?.getTracks().forEach((mediaTrack) => stream.addTrack(mediaTrack)); this.video.srcObject = stream; - if (track.kind === 'video' && 'playoutDelayHint' in event.receiver) { + if (event.track?.kind === 'video' && 'playoutDelayHint' in event.receiver) { event.receiver.playoutDelayHint = 0; } };