@limrun/ui 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ "use strict";require('./index.css');const A=require("react/jsx-runtime"),f=require("react"),hn=require("react-dom");function Dr(n){var t,c,a="";if(typeof n=="string"||typeof n=="number")a+=n;else if(typeof n=="object")if(Array.isArray(n)){var E=n.length;for(t=0;t<E;t++)n[t]&&(c=Dr(n[t]))&&(a&&(a+=" "),a+=c)}else for(c in n)n[c]&&(a&&(a+=" "),a+=c);return a}function De(){for(var n,t,c=0,a="",E=arguments.length;c<E;c++)(n=arguments[c])&&(t=Dr(n))&&(a&&(a+=" "),a+=t);return a}const wt={INJECT_KEYCODE:0,INJECT_TOUCH_EVENT:2,INJECT_TWO_FINGER_TOUCH_EVENT:18,SET_CLIPBOARD:9},U={ACTION_DOWN:0,ACTION_UP:1,ACTION_MOVE:2,ACTION_CANCEL:3,ACTION_POINTER_DOWN:5,ACTION_POINTER_UP:6,BUTTON_PRIMARY:1,BUTTON_SECONDARY:2,BUTTON_TERTIARY:4},s={ACTION_DOWN:0,ACTION_UP:1,META_NONE:0,META_SHIFT_ON:1,META_ALT_ON:2,META_CTRL_ON:4096,META_META_ON:65536,KEYCODE_0:7,KEYCODE_1:8,KEYCODE_2:9,KEYCODE_3:10,KEYCODE_4:11,KEYCODE_5:12,KEYCODE_6:13,KEYCODE_7:14,KEYCODE_8:15,KEYCODE_9:16,DPAD_UP:19,DPAD_DOWN:20,DPAD_LEFT:21,DPAD_RIGHT:22,KEYCODE_A:29,KEYCODE_B:30,KEYCODE_C:31,KEYCODE_D:32,KEYCODE_E:33,KEYCODE_F:34,KEYCODE_G:35,KEYCODE_H:36,KEYCODE_I:37,KEYCODE_J:38,KEYCODE_K:39,KEYCODE_L:40,KEYCODE_M:41,KEYCODE_N:42,KEYCODE_O:43,KEYCODE_P:44,KEYCODE_Q:45,KEYCODE_R:46,KEYCODE_S:47,KEYCODE_T:48,KEYCODE_U:49,KEYCODE_V:50,KEYCODE_W:51,KEYCODE_X:52,KEYCODE_Y:53,KEYCODE_Z:54,KEYCODE_COMMA:55,KEYCODE_PERIOD:56,KEYCODE_ALT_LEFT:57,KEYCODE_ALT_RIGHT:58,KEYCODE_SHIFT_LEFT:59,KEYCODE_SHIFT_RIGHT:60,KEYCODE_TAB:61,KEYCODE_SPACE:62,ENTER:66,DEL:67,KEYCODE_GRAVE:68,KEYCODE_MINUS:69,KEYCODE_EQUALS:70,KEYCODE_LEFT_BRACKET:71,KEYCODE_RIGHT_BRACKET:72,KEYCODE_BACKSLASH:73,KEYCODE_SEMICOLON:74,KEYCODE_APOSTROPHE:75,KEYCODE_SLASH:76,MENU:82,KEYCODE_PAGE_UP:92,KEYCODE_PAGE_DOWN:93,KEYCODE_ESCAPE:111,FORWARD_DEL:112,KEYCODE_CTRL_LEFT:113,KEYCODE_CTRL_RIGHT:114,KEYCODE_META_LEFT:117,KEYCODE_META_RIGHT:118,KEYCODE_MOVE_HOME:122,KEYCODE_MOVE_END:123,KEYCODE_INSERT:124,KEYCODE_F1:131,KEYCODE_F2:132,KEYCODE_F3:133,KEYCODE_F4:134,KEYCODE_F5:135,KEYCODE_F6:136,KEYCODE_F7:137,KEYCODE_F8:138,KEYCODE_F9:139,KEYCODE_F10:140,KEYCODE_F11:141,KEYCODE_F12:142,KEYCODE_NUMPAD_0:144,KEYCODE_NUMPAD_1:145,KEYCODE_NUMPAD_2:146,KEYCODE_NUMPAD_3:147,KEYCODE_NUMPAD_4:148,KEYCODE_NUMPAD_5:149,KEYCODE_NUMPAD_6:150,KEYCODE_NUMPAD_7:151,KEYCODE_NUMPAD_8:152,KEYCODE_NUMPAD_9:153,KEYCODE_NUMPAD_DIVIDE:154,KEYCODE_NUMPAD_MULTIPLY:155,KEYCODE_NUMPAD_SUBTRACT:156,KEYCODE_NUMPAD_ADD:157,KEYCODE_NUMPAD_DOT:158,KEYCODE_NUMPAD_COMMA:159,KEYCODE_NUMPAD_ENTER:160,KEYCODE_NUMPAD_EQUALS:161},Rr={KeyA:s.KEYCODE_A,KeyB:s.KEYCODE_B,KeyC:s.KEYCODE_C,KeyD:s.KEYCODE_D,KeyE:s.KEYCODE_E,KeyF:s.KEYCODE_F,KeyG:s.KEYCODE_G,KeyH:s.KEYCODE_H,KeyI:s.KEYCODE_I,KeyJ:s.KEYCODE_J,KeyK:s.KEYCODE_K,KeyL:s.KEYCODE_L,KeyM:s.KEYCODE_M,KeyN:s.KEYCODE_N,KeyO:s.KEYCODE_O,KeyP:s.KEYCODE_P,KeyQ:s.KEYCODE_Q,KeyR:s.KEYCODE_R,KeyS:s.KEYCODE_S,KeyT:s.KEYCODE_T,KeyU:s.KEYCODE_U,KeyV:s.KEYCODE_V,KeyW:s.KEYCODE_W,KeyX:s.KEYCODE_X,KeyY:s.KEYCODE_Y,KeyZ:s.KEYCODE_Z,Digit0:s.KEYCODE_0,Digit1:s.KEYCODE_1,Digit2:s.KEYCODE_2,Digit3:s.KEYCODE_3,Digit4:s.KEYCODE_4,Digit5:s.KEYCODE_5,Digit6:s.KEYCODE_6,Digit7:s.KEYCODE_7,Digit8:s.KEYCODE_8,Digit9:s.KEYCODE_9,Backquote:s.KEYCODE_GRAVE,Minus:s.KEYCODE_MINUS,Equal:s.KEYCODE_EQUALS,BracketLeft:s.KEYCODE_LEFT_BRACKET,BracketRight:s.KEYCODE_RIGHT_BRACKET,Backslash:s.KEYCODE_BACKSLASH,Semicolon:s.KEYCODE_SEMICOLON,Quote:s.KEYCODE_APOSTROPHE,Comma:s.KEYCODE_COMMA,Period:s.KEYCODE_PERIOD,Slash:s.KEYCODE_SLASH,Space:s.KEYCODE_SPACE,Tab:s.KEYCODE_TAB,Escape:s.KEYCODE_ESCAPE,ArrowUp:s.DPAD_UP,ArrowDown:s.DPAD_DOWN,ArrowLeft:s.DPAD_LEFT,ArrowRight:s.DPAD_RIGHT,Enter:s.ENTER,Backspace:s.DEL,Delete:s.FORWARD_DEL,Home:s.KEYCODE_MOVE_HOME,End:s.KEYCODE_MOVE_END,PageUp:s.KEYCODE_PAGE_UP,PageDown:s.KEYCODE_PAGE_DOWN,Insert:s.KEYCODE_INSERT,F1:s.KEYCODE_F1,F2:s.KEYCODE_F2,F3:s.KEYCODE_F3,F4:s.KEYCODE_F4,F5:s.KEYCODE_F5,F6:s.KEYCODE_F6,F7:s.KEYCODE_F7,F8:s.KEYCODE_F8,F9:s.KEYCODE_F9,F10:s.KEYCODE_F10,F11:s.KEYCODE_F11,F12:s.KEYCODE_F12,ShiftLeft:s.KEYCODE_SHIFT_LEFT,ShiftRight:s.KEYCODE_SHIFT_RIGHT,ControlLeft:s.KEYCODE_CTRL_LEFT,ControlRight:s.KEYCODE_CTRL_RIGHT,AltLeft:s.KEYCODE_ALT_LEFT,AltRight:s.KEYCODE_ALT_RIGHT,MetaLeft:s.KEYCODE_META_LEFT,MetaRight:s.KEYCODE_META_RIGHT,ContextMenu:s.MENU,Numpad0:s.KEYCODE_NUMPAD_0,Numpad1:s.KEYCODE_NUMPAD_1,Numpad2:s.KEYCODE_NUMPAD_2,Numpad3:s.KEYCODE_NUMPAD_3,Numpad4:s.KEYCODE_NUMPAD_4,Numpad5:s.KEYCODE_NUMPAD_5,Numpad6:s.KEYCODE_NUMPAD_6,Numpad7:s.KEYCODE_NUMPAD_7,Numpad8:s.KEYCODE_NUMPAD_8,Numpad9:s.KEYCODE_NUMPAD_9,NumpadDivide:s.KEYCODE_NUMPAD_DIVIDE,NumpadMultiply:s.KEYCODE_NUMPAD_MULTIPLY,NumpadSubtract:s.KEYCODE_NUMPAD_SUBTRACT,NumpadAdd:s.KEYCODE_NUMPAD_ADD,NumpadDecimal:s.KEYCODE_NUMPAD_DOT,NumpadComma:s.KEYCODE_NUMPAD_COMMA,NumpadEnter:s.KEYCODE_NUMPAD_ENTER,NumpadEqual:s.KEYCODE_NUMPAD_EQUALS};function vt(n,t,c,a,E,p,C=1,O=0,K=0){const T=new ArrayBuffer(32),M=new DataView(T);let N=0;return M.setUint8(N,wt.INJECT_TOUCH_EVENT),N+=1,M.setUint8(N,n),N+=1,M.setBigInt64(N,BigInt(t),!0),N+=8,M.setInt32(N,Math.round(E),!0),N+=4,M.setInt32(N,Math.round(p),!0),N+=4,M.setUint16(N,c,!0),N+=2,M.setUint16(N,a,!0),N+=2,M.setInt16(N,Math.round(C*65535),!0),N+=2,M.setInt32(N,O,!0),N+=4,M.setInt32(N,K,!0),T}function mn(n,t,c,a,E,p,C){const O=new ArrayBuffer(24),K=new DataView(O);let T=0;return K.setUint8(T,wt.INJECT_TWO_FINGER_TOUCH_EVENT),T+=1,K.setUint8(T,n),T+=1,K.setInt32(T,Math.round(a),!0),T+=4,K.setInt32(T,Math.round(E),!0),T+=4,K.setInt32(T,Math.round(p),!0),T+=4,K.setInt32(T,Math.round(C),!0),T+=4,K.setUint16(T,t,!0),T+=2,K.setUint16(T,c,!0),T+=2,K.setUint16(T,0,!0),O}function En(n,t=!0){const a=new TextEncoder().encode(n),E=new ArrayBuffer(14+a.length),p=new DataView(E);let C=0;return p.setUint8(C,wt.SET_CLIPBOARD),C+=1,p.setBigInt64(C,BigInt(0),!1),C+=8,p.setUint8(C,t?1:0),C+=1,p.setUint32(C,a.length,!1),C+=4,new Uint8Array(E,C).set(a),E}function it(n,t,c=0,a=0){const E=new ArrayBuffer(14),p=new DataView(E);let C=0;return p.setUint8(C,wt.INJECT_KEYCODE),C+=1,p.setUint8(C,n),C+=1,p.setInt32(C,t,!0),C+=4,p.setInt32(C,c,!0),C+=4,p.setInt32(C,a,!0),E}const Dt="Accessibility unavailable on this device.",Rt=500,wr=(n,t)=>Math.abs(n.x-t.x)<.5&&Math.abs(n.y-t.y)<.5&&Math.abs(n.width-t.width)<.5&&Math.abs(n.height-t.height)<.5,pn=n=>Math.max(0,n.width)*Math.max(0,n.height),gn=n=>{const t=n.find(c=>c.frame&&c.frame.width>0&&c.frame.height>0);return t?.frame?((Math.abs(t.frame.x)>.5||Math.abs(t.frame.y)>.5)&&console.warn(`[ax-tree] iOS root frame is not anchored at (0,0): (${t.frame.x},${t.frame.y}). Element positions may be slightly off from the rendered video.`),{x:0,y:0,width:t.frame.width,height:t.frame.height}):{x:0,y:0,width:1,height:1}},Cn=n=>{const t={};return typeof n.AXUniqueId=="string"&&n.AXUniqueId.length>0&&(t.AXUniqueId=n.AXUniqueId),typeof n.AXLabel=="string"&&n.AXLabel.length>0&&(t.AXLabel=n.AXLabel),typeof n.type=="string"&&n.type.length>0&&(t.className=n.type),t},yn=n=>{const t={};for(const[c,a]of Object.entries(n))c!=="children"&&(t[c]=a);return t};function Ar(n){const t=Array.isArray(n)?n:[n],c=gn(t),a=[],E=(p,C)=>{if(a.length>=Rt)return;const O=p.frame;if(O&&O.width>0&&O.height>0&&!wr(O,c)){const T=p.role_description||p.role||"",M=(typeof p.AXLabel=="string"?p.AXLabel:"")||(typeof p.title=="string"?p.title:"")||"";a.push({id:typeof p.AXUniqueId=="string"&&p.AXUniqueId.length>0?p.AXUniqueId:C,path:C,label:M,value:typeof p.AXValue=="string"?p.AXValue:"",role:T,type:typeof p.type=="string"?p.type:"",enabled:p.enabled!==!1,focused:p.focused===!0,frame:{x:O.x,y:O.y,width:O.width,height:O.height},selectors:Cn(p),raw:yn(p)})}const K=Array.isArray(p.children)?p.children:[];for(let T=0;T<K.length&&a.length<Rt;T++)E(K[T],`${C}.${T}`)};for(let p=0;p<t.length&&a.length<Rt;p++)E(t[p],String(p));return{platform:"ios",screen:{width:c.width,height:c.height},elements:a,capturedAt:Date.now()}}const On=n=>{let t={x:0,y:0,width:1,height:1},c=0;for(const a of n){const E=a.parsedBounds;if(!E)continue;const p=E.right-E.left,C=E.bottom-E.top,O=Math.max(0,p)*Math.max(0,C);O>c&&(c=O,t={x:0,y:0,width:p,height:C})}return t},_n=n=>{const t={};return typeof n.resourceId=="string"&&n.resourceId.length>0&&(t.resourceId=n.resourceId),typeof n.contentDesc=="string"&&n.contentDesc.length>0&&(t.contentDesc=n.contentDesc),typeof n.text=="string"&&n.text.length>0&&(t.text=n.text),typeof n.className=="string"&&n.className.length>0&&(t.className=n.className),t};function Sr(n){const t=On(n),c=[];for(let a=0;a<n.length&&c.length<Rt;a++){const E=n[a],p=E.parsedBounds;if(!p)continue;const C=Math.max(0,p.right-p.left),O=Math.max(0,p.bottom-p.top);if(C<=0||O<=0)continue;const K={x:p.left,y:p.top,width:C,height:O};if(wr(K,{x:0,y:0,width:t.width,height:t.height}))continue;const T=E.contentDesc||E.text||"",M=E.className||"";c.push({id:E.resourceId&&E.resourceId.length>0?E.resourceId:E.contentDesc&&E.contentDesc.length>0?`cd:${E.contentDesc}`:String(a),path:String(a),label:T,value:typeof E.text=="string"?E.text:"",role:M,type:M,enabled:E.enabled!==!1,focused:E.focused===!0,frame:K,selectors:_n(E),raw:{...E}})}return{platform:"android",screen:{width:t.width,height:t.height},elements:c,capturedAt:Date.now()}}function Mr(n,t){const c=Math.max(0,n.x),a=Math.max(0,n.y),E=Math.min(t.width,n.x+n.width),p=Math.min(t.height,n.y+n.height),C=Math.max(0,E-c),O=Math.max(0,p-a);return C>0&&O>0?{x:c,y:a,width:C,height:O}:null}function Ht(n,t){if(n===t)return!0;if(n.id!==t.id||n.path!==t.path||n.label!==t.label||n.value!==t.value||n.role!==t.role||n.type!==t.type||n.enabled!==t.enabled||n.focused!==t.focused)return!1;const c=n.frame,a=t.frame;return c.x===a.x&&c.y===a.y&&c.width===a.width&&c.height===a.height}function $t(n,t){if(n===t)return!0;if(!n||!t||n.platform!==t.platform||n.screen.width!==t.screen.width||n.screen.height!==t.screen.height||n.elements.length!==t.elements.length)return!1;for(let c=0;c<n.elements.length;c++)if(!Ht(n.elements[c],t.elements[c]))return!1;return!0}function br(n,t,c){let a=null,E=1/0;for(const p of n.elements){const C=p.frame;if(t<C.x||c<C.y||t>C.x+C.width||c>C.y+C.height)continue;const O=pn(C);O<E&&(E=O,a=p)}return a}function Nr(n,t){if(t==="ios"){if(n.selectors.AXUniqueId)return`client.tapElement({ AXUniqueId: ${JSON.stringify(n.selectors.AXUniqueId)} })`;if(n.selectors.AXLabel){const c=n.selectors.className?`, type: ${JSON.stringify(n.selectors.className)}`:"";return`client.tapElement({ AXLabel: ${JSON.stringify(n.selectors.AXLabel)}${c} })`}return null}return n.selectors.resourceId?`client.tap({ selector: { resourceId: ${JSON.stringify(n.selectors.resourceId)} } })`:n.selectors.contentDesc?`client.tap({ selector: { contentDesc: ${JSON.stringify(n.selectors.contentDesc)} } })`:n.selectors.text?`client.tap({ selector: { text: ${JSON.stringify(n.selectors.text)} } })`:null}function Ir(n){const t=n.role||n.type||"";if(!t)return"element";let c=t.replace(/^AX/,"");return c.includes(".")&&(c=c.split(".").pop()),c==="GenericElement"?"Element":(c=c.replace(/([a-z])([A-Z])/g,"$1 $2"),c)}const yr=80;function Xt(n){const t=Ir(n),c=n.label||n.value||"";if(!c)return t;const a=c.length>yr?c.slice(0,yr).trimEnd()+"…":c;return`${t} · ${a}`}const vn=500,Tn=2e3,Or=5e3,Dn=8e3,Rn=1200,wn=250,An=()=>`ax-rc-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;class Sn{platform;send;onSnapshot;onStatusChange;baseIntervalMs;maxBackoffMs;androidElementTreeOptions;pending=new Map;running=!1;timer;currentInterval;lastSnapshot=null;inflight=!1;lastBumpAtMs=0;boostUntilMs=0;status="idle";constructor(t){this.platform=t.platform,this.send=t.send,this.onSnapshot=t.onSnapshot,this.onStatusChange=t.onStatusChange,this.baseIntervalMs=t.baseIntervalMs??vn,this.maxBackoffMs=t.maxBackoffMs??Tn,this.androidElementTreeOptions=t.androidElementTreeOptions,this.currentInterval=this.baseIntervalMs}start(){this.running||(this.running=!0,this.currentInterval=this.baseIntervalMs,this.boostUntilMs=0,this.setStatus("starting"),this.runOnce())}stop(){this.running&&(this.running=!1,this.timer!==void 0&&(window.clearTimeout(this.timer),this.timer=void 0),this.failAllPending("Inspector stopped"),this.lastSnapshot=null,this.setStatus("idle"),this.onSnapshot(null))}getStatus(){return this.status}setStatus(t,c){if(this.status!==t&&(this.status=t,!!this.onStatusChange))try{this.onStatusChange(t,c)}catch(a){console.error("[AxFetcher] onStatusChange threw:",a)}}bumpActivity(){if(!this.running)return;const t=Date.now();this.boostUntilMs=t+Rn;const c=Math.max(150,Math.floor(this.baseIntervalMs/2));if(t-this.lastBumpAtMs<c){this.currentInterval=this.baseIntervalMs;return}this.lastBumpAtMs=t,this.currentInterval=this.baseIntervalMs,this.timer!==void 0&&(window.clearTimeout(this.timer),this.timer=void 0),this.inflight||this.runOnce()}async refresh(){const t=await this.requestOnce();return this.running&&this.deliver(t),t}getLatest(){return this.lastSnapshot}handleMessage(t){if(!t||typeof t.id!="string")return!1;const c=t.id;if(!this.pending.get(c))return!1;if(this.platform==="ios"){if(t.type!=="elementTreeResult")return!1;const O=typeof t.error=="string"?t.error:null;if(O)return this.settleReject(c,new Error(O)),!0;const K=typeof t.json=="string"?t.json:"";try{const T=JSON.parse(K),M=Ar(T);this.settleResolve(c,M)}catch(T){this.settleReject(c,T instanceof Error?T:new Error(String(T)))}return!0}if(t.type!=="getElementTreeResult")return!1;const E=t.error;if(E&&typeof E=="object"){const O=typeof E.message=="string"?E.message:"getElementTree failed";return this.settleReject(c,new Error(O)),!0}const p=t.payload,C=Array.isArray(p?.nodes)?p.nodes:[];try{const O=Sr(C);this.settleResolve(c,O)}catch(O){this.settleReject(c,O instanceof Error?O:new Error(String(O)))}return!0}buildRequest(t){return this.platform==="ios"?{type:"elementTree",id:t}:{type:"getElementTree",id:t,...this.androidElementTreeOptions}}async requestOnce(){const t=An();return new Promise((c,a)=>{const E=window.setTimeout(()=>{this.pending.delete(t),a(new Error("elementTree request timed out"))},Dn+(this.androidElementTreeOptions?.waitForIdleTimeoutMs??0));this.pending.set(t,{resolve:c,reject:a,timer:E}),this.send(this.buildRequest(t))||(window.clearTimeout(E),this.pending.delete(t),a(new Error("elementTree send failed (WebSocket not open)")))})}async runOnce(){if(this.running&&!this.inflight){this.inflight=!0;try{const t=await this.requestOnce();if(!this.running)return;this.deliver(t)}catch(t){if(!this.running)return;const c=t instanceof Error?t.message:String(t),a=/unavailable|not (yet )?running|failed|timeout/i.test(c);this.currentInterval=a?Or:Math.min(this.currentInterval*2,this.maxBackoffMs),this.setStatus(a?"unavailable":"error",c)}finally{this.inflight=!1,this.scheduleNext()}}}deliver(t){const c=this.lastSnapshot;if($t(c,t)){this.currentInterval=Math.min(this.currentInterval*2,this.maxBackoffMs),this.lastSnapshot=t,t.errors?.includes(Dt)||this.setStatus("ready");return}this.lastSnapshot=t,this.currentInterval=this.baseIntervalMs,t.errors?.includes(Dt)?(this.currentInterval=Or,this.setStatus("unavailable",Dt)):this.setStatus("ready"),this.onSnapshot(t)}scheduleNext(){if(!this.running)return;this.timer!==void 0&&window.clearTimeout(this.timer);const t=Date.now()<this.boostUntilMs?Math.min(wn,this.currentInterval):this.currentInterval;this.timer=window.setTimeout(()=>{this.timer=void 0,this.runOnce()},t)}settleResolve(t,c){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.resolve(c))}settleReject(t,c){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.reject(c))}failAllPending(t){for(const[c,a]of this.pending.entries())window.clearTimeout(a.timer),a.reject(new Error(t)),this.pending.delete(c)}}class Mn{generation=0;tail=Promise.resolve();get currentGeneration(){return this.generation}enqueue(t){const c=++this.generation;return this.append(c,t)}enqueueCurrent(t){return this.append(this.generation,t)}append(t,c){const a={generation:t,isCurrent:()=>t===this.generation},E=this.tail.then(()=>c(a));return this.tail=E.catch(()=>{}),E}invalidate(){++this.generation}}function bn(n){if(!n||typeof n!="object")return null;const t=n;if(t.type!=="cameraRequest"||typeof t.active!="boolean")return null;const c={active:t.active};return(t.facingMode==="user"||t.facingMode==="environment")&&(c.facingMode=t.facingMode),c}function Nn(n){const t={frameRate:{ideal:30,max:30}};return n?.facingMode&&(t.facingMode={ideal:n.facingMode}),t}function In(n,t){return!n||n.facingMode!==t.facingMode}function Yn(n){const t=n.getSettings();return{width:t.width,height:t.height,frameRate:t.frameRate,deviceId:t.deviceId,label:n.label||void 0,facingMode:t.facingMode}}function Kn(n){return{type:"cameraResult",granted:!0,camera:Yn(n)}}const kn=async n=>{if(!n)return!1;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(n),!0}catch{}try{const t=document.createElement("textarea");t.value=n,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();const c=document.execCommand("copy");return document.body.removeChild(t),c}catch{return!1}},Pn=f.memo(function({element:t,screen:c,highlighted:a,selected:E,selectable:p,onClick:C}){const O=Mr(t.frame,c);if(!O)return null;const K=Xt(t);return A.jsx("button",{type:"button",className:De("rc-inspect-box",!t.enabled&&"rc-inspect-box-disabled"),"data-ax-id":t.id,"data-ax-path":t.path,"data-ax-label":t.label||void 0,"data-ax-role":t.role||void 0,"data-highlighted":a?"true":"false","data-selected":E?"true":"false","aria-label":K,onClick:T=>{p&&(T.preventDefault(),T.stopPropagation(),C(t,{x:T.clientX,y:T.clientY}))},style:{left:`${O.x/c.width*100}%`,top:`${O.y/c.height*100}%`,width:`${O.width/c.width*100}%`,height:`${O.height/c.height*100}%`}})},(n,t)=>n.highlighted===t.highlighted&&n.selected===t.selected&&n.selectable===t.selectable&&n.screen.width===t.screen.width&&n.screen.height===t.screen.height&&n.onClick===t.onClick&&Ht(n.element,t.element)),Ln=260,Un=220,xn=6,Fn=8,Wn=f.memo(function({element:t,platform:c,anchor:a,cursorAnchored:E,showActions:p,onTap:C}){const[O,K]=f.useState(null);f.useEffect(()=>{if(!O)return;const X=window.setTimeout(()=>K(null),1100);return()=>window.clearTimeout(X)},[O]);const T=f.useMemo(()=>{const X=Ln,ne=Un,J=xn,$=Fn,fe=typeof window<"u"?window.innerWidth:1024,we=typeof window<"u"?window.innerHeight:768,F=a.x+J+X<=fe-$,he=a.y-J-ne>=$;let Xe=F?a.x+J:a.x-J,me=he?a.y-J:a.y+J;const At=`translate(${F?"0":"-100%"}, ${he?"-100%":"0"})`;return Xe=Math.max($+(F?0:X),Math.min(fe-$-(F?X:0),Xe)),me=Math.max($+(he?ne:0),Math.min(we-$-(he?0:ne),me)),{left:`${Xe}px`,top:`${me}px`,transform:At}},[a.x,a.y]),M=f.useMemo(()=>Nr(t,c),[t,c]),N=c==="ios"?t.selectors.AXUniqueId:t.selectors.resourceId,re=c==="ios"?"AXUniqueId":"resourceId",ae=f.useCallback(async(X,ne)=>{if(!X)return;await kn(X)&&K(ne)},[]),de=Ir(t),ct=t.label||t.value||de,Re=Xt(t);return hn.createPortal(A.jsxs("div",{className:"rc-inspect-card","data-cursor-anchored":E?"true":"false",style:T,onClick:X=>X.stopPropagation(),onMouseDown:X=>X.stopPropagation(),onMouseMove:X=>X.stopPropagation(),children:[A.jsxs("div",{className:"rc-inspect-card-header",children:[A.jsx("span",{className:"rc-inspect-card-role",children:de}),!t.enabled&&A.jsx("span",{className:"rc-inspect-card-tag",children:"disabled"}),t.focused&&A.jsx("span",{className:"rc-inspect-card-tag rc-inspect-card-tag-blue",children:"focused"})]}),A.jsx("p",{className:"rc-inspect-card-title",title:Re,children:ct}),N&&A.jsxs("div",{className:"rc-inspect-card-row",children:[A.jsxs("span",{className:"rc-inspect-card-row-label",children:[re,":"]}),A.jsx("span",{className:"rc-inspect-card-row-value",children:N})]}),t.value&&t.value!==t.label&&A.jsxs("div",{className:"rc-inspect-card-row",children:[A.jsx("span",{className:"rc-inspect-card-row-label",children:"value:"}),A.jsx("span",{className:"rc-inspect-card-row-value",children:t.value})]}),A.jsxs("div",{className:"rc-inspect-card-row",children:[A.jsx("span",{className:"rc-inspect-card-row-label",children:"frame:"}),A.jsxs("span",{className:"rc-inspect-card-row-value",children:[Math.round(t.frame.width),"×",Math.round(t.frame.height)," @ ",Math.round(t.frame.x),",",Math.round(t.frame.y)]})]}),p&&A.jsxs("div",{className:"rc-inspect-card-actions",children:[A.jsx("button",{type:"button",className:"rc-inspect-card-btn rc-inspect-card-btn-primary",onClick:()=>C(t,a),children:"Tap"}),A.jsx("button",{type:"button",className:De("rc-inspect-card-btn",O==="selector"&&"rc-inspect-card-btn-copied"),disabled:!M,title:M??"No usable selector for this element",onClick:()=>ae(M??void 0,"selector"),children:O==="selector"?"Copied!":"Copy selector"}),A.jsx("button",{type:"button",className:De("rc-inspect-card-btn",O==="id"&&"rc-inspect-card-btn-copied"),disabled:!N,title:N??`No ${re}`,onClick:()=>ae(N,"id"),children:O==="id"?"Copied!":`Copy ${re}`})]})]}),document.body)}),Hn=f.memo(function({snapshot:t,geometry:c,highlightedId:a,selectedId:E,mode:p,cursorPosition:C,frozenCursorPosition:O,onSelectChange:K,onTapElement:T}){const M=p==="select",N=M?a!==null&&a!==E:a!==null,re=M?a??E:a,ae=f.useMemo(()=>{const $=new Map;if(!t)return $;for(const fe of t.elements)$.set(fe.id,fe);return $},[t]),de=f.useMemo(()=>re?ae.get(re)??null:null,[re,ae]);if(!(!!t&&!!c&&t.screen.width>0&&t.screen.height>0&&t.elements.length>0))return null;const Re=N?C:O??C,X=N,ne=M&&!N&&E!==null,J=$=>{M&&$.target===$.currentTarget&&K(null,null)};return A.jsxs(A.Fragment,{children:[A.jsx("div",{className:De("rc-inspect-overlay",M&&"rc-inspect-overlay-select"),style:{left:`${c.left}px`,top:`${c.top}px`,width:`${c.width}px`,height:`${c.height}px`},onClick:J,children:t.elements.map($=>A.jsx(Pn,{element:$,screen:t.screen,highlighted:$.id===a,selected:$.id===E,selectable:M,onClick:K},$.id))}),de&&Re&&A.jsx(Wn,{element:de,platform:t.platform,anchor:Re,cursorAnchored:X,showActions:ne,onTap:T})]})}),W=(...n)=>{window.debugRemoteControl&&console.log(...n)},R=(...n)=>{window.debugRemoteControl&&console.warn(...n)},x=(n,t,...c)=>{if(t)try{t(...c)}catch(a){console.error(`[RemoteControl] customer callback "${n}" threw:`,a)}},Tt=n=>Object.entries(U).find(([c,a])=>c.startsWith("ACTION_")&&a===n)?.[0]??String(n),$n=n=>n.includes("/android_")?"android":"ios",_r=(n,t)=>{const c=new URL(n);return c.searchParams.set("token",t),c.toString()},vr=1920,Tr=1200,Wt=3,Xn=1e3,Bn=15e3,qn=3e3,Vn=4e3,jn=(n,t)=>n===vr&&t===Tr||n===Tr&&t===vr,Gn={ios:{videoBorderRadiusMultiplier:.15,loadingLogoSize:"20%",videoPosition:{portrait:{heightMultiplier:.9678},landscape:{widthMultiplier:.9678}}},android:{videoBorderRadiusMultiplier:.13,loadingLogoSize:"40%",videoPosition:{portrait:{heightMultiplier:.967},landscape:{widthMultiplier:.962}}}};function Jn(n){const t=n.code,c=Rr[t];if(!c)return R(`Unknown event.code: ${t}, key: ${n.key}`),null;let a=s.META_NONE;const E=t>="KeyA"&&t<="KeyZ",p=n.getModifierState("CapsLock"),C=n.shiftKey;let O=C;return E&&(O=C!==p),O&&(a|=s.META_SHIFT_ON),n.ctrlKey&&(a|=s.META_CTRL_ON),n.altKey&&(a|=s.META_ALT_ON),n.metaKey&&(a|=s.META_META_ON),{keycode:c,metaState:a}}const zn=f.forwardRef(({className:n,url:t,token:c,sessionId:a,openUrl:E,showFrame:p=!0,autoReconnect:C=!1,onTerminated:O,assets:K,onConnectionStateChange:T,inspectMode:M,onAxSnapshotChange:N,onInspectSelectionChange:re,onAxStatusChange:ae,axPollIntervalMs:de,axMaxBackoffMs:ct,androidElementTreeOptions:Re,onCameraDemandChange:X,onCameraStats:ne,microphoneEnabled:J=!1,onMicrophoneStateChange:$},fe)=>{const we=f.useRef(null),F=f.useRef(null),he=f.useRef(null),[Xe,me]=f.useState(!1),[Bt,Be]=f.useState(!1),[At,qt]=f.useState(!1),Ae=f.useRef(!1),St=f.useRef(!1),[Vt,Yr]=f.useState(!1),[Kr,kr]=f.useState(!1),[Pr,jt]=f.useState({}),D=f.useRef(null),H=f.useRef(null),L=f.useRef(null),Se=f.useRef(void 0),qe=f.useRef(void 0),Ve=f.useRef(void 0),st=f.useRef(void 0),Me=f.useRef(void 0),Ee=f.useRef(0),at=f.useRef(0),be=f.useRef(!1),Mt=f.useRef(C);Mt.current=C;const pe=f.useRef(null),z=f.useRef(null),ge=f.useRef(void 0),bt=f.useMemo(()=>new Mn,[]),ce=f.useRef(X);ce.current=X;const ut=f.useRef(ne);ut.current=ne;const je=f.useRef(null),lt=f.useRef(null),Nt=f.useRef(J);Nt.current=J;const It=f.useRef(!1),Ge=f.useRef($);Ge.current=$;const Je=f.useRef(null),oe=f.useRef(null),dt=f.useRef(0),Gt=f.useRef(Promise.resolve()),Ne=f.useRef(null),ze=f.useRef(!1),ue=f.useRef(new Map),se=f.useRef(new Map),Ce=f.useRef(new Map),ye=f.useRef(new Map),V=f.useRef(new Map),Oe=f.useRef(!1),[Lr,Ur]=f.useState(!1),B=f.useRef(null),Ie=f.useRef(null),Qe=f.useRef({handle:()=>{},end:()=>{}}),[_e,ft]=f.useState(null),j=f.useRef(null),[Jt,zt]=f.useState(null),[Yt,Ze]=f.useState(null),[Kt,ht]=f.useState(null),[xr,Qt]=f.useState(null),[Fr,Zt]=f.useState(null),mt=f.useRef(null),Z=f.useRef(void 0),er=e=>{mt.current=e,Z.current===void 0&&(Z.current=window.requestAnimationFrame(()=>{Z.current=void 0,Zt(mt.current)}))},[Wr,Ye]=f.useState(null),Ke=f.useRef(M);Ke.current=M;const ke=f.useRef(null);ke.current=Jt;const kt=f.useRef(N);kt.current=N;const Pe=f.useRef(re);Pe.current=re;const tr=f.useRef(ae);tr.current=ae;const rr=f.useRef(O);rr.current=O;const nr=f.useRef(T);nr.current=T;const Pt=f.useRef(null),Le=e=>{Pt.current!==e&&(Pt.current=e,x("onConnectionStateChange",nr.current,e))},et=M===!0||M==="hover-only",Hr=M==="hover-only"?"hover-only":"select",ee=f.useMemo(()=>a||Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),[a]),ie=f.useMemo(()=>$n(t),[t]),Ue=Gn[ie],tt=K?.[ie],or=ie==="android"&&Kr?Vt?tt?.tabletFrameLandscape:tt?.tabletFrame:Vt?tt?.frameLandscape:tt?.frame,ir=tt?.loadingLogo,Et=p&&!!or,k=e=>{W(e)},te=e=>{!L.current||L.current.readyState!=="open"||(L.current.send(e),j.current?.bumpActivity())},cr=-10,sr=(e,i)=>{const r=rt();if(!r)return;const o=Fe(r,e,i);if(!o)return;const{videoX:m,videoY:l,videoWidth:h,videoHeight:u}=o,g=vt(U.ACTION_DOWN,cr,h,u,m,l,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);g&&te(g),window.setTimeout(()=>{const _=vt(U.ACTION_UP,cr,h,u,m,l,0,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);_&&te(_)},60)},$r=(e,i)=>{const r=rt();if(!r||i.screen.width<=0||i.screen.height<=0)return;const o=e.frame.x+e.frame.width/2,m=e.frame.y+e.frame.height/2,l=o/i.screen.width*r.actualWidth,h=m/i.screen.height*r.actualHeight,u=r.videoRect.left+r.offsetX+l,g=r.videoRect.top+r.offsetY+h;sr(u,g)},pt=-1,gt=-2,ve=-3,xe=(e,i,r,o,m,l)=>{const h=vt(e,i,r,o,m,l,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);h&&(W("[rc-touch] sendSingleTouch",{action:e,actionName:Tt(e),pointerId:i,x:m,y:l,video:{width:r,height:o}}),te(h))},Te=(e,i,r)=>{if(!r)return;const{videoX:o,videoY:m,videoWidth:l,videoHeight:h}=r;let u=null,g=null,_=1;const b=U.BUTTON_PRIMARY;switch(i){case"down":e!==ve&&Qe.current.end(),u=V.current.size===0?U.ACTION_DOWN:U.ACTION_POINTER_DOWN,g={x:o,y:m},V.current.set(e,g),e===-1&&F.current?.focus();break;case"move":V.current.has(e)&&(u=U.ACTION_MOVE,g={x:o,y:m},V.current.set(e,g));break;case"up":case"cancel":V.current.has(e)&&(g=V.current.get(e),V.current.delete(e),i==="cancel"?u=U.ACTION_CANCEL:u=V.current.size===0?U.ACTION_UP:U.ACTION_POINTER_UP);break}if(u!==null&&g!==null){W("[rc-touch][mouse->touch] sending",{pointerId:e,eventType:i,action:u,actionName:Tt(u),positionToSend:g,video:{width:l,height:h},altHeld:Oe.current,activePointersAfter:Array.from(V.current.entries()).map(([w,y])=>({id:w,x:y.x,y:y.y}))});const v=vt(u,e,l,h,g.x,g.y,_,b,b);v&&(W("[rc-touch][mouse->touch] buffer",{pointerId:e,actionName:Tt(u),byteLength:v.byteLength}),te(v))}else(i==="up"||i==="cancel")&&V.current.delete(e)},Lt=e=>{if(Oe.current!==e&&(Oe.current=e,Ur(e),e||ft(null),W("[rc-touch][alt] updateAltHeld",{nextHeld:e,activePointerIds:Array.from(V.current.keys())}),ie==="ios"&&L.current&&L.current.readyState==="open")){const i=e?s.ACTION_DOWN:s.ACTION_UP,r=it(i,s.KEYCODE_ALT_LEFT,0,s.META_NONE);W("[rc-touch][alt] sending Indigo modifier keycode",{action:i,keycode:s.KEYCODE_ALT_LEFT}),r&&te(r)}},rt=()=>{const e=F.current,i=we.current;if(!e||!i)return null;const r=e.videoWidth,o=e.videoHeight;if(!r||!o)return null;const m=e.getBoundingClientRect(),l=i.getBoundingClientRect(),h=m.width,u=m.height,g=r/o,_=h/u;let b=h,v=u;g>_?v=h/g:b=u*g;const w=(h-b)/2,y=(u-v)/2;return{videoWidth:r,videoHeight:o,videoRect:m,containerRect:l,actualWidth:b,actualHeight:v,offsetX:w,offsetY:y}},Fe=(e,i,r)=>{const o=i-e.videoRect.left-e.offsetX,m=r-e.videoRect.top-e.offsetY,l=Math.max(0,Math.min(e.actualWidth,o)),h=Math.max(0,Math.min(e.actualHeight,m)),u=Math.max(0,Math.min(e.videoWidth,l/e.actualWidth*e.videoWidth)),g=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight));return{videoX:u,videoY:g,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},Xr=(e,i,r)=>{const o=i-e.videoRect.left-e.offsetX,m=r-e.videoRect.top-e.offsetY,l=Math.max(0,Math.min(e.actualWidth,o)),h=Math.max(0,Math.min(e.actualHeight,m)),u=Math.max(0,Math.min(e.videoWidth,l/e.actualWidth*e.videoWidth)),g=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight)),_=e.videoWidth-u,b=e.videoHeight-g,v=e.videoRect.left+e.offsetX,w=e.videoRect.top+e.offsetY,y=v-e.containerRect.left+l,d=w-e.containerRect.top+h,I=v-e.containerRect.left+(e.actualWidth-l),P=w-e.containerRect.top+(e.actualHeight-h);return{containerX:y,containerY:d,mirrorContainerX:I,mirrorContainerY:P,videoX:u,videoY:g,mirrorVideoX:_,mirrorVideoY:b,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},Br=(e,i,r,o,m,l,h)=>{const u=mn(e,i,r,o,m,l,h);W("[rc-touch2] sendTwoFingerMessage (iOS)",{actionName:Tt(e),video:{width:i,height:r},p0:{x:o,y:m},p1:{x:l,y:h},byteLength:u.byteLength}),te(u)},We=(e,i,r,o,m,l,h,u,g)=>{if(W("[rc-touch2] applyTwoFingerEvent",{platform:ie,eventType:e,video:{width:i,height:r},p0:{x:o,y:m,id:u},p1:{x:l,y:h,id:g}}),e==="down"&&Qe.current.end(),ie==="ios"){const _=e==="down"?U.ACTION_DOWN:e==="move"?U.ACTION_MOVE:U.ACTION_UP;Br(_,i,r,o,m,l,h)}else e==="down"?(xe(U.ACTION_DOWN,u,i,r,o,m),xe(U.ACTION_POINTER_DOWN,g,i,r,l,h)):e==="move"?(xe(U.ACTION_MOVE,u,i,r,o,m),xe(U.ACTION_MOVE,g,i,r,l,h)):(xe(U.ACTION_POINTER_UP,g,i,r,l,h),xe(U.ACTION_UP,u,i,r,o,m))},qr=(e,i,r)=>{if(!Oe.current){_e!==null&&ft(null);return}const o=Xr(e,i,r);ft(o)},Vr=(e,i,r)=>{const o=ke.current;if(!o||o.screen.width<=0||o.screen.height<=0)return null;const m=i-e.videoRect.left-e.offsetX,l=r-e.videoRect.top-e.offsetY;if(m<0||l<0||m>e.actualWidth||l>e.actualHeight)return null;const h=m/e.actualWidth*o.screen.width,u=l/e.actualHeight*o.screen.height;return br(o,h,u)},le=e=>{e.preventDefault(),e.stopPropagation();const i=rt();if((Ke.current===!0||Ke.current==="hover-only")&&!("touches"in e))if(e.type==="mousemove"){if(er({x:e.clientX,y:e.clientY}),i){const o=Vr(i,e.clientX,e.clientY);Ze(o?.id??null)}}else e.type==="mouseleave"&&(er(null),Ze(null));if(Ke.current!==!0&&(!("touches"in e)&&i&&(e.type==="mousemove"?qr(i,e.clientX,e.clientY):e.type==="mouseleave"&&ft(null)),!(!L.current||L.current.readyState!=="open"||!F.current||!i)))if("touches"in e){const o=e.touches,m=e.changedTouches;let l;switch(e.type){case"touchstart":l="down";break;case"touchmove":l="move";break;case"touchend":l="up";break;case"touchcancel":l="cancel";break;default:return}if(o.length===2){const h=o[0],u=o[1],g=Fe(i,h.clientX,h.clientY),_=Fe(i,u.clientX,u.clientY);if(!g||!_)return;B.current?B.current.source==="real-touch"&&(B.current.finger0={x:g.videoX,y:g.videoY},B.current.finger1={x:_.videoX,y:_.videoY},We("move",g.videoWidth,g.videoHeight,g.videoX,g.videoY,_.videoX,_.videoY,B.current.pointerId0,B.current.pointerId1)):(B.current={finger0:{x:g.videoX,y:g.videoY},finger1:{x:_.videoX,y:_.videoY},videoSize:{width:g.videoWidth,height:g.videoHeight},source:"real-touch",pointerId0:h.identifier,pointerId1:u.identifier},We("down",g.videoWidth,g.videoHeight,g.videoX,g.videoY,_.videoX,_.videoY,h.identifier,u.identifier))}else if(o.length<2&&B.current?.source==="real-touch"){const h=B.current;We("up",h.videoSize.width,h.videoSize.height,h.finger0.x,h.finger0.y,h.finger1.x,h.finger1.y,h.pointerId0,h.pointerId1),B.current=null;return}else{if(o.length>2)return;{const h=m[0];if(h){const u=Fe(i,h.clientX,h.clientY);Te(h.identifier,l,u)}}}}else{let m=null;const l=B.current?.source==="alt-mouse";switch(e.type){case"mousedown":e.button===0&&(m="down");break;case"mousemove":(l||V.current.has(-1))&&(m="move");break;case"mouseup":e.button===0&&(m="up");break;case"mouseleave":(l||V.current.has(-1))&&(m="up");break}if(m){const h=Fe(i,e.clientX,e.clientY);if(!h)return;W("[rc-touch][mouse] event",{domType:e.type,eventType:m,button:e.button,buttons:e.buttons,client:{x:e.clientX,y:e.clientY},altHeldRef:Oe.current,inTwoFingerMode:l,geometry:{videoX:h.videoX,videoY:h.videoY,videoWidth:h.videoWidth,videoHeight:h.videoHeight},activePointerIds:Array.from(V.current.keys())}),Oe.current||l?jr(m,h):Te(-1,m,h)}}},jr=(e,i)=>{const{videoX:r,videoY:o,videoWidth:m,videoHeight:l}=i,h=m-r,u=l-o;if(e==="down"){B.current={finger0:{x:r,y:o},finger1:{x:h,y:u},videoSize:{width:m,height:l},source:"alt-mouse",pointerId0:pt,pointerId1:gt},F.current?.focus(),We("down",m,l,r,o,h,u,pt,gt);return}if(e==="move"){B.current?.source==="alt-mouse"&&(B.current.finger0={x:r,y:o},B.current.finger1={x:h,y:u},We("move",m,l,r,o,h,u,pt,gt));return}if(e==="up"||e==="cancel"){const g=B.current;if(g?.source==="alt-mouse"){const{finger0:_,finger1:b,videoSize:v}=g;We("up",v.width,v.height,_.x,_.y,b.x,b.y,pt,gt),B.current=null}return}},Gr=150,ar=()=>{const e=Ie.current;e&&(window.clearTimeout(e.endTimer),Te(ve,"up",e.pos),Ie.current=null)},Jr=e=>{if(e.ctrlKey||Oe.current||B.current)return;const i=V.current.size;if(i>1||i===1&&!V.current.has(ve))return;const r=rt();if(!r)return;const o=e.clientX-r.videoRect.left-r.offsetX,m=e.clientY-r.videoRect.top-r.offsetY;if(o<0||o>r.actualWidth||m<0||m>r.actualHeight)return;const l=Fe(r,e.clientX,e.clientY);if(!l)return;e.preventDefault();const h=(e.deltaMode===1?16:e.deltaMode===2?r.actualWidth:1)*(r.videoWidth/r.actualWidth),u=(e.deltaMode===1?16:e.deltaMode===2?r.actualHeight:1)*(r.videoHeight/r.actualHeight),g=-e.deltaX*h,_=-e.deltaY*u,b=P=>{window.clearTimeout(P.endTimer),P.endTimer=window.setTimeout(ar,Gr)};if(g===0&&_===0){Ie.current&&b(Ie.current);return}const v=()=>({videoWidth:l.videoWidth,videoHeight:l.videoHeight,videoX:Math.abs(g)>Math.abs(_)?Math.min(Math.max(l.videoX,l.videoWidth*.2),l.videoWidth*.8):l.videoX,videoY:Math.abs(_)>=Math.abs(g)?Math.min(Math.max(l.videoY,l.videoHeight*.2),l.videoHeight*.8):l.videoY}),w=P=>({...P,videoX:Math.min(Math.max(P.videoX+g,0),P.videoWidth),videoY:Math.min(Math.max(P.videoY+_,0),P.videoHeight)});let y=Ie.current;if(y)window.clearTimeout(y.endTimer);else{const P=v();Te(ve,"down",P),y={pos:P,endTimer:0},Ie.current=y}let d=y.pos,I=w(d);I.videoX===d.videoX&&I.videoY===d.videoY&&(Te(ve,"up",d),d=v(),Te(ve,"down",d),I=w(d)),Te(ve,"move",I),y.pos=I,b(y)};f.useEffect(()=>{Qe.current={handle:Jr,end:ar}}),f.useEffect(()=>{const e=we.current;if(!e)return;const i=r=>Qe.current.handle(r);return e.addEventListener("wheel",i,{passive:!1}),()=>{Qe.current.end(),e.removeEventListener("wheel",i)}},[]),f.useEffect(()=>{const e=o=>{o.key==="Alt"&&Lt(!0)},i=o=>{o.key==="Alt"&&Lt(!1)},r=()=>{Lt(!1)};return window.addEventListener("keydown",e,!0),window.addEventListener("keyup",i,!0),window.addEventListener("blur",r),()=>{window.removeEventListener("keydown",e,!0),window.removeEventListener("keyup",i,!0),window.removeEventListener("blur",r)}},[]);const ur=e=>{if(e.preventDefault(),e.stopPropagation(),W("Keyboard event:",{type:e.type,key:e.key,keyCode:e.keyCode,code:e.code,target:e.target.tagName,focused:document.activeElement===F.current}),document.activeElement!==F.current){R("Video element not focused, skipping keyboard event");return}if(!L.current||L.current.readyState!=="open"){R("Data channel not ready for keyboard event:",L.current?.readyState);return}if(e.type==="keydown"){if(e.key.toLowerCase()==="v"&&(e.metaKey||e.ctrlKey)){W("Paste shortcut detected"),navigator.clipboard.readText().then(r=>{if(r){W("Pasting text via SET_CLIPBOARD:",r.substring(0,20)+(r.length>20?"...":""));const o=En(r,!0);te(o)}}).catch(r=>{console.error("Failed to read clipboard contents: ",r)});return}if(e.key.toLowerCase()==="m"&&(e.metaKey||e.ctrlKey)){W("Menu shortcut detected");const r=it(s.ACTION_DOWN,s.MENU,0,s.META_NONE);te(r);const o=it(s.ACTION_UP,s.MENU,0,s.META_NONE);te(o);return}}const i=Jn(e);if(i){const{keycode:r,metaState:o}=i,m=e.type==="keydown"?s.ACTION_DOWN:s.ACTION_UP;W(`Sending Keycode: key=${e.key}, code=${r}, action=${m}, meta=${o}`);const l=it(m,r,0,o);te(l)}else W(`Ignoring unhandled key event: type=${e.type}, key=${e.key}`)},zr=()=>{D.current&&D.current.readyState===WebSocket.OPEN&&D.current.send(JSON.stringify({type:"keepAlive",sessionId:ee}))},lr=()=>{Se.current&&window.clearInterval(Se.current),Se.current=window.setInterval(zr,1e4)},dr=()=>{Se.current&&(window.clearInterval(Se.current),Se.current=void 0)},Ct=()=>{qe.current&&(window.clearTimeout(qe.current),qe.current=void 0)},yt=()=>{Ve.current&&(window.clearTimeout(Ve.current),Ve.current=void 0)},nt=()=>{st.current&&(window.clearInterval(st.current),st.current=void 0)},ot=()=>{Me.current!==void 0&&(window.clearTimeout(Me.current),Me.current=void 0)},Qr=()=>{ze.current||(ze.current=!0,nt(),me(!0),Le("connected"))},G=e=>{for(const i of e.getTracks())try{i.stop()}catch(r){R("track.stop() failed:",r)}},Zr=()=>{const e=z.current;e&&(z.current=null,G(e))},fr=e=>{const i=Gt.current.then(e).catch(r=>{R("microphone operation failed:",r)});return Gt.current=i,i},Ut=()=>Nt.current||It.current,hr=e=>{const i=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;Ne.current=i,e.send(JSON.stringify({type:"microphoneStart",id:i}))},xt=()=>fr(()=>en()),en=async()=>{const e=dt.current,i=()=>e===dt.current&&Ut(),r=u=>{x("onMicrophoneStateChange",Ge.current,{active:!1,error:u})};if(!i())return;const o=D.current,m=Je.current;if(!o||o.readyState!==WebSocket.OPEN||!m||oe.current)return;if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){console.warn("[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost)."),r("Microphone capture requires a secure context (https)");return}let l=null;try{l=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})}catch(u){console.warn("[RemoteControl] microphone getUserMedia denied/failed:",u)}if(!i()){l&&G(l);return}if(!l){r("Microphone permission denied or no device available");return}const h=l.getAudioTracks()[0]??null;if(!h){G(l),r("Captured stream has no audio track");return}try{await m.replaceTrack(h)}catch(u){R("replaceTrack(audioTrack) failed:",u),G(l),r("Failed to attach the microphone track to the connection");return}if(!i()){try{await m.replaceTrack(null)}catch(u){R("replaceTrack(null) on stale mic attach failed:",u)}G(l);return}oe.current=l,h.onended=()=>{oe.current===l&&Ot("microphone capture ended by the browser")},hr(o),x("onMicrophoneStateChange",Ge.current,{active:!0,label:h.label||void 0})},Ot=e=>(++dt.current,Ne.current=null,fr(async()=>{const i=Je.current,r=oe.current;if(oe.current=null,i&&r)try{await i.replaceTrack(null)}catch(m){R("replaceTrack(null) on mic detach failed:",m)}r&&G(r);const o=D.current;if(r&&o&&o.readyState===WebSocket.OPEN){const m=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;o.send(JSON.stringify({type:"microphoneStop",id:m}))}(r||e)&&x("onMicrophoneStateChange",Ge.current,{active:!1,...e!==void 0&&{error:e}})})),mr=(e,i)=>{let r;try{r=Kn(i),console.info(`[RemoteControl] camera capture: ${r.camera?.width}x${r.camera?.height} @ ${r.camera?.frameRate??"?"}fps`+(r.camera?.label?` — ${r.camera.label}`:""))}catch(o){R("getSettings() on outbound camera track failed:",o),r={type:"cameraResult",granted:!0,camera:{label:i.label||void 0}}}e.send(JSON.stringify(r)),x("onCameraDemandChange",ce.current,!0,!0,r.camera)},tn=e=>{if(!e)return;const i=e.indexOf("/"),o=(i>=0?e.slice(i+1):e).toUpperCase();return o==="HEVC"?"H265":o},rn=async()=>{const e=pe.current,i=ut.current;if(!e||!i)return;let r;try{r=await e.getStats()}catch{return}let o,m,l;if(r.forEach(w=>{w.type==="outbound-rtp"&&w.kind==="video"?o=w:w.type==="remote-inbound-rtp"&&w.kind==="video"&&(l=w)}),o?.codecId){const w=r.get(o.codecId);w&&(m=w.mimeType)}if(!o)return;const h=o.timestamp??Date.now(),u=lt.current;let g,_,b;if(u&&h>u.timestamp){const w=(h-u.timestamp)/1e3;if(typeof o.framesEncoded=="number"&&typeof u.framesEncoded=="number"&&(g=Math.max(0,(o.framesEncoded-u.framesEncoded)/w)),typeof o.bytesSent=="number"&&typeof u.bytesSent=="number"&&(_=Math.max(0,(o.bytesSent-u.bytesSent)*8/w)),typeof o.packetsSent=="number"&&typeof u.packetsSent=="number"&&l&&typeof l.packetsLost=="number"&&typeof u.packetsLost=="number"){const y=o.packetsSent-u.packetsSent,d=l.packetsLost-u.packetsLost;y>0&&(b=Math.max(0,Math.min(100,d/y*100)))}}lt.current={timestamp:h,framesEncoded:o.framesEncoded,bytesSent:o.bytesSent,packetsSent:o.packetsSent,packetsLost:l?.packetsLost};const v={codec:tn(m),encoderImplementation:o.encoderImplementation,hardwareAccelerated:typeof o.powerEfficientEncoder=="boolean"?o.powerEfficientEncoder:void 0,framesPerSecond:g,framesEncoded:o.framesEncoded,bitrateBps:_,width:o.frameWidth,height:o.frameHeight,qualityLimitationReason:o.qualityLimitationReason,rttMs:typeof l?.roundTripTime=="number"?l.roundTripTime*1e3:void 0,packetsLostPct:b};x("onCameraStats",ut.current,v)},Er=()=>{je.current===null&&(lt.current=null,je.current=setInterval(()=>{rn()},1e3))},_t=()=>{je.current!==null&&(clearInterval(je.current),je.current=null),lt.current=null,x("onCameraStats",ut.current,null)},nn=(e,i,r,o)=>bt.enqueue(async({isCurrent:m})=>{const l=()=>m()&&o()&&D.current===i&&pe.current===r;if(!l())return;if(!e.active){const v=z.current;try{await r.replaceTrack(null)}catch(w){R("replaceTrack(null) on camera detach failed:",w)}if(z.current===v&&(z.current=null,ge.current=void 0,v&&G(v)),_t(),!l())return;x("onCameraDemandChange",ce.current,!1);return}x("onCameraDemandChange",ce.current,!0);const h=z.current,u=h?.getVideoTracks()[0],g=ge.current;if(u?.readyState==="live"&&g&&!In(g,e)){ge.current=e,mr(i,u),Er();return}if(h){try{await r.replaceTrack(null)}catch(v){R("replaceTrack(null) before camera switch failed:",v)}if(z.current===h&&(z.current=null,ge.current=void 0,G(h)),_t(),!l())return}if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){if(console.warn("[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost). Replying cameraResult granted=false so limulator falls back to black frames."),!l())return;i.send(JSON.stringify({type:"cameraResult",granted:!1})),x("onCameraDemandChange",ce.current,!0,!1);return}let _=null;try{_=await navigator.mediaDevices.getUserMedia({video:Nn(e),audio:!1})}catch(v){console.warn("[RemoteControl] getUserMedia denied/failed:",v)}if(!l()){_&&G(_);return}if(!_){i.send(JSON.stringify({type:"cameraResult",granted:!1})),x("onCameraDemandChange",ce.current,!0,!1);return}const b=_.getVideoTracks()[0]??null;if(!b){if(G(_),!l())return;i.send(JSON.stringify({type:"cameraResult",granted:!1})),x("onCameraDemandChange",ce.current,!0,!1);return}try{b.contentHint="motion"}catch{}try{await r.replaceTrack(b)}catch(v){if(R("replaceTrack(videoTrack) failed:",v),G(_),!l())return;i.send(JSON.stringify({type:"cameraResult",granted:!1})),x("onCameraDemandChange",ce.current,!0,!1);return}if(!l()){try{await r.replaceTrack(null)}catch(v){R("replaceTrack(null) for stale camera attach failed:",v)}G(_);return}try{const v=r.getParameters();(!v.encodings||v.encodings.length===0)&&(v.encodings=[{}]),v.encodings[0].maxBitrate=8e6,v.encodings[0].maxFramerate=30,v.degradationPreference="maintain-framerate",await r.setParameters(v)}catch(v){R("setParameters on outbound camera failed:",v)}if(!l()){try{await r.replaceTrack(null)}catch(v){R("replaceTrack(null) for stale camera finalize failed:",v)}G(_);return}z.current=_,ge.current=e,b.onended=()=>{z.current===_&&bt.enqueueCurrent(async({isCurrent:v})=>{if(!(!v()||z.current!==_||!o()||D.current!==i||pe.current!==r)){try{await r.replaceTrack(null)}catch(w){R("replaceTrack(null) after camera ended failed:",w)}!v()||z.current!==_||!o()||D.current!==i||pe.current!==r||(z.current=null,ge.current=void 0,G(_),_t(),i.send(JSON.stringify({type:"cameraResult",granted:!1})),x("onCameraDemandChange",ce.current,!0,!1))}}).catch(v=>R("camera ended cleanup failed:",v))},l()&&(mr(i,b),Er())}),He=()=>{yt(),ot(),nt(),j.current&&(j.current.stop(),j.current=null),bt.invalidate(),_t(),Zr(),ge.current=void 0,pe.current=null,++dt.current,It.current=!1,Ne.current=null,oe.current&&(G(oe.current),oe.current=null,x("onMicrophoneStateChange",Ge.current,{active:!1})),Je.current=null,Z.current!==void 0&&(window.cancelAnimationFrame(Z.current),Z.current=void 0),D.current&&(D.current.onopen=null,D.current.onmessage=null,D.current.onerror=null,D.current.onclose=null,D.current.close(),D.current=null),H.current&&(H.current.onconnectionstatechange=null,H.current.oniceconnectionstatechange=null,H.current.ontrack=null,H.current.onicecandidate=null,H.current.close(),H.current=null),F.current&&(F.current.srcObject=null),L.current&&(L.current.onopen=null,L.current.onclose=null,L.current.onerror=null,L.current.close(),L.current=null)},pr=()=>{document.hidden?dr():lr()},on=async()=>{if(typeof navigator<"u"&&navigator.onLine===!1)return!1;let e;try{const o=new URL(t);o.protocol=o.protocol==="wss:"?"https:":o.protocol==="ws:"?"http:":o.protocol,e=_r(o.toString(),c)}catch{return!1}const i=new AbortController,r=window.setTimeout(()=>i.abort(),Vn);try{return(await fetch(e,{method:"GET",cache:"no-store",signal:i.signal})).status===404}catch{return!1}finally{window.clearTimeout(r)}},cn=()=>{Ae.current||(Ae.current=!0,qt(!0),Be(!1),Ee.current+=1,Ct(),yt(),ot(),He(),k("Instance terminated"),Le("terminated"),x("onTerminated",rr.current))},sn=()=>{Ae.current||St.current||(St.current=!0,on().then(e=>{St.current=!1,e&&cn()}))},$e=(e,i)=>{if(Ae.current||i!==Ee.current)return;if(sn(),be.current){if(!Mt.current){k(`Connection failed after it was established: ${e}`),Be(!0),Le("failed"),He();return}k(`Reconnecting after established session dropped: ${e}`),be.current=!1,at.current=-1}Ct();const r=at.current+1;if(r>=Wt){k(`Connection failed after ${Wt} attempts: ${e}`),Be(!0),Le("failed"),He();return}k(`Retrying connection (${r+1}/${Wt})`),Le("reconnecting"),He(),qe.current=window.setTimeout(()=>{qe.current=void 0,i===Ee.current&&gr(r)},Xn)},gr=async(e=0)=>{if(Ae.current)return;const i=Ee.current+1;Ee.current=i,at.current=e,be.current=!1,Be(!1),e===0&&Pt.current!=="reconnecting"&&Le("connecting"),Ct(),yt(),nt(),ze.current=!1,me(!1),He();const r=()=>i===Ee.current;Ve.current=window.setTimeout(()=>{Ve.current=void 0,!(!r()||be.current)&&$e("Connection did not succeed within 15 seconds",i)},Bn);try{const o=new WebSocket(_r(t,c));if(D.current=o,await new Promise((y,d)=>{let I=!1;const P=window.setTimeout(()=>d(new Error("WebSocket connection timeout")),3e4),S=Y=>{I||(I=!0,window.clearTimeout(P),Y())};o.onopen=()=>{!r()||D.current!==o||S(y)},o.onerror=Y=>{!r()||D.current!==o||(k("WebSocket error: "+Y),S(()=>d(new Error("WebSocket connection failed"))))},o.onclose=()=>{!r()||D.current!==o||(k("WebSocket closed"),S(()=>d(new Error("WebSocket closed before connection was established"))))}}),!r()||D.current!==o)return;o.onerror=y=>{!r()||D.current!==o||k("WebSocket error: "+y)},o.onclose=()=>{!r()||D.current!==o||k("WebSocket closed")};const m=new Promise((y,d)=>{const I=Y=>{window.clearTimeout(P),o.removeEventListener("message",S),Y()},P=window.setTimeout(()=>I(()=>d(new Error("RTCConfiguration timeout"))),3e4),S=Y=>{if(!(!r()||D.current!==o))try{const q=JSON.parse(Y.data);if(q.type==="signalingError"&&q.requestType==="requestRtcConfiguration"&&q.sessionId===ee){const Q=typeof q.error=="string"?q.error:"Unable to load streaming configuration";I(()=>d(new Error(Q)))}else q.type==="rtcConfiguration"&&I(()=>y({rtcConfiguration:q.rtcConfiguration,cameraSupported:q.cameraSupported===!0}))}catch(q){console.error("Error handling RTC configuration:",q),I(()=>d(q))}};o.addEventListener("message",S),o.send(JSON.stringify({type:"requestRtcConfiguration",sessionId:ee}))}),{rtcConfiguration:l,cameraSupported:h}=await m;if(!r()||D.current!==o)return;const u=new RTCPeerConnection(l);H.current=u,u.addTransceiver("audio",{direction:"recvonly"});const g=u.addTransceiver("video",{direction:"recvonly"}),_=ie==="ios"||h,b=_?u.addTransceiver("video",{direction:"sendonly"}):null;pe.current=b?.sender??null;const v=_?u.addTransceiver("audio",{direction:"sendonly"}):null;if(Je.current=v?.sender??null,RTCRtpReceiver.getCapabilities){const y=RTCRtpReceiver.getCapabilities("video");if(y&&y.codecs){const I=y.codecs.sort((P,S)=>{const Y=q=>{const Q=q.mimeType.toLowerCase();return Q.includes("vp9")?1:Q.includes("h265")||Q.includes("hevc")?2:Q.includes("h264")||Q.includes("avc")?3:4};return Y(P)-Y(S)});g.setCodecPreferences(I),W("Set codec preferences:",I.map(P=>P.mimeType).join(", "))}}if(b&&RTCRtpSender.getCapabilities){const y=RTCRtpSender.getCapabilities("video");if(y&&y.codecs){const d=new Set(["42e01f","42e028","640c1f"]),I=S=>{const Y=S.mimeType.toLowerCase(),Q=(S.sdpFmtpLine||"").toLowerCase().match(/profile-level-id=([0-9a-f]{6})/),fn=Q?Q[1]:"";return Y==="video/h265"||Y==="video/hevc"?1:Y==="video/h264"&&d.has(fn)?2:Y==="video/h264"?3:Y==="video/vp9"?4:Y==="video/vp8"?5:Y==="video/rtx"||Y==="video/red"||Y==="video/ulpfec"?0:6},P=[...y.codecs].sort((S,Y)=>I(S)-I(Y));try{b.setCodecPreferences(P),W("Outbound camera codec preferences:",P.map(S=>`${S.mimeType}${S.sdpFmtpLine?`[${S.sdpFmtpLine}]`:""}`).join(", "))}catch(S){R("Failed to set outbound camera codec preferences:",S)}}}const w=u.createDataChannel("control",{ordered:!0,negotiated:!0,id:1});if(L.current=w,w.onopen=()=>{if(!r()||L.current!==w||D.current!==o)return;be.current=!0,yt(),k("Control channel opened"),j.current||(j.current=new Sn({platform:ie,baseIntervalMs:de,maxBackoffMs:ct,androidElementTreeOptions:Re,send:d=>{if(!D.current||D.current.readyState!==WebSocket.OPEN)return!1;try{return D.current.send(JSON.stringify(d)),!0}catch{return!1}},onSnapshot:d=>{zt(I=>$t(I,d)?I:d),queueMicrotask(()=>{x("onAxSnapshotChange",kt.current,d)})},onStatusChange:(d,I)=>{x("onAxStatusChange",tr.current,d,I)}}),(Ke.current===!0||Ke.current==="hover-only")&&j.current.start());const y=()=>{!r()||ze.current||L.current!==w||D.current!==o||o.readyState!==WebSocket.OPEN||o.send(JSON.stringify({type:"requestFrame",sessionId:ee}))};if(y(),nt(),st.current=window.setInterval(()=>{if(!r()||ze.current||L.current!==w||D.current!==o||o.readyState!==WebSocket.OPEN){nt();return}y()},250),E){try{const d=decodeURIComponent(E);k("Opening URL"),o.send(JSON.stringify({type:"openUrl",url:d,sessionId:ee}))}catch(d){console.error({error:d},"Error decoding URL, falling back to the original URL"),o.send(JSON.stringify({type:"openUrl",url:E,sessionId:ee}))}j.current?.bumpActivity()}},w.onclose=()=>{!r()||L.current!==w||k("Control channel closed")},w.onerror=y=>{!r()||L.current!==w||(console.error("Control channel error:",y),k("Control channel error: "+y))},u.onconnectionstatechange=()=>{!r()||H.current!==u||(k("Connection state: "+u.connectionState),u.connectionState==="failed"&&$e("WebRTC connection entered failed state",i))},u.oniceconnectionstatechange=()=>{if(!r()||H.current!==u)return;const y=u.iceConnectionState;if(k("ICE state: "+y),y==="connected"||y==="completed"){ot(),Ut()&&!oe.current&&xt();return}if(y==="failed"){ot(),$e("ICE connection entered failed state",i);return}y==="disconnected"&&Mt.current&&Me.current===void 0&&(Me.current=window.setTimeout(()=>{Me.current=void 0,!(!r()||H.current!==u)&&u.iceConnectionState==="disconnected"&&$e("ICE stayed disconnected past grace period",i)},qn))},u.ontrack=y=>{!r()||H.current!==u||(k("Received remote track: "+y.track.kind),y.track.kind==="video"&&F.current&&(W(`[${new Date().toISOString()}] Video track received:`,y.track),F.current.srcObject=y.streams[0]))},u.onicecandidate=y=>{if(!(!r()||H.current!==u||D.current!==o))if(y.candidate&&o.readyState===WebSocket.OPEN){const d={type:"candidate",candidate:y.candidate.candidate,sdpMid:y.candidate.sdpMid,sdpMLineIndex:y.candidate.sdpMLineIndex,sessionId:ee};o.send(JSON.stringify(d)),k("Sent ICE candidate")}else k("ICE candidate gathering completed")},o.onmessage=async y=>{if(!r()||D.current!==o)return;let d;try{d=JSON.parse(y.data)}catch(I){R("Error parsing message:",I);return}if(!j.current?.handleMessage(d))switch(k("Received: "+d.type),d.type){case"signalingError":{if(d.requestType!=="offer"||d.sessionId!==ee)break;const S=typeof d.error=="string"?d.error:"Unable to establish the streaming connection";k("Error: "+S),$e(S,i);break}case"answer":if(!H.current||H.current!==u){k("No peer connection, skipping answer");break}if(await u.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:d.sdp})),!r()||H.current!==u)return;k("Set remote description");break;case"candidate":if(!H.current||H.current!==u){k("No peer connection, skipping candidate");break}if(await u.addIceCandidate(new RTCIceCandidate({candidate:d.candidate,sdpMid:d.sdpMid,sdpMLineIndex:d.sdpMLineIndex})),!r()||H.current!==u)return;k("Added ICE candidate");break;case"screenshot":case"screenshotResult":{if(typeof d.id!="string"){R("Received invalid screenshot success message:",d);break}const S=Qn(d);if(S){const Q=se.current.get(d.id);if(!Q){R(`Received screenshot error for unknown or handled id: ${d.id}`);break}R(`Received screenshot error for id ${d.id}: ${S}`),Q(new Error(S)),ue.current.delete(d.id),se.current.delete(d.id);break}const Y=Zn(d);if(!Y){R("Received screenshot message without image data:",d);break}const q=ue.current.get(d.id);if(!q){R(`Received screenshot data for unknown or handled id: ${d.id}`);break}W(`Received screenshot data for id ${d.id}`),q(Y),ue.current.delete(d.id),se.current.delete(d.id);break}case"screenshotError":if(typeof d.id!="string"||typeof d.message!="string"){R("Received invalid screenshot error message:",d);break}const I=se.current.get(d.id);if(!I){R(`Received screenshot error for unknown or handled id: ${d.id}`);break}R(`Received screenshot error for id ${d.id}: ${d.message}`),I(new Error(d.message)),ue.current.delete(d.id),se.current.delete(d.id);break;case"cameraRequest":{const S=pe.current;if(!S)break;const Y=bn(d);if(!Y){R("Received invalid cameraRequest:",d);break}console.info("[RemoteControl] cameraRequest received:",Y.active,Y.facingMode),await nn(Y,o,S,r);break}case"microphoneRequest":{if(!Je.current)break;const S=d.active===!0;if(It.current=S,console.info("[RemoteControl] microphoneRequest received, active=",S),!S){Nt.current||await Ot();break}if(oe.current){hr(o);break}await xt();break}case"microphoneStartResult":{if(Ne.current===null||d.id!==Ne.current)break;Ne.current=null,typeof d.error=="string"&&(console.warn("[RemoteControl] microphoneStart rejected by host:",d.error),Ot(d.error));break}case"terminateAppResult":if(typeof d.id!="string"){R("Received invalid terminateApp result message:",d);break}if(typeof d.error=="string"){const S=ye.current.get(d.id);if(!S){R(`Received terminateApp error for unknown or handled id: ${d.id}`);break}R(`Received terminateApp error for id ${d.id}: ${d.error}`),S(new Error(d.error)),Ce.current.delete(d.id),ye.current.delete(d.id);break}const P=Ce.current.get(d.id);if(!P){R(`Received terminateApp result for unknown or handled id: ${d.id}`);break}W(`Received terminateApp success for id ${d.id}`),P(),Ce.current.delete(d.id),ye.current.delete(d.id);break;default:R(`Received unhandled message type: ${d.type}`,d);break}},H.current===u){const y=await u.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!1});if(!r()||H.current!==u||(await u.setLocalDescription(y),!r()||H.current!==u))return;r()&&D.current===o&&o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({type:"offer",sdp:y.sdp,sessionId:ee})),k("Sent offer")}}catch(o){if(!r())return;const m=o instanceof Error?o.message:String(o);k("Error: "+m),$e(m,i)}},Ft=()=>{Ae.current=!1,qt(!1),gr(0)},an=()=>{Ee.current+=1,at.current=0,be.current=!1,Ct(),ot(),He(),k("Stopped")},un=e=>{e.stopPropagation(),Ft()};f.useEffect(()=>{Ut()?xt():Ot()},[J]),f.useEffect(()=>(me(!1),Ft(),document.hidden||lr(),document.addEventListener("visibilitychange",pr),()=>{dr(),an(),document.removeEventListener("visibilitychange",pr)}),[t,c,a]);const Cr=()=>{const e=rt();if(!e){Qt(null);return}const i={left:e.videoRect.left-e.containerRect.left+e.offsetX,top:e.videoRect.top-e.containerRect.top+e.offsetY,width:e.actualWidth,height:e.actualHeight};Qt(r=>r&&r.left===i.left&&r.top===i.top&&r.width===i.width&&r.height===i.height?r:i)};f.useEffect(()=>{const e=F.current,i=he.current,r=we.current;if(!e)return;const o=()=>{if(!Et||!i){jt({}),Cr();return}const h=i.clientWidth,u=i.clientHeight;if(h===0||u===0)return;const g=e.videoWidth>e.videoHeight;Yr(g),kr(ie==="android"&&jn(e.videoWidth,e.videoHeight));const _=g?Ue.videoPosition.landscape:Ue.videoPosition.portrait;let b={};_.heightMultiplier?(b.height=`${u*_.heightMultiplier}px`,b.width="auto"):_.widthMultiplier&&(b.width=`${h*_.widthMultiplier}px`,b.height="auto"),b.borderRadius=`${g?u*Ue.videoBorderRadiusMultiplier:h*Ue.videoBorderRadiusMultiplier}px`,jt(b),Cr()},m=new ResizeObserver(()=>{o()});i&&m.observe(i),m.observe(e),r&&m.observe(r),i&&i.addEventListener("load",o),e.addEventListener("loadedmetadata",o),e.addEventListener("resize",o);const l=()=>j.current?.bumpActivity();return e.addEventListener("resize",l),o(),()=>{m.disconnect(),e.removeEventListener("loadedmetadata",o),e.removeEventListener("resize",o),e.removeEventListener("resize",l),i&&i.removeEventListener("load",o)}},[Ue,Et]),f.useEffect(()=>{const e=j.current;et?e?.start():(e?.stop(),zt(null),Ze(null),ht(null),Zt(null),Ye(null),mt.current=null,Z.current!==void 0&&(window.cancelAnimationFrame(Z.current),Z.current=void 0),x("onAxSnapshotChange",kt.current,null))},[et]),f.useEffect(()=>()=>{Z.current!==void 0&&(window.cancelAnimationFrame(Z.current),Z.current=void 0)},[]),f.useEffect(()=>{if(!et)return;const e=i=>{i.key==="Escape"&&(Kt||Yt)&&(ht(null),Ze(null),Ye(null),x("onInspectSelectionChange",Pe.current,null))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[et,Kt,Yt]);const ln=()=>{F.current&&F.current.focus()};f.useImperativeHandle(fe,()=>({openUrl:e=>{if(!D.current||D.current.readyState!==WebSocket.OPEN){R("WebSocket not open, cannot send open_url command via ref.");return}try{const i=decodeURIComponent(e);k("Opening URL"),D.current.send(JSON.stringify({type:"openUrl",url:i,sessionId:ee}))}catch(i){R("Error decoding or sending URL via ref:",{error:i,url:e}),D.current.send(JSON.stringify({type:"openUrl",url:e,sessionId:ee}))}j.current?.bumpActivity()},sendKeyEvent:e=>{if(!L.current||L.current.readyState!=="open"){R("Data channel not ready for imperative key command:",L.current?.readyState);return}const i=Rr[e.code];if(!i){R(`Unknown event.code for imperative command: ${e.code}`);return}let r=s.META_NONE;e.shiftKey&&(r|=s.META_SHIFT_ON),e.altKey&&(r|=s.META_ALT_ON),e.ctrlKey&&(r|=s.META_CTRL_ON),e.metaKey&&(r|=s.META_META_ON);const o=e.type==="keydown"?s.ACTION_DOWN:s.ACTION_UP;W(`Sending Imperative Key Command: code=${e.code}, keycode=${i}, action=${o}, meta=${r}`);const m=it(o,i,0,r);m&&te(m)},screenshot:()=>new Promise((e,i)=>{if(!D.current||D.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send screenshot command."),i(new Error("WebSocket is not connected or connection is not open."));const r=`ui-ss-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,o={type:"screenshot",id:r};ue.current.set(r,e),se.current.set(r,i),W("Sending screenshot request:",o);try{D.current.send(JSON.stringify(o))}catch(m){R("Failed to send screenshot request immediately:",m),ue.current.delete(r),se.current.delete(r),i(m);return}setTimeout(()=>{ue.current.has(r)&&(R(`Screenshot request timed out for id ${r}`),se.current.get(r)?.(new Error("Screenshot request timed out")),ue.current.delete(r),se.current.delete(r))},3e4)}),terminateApp:e=>new Promise((i,r)=>{if(!D.current||D.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send terminateApp command."),r(new Error("WebSocket is not connected or connection is not open."));const o=`ui-term-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,m={type:"terminateApp",id:o,bundleId:e};Ce.current.set(o,i),ye.current.set(o,r),W("Sending terminateApp request:",m);try{D.current.send(JSON.stringify(m))}catch(l){R("Failed to send terminateApp request immediately:",l),Ce.current.delete(o),ye.current.delete(o),r(l);return}j.current?.bumpActivity(),setTimeout(()=>{Ce.current.has(o)&&(R(`terminateApp request timed out for id ${o}`),ye.current.get(o)?.(new Error("terminateApp request timed out")),Ce.current.delete(o),ye.current.delete(o))},3e4)}),reconnect:()=>Ft(),refreshAxTree:async()=>{const e=j.current;if(!e)throw new Error("Inspect mode is not active");return e.refresh()},getAxSnapshot:()=>ke.current,setInspectHighlight:e=>{Ze(e?.id??null)},setInspectSelection:e=>{ht(e?.id??null),Ye(e?mt.current:null);const i=ke.current;e&&i?x("onInspectSelectionChange",Pe.current,{element:e,snapshot:i}):x("onInspectSelectionChange",Pe.current,null)},getAxStatus:()=>j.current?.getStatus()??"idle"}));const dn=Lr&&_e!==null;return A.jsxs("div",{ref:we,className:De("rc-container",n),style:{touchAction:"none"},onMouseDown:le,onMouseMove:le,onMouseUp:le,onMouseLeave:le,onTouchStart:le,onTouchMove:le,onTouchEnd:le,onTouchCancel:le,children:[dn&&_e&&A.jsxs(A.Fragment,{children:[A.jsx("div",{className:"rc-touch-indicator",style:{left:`${_e.containerX}px`,top:`${_e.containerY}px`}}),A.jsx("div",{className:"rc-touch-indicator",style:{left:`${_e.mirrorContainerX}px`,top:`${_e.mirrorContainerY}px`}})]}),Et&&A.jsx("img",{ref:he,src:or,alt:"",className:ie==="ios"?De("rc-phone-frame","rc-phone-frame-ios"):"rc-phone-frame",draggable:!1}),A.jsx("video",{ref:F,className:De("rc-video",!Et&&"rc-video-frameless",!Xe&&"rc-video-loading"),style:{...Pr,...ir?{backgroundImage:`url("${ir}")`,backgroundRepeat:"no-repeat",backgroundPosition:"center",backgroundSize:Ue.loadingLogoSize}:{}},autoPlay:!0,playsInline:!0,muted:!0,tabIndex:0,onKeyDown:ur,onKeyUp:ur,onClick:ln,onLoadedData:Qr,onFocus:()=>{F.current&&(F.current.style.outline="none")},onBlur:()=>{F.current&&(F.current.style.outline="none")}}),et&&A.jsx(Hn,{snapshot:Jt,geometry:xr,highlightedId:Yt,selectedId:Kt,mode:Hr,cursorPosition:Fr,frozenCursorPosition:Wr,onSelectChange:(e,i)=>{ht(e?.id??null),e&&i?Ye(i):e||Ye(null);const r=ke.current;e&&r?x("onInspectSelectionChange",Pe.current,{element:e,snapshot:r}):x("onInspectSelectionChange",Pe.current,null)},onTapElement:(e,i)=>{if(i){sr(i.x,i.y);return}const r=ke.current;r&&$r(e,r)}}),At?A.jsxs("div",{className:"rc-terminated",role:"status",children:[A.jsx("div",{className:"rc-terminated-title",children:"Instance terminated"}),A.jsx("div",{className:"rc-terminated-message",children:"This instance no longer exists and can't be reconnected."})]}):Bt&&A.jsx("button",{type:"button",className:"rc-retry-button",onClick:un,children:"Retry"})]})}),Qn=n=>typeof n.message=="string"?n.message:typeof n.error=="string"?n.error:null,Zn=n=>typeof n.dataUri=="string"?{dataUri:n.dataUri}:typeof n.base64=="string"?n.base64.startsWith("data:")?{dataUri:n.base64}:{dataUri:`data:${n.base64.startsWith("/9j/")?"image/jpeg":"image/png"};base64,${n.base64}`}:null;exports.AX_UNAVAILABLE_ERROR=Dt;exports.RemoteControl=zn;exports.axElementAtPoint=br;exports.axElementSelectorExpression=Nr;exports.axElementSummary=Xt;exports.axElementsEqual=Ht;exports.axSnapshotsEqual=$t;exports.clampAxFrameForScreen=Mr;exports.normalizeAndroidTree=Sr;exports.normalizeIosTree=Ar;
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "@limrun/ui",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "publishConfig": {
5
- "access": "public",
6
- "tag": "next"
5
+ "access": "public"
7
6
  },
8
7
  "main": "./dist/index.js",
9
8
  "module": "./dist/index.js",
@@ -14,6 +13,11 @@
14
13
  "import": "./dist/index.js",
15
14
  "require": "./dist/index.cjs"
16
15
  },
16
+ "./lite": {
17
+ "types": "./dist/lite.d.ts",
18
+ "import": "./dist/lite.js",
19
+ "require": "./dist/lite.cjs"
20
+ },
17
21
  "./package.json": "./package.json"
18
22
  },
19
23
  "scripts": {
@@ -49,9 +53,12 @@
49
53
  "vite": "^7.1.4",
50
54
  "vite-plugin-dts": "^4.5.4",
51
55
  "vite-plugin-lib-inject-css": "^2.2.2",
52
- "vitest": "^3.2.6"
56
+ "vitest": "^4.1.11"
53
57
  },
54
58
  "dependencies": {
55
59
  "clsx": "^2.1.1"
60
+ },
61
+ "resolutions": {
62
+ "vite": "^7.1.4"
56
63
  }
57
64
  }
@@ -0,0 +1,14 @@
1
+ import { forwardRef } from 'react';
2
+ import {
3
+ RemoteControl as RemoteControlBase,
4
+ type RemoteControlHandle,
5
+ type RemoteControlProps,
6
+ } from './remote-control';
7
+ import { defaultRemoteControlAssets } from '../frame-assets';
8
+
9
+ // The default export: RemoteControl with Limrun's device frames unless the
10
+ // caller supplies its own assets.
11
+ export const RemoteControl = forwardRef<RemoteControlHandle, RemoteControlProps>((props, ref) => (
12
+ <RemoteControlBase ref={ref} assets={defaultRemoteControlAssets} {...props} />
13
+ ));
14
+ RemoteControl.displayName = 'RemoteControl';