From 7ecd8df32ec2b6856b637496df3938a4ab08e81c Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 26 Apr 2026 17:47:10 -0400 Subject: [PATCH] refactor(web): simplify run logs view Drop unjustified useMemo around byteCount, add void to mutate(), let errorMessage return undefined for non-Error values so the description doesn't duplicate the retry button label, and reuse formatBytes (hoisted to lib/format.ts from insights-editor) so log size renders as "1.23 MB" instead of "1,234,567 bytes". Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/fabro-web/app/lib/format.ts | 10 ++ apps/fabro-web/app/routes/insights-editor.tsx | 8 +- apps/fabro-web/app/routes/run-logs.tsx | 14 +- .../{entry-2fvwpvjj.js => entry-ge8df28x.js} | 164 +++++++++--------- lib/crates/fabro-spa/assets/index.html | 2 +- 5 files changed, 100 insertions(+), 98 deletions(-) rename lib/crates/fabro-spa/assets/assets/{entry-2fvwpvjj.js => entry-ge8df28x.js} (83%) diff --git a/apps/fabro-web/app/lib/format.ts b/apps/fabro-web/app/lib/format.ts index ce3213617..76fb2c720 100644 --- a/apps/fabro-web/app/lib/format.ts +++ b/apps/fabro-web/app/lib/format.ts @@ -19,6 +19,16 @@ export function formatElapsedSecs(secs: number): string { return remainHrs > 0 ? `${days}d ${remainHrs}h` : `${days}d`; } +/** + * Format a byte count for display (e.g., "1.23 MB", "247.32 KB", "742 B"). + */ +export function formatBytes(bytes: number): string { + if (bytes >= 1e9) return `${(bytes / 1e9).toFixed(2)} GB`; + if (bytes >= 1e6) return `${(bytes / 1e6).toFixed(2)} MB`; + if (bytes >= 1e3) return `${(bytes / 1e3).toFixed(2)} KB`; + return `${bytes} B`; +} + /** * Format seconds into a duration string for display (e.g., "1m 12s", "23s"). */ diff --git a/apps/fabro-web/app/routes/insights-editor.tsx b/apps/fabro-web/app/routes/insights-editor.tsx index cede20d1f..737176f41 100644 --- a/apps/fabro-web/app/routes/insights-editor.tsx +++ b/apps/fabro-web/app/routes/insights-editor.tsx @@ -15,6 +15,7 @@ import { ArrowPathIcon, PencilIcon, } from "@heroicons/react/24/outline"; +import { formatBytes } from "../lib/format"; // ── Types ── @@ -95,13 +96,6 @@ function generateMockResult(sql: string): QueryResult { // ── Formatting helpers ── -function formatBytes(bytes: number): string { - if (bytes >= 1e9) return `${(bytes / 1e9).toFixed(2)} GB`; - if (bytes >= 1e6) return `${(bytes / 1e6).toFixed(2)} MB`; - if (bytes >= 1e3) return `${(bytes / 1e3).toFixed(2)} KB`; - return `${bytes} B`; -} - function formatNumber(n: number): string { return n.toLocaleString(); } diff --git a/apps/fabro-web/app/routes/run-logs.tsx b/apps/fabro-web/app/routes/run-logs.tsx index 3540a2f75..9bdf6cfb2 100644 --- a/apps/fabro-web/app/routes/run-logs.tsx +++ b/apps/fabro-web/app/routes/run-logs.tsx @@ -4,6 +4,7 @@ import { useParams } from "react-router"; import { EmptyState, ErrorState, LoadingState } from "../components/state"; import { StageSidebar } from "../components/stage-sidebar"; import { CopyButton } from "../components/ui"; +import { formatBytes } from "../lib/format"; import { useRun, useRunLogs, useRunStages } from "../lib/queries"; import { mapRunStagesToSidebarStages } from "../lib/stage-sidebar"; @@ -36,7 +37,7 @@ function renderBody(logsQuery: ReturnType) { logsQuery.mutate()} + onRetry={() => void logsQuery.mutate()} /> ); } @@ -55,15 +56,13 @@ function renderBody(logsQuery: ReturnType) { } function LogPanel({ text }: { text: string }) { - const byteCount = useMemo(() => new Blob([text]).size, [text]); + const byteCount = new Blob([text]).size; return (
runtime/server.log
- - {byteCount.toLocaleString()} bytes - + {formatBytes(byteCount)}
@@ -74,7 +73,6 @@ function LogPanel({ text }: { text: string }) { ); } -function errorMessage(error: unknown): string { - if (error instanceof Error) return error.message; - return "Please try again."; +function errorMessage(error: unknown): string | undefined { + return error instanceof Error ? error.message : undefined; } diff --git a/lib/crates/fabro-spa/assets/assets/entry-2fvwpvjj.js b/lib/crates/fabro-spa/assets/assets/entry-ge8df28x.js similarity index 83% rename from lib/crates/fabro-spa/assets/assets/entry-2fvwpvjj.js rename to lib/crates/fabro-spa/assets/assets/entry-ge8df28x.js index f44c1e430..da7c2aa1d 100644 --- a/lib/crates/fabro-spa/assets/assets/entry-2fvwpvjj.js +++ b/lib/crates/fabro-spa/assets/assets/entry-ge8df28x.js @@ -1,16 +1,16 @@ -import{P as n,Q as b0,R as U8}from"./chunk-dep0g6mr.js";import{$ as k,aa as RZ,ba as E5,ca as x}from"./chunk-gf0502ds.js";var zS=RZ((fo)=>{(function(){function Z(){if(I=!1,u){var i=fo.unstable_now();a=i;var e=!0;try{Z:{L=!1,T&&(T=!1,S(c),c=-1),R=!0;var K0=b;try{J:{B(i);for(v=Y(_);v!==null&&!(v.expirationTime>i&&W());){var o=v.callback;if(typeof o==="function"){v.callback=null,b=v.priorityLevel;var q0=o(v.expirationTime<=i);if(i=fo.unstable_now(),typeof q0==="function"){v.callback=q0,B(i),e=!0;break J}v===Y(_)&&q(_),B(i)}else q(_);v=Y(_)}if(v!==null)e=!0;else{var _0=Y(A);_0!==null&&U($,_0.startTime-i),e=!1}}break Z}finally{v=null,b=K0,R=!1}e=void 0}}finally{e?Y0():u=!1}}}function J(i,e){var K0=i.length;i.push(e);Z:for(;0>>1,q0=i[o];if(0>>1;o<_0;){var D0=2*(o+1)-1,A0=i[D0],t=D0+1,B0=i[t];if(0>z(A0,K0))tz(B0,A0)?(i[o]=B0,i[t]=K0,o=t):(i[o]=A0,i[D0]=K0,o=D0);else if(tz(B0,K0))i[o]=B0,i[t]=K0,o=t;else break Z}}return e}function z(i,e){var K0=i.sortIndex-e.sortIndex;return K0!==0?K0:i.id-e.id}function B(i){for(var e=Y(A);e!==null;){if(e.callback===null)q(A);else if(e.startTime<=i)q(A),e.sortIndex=e.expirationTime,J(_,e);else break;e=Y(A)}}function $(i){if(T=!1,B(i),!L)if(Y(_)!==null)L=!0,u||(u=!0,Y0());else{var e=Y(A);e!==null&&U($,e.startTime-i)}}function W(){return I?!0:fo.unstable_now()-ai||125o?(i.sortIndex=K0,J(A,i),Y(_)===null&&i===Y(A)&&(T?(S(c),c=-1):T=!0,U($,K0-o))):(i.sortIndex=q0,J(_,i),L||R||(L=!0,u||(u=!0,Y0()))),i},fo.unstable_shouldYield=W,fo.unstable_wrapCallback=function(i){var e=b;return function(){var K0=b;b=e;try{return i.apply(this,arguments)}finally{b=K0}}},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var KS=RZ((go)=>{var yF=k(n());(function(){function Z(){}function J(N){return""+N}function Y(N,O,_){var A=3{(function(){function Z(){if(I=!1,u){var i=go.unstable_now();a=i;var e=!0;try{Z:{L=!1,T&&(T=!1,S(c),c=-1),R=!0;var K0=b;try{J:{B(i);for(v=Y(_);v!==null&&!(v.expirationTime>i&&W());){var o=v.callback;if(typeof o==="function"){v.callback=null,b=v.priorityLevel;var q0=o(v.expirationTime<=i);if(i=go.unstable_now(),typeof q0==="function"){v.callback=q0,B(i),e=!0;break J}v===Y(_)&&q(_),B(i)}else q(_);v=Y(_)}if(v!==null)e=!0;else{var _0=Y(A);_0!==null&&U($,_0.startTime-i),e=!1}}break Z}finally{v=null,b=K0,R=!1}e=void 0}}finally{e?Y0():u=!1}}}function J(i,e){var K0=i.length;i.push(e);Z:for(;0>>1,q0=i[o];if(0>>1;o<_0;){var D0=2*(o+1)-1,A0=i[D0],t=D0+1,B0=i[t];if(0>z(A0,K0))tz(B0,A0)?(i[o]=B0,i[t]=K0,o=t):(i[o]=A0,i[D0]=K0,o=D0);else if(tz(B0,K0))i[o]=B0,i[t]=K0,o=t;else break Z}}return e}function z(i,e){var K0=i.sortIndex-e.sortIndex;return K0!==0?K0:i.id-e.id}function B(i){for(var e=Y(A);e!==null;){if(e.callback===null)q(A);else if(e.startTime<=i)q(A),e.sortIndex=e.expirationTime,J(_,e);else break;e=Y(A)}}function $(i){if(T=!1,B(i),!L)if(Y(_)!==null)L=!0,u||(u=!0,Y0());else{var e=Y(A);e!==null&&U($,e.startTime-i)}}function W(){return I?!0:go.unstable_now()-ai||125o?(i.sortIndex=K0,J(A,i),Y(_)===null&&i===Y(A)&&(T?(S(c),c=-1):T=!0,U($,K0-o))):(i.sortIndex=q0,J(_,i),L||R||(L=!0,u||(u=!0,Y0()))),i},go.unstable_shouldYield=W,go.unstable_wrapCallback=function(i){var e=b;return function(){var K0=b;b=e;try{return i.apply(this,arguments)}finally{b=K0}}},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var KS=RZ((mo)=>{var DF=k(n());(function(){function Z(){}function J(N){return""+N}function Y(N,O,_){var A=3` tag.%s',_),typeof N==="string"&&typeof O==="object"&&O!==null&&typeof O.as==="string"){_=O.as;var A=q(_,O.crossOrigin);W.d.L(N,_,{crossOrigin:A,integrity:typeof O.integrity==="string"?O.integrity:void 0,nonce:typeof O.nonce==="string"?O.nonce:void 0,type:typeof O.type==="string"?O.type:void 0,fetchPriority:typeof O.fetchPriority==="string"?O.fetchPriority:void 0,referrerPolicy:typeof O.referrerPolicy==="string"?O.referrerPolicy:void 0,imageSrcSet:typeof O.imageSrcSet==="string"?O.imageSrcSet:void 0,imageSizes:typeof O.imageSizes==="string"?O.imageSizes:void 0,media:typeof O.media==="string"?O.media:void 0})}},go.preloadModule=function(N,O){var _="";typeof N==="string"&&N||(_+=" The `href` argument encountered was "+z(N)+"."),O!==void 0&&typeof O!=="object"?_+=" The `options` argument encountered was "+z(O)+".":O&&("as"in O)&&typeof O.as!=="string"&&(_+=" The `as` option encountered was "+z(O.as)+"."),_&&console.error('ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `` tag.%s',_),typeof N==="string"&&(O?(_=q(O.as,O.crossOrigin),W.d.m(N,{as:typeof O.as==="string"&&O.as!=="script"?O.as:void 0,crossOrigin:_,integrity:typeof O.integrity==="string"?O.integrity:void 0})):W.d.m(N))},go.requestFormReset=function(N){W.d.r(N)},go.unstable_batchedUpdates=function(N,O){return N(O)},go.useFormState=function(N,O,_){return $().useFormState(N,O,_)},go.useFormStatus=function(){return $().useHostTransitionStatus()},go.version="19.2.4",typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var h3=RZ((kq0,BS)=>{var mo=k(KS());BS.exports=mo});var $S=RZ((ho)=>{var p1=k(zS()),NX=k(n()),DF=k(h3());(function(){function Z(Q,X){for(Q=Q.memoizedState;Q!==null&&0=X.length)return G;var M=X[K],H=I2(Q)?Q.slice():P1({},Q);return H[M]=J(Q[M],X,K+1,G),H}function Y(Q,X,K){if(X.length!==K.length)console.warn("copyWithRename() expects paths of the same length");else{for(var G=0;Gu8?console.error("Unexpected pop."):(X!==KA[u8]&&console.error("Unexpected Fiber popped."),Q.current=zA[u8],zA[u8]=null,KA[u8]=null,u8--)}function Q0(Q,X,K){u8++,zA[u8]=Q.current,KA[u8]=K,Q.current=X}function W0(Q){return Q===null&&console.error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue."),Q}function i(Q,X){Q0(n9,X,Q),Q0(AK,Q,Q),Q0(t9,null,Q);var K=X.nodeType;switch(K){case 9:case 11:K=K===9?"#document":"#fragment",X=(X=X.documentElement)?(X=X.namespaceURI)?cy(X):t8:t8;break;default:if(K=X.tagName,X=X.namespaceURI)X=cy(X),X=dy(X,K);else switch(K){case"svg":X=wX;break;case"math":X=vU;break;default:X=t8}}K=K.toLowerCase(),K=ub(null,K),K={context:X,ancestorInfo:K},Y0(t9,Q),Q0(t9,K,Q)}function e(Q){Y0(t9,Q),Y0(AK,Q),Y0(n9,Q)}function K0(){return W0(t9.current)}function o(Q){Q.memoizedState!==null&&Q0(bG,Q,Q);var X=W0(t9.current),K=Q.type,G=dy(X.context,K);K=ub(X.ancestorInfo,K),G={context:G,ancestorInfo:K},X!==G&&(Q0(AK,Q,Q),Q0(t9,G,Q))}function q0(Q){AK.current===Q&&(Y0(t9,Q),Y0(AK,Q)),bG.current===Q&&(Y0(bG,Q),WB._currentValue=JY)}function _0(){}function D0(){if(FK===0){FD=console.log,PD=console.info,VD=console.warn,vD=console.error,LD=console.group,RD=console.groupCollapsed,bD=console.groupEnd;var Q={configurable:!0,enumerable:!0,value:_0,writable:!0};Object.defineProperties(console,{info:Q,log:Q,warn:Q,error:Q,group:Q,groupCollapsed:Q,groupEnd:Q})}FK++}function A0(){if(FK--,FK===0){var Q={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:P1({},Q,{value:FD}),info:P1({},Q,{value:PD}),warn:P1({},Q,{value:VD}),error:P1({},Q,{value:vD}),group:P1({},Q,{value:LD}),groupCollapsed:P1({},Q,{value:RD}),groupEnd:P1({},Q,{value:bD})})}0>FK&&console.error("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}function t(Q){var X=Error.prepareStackTrace;if(Error.prepareStackTrace=void 0,Q=Q.stack,Error.prepareStackTrace=X,Q.startsWith(`Error: react-stack-top-frame +See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.`),N}typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());var W={d:{f:Z,r:function(){throw Error("Invalid form element. requestFormReset must be passed a form that was rendered by React.")},D:Z,C:Z,L:Z,m:Z,X:Z,S:Z,M:Z},p:0,findDOMNode:null},U=Symbol.for("react.portal"),w=DF.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;typeof Map==="function"&&Map.prototype!=null&&typeof Map.prototype.forEach==="function"&&typeof Set==="function"&&Set.prototype!=null&&typeof Set.prototype.clear==="function"&&typeof Set.prototype.forEach==="function"||console.error("React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),mo.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=W,mo.createPortal=function(N,O){var _=2` tag.%s',_),typeof N==="string"&&typeof O==="object"&&O!==null&&typeof O.as==="string"){_=O.as;var A=q(_,O.crossOrigin);W.d.L(N,_,{crossOrigin:A,integrity:typeof O.integrity==="string"?O.integrity:void 0,nonce:typeof O.nonce==="string"?O.nonce:void 0,type:typeof O.type==="string"?O.type:void 0,fetchPriority:typeof O.fetchPriority==="string"?O.fetchPriority:void 0,referrerPolicy:typeof O.referrerPolicy==="string"?O.referrerPolicy:void 0,imageSrcSet:typeof O.imageSrcSet==="string"?O.imageSrcSet:void 0,imageSizes:typeof O.imageSizes==="string"?O.imageSizes:void 0,media:typeof O.media==="string"?O.media:void 0})}},mo.preloadModule=function(N,O){var _="";typeof N==="string"&&N||(_+=" The `href` argument encountered was "+z(N)+"."),O!==void 0&&typeof O!=="object"?_+=" The `options` argument encountered was "+z(O)+".":O&&("as"in O)&&typeof O.as!=="string"&&(_+=" The `as` option encountered was "+z(O.as)+"."),_&&console.error('ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `` tag.%s',_),typeof N==="string"&&(O?(_=q(O.as,O.crossOrigin),W.d.m(N,{as:typeof O.as==="string"&&O.as!=="script"?O.as:void 0,crossOrigin:_,integrity:typeof O.integrity==="string"?O.integrity:void 0})):W.d.m(N))},mo.requestFormReset=function(N){W.d.r(N)},mo.unstable_batchedUpdates=function(N,O){return N(O)},mo.useFormState=function(N,O,_){return $().useFormState(N,O,_)},mo.useFormStatus=function(){return $().useHostTransitionStatus()},mo.version="19.2.4",typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var h3=RZ((kq0,BS)=>{var ho=k(KS());BS.exports=ho});var $S=RZ((po)=>{var p1=k(zS()),NX=k(n()),IF=k(h3());(function(){function Z(Q,X){for(Q=Q.memoizedState;Q!==null&&0=X.length)return G;var M=X[K],H=I2(Q)?Q.slice():P1({},Q);return H[M]=J(Q[M],X,K+1,G),H}function Y(Q,X,K){if(X.length!==K.length)console.warn("copyWithRename() expects paths of the same length");else{for(var G=0;Gu8?console.error("Unexpected pop."):(X!==BA[u8]&&console.error("Unexpected Fiber popped."),Q.current=KA[u8],KA[u8]=null,BA[u8]=null,u8--)}function Q0(Q,X,K){u8++,KA[u8]=Q.current,BA[u8]=K,Q.current=X}function W0(Q){return Q===null&&console.error("Expected host context to exist. This error is likely caused by a bug in React. Please file an issue."),Q}function i(Q,X){Q0(n9,X,Q),Q0(AK,Q,Q),Q0(t9,null,Q);var K=X.nodeType;switch(K){case 9:case 11:K=K===9?"#document":"#fragment",X=(X=X.documentElement)?(X=X.namespaceURI)?cy(X):t8:t8;break;default:if(K=X.tagName,X=X.namespaceURI)X=cy(X),X=dy(X,K);else switch(K){case"svg":X=wX;break;case"math":X=vU;break;default:X=t8}}K=K.toLowerCase(),K=ub(null,K),K={context:X,ancestorInfo:K},Y0(t9,Q),Q0(t9,K,Q)}function e(Q){Y0(t9,Q),Y0(AK,Q),Y0(n9,Q)}function K0(){return W0(t9.current)}function o(Q){Q.memoizedState!==null&&Q0(bG,Q,Q);var X=W0(t9.current),K=Q.type,G=dy(X.context,K);K=ub(X.ancestorInfo,K),G={context:G,ancestorInfo:K},X!==G&&(Q0(AK,Q,Q),Q0(t9,G,Q))}function q0(Q){AK.current===Q&&(Y0(t9,Q),Y0(AK,Q)),bG.current===Q&&(Y0(bG,Q),WB._currentValue=JY)}function _0(){}function D0(){if(FK===0){FD=console.log,PD=console.info,VD=console.warn,vD=console.error,LD=console.group,RD=console.groupCollapsed,bD=console.groupEnd;var Q={configurable:!0,enumerable:!0,value:_0,writable:!0};Object.defineProperties(console,{info:Q,log:Q,warn:Q,error:Q,group:Q,groupCollapsed:Q,groupEnd:Q})}FK++}function A0(){if(FK--,FK===0){var Q={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:P1({},Q,{value:FD}),info:P1({},Q,{value:PD}),warn:P1({},Q,{value:VD}),error:P1({},Q,{value:vD}),group:P1({},Q,{value:LD}),groupCollapsed:P1({},Q,{value:RD}),groupEnd:P1({},Q,{value:bD})})}0>FK&&console.error("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}function t(Q){var X=Error.prepareStackTrace;if(Error.prepareStackTrace=void 0,Q=Q.stack,Error.prepareStackTrace=X,Q.startsWith(`Error: react-stack-top-frame `)&&(Q=Q.slice(29)),X=Q.indexOf(` `),X!==-1&&(Q=Q.slice(X+1)),X=Q.indexOf("react_stack_bottom_frame"),X!==-1&&(X=Q.lastIndexOf(` -`,X)),X!==-1)Q=Q.slice(0,X);else return"";return Q}function B0(Q){if(BA===void 0)try{throw Error()}catch(K){var X=K.stack.trim().match(/\n( *(at )?)/);BA=X&&X[1]||"",TD=-1)":-1F||D[H]!==l[F]){var r=` -`+D[H].replace(" at new "," at ");return Q.displayName&&r.includes("")&&(r=r.replace("",Q.displayName)),typeof Q==="function"&&WA.set(Q,r),r}while(1<=H&&0<=F);break}}}finally{$A=!1,$0.H=G,A0(),Error.prepareStackTrace=K}return D=(D=Q?Q.displayName||Q.name:"")?B0(D):"",typeof Q==="function"&&WA.set(Q,D),D}function w0(Q,X){switch(Q.tag){case 26:case 27:case 5:return B0(Q.type);case 16:return B0("Lazy");case 13:return Q.child!==X&&X!==null?B0("Suspense Fallback"):B0("Suspense");case 19:return B0("SuspenseList");case 0:case 15:return I0(Q.type,!1);case 11:return I0(Q.type.render,!1);case 1:return I0(Q.type,!0);case 31:return B0("Activity");default:return""}}function d0(Q){try{var X="",K=null;do{X+=w0(Q,K);var G=Q._debugInfo;if(G)for(var M=G.length-1;0<=M;M--){var H=G[M];if(typeof H.name==="string"){var F=X;Z:{var{name:V,env:C,debugLocation:D}=H;if(D!=null){var l=t(D),r=l.lastIndexOf(` +`+D[H].replace(" at new "," at ");return Q.displayName&&r.includes("")&&(r=r.replace("",Q.displayName)),typeof Q==="function"&&GA.set(Q,r),r}while(1<=H&&0<=F);break}}}finally{WA=!1,$0.H=G,A0(),Error.prepareStackTrace=K}return D=(D=Q?Q.displayName||Q.name:"")?B0(D):"",typeof Q==="function"&&GA.set(Q,D),D}function w0(Q,X){switch(Q.tag){case 26:case 27:case 5:return B0(Q.type);case 16:return B0("Lazy");case 13:return Q.child!==X&&X!==null?B0("Suspense Fallback"):B0("Suspense");case 19:return B0("SuspenseList");case 0:case 15:return I0(Q.type,!1);case 11:return I0(Q.type.render,!1);case 1:return I0(Q.type,!0);case 31:return B0("Activity");default:return""}}function d0(Q){try{var X="",K=null;do{X+=w0(Q,K);var G=Q._debugInfo;if(G)for(var M=G.length-1;0<=M;M--){var H=G[M];if(typeof H.name==="string"){var F=X;Z:{var{name:V,env:C,debugLocation:D}=H;if(D!=null){var l=t(D),r=l.lastIndexOf(` `),h=r===-1?l:l.slice(r+1);if(h.indexOf(V)!==-1){var J0=` `+h;break Z}}J0=B0(V+(C?" ["+C+"]":""))}X=F+J0}}K=Q,Q=Q.return}while(Q);return X}catch(V0){return` Error generating stack: `+V0.message+` @@ -18,7 +18,7 @@ Error generating stack: `+V0.message+` `+M)}}else if(Q.debugStack!=null){var H=Q.debugStack;(Q=Q.owner)&&H&&(X+=` `+t(H))}else break;var F=X}catch(V){F=` Error generating stack: `+V.message+` -`+V.stack}return F}function P0(Q,X,K,G,M,H,F){var V=x4;L1(Q);try{return Q!==null&&Q._debugTask?Q._debugTask.run(X.bind(null,K,G,M,H,F)):X(K,G,M,H,F)}finally{L1(V)}throw Error("runWithFiberInDEV should never be called in production. This is a bug in React.")}function L1(Q){$0.getCurrentStack=Q===null?null:J1,I3=!1,x4=Q}function q5(Q){return typeof Symbol==="function"&&Symbol.toStringTag&&Q[Symbol.toStringTag]||Q.constructor.name||"Object"}function c5(Q){try{return $7(Q),!1}catch(X){return!0}}function $7(Q){return""+Q}function U1(Q,X){if(c5(Q))return console.error("The provided `%s` attribute is an unsupported type %s. This value must be coerced to a string before using it here.",X,q5(Q)),$7(Q)}function k1(Q,X){if(c5(Q))return console.error("The provided `%s` CSS property is an unsupported type %s. This value must be coerced to a string before using it here.",X,q5(Q)),$7(Q)}function e1(Q){if(c5(Q))return console.error("Form field values (value, checked, defaultValue, or defaultChecked props) must be strings, not %s. This value must be coerced to a string before using it here.",q5(Q)),$7(Q)}function Z5(Q){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")return!1;var X=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(X.isDisabled)return!0;if(!X.supportsFiber)return console.error("The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. https://react.dev/link/react-devtools"),!0;try{xQ=X.inject(Q),D7=X}catch(K){console.error("React instrumentation encountered an error: %o.",K)}return X.checkDCE?!0:!1}function m0(Q){if(typeof Js==="function"&&Ys(Q),D7&&typeof D7.setStrictMode==="function")try{D7.setStrictMode(xQ,Q)}catch(X){E3||(E3=!0,console.error("React instrumentation encountered an error: %o",X))}}function C2(Q){return Q>>>=0,Q===0?32:31-(Qs(Q)/Xs|0)|0}function O5(Q){var X=Q&42;if(X!==0)return X;switch(Q&-Q){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 Q&261888;case 262144:case 524288:case 1048576:case 2097152:return Q&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return Q&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return console.error("Should have found matching lanes. This is a bug in React."),Q}}function z5(Q,X,K){var G=Q.pendingLanes;if(G===0)return 0;var M=0,H=Q.suspendedLanes,F=Q.pingedLanes;Q=Q.warmLanes;var V=G&134217727;return V!==0?(G=V&~H,G!==0?M=O5(G):(F&=V,F!==0?M=O5(F):K||(K=V&~Q,K!==0&&(M=O5(K))))):(V=G&~H,V!==0?M=O5(V):F!==0?M=O5(F):K||(K=G&~Q,K!==0&&(M=O5(K)))),M===0?0:X!==0&&X!==M&&(X&H)===0&&(H=M&-M,K=X&-X,H>=K||H===32&&(K&4194048)!==0)?X:M}function W5(Q,X){return(Q.pendingLanes&~(Q.suspendedLanes&~Q.pingedLanes)&X)===0}function m7(Q,X){switch(Q){case 1:case 2:case 4:case 8:case 64:return X+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 X+5000;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return console.error("Should have found matching lanes. This is a bug in React."),-1}}function G4(){var Q=yG;return yG<<=1,(yG&62914560)===0&&(yG=4194304),Q}function W7(Q){for(var X=[],K=0;31>K;K++)X.push(Q);return X}function T5(Q,X){Q.pendingLanes|=X,X!==268435456&&(Q.suspendedLanes=0,Q.pingedLanes=0,Q.warmLanes=0)}function J5(Q,X,K,G,M,H){var F=Q.pendingLanes;Q.pendingLanes=K,Q.suspendedLanes=0,Q.pingedLanes=0,Q.warmLanes=0,Q.expiredLanes&=K,Q.entangledLanes&=K,Q.errorRecoveryDisabledLanes&=K,Q.shellSuspendCounter=0;var{entanglements:V,expirationTimes:C,hiddenUpdates:D}=Q;for(K=F&~K;0"u")return null;try{return Q.activeElement||Q.body}catch(X){return Q.body}}function y0(Q){return Q.replace($s,function(X){return"\\"+X.charCodeAt(0).toString(16)+" "})}function u0(Q,X){X.checked===void 0||X.defaultChecked===void 0||SD||(console.error("%s contains an input of type %s with both checked and defaultChecked props. Input elements must be either controlled or uncontrolled (specify either the checked prop, or the defaultChecked prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components",b1()||"A component",X.type),SD=!0),X.value===void 0||X.defaultValue===void 0||ED||(console.error("%s contains an input of type %s with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://react.dev/link/controlled-components",b1()||"A component",X.type),ED=!0)}function h0(Q,X,K,G,M,H,F,V){if(Q.name="",F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"?(U1(F,"type"),Q.type=F):Q.removeAttribute("type"),X!=null)if(F==="number"){if(X===0&&Q.value===""||Q.value!=X)Q.value=""+s(X)}else Q.value!==""+s(X)&&(Q.value=""+s(X));else F!=="submit"&&F!=="reset"||Q.removeAttribute("value");X!=null?f0(Q,F,s(X)):K!=null?f0(Q,F,s(K)):G!=null&&Q.removeAttribute("value"),M==null&&H!=null&&(Q.defaultChecked=!!H),M!=null&&(Q.checked=M&&typeof M!=="function"&&typeof M!=="symbol"),V!=null&&typeof V!=="function"&&typeof V!=="symbol"&&typeof V!=="boolean"?(U1(V,"name"),Q.name=""+s(V)):Q.removeAttribute("name")}function i0(Q,X,K,G,M,H,F,V){if(H!=null&&typeof H!=="function"&&typeof H!=="symbol"&&typeof H!=="boolean"&&(U1(H,"type"),Q.type=H),X!=null||K!=null){if(!(H!=="submit"&&H!=="reset"||X!==void 0&&X!==null)){H0(Q);return}K=K!=null?""+s(K):"",X=X!=null?""+s(X):K,V||X===Q.value||(Q.value=X),Q.defaultValue=X}G=G!=null?G:M,G=typeof G!=="function"&&typeof G!=="symbol"&&!!G,Q.checked=V?Q.checked:!!G,Q.defaultChecked=!!G,F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"&&(U1(F,"name"),Q.name=F),H0(Q)}function f0(Q,X,K){X==="number"&&C0(Q.ownerDocument)===Q||Q.defaultValue===""+K||(Q.defaultValue=""+K)}function f1(Q,X){X.value==null&&(typeof X.children==="object"&&X.children!==null?NX.Children.forEach(X.children,function(K){K==null||typeof K==="string"||typeof K==="number"||typeof K==="bigint"||xD||(xD=!0,console.error("Cannot infer the option value of complex children. Pass a `value` prop or use a plain string as children to