diff --git a/apps/fabro-web/app/routes/run-files.tsx b/apps/fabro-web/app/routes/run-files.tsx
index 20426a135..5622c4e6d 100644
--- a/apps/fabro-web/app/routes/run-files.tsx
+++ b/apps/fabro-web/app/routes/run-files.tsx
@@ -6,19 +6,32 @@ import {
type ReactElement,
} from "react";
import {
- isRouteErrorResponse,
+ useMatches,
useNavigation,
useParams,
useRevalidator,
- useRouteError,
} from "react-router";
-import { MultiFileDiff, PatchDiff } from "@pierre/diffs/react";
+import { MultiFileDiff, PatchDiff, Virtualizer } from "@pierre/diffs/react";
import { useTheme } from "../lib/theme";
import { apiJsonOrNull } from "../api";
import type {
FileDiff as ApiFileDiff,
PaginatedRunFileList,
} from "@qltysh/fabro-api-client";
+import {
+ DegradedBanner,
+ pickPlaceholder,
+} from "./run-files/placeholders";
+import {
+ deriveEmptyKind,
+ EmptyState,
+ InlineErrorBanner,
+ LoadingSkeleton,
+ RunFilesErrorBoundary,
+ Toast,
+} from "./run-files/states";
+import { useFileKeyboardNav } from "./run-files/keyboard";
+import { Toolbar, type DiffStyle } from "./run-files/toolbar";
export const handle = { wide: true };
@@ -30,184 +43,30 @@ export async function loader({ request, params }: any) {
return data;
}
-// Events that can change the diff. CheckpointCompleted is the canonical
-// signal; the others cover terminal state transitions that also merit a
-// refresh.
+// Events that should trigger a revalidation. CheckpointCompleted is the
+// canonical signal; terminal events cover the final-state transitions too.
const REFRESH_EVENTS = new Set([
"checkpoint.completed",
"run.completed",
"run.failed",
]);
-const PLACEHOLDER_CLASSES =
- "flex items-center justify-between rounded-md border border-line bg-panel/60 px-4 py-3 text-sm text-fg-muted";
+const MD_BREAKPOINT_PX = 768;
+const DIFF_STYLE_STORAGE_KEY = "fabro.run-files.diff-style";
-function DegradedBanner({ reason }: { reason?: string }) {
- return (
-
- {banner_copy_for_reason(reason)}
-
- );
-}
+export const ErrorBoundary = RunFilesErrorBoundary;
-function banner_copy_for_reason(reason: string | undefined): string {
- switch (reason) {
- case "sandbox_gone":
- return "Showing final patch only. This run's sandbox has been cleaned up, so individual file contents are no longer available.";
- case "provider_unsupported":
- return "Live diff isn't supported for this sandbox provider. Showing the patch captured at the last checkpoint.";
- case "sandbox_unreachable":
- default:
- return "Couldn't reach this run's sandbox. Showing the patch captured at the last checkpoint — refresh to try again.";
- }
-}
-
-function SensitivePlaceholder({ name }: { name: string }) {
- return (
-
+ );
+}
+
+/// Render the highest-priority placeholder for a file, or `null` if the file
+/// should render as a normal diff. Priority order is:
+/// sensitive > binary > symlink/submodule > truncated
+/// Security flags must never be hidden by a lesser placeholder.
+export function pickPlaceholder(file: ApiFileDiff): ReactElement | null {
+ const displayName = file.new_file.name || file.old_file.name;
+ if (file.sensitive) {
+ return ;
+ }
+ if (file.binary) {
+ return ;
+ }
+ if (file.change_kind === "symlink") {
+ return ;
+ }
+ if (file.change_kind === "submodule") {
+ return (
+
+ );
+ }
+ if (file.truncated) {
+ return (
+
+ );
+ }
+ return null;
+}
+
+export function DegradedBanner({ reason }: { reason?: string }) {
+ return (
+
+ {bannerCopyForReason(reason)}
+
+ );
+}
+
+export function bannerCopyForReason(reason: string | undefined): string {
+ switch (reason) {
+ case "sandbox_gone":
+ return "Showing final patch only. This run's sandbox has been cleaned up, so individual file contents are no longer available.";
+ case "provider_unsupported":
+ return "Live diff isn't supported for this sandbox provider. Showing the patch captured at the last checkpoint.";
+ case "sandbox_unreachable":
+ default:
+ return "Couldn't reach this run's sandbox. Showing the patch captured at the last checkpoint — refresh to try again.";
+ }
+}
diff --git a/apps/fabro-web/app/routes/run-files/states.tsx b/apps/fabro-web/app/routes/run-files/states.tsx
new file mode 100644
index 000000000..7b537fd9d
--- /dev/null
+++ b/apps/fabro-web/app/routes/run-files/states.tsx
@@ -0,0 +1,192 @@
+import { isRouteErrorResponse, useRouteError } from "react-router";
+
+/**
+ * R4 empty-state taxonomy. See plan § Unit 11:
+ * - `starting` (R4a): run still spinning up, no base_sha yet
+ * - `no_changes` (R4b): run completed but touched no files
+ * - `failed_before_checkpoint` (R4c1): failed run without captured diff
+ * - `diff_lost` (R4c2): succeeded run whose diff is no longer recoverable
+ * - `unknown`: fallback — loader returned null (404/501/other)
+ */
+export type EmptyKind =
+ | "starting"
+ | "no_changes"
+ | "failed_before_checkpoint"
+ | "diff_lost"
+ | "unknown";
+
+export function EmptyState({ kind }: { kind: EmptyKind }) {
+ return (
+
+ {emptyStateCopy(kind)}
+
+ );
+}
+
+export function emptyStateCopy(kind: EmptyKind): string {
+ switch (kind) {
+ case "starting":
+ return "Run is still starting. Files will appear once it begins.";
+ case "no_changes":
+ return "This run didn't change any files.";
+ case "failed_before_checkpoint":
+ return "This run failed before capturing any changes.";
+ case "diff_lost":
+ return "The diff for this run is no longer available. If you expect files here, please report it.";
+ case "unknown":
+ default:
+ return "The diff for this run is not available right now.";
+ }
+}
+
+/// Derive the empty-state variant from the full loader context. `runStatus`
+/// comes from the parent run loader; its absence collapses to the "unknown"
+/// catchall so the empty state never displays misleading copy.
+export function deriveEmptyKind(args: {
+ runStatus: string | undefined;
+ totalChanged: number;
+ degraded: boolean;
+}): EmptyKind {
+ const { runStatus, totalChanged, degraded } = args;
+ if (!runStatus) {
+ return "unknown";
+ }
+ const normalized = runStatus.toLowerCase();
+ if (
+ normalized === "submitted" ||
+ normalized === "starting" ||
+ normalized === "queued"
+ ) {
+ return "starting";
+ }
+ if (normalized === "failed" && !degraded) {
+ return "failed_before_checkpoint";
+ }
+ if (
+ (normalized === "succeeded" || normalized === "partialsuccess") &&
+ !degraded
+ ) {
+ // If the run ran successfully and we still have no diff data, the
+ // projection's final_patch was never captured (or was lost). R4(c2).
+ if (totalChanged > 0) {
+ return "diff_lost";
+ }
+ return "no_changes";
+ }
+ if (totalChanged === 0) {
+ return "no_changes";
+ }
+ return "diff_lost";
+}
+
+export function LoadingSkeleton() {
+ return (
+
+ );
+}
+
+export function Toast({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+/**
+ * Route-level ErrorBoundary that handles the documented status codes from
+ * the plan § Unit 11 taxonomy. 500 responses with a `request_id` in the
+ * body surface it in the copy so users can cite it when contacting support.
+ */
+export function RunFilesErrorBoundary() {
+ const error = useRouteError();
+ if (isRouteErrorResponse(error)) {
+ if (error.status === 401 || error.status === 403) {
+ return (
+
i?(p.sortIndex=Z0,Y(_,p),J(A)===null&&p===J(_)&&(v?(j(o),o=-1):v=!0,G(W,Z0-i))):(p.sortIndex=B0,Y(A,p),C||T||(C=!0,g||(g=!0,J0()))),p},Xl.unstable_shouldYield=U,Xl.unstable_wrapCallback=function(p){var X0=R;return function(){var Z0=R;R=X0;try{return p.apply(this,arguments)}finally{R=Z0}}},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var NE=_8((ql)=>{var gA=u(Q0());(function(){function Z(){}function Y(H){return""+H}function J(H,O,A){var _=3` tag.%s',A),typeof H==="string"&&typeof O==="object"&&O!==null&&typeof O.as==="string"){A=O.as;var _=q(A,O.crossOrigin);U.d.L(H,A,{crossOrigin:_,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})}},ql.preloadModule=function(H,O){var A="";typeof H==="string"&&H||(A+=" The `href` argument encountered was "+z(H)+"."),O!==void 0&&typeof O!=="object"?A+=" The `options` argument encountered was "+z(O)+".":O&&("as"in O)&&typeof O.as!=="string"&&(A+=" The `as` option encountered was "+z(O.as)+"."),A&&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',A),typeof H==="string"&&(O?(A=q(O.as,O.crossOrigin),U.d.m(H,{as:typeof O.as==="string"&&O.as!=="script"?O.as:void 0,crossOrigin:A,integrity:typeof O.integrity==="string"?O.integrity:void 0})):U.d.m(H))},ql.requestFormReset=function(H){U.d.r(H)},ql.unstable_batchedUpdates=function(H,O){return H(O)},ql.useFormState=function(H,O,A){return W().useFormState(H,O,A)},ql.useFormStatus=function(){return W().useHostTransitionStatus()},ql.version="19.2.4",typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop==="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()});var A3=_8((i90,HE)=>{var zl=u(NE());HE.exports=zl});var OE=_8((Kl)=>{var r1=u(wE()),PJ=u(Q0()),uA=u(A3());(function(){function Z(Q,X){for(Q=Q.memoizedState;Q!==null&&0=X.length)return $;var M=X[K],N=R2(Q)?Q.slice():E1({},Q);return N[M]=Y(Q[M],X,K+1,$),N}function J(Q,X,K){if(X.length!==K.length)console.warn("copyWithRename() expects paths of the same length");else{for(var $=0;$Q8?console.error("Unexpected pop."):(X!==HO[Q8]&&console.error("Unexpected Fiber popped."),Q.current=NO[Q8],NO[Q8]=null,HO[Q8]=null,Q8--)}function K0(Q,X,K){Q8++,NO[Q8]=Q.current,HO[Q8]=K,Q.current=X}function n(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 p(Q,X){K0(w9,X,Q),K0(Bz,Q,Q),K0(M9,null,Q);var K=X.nodeType;switch(K){case 9:case 11:K=K===9?"#document":"#fragment",X=(X=X.documentElement)?(X=X.namespaceURI)?tT(X):H8:H8;break;default:if(K=X.tagName,X=X.namespaceURI)X=tT(X),X=nT(X,K);else switch(K){case"svg":X=_J;break;case"math":X=qU;break;default:X=H8}}K=K.toLowerCase(),K=lL(null,K),K={context:X,ancestorInfo:K},J0(M9,Q),K0(M9,K,Q)}function X0(Q){J0(M9,Q),J0(Bz,Q),J0(w9,Q)}function Z0(){return n(M9.current)}function i(Q){Q.memoizedState!==null&&K0(B$,Q,Q);var X=n(M9.current),K=Q.type,$=nT(X.context,K);K=lL(X.ancestorInfo,K),$={context:$,ancestorInfo:K},X!==$&&(K0(Bz,Q,Q),K0(M9,$,Q))}function B0(Q){Bz.current===Q&&(J0(M9,Q),J0(Bz,Q)),B$.current===Q&&(J0(B$,Q),ez._currentValue=UY)}function k(){}function U0(){if(Wz===0){DC=console.log,bC=console.info,EC=console.warn,yC=console.error,IC=console.group,jC=console.groupCollapsed,SC=console.groupEnd;var Q={configurable:!0,enumerable:!0,value:k,writable:!0};Object.defineProperties(console,{info:Q,log:Q,warn:Q,error:Q,group:Q,groupCollapsed:Q,groupEnd:Q})}Wz++}function H0(){if(Wz--,Wz===0){var Q={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:E1({},Q,{value:DC}),info:E1({},Q,{value:bC}),warn:E1({},Q,{value:EC}),error:E1({},Q,{value:yC}),group:E1({},Q,{value:IC}),groupCollapsed:E1({},Q,{value:jC}),groupEnd:E1({},Q,{value:SC})})}0>Wz&&console.error("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}function M0(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 L0(Q){if(OO===void 0)try{throw Error()}catch(K){var X=K.stack.trim().match(/\n( *(at )?)/);OO=X&&X[1]||"",xC=-1)":-1F||y[N]!==a[F]){var s=`
+`+y[N].replace(" at new "," at ");return Q.displayName&&s.includes("")&&(s=s.replace("",Q.displayName)),typeof Q==="function"&&_O.set(Q,s),s}while(1<=N&&0<=F);break}}}finally{AO=!1,G0.H=$,H0(),Error.prepareStackTrace=K}return y=(y=Q?Q.displayName||Q.name:"")?L0(y):"",typeof Q==="function"&&_O.set(Q,y),y}function w0(Q,X){switch(Q.tag){case 26:case 27:case 5:return L0(Q.type);case 16:return L0("Lazy");case 13:return Q.child!==X&&X!==null?L0("Suspense Fallback"):L0("Suspense");case 19:return L0("SuspenseList");case 0:case 15:return u0(Q.type,!1);case 11:return u0(Q.type.render,!1);case 1:return u0(Q.type,!0);case 31:return L0("Activity");default:return""}}function c0(Q){try{var X="",K=null;do{X+=w0(Q,K);var $=Q._debugInfo;if($)for(var M=$.length-1;0<=M;M--){var N=$[M];if(typeof N.name==="string"){var F=X;Z:{var{name:V,env:D,debugLocation:y}=N;if(y!=null){var a=M0(y),s=a.lastIndexOf(`
+`),c=s===-1?a:a.slice(s+1);if(c.indexOf(V)!==-1){var q0=`
+`+c;break Z}}q0=L0(V+(D?" ["+D+"]":""))}X=F+q0}}K=Q,Q=Q.return}while(Q);return X}catch(T0){return`
+Error generating stack: `+T0.message+`
+`+T0.stack}}function o0(Q){return(Q=Q?Q.displayName||Q.name:"")?L0(Q):""}function v1(){if(P4===null)return null;var Q=P4._debugOwner;return Q!=null?o(Q):null}function z1(){if(P4===null)return"";var Q=P4;try{var X="";switch(Q.tag===6&&(Q=Q.return),Q.tag){case 26:case 27:case 5:X+=L0(Q.type);break;case 13:X+=L0("Suspense");break;case 19:X+=L0("SuspenseList");break;case 31:X+=L0("Activity");break;case 30:case 0:case 15:case 1:Q._debugOwner||X!==""||(X+=o0(Q.type));break;case 11:Q._debugOwner||X!==""||(X+=o0(Q.type.render))}for(;Q;)if(typeof Q.tag==="number"){var K=Q;Q=K._debugOwner;var $=K._debugStack;if(Q&&$){var M=M0($);M!==""&&(X+=`
+`+M)}}else if(Q.debugStack!=null){var N=Q.debugStack;(Q=Q.owner)&&N&&(X+=`
+`+M0(N))}else break;var F=X}catch(V){F=`
+Error generating stack: `+V.message+`
+`+V.stack}return F}function v0(Q,X,K,$,M,N,F){var V=P4;C1(Q);try{return Q!==null&&Q._debugTask?Q._debugTask.run(X.bind(null,K,$,M,N,F)):X(K,$,M,N,F)}finally{C1(V)}throw Error("runWithFiberInDEV should never be called in production. This is a bug in React.")}function C1(Q){G0.getCurrentStack=Q===null?null:z1,B3=!1,P4=Q}function Y5(Q){return typeof Symbol==="function"&&Symbol.toStringTag&&Q[Symbol.toStringTag]||Q.constructor.name||"Object"}function e5(Q){try{return w5(Q),!1}catch(X){return!0}}function w5(Q){return""+Q}function w1(Q,X){if(e5(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,Y5(Q)),w5(Q)}function m6(Q,X){if(e5(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,Y5(Q)),w5(Q)}function K1(Q){if(e5(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.",Y5(Q)),w5(Q)}function U4(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{mQ=X.inject(Q),A7=X}catch(K){console.error("React instrumentation encountered an error: %o.",K)}return X.checkDCE?!0:!1}function S1(Q){if(typeof Fc==="function"&&Pc(Q),A7&&typeof A7.setStrictMode==="function")try{A7.setStrictMode(mQ,Q)}catch(X){W3||(W3=!0,console.error("React instrumentation encountered an error: %o",X))}}function N6(Q){return Q>>>=0,Q===0?32:31-(Vc(Q)/Lc|0)|0}function n2(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 f4(Q,X,K){var $=Q.pendingLanes;if($===0)return 0;var M=0,N=Q.suspendedLanes,F=Q.pingedLanes;Q=Q.warmLanes;var V=$&134217727;return V!==0?($=V&~N,$!==0?M=n2($):(F&=V,F!==0?M=n2(F):K||(K=V&~Q,K!==0&&(M=n2(K))))):(V=$&~N,V!==0?M=n2(V):F!==0?M=n2(F):K||(K=$&~Q,K!==0&&(M=n2(K)))),M===0?0:X!==0&&X!==M&&(X&N)===0&&(N=M&-M,K=X&-X,N>=K||N===32&&(K&4194048)!==0)?X:M}function k2(Q,X){return(Q.pendingLanes&~(Q.suspendedLanes&~Q.pingedLanes)&X)===0}function H6(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 O6(){var Q=U$;return U$<<=1,(U$&62914560)===0&&(U$=4194304),Q}function e2(Q){for(var X=[],K=0;31>K;K++)X.push(Q);return X}function R5(Q,X){Q.pendingLanes|=X,X!==268435456&&(Q.suspendedLanes=0,Q.pingedLanes=0,Q.warmLanes=0)}function $2(Q,X,K,$,M,N){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:D,hiddenUpdates:y}=Q;for(K=F&~K;0"u")return null;try{return Q.activeElement||Q.body}catch(X){return Q.body}}function j0(Q){return Q.replace(Dc,function(X){return"\\"+X.charCodeAt(0).toString(16)+" "})}function d0(Q,X){X.checked===void 0||X.defaultChecked===void 0||mC||(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",v1()||"A component",X.type),mC=!0),X.value===void 0||X.defaultValue===void 0||hC||(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",v1()||"A component",X.type),hC=!0)}function r0(Q,X,K,$,M,N,F,V){if(Q.name="",F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"?(w1(F,"type"),Q.type=F):Q.removeAttribute("type"),X!=null)if(F==="number"){if(X===0&&Q.value===""||Q.value!=X)Q.value=""+t(X)}else Q.value!==""+t(X)&&(Q.value=""+t(X));else F!=="submit"&&F!=="reset"||Q.removeAttribute("value");X!=null?l0(Q,F,t(X)):K!=null?l0(Q,F,t(K)):$!=null&&Q.removeAttribute("value"),M==null&&N!=null&&(Q.defaultChecked=!!N),M!=null&&(Q.checked=M&&typeof M!=="function"&&typeof M!=="symbol"),V!=null&&typeof V!=="function"&&typeof V!=="symbol"&&typeof V!=="boolean"?(w1(V,"name"),Q.name=""+t(V)):Q.removeAttribute("name")}function Z1(Q,X,K,$,M,N,F,V){if(N!=null&&typeof N!=="function"&&typeof N!=="symbol"&&typeof N!=="boolean"&&(w1(N,"type"),Q.type=N),X!=null||K!=null){if(!(N!=="submit"&&N!=="reset"||X!==void 0&&X!==null)){P0(Q);return}K=K!=null?""+t(K):"",X=X!=null?""+t(X):K,V||X===Q.value||(Q.value=X),Q.defaultValue=X}$=$!=null?$:M,$=typeof $!=="function"&&typeof $!=="symbol"&&!!$,Q.checked=V?Q.checked:!!$,Q.defaultChecked=!!$,F!=null&&typeof F!=="function"&&typeof F!=="symbol"&&typeof F!=="boolean"&&(w1(F,"name"),Q.name=F),P0(Q)}function l0(Q,X,K){X==="number"&&I0(Q.ownerDocument)===Q||Q.defaultValue===""+K||(Q.defaultValue=""+K)}function p1(Q,X){X.value==null&&(typeof X.children==="object"&&X.children!==null?PJ.Children.forEach(X.children,function(K){K==null||typeof K==="string"||typeof K==="number"||typeof K==="bigint"||cC||(cC=!0,console.error("Cannot infer the option value of complex children. Pass a `value` prop or use a plain string as children to