@xenon-device-management/xenon 1.7.0 → 1.7.1
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.
- package/lib/package.json +1 -1
- package/lib/public/assets/{ApiKeyGate-BSN8crwz.js → ApiKeyGate-DBl_AZ8N.js} +1 -1
- package/lib/public/assets/{BugReportButton-DNja1wQ1.js → BugReportButton-Cz4aeGCX.js} +1 -1
- package/lib/public/assets/{DeviceMosaicView-DVk1IpIR.js → DeviceMosaicView-DP4AanNV.js} +1 -1
- package/lib/public/assets/{EmptyState-CqQ21n-H.js → EmptyState-BwaAbjZt.js} +1 -1
- package/lib/public/assets/{FieldGroup-DE3u01Nu.js → FieldGroup-CGdoHDQ3.js} +1 -1
- package/lib/public/assets/{Modal-BJcFdiBP.js → Modal-OY-an2g6.js} +1 -1
- package/lib/public/assets/{SegmentedControl-CSHjmrvy.js → SegmentedControl-C_gsCi2P.js} +1 -1
- package/lib/public/assets/{SettingCard-M-lFn_Wm.js → SettingCard-CRlStb6_.js} +1 -1
- package/lib/public/assets/{Table-B3EUgBi6.js → Table-CbmGiPJe.js} +1 -1
- package/lib/public/assets/{activity-DK3R5GAb.js → activity-BhRPBZ3G.js} +1 -1
- package/lib/public/assets/{ai-settings-AKMDh8pd.js → ai-settings-DteGlf4r.js} +1 -1
- package/lib/public/assets/{api-keys-B5Q1EkGN.js → api-keys-BmikiaSF.js} +1 -1
- package/lib/public/assets/{apps-CWWrkTZW.js → apps-BfEC5qsb.js} +1 -1
- package/lib/public/assets/apps-DS59NYjg.css +1 -0
- package/lib/public/assets/{arrow-left-9933DNlF.js → arrow-left-y_SSjJz-.js} +1 -1
- package/lib/public/assets/{arrow-up-right-B7q_1mXs.js → arrow-up-right-NQ8ZGfd3.js} +1 -1
- package/lib/public/assets/{builds-page-DgWXOgh5.js → builds-page-DkLt4J8-.js} +2 -2
- package/lib/public/assets/{button-lkxVyarW.js → button-wz7ra9cW.js} +1 -1
- package/lib/public/assets/{check-BkT38An9.js → check-CV94AcJF.js} +1 -1
- package/lib/public/assets/{chevron-right-WELZ1Z8v.js → chevron-right-_iIkyWqd.js} +1 -1
- package/lib/public/assets/{circle-check--2DSsfaI.js → circle-check-0COJnxUq.js} +1 -1
- package/lib/public/assets/{circle-x-x7R8vTBo.js → circle-x-DGNoObyH.js} +1 -1
- package/lib/public/assets/{clock-DIpGd4Pn.js → clock-DwtXByAH.js} +1 -1
- package/lib/public/assets/{copy-CEcFYYHm.js → copy-DL_iD5Dh.js} +1 -1
- package/lib/public/assets/device-explorer-CKcXaWmZ.css +1 -0
- package/lib/public/assets/device-explorer-CpC-MZNT.js +210 -0
- package/lib/public/assets/{download-CaKkGvKw.js → download-aeG6Qqs8.js} +1 -1
- package/lib/public/assets/{forgot-password-CsAF11d2.js → forgot-password-Cu05XOKH.js} +1 -1
- package/lib/public/assets/{funnel-D2rLIKlM.js → funnel-ChogDM6h.js} +1 -1
- package/lib/public/assets/{index-BrVV0Kla.js → index-CkwQBzCl.js} +2 -2
- package/lib/public/assets/index-gXUPv-oo.css +1 -0
- package/lib/public/assets/{layers-DZwF8z_0.js → layers-a5nj78PI.js} +1 -1
- package/lib/public/assets/{lock-CVUUnm1V.js → lock-CqQvL12G.js} +1 -1
- package/lib/public/assets/{login-BavGkTli.js → login-DoaCgEPu.js} +1 -1
- package/lib/public/assets/{maintenance-settings-Vr_u8hoR.js → maintenance-settings-CBnV_5Rl.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-n4xUMxHJ.js → mouse-pointer-2-De_oynWc.js} +1 -1
- package/lib/public/assets/{overview-DVgoOoYF.js → overview-DvyGTzku.js} +1 -1
- package/lib/public/assets/{page-header-C0pnt4xz.js → page-header-BeUDGs-O.js} +1 -1
- package/lib/public/assets/{plus-BObE-_z6.js → plus-BM5UAzcK.js} +1 -1
- package/lib/public/assets/{profile-page-DNKD4MS2.js → profile-page-Cner_Muq.js} +1 -1
- package/lib/public/assets/{reset-password-C2gSMy8a.js → reset-password-BKWBemnU.js} +1 -1
- package/lib/public/assets/{runbook-page-BRxjWJVQ.js → runbook-page-CXZdhAjc.js} +1 -1
- package/lib/public/assets/{selector-detail-page-DcV8jQuX.js → selector-detail-page-C6yA7Lwl.js} +1 -1
- package/lib/public/assets/{selector-health-DraY2a4b.js → selector-health-BWOVdnlp.js} +1 -1
- package/lib/public/assets/{selector-health-page-tb5e3CXy.js → selector-health-page-CrR7bh4f.js} +2 -2
- package/lib/public/assets/{session-detail-page-CEtQr37W.js → session-detail-page-DzW5PcxL.js} +1 -1
- package/lib/public/assets/{settings-Cr-YjLbX.js → settings-COrR3YcC.js} +1 -1
- package/lib/public/assets/{shield-BBc4qisQ.js → shield-CAA9vrIs.js} +1 -1
- package/lib/public/assets/{shield-alert-BfoPJ8q_.js → shield-alert-Dm3Oz4Kc.js} +1 -1
- package/lib/public/assets/{status-pill-outline-Cc4PF7Mg.js → status-pill-outline-3FA5raqd.js} +1 -1
- package/lib/public/assets/{tablet-CaOqzQv_.js → tablet-CWU6hxZF.js} +1 -1
- package/lib/public/assets/{teams-B3Tt_9i2.js → teams-xa_B0pyz.js} +1 -1
- package/lib/public/assets/{trash-2-CE5TRHb2.js → trash-2-DUWA0N9n.js} +1 -1
- package/lib/public/assets/{useSocket-Bkt5i-U6.js → useSocket-lsg6f_Dn.js} +1 -1
- package/lib/public/assets/{users-BIvjvjM6.js → users-DJDpKaGy.js} +1 -1
- package/lib/public/assets/{webhook-settings-dAp8wwEB.js → webhook-settings-BPf_iC_h.js} +1 -1
- package/lib/public/assets/{zap-BzdRuL9F.js → zap-D8JQHaNH.js} +1 -1
- package/lib/public/index.html +2 -2
- package/lib/src/app/routers/auth.js +19 -2
- package/lib/src/scripts/run-migrations.js +14 -3
- package/lib/test/unit/auth-me-auth-disabled.test.js +77 -0
- package/lib/test/unit/run-migrations-fail-fast.test.js +87 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/lib/public/assets/apps-Dt5dUIag.css +0 -1
- package/lib/public/assets/device-explorer-3H1hf8ld.css +0 -1
- package/lib/public/assets/device-explorer-nV6L3w7x.js +0 -210
- package/lib/public/assets/index-Dz1K6OJU.css +0 -1
package/lib/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as n,j as e}from"./index-
|
|
1
|
+
import{r as n,j as e}from"./index-CkwQBzCl.js";function x({children:c}){const[i,s]=n.useState(null),[o,l]=n.useState(""),[r,a]=n.useState(null);if(n.useEffect(()=>{fetch("/xenon/api/health").then(()=>fetch("/xenon/api/sessions",{credentials:"include"})).then(t=>s(t.status!==401)).catch(()=>s(!1))},[]),i===null)return e.jsx("div",{style:{padding:40},children:"Loading…"});if(i)return e.jsx(e.Fragment,{children:c});async function u(t){t.preventDefault(),a(null);const d=await fetch("/xenon/api/auth/dashboard-session",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({apiKey:o.trim()})});if(d.ok)s(!0);else{const p=await d.json().catch(()=>({}));a(p.error||"Invalid key")}}return e.jsxs("div",{style:{maxWidth:420,margin:"120px auto",padding:24},children:[e.jsx("h2",{children:"Sign in to Xenon"}),e.jsxs("p",{children:["Paste an API key. First-time setup: the bootstrap key is in"," ",e.jsx("code",{children:"~/.cache/xenon/bootstrap-key.txt"})," on the server."]}),e.jsxs("form",{onSubmit:u,children:[e.jsx("input",{type:"password",value:o,onChange:t=>l(t.target.value),placeholder:"API key",style:{width:"100%",padding:8,boxSizing:"border-box"},autoFocus:!0}),e.jsx("button",{type:"submit",style:{marginTop:12,padding:"8px 16px"},children:"Continue"})]}),r&&e.jsx("p",{style:{color:"crimson",marginTop:12},children:r})]})}export{x as ApiKeyGate};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as m,j as t,X as T}from"./index-BrVV0Kla.js";import{A as U,I as le}from"./keycodes-bIEJfQzr.js";function de(e,r){return e!=="auto"?e:r<=1?"1":r===2?"2x1":r<=4?"2x2":"3x2"}const ue={selected:new Set,layout:"2x2",tiles:[],groupId:null,recording:!1,startedAt:null,annotateMode:!1,shape:"RECT",color:"#ff3333",errorBanner:null};function fe(e,r){switch(r.type){case"SET_LAYOUT":return{...e,layout:r.layout};case"TOGGLE_SELECTED":{const n=new Set(e.selected);return n.has(r.udid)?n.delete(r.udid):n.add(r.udid),{...e,selected:n}}case"CLEAR_SELECTED":return{...e,selected:new Set};case"SET_TILES":return{...e,tiles:r.tiles};case"ADD_TILE":return e.tiles.some(n=>n.udid===r.tile.udid)?e:{...e,tiles:[...e.tiles,r.tile]};case"REMOVE_TILE":return{...e,tiles:e.tiles.filter(n=>n.udid!==r.udid)};case"BIND_RECORDING_IDS":{const n=e.tiles.map(l=>({...l,recordingId:r.map[l.udid]??l.recordingId}));return{...e,tiles:n}}case"START_RECORDING":{const n=e.tiles.map(l=>({...l,recordingId:r.tileIds[l.udid]??l.recordingId}));return{...e,groupId:r.groupId,recording:!0,startedAt:r.startedAt,tiles:n}}case"STOP_RECORDING":return{...e,recording:!1};case"SET_ANNOTATE_MODE":return{...e,annotateMode:r.enabled};case"SET_SHAPE":return{...e,shape:r.shape};case"SET_COLOR":return{...e,color:r.color};case"SET_ERROR_BANNER":return{...e,errorBanner:r.message};default:return e}}const V=m.createContext(null);function me(){const e=m.useContext(V);if(!e)throw new Error("useMosaic must be used inside <MosaicContext.Provider>");return e}function xe(){return m.useReducer(fe,ue)}function he(e){switch(e){case"automation":return"In automation";case"manual_other":return"Manual control by another user";case"manual_self":return"In your mosaic";case"recording_other_group":return"Recording in another group";default:return e?"Busy":null}}const G=[{id:"ios",label:"iOS",match:e=>e==="ios"},{id:"android",label:"Android",match:e=>e==="android"},{id:"tvos",label:"tvOS",match:e=>e==="tvos"},{id:"androidtv",label:"Android TV",match:e=>e==="androidtv"||e==="android-tv"},{id:"other",label:"Other",match:()=>!0}];function pe(e){return e?e==="androidtv"||e==="android-tv"?"ANDROID TV":e.toUpperCase():""}function ge({devices:e,inMosaic:r,onToggle:n}){const[l,b]=m.useState(""),[f,w]=m.useState({}),N=m.useMemo(()=>{const u=l.trim().toLowerCase();return u?e.filter(g=>g.udid.toLowerCase().includes(u)||(g.name??"").toLowerCase().includes(u)||(g.platform??"").toLowerCase().includes(u)):e},[e,l]),v=m.useMemo(()=>{const u=G.map(o=>({id:o.id,label:o.label,rows:[]})),g=o=>u.find((c,s)=>G[s].match(o))??u[u.length-1];for(const o of N)g((o.platform??"").toLowerCase()).rows.push(o);return u.filter(o=>o.rows.length>0)},[N]);return e.length===0?t.jsx("div",{className:"text-xs text-[var(--text-dim)] p-3",children:"No devices online."}):t.jsxs("div",{className:"flex flex-col gap-2",children:[t.jsxs("div",{className:"relative",children:[t.jsx("span",{"aria-hidden":!0,className:"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-dim)] text-xs",children:"⌕"}),t.jsx("input",{type:"text",value:l,placeholder:"Filter devices...",onChange:u=>b(u.target.value),className:"w-full pl-7 pr-2 py-1.5 text-xs rounded border border-[var(--border)] bg-transparent placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--accent,#3b82f6)]"})]}),v.map(u=>{const g=f[u.id];return t.jsxs("section",{className:"flex flex-col gap-1",children:[t.jsxs("button",{type:"button",onClick:()=>w(o=>({...o,[u.id]:!o[u.id]})),className:"flex items-center justify-between w-full text-[10px] uppercase tracking-wider text-[var(--text-dim)] hover:text-white px-1 py-0.5",children:[t.jsxs("span",{className:"flex items-center gap-1.5",children:[t.jsx("span",{"aria-hidden":!0,className:`inline-block transition-transform ${g?"-rotate-90":"rotate-0"}`,children:"▾"}),u.label]}),t.jsx("span",{children:u.rows.length})]}),!g&&t.jsx("ul",{className:"flex flex-col gap-1 text-sm",children:u.rows.map(o=>{const c=o.busyReason==="manual_self",s=r.has(o.udid),x=!!o.busy&&!c&&!s,R=he(o.busyReason),i=!x;return t.jsx("li",{children:t.jsxs("button",{type:"button",disabled:x,draggable:!x,onDragStart:d=>{d.dataTransfer.effectAllowed="copy",d.dataTransfer.setData("application/x-xenon-udid",o.udid),d.dataTransfer.setData("text/plain",o.udid)},onClick:()=>n(o.udid),className:`w-full flex items-center gap-2 px-2 py-1.5 rounded text-left border transition-colors ${x?"opacity-60 cursor-not-allowed border-transparent":s?"border-emerald-500/40 bg-emerald-500/5 hover:bg-emerald-500/10":"border-transparent hover:border-[var(--border)] hover:bg-[var(--surface-2,rgba(255,255,255,0.04))]"}`,title:x?`${R} — release first`:s?"Click to remove from mosaic (or drag to a cell)":"Click to add to mosaic (or drag to a cell)",children:[t.jsx("span",{"aria-hidden":!0,className:`inline-flex items-center justify-center w-4 h-4 text-xs ${s?"text-emerald-400":"text-[var(--text-dim)]"}`,children:s?"●":"○"}),t.jsx("span",{"aria-hidden":!0,className:`inline-block w-1.5 h-1.5 rounded-full ${i?"bg-emerald-400 shadow-[0_0_4px_rgba(52,211,153,0.7)]":"bg-yellow-500"}`}),t.jsx("span",{className:"font-medium flex-1 truncate text-[13px]",children:o.name??o.udid}),o.platform&&t.jsx("span",{className:"text-[9px] uppercase tracking-wider px-1.5 py-0.5 rounded bg-[var(--surface-2,rgba(255,255,255,0.06))] text-[var(--text-dim)]",children:pe(o.platform)})]})},o.udid)})})]},u.id)}),l&&v.length===0&&t.jsxs("div",{className:"text-xs text-[var(--text-dim)] px-1 py-2",children:['No devices match "',l,'".']})]})}const be=[{id:"1",label:"1",icon:t.jsx(ye,{})},{id:"2x1",label:"2×1",icon:t.jsx(we,{})},{id:"2x2",label:"2×2",icon:t.jsx(Ne,{})},{id:"3x2",label:"3×2",icon:t.jsx(je,{})},{id:"auto",label:"Auto",icon:t.jsx(Re,{})}];function ve({value:e,onChange:r}){return t.jsx("div",{role:"tablist",className:"inline-flex border border-[var(--border)] rounded-md overflow-hidden text-xs bg-[var(--surface-1,rgba(255,255,255,0.02))]",children:be.map(n=>{const l=e===n.id;return t.jsxs("button",{role:"tab","aria-selected":l,onClick:()=>r(n.id),className:`flex items-center gap-1.5 px-2.5 py-1.5 border-r border-[var(--border)] last:border-r-0 transition-colors ${l?"bg-[var(--surface-2,#2a2a2a)] text-white":"text-[var(--text-dim)] hover:bg-[var(--surface-2,rgba(255,255,255,0.04))] hover:text-white"}`,title:`Layout: ${n.label}`,children:[t.jsx("span",{className:"w-3.5 h-3.5 inline-flex items-center justify-center",children:n.icon}),t.jsx("span",{children:n.label})]},n.id)})})}function k(e){return t.jsx("rect",{rx:1.2,ry:1.2,fill:"currentColor",...e})}function ye(){return t.jsx("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:k({x:2,y:2,width:10,height:10})})}function we(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1.5,y:3,width:5,height:8}),k({x:7.5,y:3,width:5,height:8})]})}function Ne(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1.5,y:1.5,width:5,height:5}),k({x:7.5,y:1.5,width:5,height:5}),k({x:1.5,y:7.5,width:5,height:5}),k({x:7.5,y:7.5,width:5,height:5})]})}function je(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1,y:1.5,width:3.3,height:5}),k({x:5.35,y:1.5,width:3.3,height:5}),k({x:9.7,y:1.5,width:3.3,height:5}),k({x:1,y:7.5,width:3.3,height:5}),k({x:5.35,y:7.5,width:3.3,height:5}),k({x:9.7,y:7.5,width:3.3,height:5})]})}function Re(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.4",children:[t.jsx("rect",{x:"2",y:"2",width:"10",height:"10",rx:"1.5"}),t.jsx("circle",{cx:"7",cy:"7",r:"1.5",fill:"currentColor",stroke:"none"})]})}function Ee({enabled:e,shape:r,color:n,onCommit:l}){const b=m.useRef(null),[f,w]=m.useState(null);m.useEffect(()=>{const c=b.current;if(!c)return;const s=()=>{c.width=c.clientWidth,c.height=c.clientHeight,N()};s();const x=new ResizeObserver(s);return x.observe(c),()=>x.disconnect()},[]);const N=m.useCallback(()=>{const c=b.current;if(!c)return;const s=c.getContext("2d");if(s&&(s.clearRect(0,0,c.width,c.height),!!f)){if(s.strokeStyle=n,s.lineWidth=3,r==="RECT"||r==="ARROW"||r==="FREEHAND")s.strokeRect(Math.min(f.startX,f.curX),Math.min(f.startY,f.curY),Math.abs(f.curX-f.startX),Math.abs(f.curY-f.startY));else if(r==="CIRCLE"){const x=Math.hypot(f.curX-f.startX,f.curY-f.startY);s.beginPath(),s.arc(f.startX,f.startY,x,0,Math.PI*2),s.stroke()}}},[f,n,r]);m.useEffect(()=>{N()},[f,N]);const v=c=>{const x=b.current.getBoundingClientRect();return{px:c.clientX-x.left,py:c.clientY-x.top,w:x.width,h:x.height}},u=c=>{if(!e)return;const s=v(c);w({startX:s.px,startY:s.py,curX:s.px,curY:s.py})},g=c=>{if(!f)return;const s=v(c);w({...f,curX:s.px,curY:s.py})},o=c=>{if(!f||!e)return;const s=v(c),x=Math.min(f.startX,s.px)/s.w,R=Math.min(f.startY,s.py)/s.h,i=Math.abs(s.px-f.startX)/s.w,d=Math.abs(s.py-f.startY)/s.h;i>.005&&d>.005&&l({shape:r,color:n,geometry:{x,y:R,w:i,h:d}}),w(null)};return t.jsx("canvas",{ref:b,style:{position:"absolute",inset:0,pointerEvents:e?"auto":"none",cursor:e?"crosshair":"default"},onMouseDown:u,onMouseMove:g,onMouseUp:o,onMouseLeave:()=>w(null)})}const Te=10,Se=500;function Ce({udid:e,name:r,recordingId:n,annotateMode:l,shape:b,color:f,aspect:w="9 / 16",screenWidth:N,screenHeight:v,platform:u,onAnnotation:g,onRemove:o}){const[c,s]=m.useState("connecting"),[x,R]=m.useState(0),[i,d]=m.useState([]),[p,j]=m.useState(!1),O=m.useRef(null),_=m.useRef(null),y=u==="android"||u==="androidtv"||u==="android-tv",S=u==="ios"||u==="tvos",E=!l&&!!N&&!!v,X=(a,h,C)=>{const A=N,D=v,M=Math.min(1,Math.max(0,(a-C.left)/C.width)),I=Math.min(1,Math.max(0,(h-C.top)/C.height));return{x:Math.round(M*A),y:Math.round(I*D)}},Z=(a,h,C)=>{const A=Date.now()+Math.random(),D=a-C.left,M=h-C.top;d(I=>[...I,{id:A,x:D,y:M}]),window.setTimeout(()=>{d(I=>I.filter(B=>B.id!==A))},500)},Q=a=>{if(!E||c!=="live"||a.button!==0)return;const h=a.currentTarget;h.setPointerCapture(a.pointerId),_.current={startX:a.clientX,startY:a.clientY,startTime:Date.now(),rect:h.getBoundingClientRect()},Z(a.clientX,a.clientY,_.current.rect),h.focus()},ee=async a=>{var H,K;const h=_.current;if(_.current=null,!h||!E)return;try{a.currentTarget.releasePointerCapture(a.pointerId)}catch{}const C=a.clientX-h.startX,A=a.clientY-h.startY,D=Math.hypot(C,A),M=Date.now()-h.startTime,I=X(h.startX,h.startY,h.rect),B=D<Te;try{if(B&&M<Se)await T.tap(e,I.x,I.y);else if(B)await((K=(H=T).touchAndHold)==null?void 0:K.call(H,e,I.x,I.y,M));else{const P=X(a.clientX,a.clientY,h.rect);await T.swipe(e,I.x,I.y,P.x,P.y)}}catch(P){console.error(`[DeviceTile] gesture failed for ${e}`,P)}},te=()=>{_.current=null},re=async a=>{if(!E||c!=="live"||a.metaKey||a.ctrlKey||a.altKey)return;const h=a.key;try{if(h.length===1){a.preventDefault(),await T.typeText(e,h);return}if(h==="Backspace"){a.preventDefault(),y?await T.pressKey(e,67):await T.typeText(e,"\b");return}if(h==="Enter"){a.preventDefault(),y?await T.pressKey(e,66):await T.typeText(e,`
|
|
1
|
+
import{r as m,j as t,X as T}from"./index-CkwQBzCl.js";import{A as U,I as le}from"./keycodes-bIEJfQzr.js";function de(e,r){return e!=="auto"?e:r<=1?"1":r===2?"2x1":r<=4?"2x2":"3x2"}const ue={selected:new Set,layout:"2x2",tiles:[],groupId:null,recording:!1,startedAt:null,annotateMode:!1,shape:"RECT",color:"#ff3333",errorBanner:null};function fe(e,r){switch(r.type){case"SET_LAYOUT":return{...e,layout:r.layout};case"TOGGLE_SELECTED":{const n=new Set(e.selected);return n.has(r.udid)?n.delete(r.udid):n.add(r.udid),{...e,selected:n}}case"CLEAR_SELECTED":return{...e,selected:new Set};case"SET_TILES":return{...e,tiles:r.tiles};case"ADD_TILE":return e.tiles.some(n=>n.udid===r.tile.udid)?e:{...e,tiles:[...e.tiles,r.tile]};case"REMOVE_TILE":return{...e,tiles:e.tiles.filter(n=>n.udid!==r.udid)};case"BIND_RECORDING_IDS":{const n=e.tiles.map(l=>({...l,recordingId:r.map[l.udid]??l.recordingId}));return{...e,tiles:n}}case"START_RECORDING":{const n=e.tiles.map(l=>({...l,recordingId:r.tileIds[l.udid]??l.recordingId}));return{...e,groupId:r.groupId,recording:!0,startedAt:r.startedAt,tiles:n}}case"STOP_RECORDING":return{...e,recording:!1};case"SET_ANNOTATE_MODE":return{...e,annotateMode:r.enabled};case"SET_SHAPE":return{...e,shape:r.shape};case"SET_COLOR":return{...e,color:r.color};case"SET_ERROR_BANNER":return{...e,errorBanner:r.message};default:return e}}const V=m.createContext(null);function me(){const e=m.useContext(V);if(!e)throw new Error("useMosaic must be used inside <MosaicContext.Provider>");return e}function xe(){return m.useReducer(fe,ue)}function he(e){switch(e){case"automation":return"In automation";case"manual_other":return"Manual control by another user";case"manual_self":return"In your mosaic";case"recording_other_group":return"Recording in another group";default:return e?"Busy":null}}const G=[{id:"ios",label:"iOS",match:e=>e==="ios"},{id:"android",label:"Android",match:e=>e==="android"},{id:"tvos",label:"tvOS",match:e=>e==="tvos"},{id:"androidtv",label:"Android TV",match:e=>e==="androidtv"||e==="android-tv"},{id:"other",label:"Other",match:()=>!0}];function pe(e){return e?e==="androidtv"||e==="android-tv"?"ANDROID TV":e.toUpperCase():""}function ge({devices:e,inMosaic:r,onToggle:n}){const[l,b]=m.useState(""),[f,w]=m.useState({}),N=m.useMemo(()=>{const u=l.trim().toLowerCase();return u?e.filter(g=>g.udid.toLowerCase().includes(u)||(g.name??"").toLowerCase().includes(u)||(g.platform??"").toLowerCase().includes(u)):e},[e,l]),v=m.useMemo(()=>{const u=G.map(o=>({id:o.id,label:o.label,rows:[]})),g=o=>u.find((c,s)=>G[s].match(o))??u[u.length-1];for(const o of N)g((o.platform??"").toLowerCase()).rows.push(o);return u.filter(o=>o.rows.length>0)},[N]);return e.length===0?t.jsx("div",{className:"text-xs text-[var(--text-dim)] p-3",children:"No devices online."}):t.jsxs("div",{className:"flex flex-col gap-2",children:[t.jsxs("div",{className:"relative",children:[t.jsx("span",{"aria-hidden":!0,className:"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-dim)] text-xs",children:"⌕"}),t.jsx("input",{type:"text",value:l,placeholder:"Filter devices...",onChange:u=>b(u.target.value),className:"w-full pl-7 pr-2 py-1.5 text-xs rounded border border-[var(--border)] bg-transparent placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--accent,#3b82f6)]"})]}),v.map(u=>{const g=f[u.id];return t.jsxs("section",{className:"flex flex-col gap-1",children:[t.jsxs("button",{type:"button",onClick:()=>w(o=>({...o,[u.id]:!o[u.id]})),className:"flex items-center justify-between w-full text-[10px] uppercase tracking-wider text-[var(--text-dim)] hover:text-white px-1 py-0.5",children:[t.jsxs("span",{className:"flex items-center gap-1.5",children:[t.jsx("span",{"aria-hidden":!0,className:`inline-block transition-transform ${g?"-rotate-90":"rotate-0"}`,children:"▾"}),u.label]}),t.jsx("span",{children:u.rows.length})]}),!g&&t.jsx("ul",{className:"flex flex-col gap-1 text-sm",children:u.rows.map(o=>{const c=o.busyReason==="manual_self",s=r.has(o.udid),x=!!o.busy&&!c&&!s,R=he(o.busyReason),i=!x;return t.jsx("li",{children:t.jsxs("button",{type:"button",disabled:x,draggable:!x,onDragStart:d=>{d.dataTransfer.effectAllowed="copy",d.dataTransfer.setData("application/x-xenon-udid",o.udid),d.dataTransfer.setData("text/plain",o.udid)},onClick:()=>n(o.udid),className:`w-full flex items-center gap-2 px-2 py-1.5 rounded text-left border transition-colors ${x?"opacity-60 cursor-not-allowed border-transparent":s?"border-emerald-500/40 bg-emerald-500/5 hover:bg-emerald-500/10":"border-transparent hover:border-[var(--border)] hover:bg-[var(--surface-2,rgba(255,255,255,0.04))]"}`,title:x?`${R} — release first`:s?"Click to remove from mosaic (or drag to a cell)":"Click to add to mosaic (or drag to a cell)",children:[t.jsx("span",{"aria-hidden":!0,className:`inline-flex items-center justify-center w-4 h-4 text-xs ${s?"text-emerald-400":"text-[var(--text-dim)]"}`,children:s?"●":"○"}),t.jsx("span",{"aria-hidden":!0,className:`inline-block w-1.5 h-1.5 rounded-full ${i?"bg-emerald-400 shadow-[0_0_4px_rgba(52,211,153,0.7)]":"bg-yellow-500"}`}),t.jsx("span",{className:"font-medium flex-1 truncate text-[13px]",children:o.name??o.udid}),o.platform&&t.jsx("span",{className:"text-[9px] uppercase tracking-wider px-1.5 py-0.5 rounded bg-[var(--surface-2,rgba(255,255,255,0.06))] text-[var(--text-dim)]",children:pe(o.platform)})]})},o.udid)})})]},u.id)}),l&&v.length===0&&t.jsxs("div",{className:"text-xs text-[var(--text-dim)] px-1 py-2",children:['No devices match "',l,'".']})]})}const be=[{id:"1",label:"1",icon:t.jsx(ye,{})},{id:"2x1",label:"2×1",icon:t.jsx(we,{})},{id:"2x2",label:"2×2",icon:t.jsx(Ne,{})},{id:"3x2",label:"3×2",icon:t.jsx(je,{})},{id:"auto",label:"Auto",icon:t.jsx(Re,{})}];function ve({value:e,onChange:r}){return t.jsx("div",{role:"tablist",className:"inline-flex border border-[var(--border)] rounded-md overflow-hidden text-xs bg-[var(--surface-1,rgba(255,255,255,0.02))]",children:be.map(n=>{const l=e===n.id;return t.jsxs("button",{role:"tab","aria-selected":l,onClick:()=>r(n.id),className:`flex items-center gap-1.5 px-2.5 py-1.5 border-r border-[var(--border)] last:border-r-0 transition-colors ${l?"bg-[var(--surface-2,#2a2a2a)] text-white":"text-[var(--text-dim)] hover:bg-[var(--surface-2,rgba(255,255,255,0.04))] hover:text-white"}`,title:`Layout: ${n.label}`,children:[t.jsx("span",{className:"w-3.5 h-3.5 inline-flex items-center justify-center",children:n.icon}),t.jsx("span",{children:n.label})]},n.id)})})}function k(e){return t.jsx("rect",{rx:1.2,ry:1.2,fill:"currentColor",...e})}function ye(){return t.jsx("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:k({x:2,y:2,width:10,height:10})})}function we(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1.5,y:3,width:5,height:8}),k({x:7.5,y:3,width:5,height:8})]})}function Ne(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1.5,y:1.5,width:5,height:5}),k({x:7.5,y:1.5,width:5,height:5}),k({x:1.5,y:7.5,width:5,height:5}),k({x:7.5,y:7.5,width:5,height:5})]})}function je(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[k({x:1,y:1.5,width:3.3,height:5}),k({x:5.35,y:1.5,width:3.3,height:5}),k({x:9.7,y:1.5,width:3.3,height:5}),k({x:1,y:7.5,width:3.3,height:5}),k({x:5.35,y:7.5,width:3.3,height:5}),k({x:9.7,y:7.5,width:3.3,height:5})]})}function Re(){return t.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.4",children:[t.jsx("rect",{x:"2",y:"2",width:"10",height:"10",rx:"1.5"}),t.jsx("circle",{cx:"7",cy:"7",r:"1.5",fill:"currentColor",stroke:"none"})]})}function Ee({enabled:e,shape:r,color:n,onCommit:l}){const b=m.useRef(null),[f,w]=m.useState(null);m.useEffect(()=>{const c=b.current;if(!c)return;const s=()=>{c.width=c.clientWidth,c.height=c.clientHeight,N()};s();const x=new ResizeObserver(s);return x.observe(c),()=>x.disconnect()},[]);const N=m.useCallback(()=>{const c=b.current;if(!c)return;const s=c.getContext("2d");if(s&&(s.clearRect(0,0,c.width,c.height),!!f)){if(s.strokeStyle=n,s.lineWidth=3,r==="RECT"||r==="ARROW"||r==="FREEHAND")s.strokeRect(Math.min(f.startX,f.curX),Math.min(f.startY,f.curY),Math.abs(f.curX-f.startX),Math.abs(f.curY-f.startY));else if(r==="CIRCLE"){const x=Math.hypot(f.curX-f.startX,f.curY-f.startY);s.beginPath(),s.arc(f.startX,f.startY,x,0,Math.PI*2),s.stroke()}}},[f,n,r]);m.useEffect(()=>{N()},[f,N]);const v=c=>{const x=b.current.getBoundingClientRect();return{px:c.clientX-x.left,py:c.clientY-x.top,w:x.width,h:x.height}},u=c=>{if(!e)return;const s=v(c);w({startX:s.px,startY:s.py,curX:s.px,curY:s.py})},g=c=>{if(!f)return;const s=v(c);w({...f,curX:s.px,curY:s.py})},o=c=>{if(!f||!e)return;const s=v(c),x=Math.min(f.startX,s.px)/s.w,R=Math.min(f.startY,s.py)/s.h,i=Math.abs(s.px-f.startX)/s.w,d=Math.abs(s.py-f.startY)/s.h;i>.005&&d>.005&&l({shape:r,color:n,geometry:{x,y:R,w:i,h:d}}),w(null)};return t.jsx("canvas",{ref:b,style:{position:"absolute",inset:0,pointerEvents:e?"auto":"none",cursor:e?"crosshair":"default"},onMouseDown:u,onMouseMove:g,onMouseUp:o,onMouseLeave:()=>w(null)})}const Te=10,Se=500;function Ce({udid:e,name:r,recordingId:n,annotateMode:l,shape:b,color:f,aspect:w="9 / 16",screenWidth:N,screenHeight:v,platform:u,onAnnotation:g,onRemove:o}){const[c,s]=m.useState("connecting"),[x,R]=m.useState(0),[i,d]=m.useState([]),[p,j]=m.useState(!1),O=m.useRef(null),_=m.useRef(null),y=u==="android"||u==="androidtv"||u==="android-tv",S=u==="ios"||u==="tvos",E=!l&&!!N&&!!v,X=(a,h,C)=>{const A=N,D=v,M=Math.min(1,Math.max(0,(a-C.left)/C.width)),I=Math.min(1,Math.max(0,(h-C.top)/C.height));return{x:Math.round(M*A),y:Math.round(I*D)}},Z=(a,h,C)=>{const A=Date.now()+Math.random(),D=a-C.left,M=h-C.top;d(I=>[...I,{id:A,x:D,y:M}]),window.setTimeout(()=>{d(I=>I.filter(B=>B.id!==A))},500)},Q=a=>{if(!E||c!=="live"||a.button!==0)return;const h=a.currentTarget;h.setPointerCapture(a.pointerId),_.current={startX:a.clientX,startY:a.clientY,startTime:Date.now(),rect:h.getBoundingClientRect()},Z(a.clientX,a.clientY,_.current.rect),h.focus()},ee=async a=>{var H,K;const h=_.current;if(_.current=null,!h||!E)return;try{a.currentTarget.releasePointerCapture(a.pointerId)}catch{}const C=a.clientX-h.startX,A=a.clientY-h.startY,D=Math.hypot(C,A),M=Date.now()-h.startTime,I=X(h.startX,h.startY,h.rect),B=D<Te;try{if(B&&M<Se)await T.tap(e,I.x,I.y);else if(B)await((K=(H=T).touchAndHold)==null?void 0:K.call(H,e,I.x,I.y,M));else{const P=X(a.clientX,a.clientY,h.rect);await T.swipe(e,I.x,I.y,P.x,P.y)}}catch(P){console.error(`[DeviceTile] gesture failed for ${e}`,P)}},te=()=>{_.current=null},re=async a=>{if(!E||c!=="live"||a.metaKey||a.ctrlKey||a.altKey)return;const h=a.key;try{if(h.length===1){a.preventDefault(),await T.typeText(e,h);return}if(h==="Backspace"){a.preventDefault(),y?await T.pressKey(e,67):await T.typeText(e,"\b");return}if(h==="Enter"){a.preventDefault(),y?await T.pressKey(e,66):await T.typeText(e,`
|
|
2
2
|
`);return}if(h==="Tab"){a.preventDefault(),await T.typeText(e," ");return}h==="Escape"&&y&&(a.preventDefault(),await T.pressKey(e,U.BACK))}catch(C){console.error(`[DeviceTile] keystroke "${h}" failed for ${e}`,C)}},ne=()=>T.pressKey(e,y?U.HOME:le.HOME).catch(a=>console.error(`[DeviceTile] home failed for ${e}`,a)),se=()=>T.pressKey(e,U.BACK).catch(a=>console.error(`[DeviceTile] back failed for ${e}`,a)),oe=()=>T.pressKey(e,U.APP_SWITCH).catch(a=>console.error(`[DeviceTile] app-switch failed for ${e}`,a)),ae=async()=>{try{const a=await T.getScreenshot(e),h=(a==null?void 0:a.screenshot)??(a==null?void 0:a.value)??a;if(!h)return;const C=await fetch(`data:image/png;base64,${h}`).then(M=>M.blob()),A=URL.createObjectURL(C),D=document.createElement("a");D.href=A,D.download=`${r||e}-${Date.now()}.png`,document.body.appendChild(D),D.click(),D.remove(),setTimeout(()=>URL.revokeObjectURL(A),1e3)}catch(a){console.error(`[DeviceTile] screenshot failed for ${e}`,a)}};m.useEffect(()=>{console.log(`[DeviceTile] Rendering ${e} in state: ${c}`)},[e,c]);const ie=`/xenon/api/control/${encodeURIComponent(e)}/stream?t=${x}`;m.useEffect(()=>{if(c!=="connecting")return;const a=setTimeout(()=>{s(h=>h==="connecting"?"unavailable":h)},9e4);return()=>clearTimeout(a)},[c,x]);const ce=()=>{s("connecting"),R(Date.now())},L=!!n,W=r||e.slice(0,16)+"…";return t.jsxs("div",{className:"flex items-stretch justify-center w-full h-full min-h-0 min-w-0 gap-2",children:[t.jsxs("div",{className:"relative bg-[#000] rounded-lg overflow-hidden border border-[var(--border)] group max-h-full max-w-full self-center",style:{aspectRatio:w,height:"100%"},children:[c==="connecting"&&t.jsxs("div",{className:"flex flex-col items-center justify-center bg-neutral-900 text-neutral-400 absolute inset-0 z-20",children:[t.jsxs("div",{className:"relative flex items-center justify-center",children:[t.jsx("div",{className:"w-12 h-12 border-4 border-neutral-800 border-t-red-500 rounded-full animate-spin"}),t.jsx("div",{className:"absolute text-[10px] text-red-500 font-bold",children:"WDA"})]}),t.jsx("div",{className:"mt-4 font-bold text-neutral-200",children:"Starting Stream…"}),t.jsx("div",{className:"text-[10px] mt-1 text-neutral-500 opacity-60 font-mono",children:e}),t.jsx("div",{className:"text-[10px] mt-4 text-neutral-400 bg-white/5 px-2 py-1 rounded",children:"Waiting for device connection..."})]}),c==="unavailable"&&t.jsx("div",{className:"flex items-center justify-center bg-black text-neutral-400 absolute inset-0 z-20",children:t.jsxs("div",{className:"text-center p-6",children:[t.jsx("div",{className:"text-5xl mb-4 opacity-20",children:"📵"}),t.jsx("div",{className:"font-bold text-white text-lg",children:"Connection Failed"}),t.jsx("p",{className:"text-xs mt-2 text-neutral-500 leading-relaxed max-w-[240px] mx-auto",children:"We couldn't connect to the WDA MJPEG stream on port 9100. If automation is running, ensure it hasn't blocked the MJPEG port."}),t.jsx("button",{className:"mt-6 text-sm font-semibold px-6 py-2.5 rounded-full bg-red-600 hover:bg-red-500 text-white transition-all shadow-[0_0_20px_rgba(220,38,38,0.3)] active:scale-95",onClick:ce,children:"Retry Connection"})]})}),t.jsx("img",{src:ie,alt:W,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",draggable:!1,style:{opacity:c==="live"?1:0,transition:"opacity 0.3s ease-in-out"},onLoad:()=>{console.log(`[DeviceTile] Image LOADED for ${e}`),s("live")},onError:a=>{console.error(`[DeviceTile] Image ERROR for ${e}`,a),s("unavailable")}},x),E&&c==="live"&&t.jsx("div",{ref:O,className:`absolute inset-0 z-10 touch-none outline-none ${p?"ring-2 ring-emerald-400/60 ring-inset rounded-lg":""}`,tabIndex:0,onPointerDown:Q,onPointerUp:ee,onPointerCancel:te,onKeyDown:re,onFocus:()=>j(!0),onBlur:()=>j(!1)}),t.jsx("div",{className:"absolute inset-0 z-20 pointer-events-none overflow-hidden",children:i.map(a=>t.jsx("span",{className:"absolute block w-10 h-10 rounded-full border-2 border-emerald-300/80 animate-ping",style:{left:a.x-20,top:a.y-20}},a.id))}),L&&l&&t.jsx(Ee,{enabled:!0,shape:b,color:f,onCommit:a=>g(n,a)}),L&&t.jsx("div",{className:"absolute top-3 left-3 z-30 pointer-events-none",children:t.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-red-600 text-white text-[9px] font-black shadow-lg",children:"REC"})}),t.jsxs("div",{className:"absolute top-3 left-3 z-30 flex flex-col gap-1.5 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-150",children:[c==="live"&&!L&&t.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-emerald-500 text-black text-[9px] font-black shadow-lg w-fit",children:"LIVE"}),t.jsx("span",{className:"px-2 py-1 rounded bg-black/80 text-white text-[11px] font-medium backdrop-blur-md border border-white/10 shadow-xl truncate max-w-[180px]",children:W})]})]}),t.jsx(ke,{streamState:c,recording:L,isIOS:S,isAndroid:y,platform:u,onClose:!L&&o?()=>o(e):void 0,sendHome:ne,sendBack:se,sendAppSwitch:oe,captureScreenshot:ae,displayName:W})]})}function ke({streamState:e,recording:r,isIOS:n,isAndroid:l,platform:b,onClose:f,sendHome:w,sendBack:N,sendAppSwitch:v,captureScreenshot:u,displayName:g}){const o=e==="live";return!f&&!o?null:t.jsxs("div",{className:"self-stretch w-9 flex flex-col items-center justify-between gap-1 py-2 rounded-lg bg-black/40 border border-white/10 backdrop-blur-md text-white",children:[t.jsx("div",{className:"flex flex-col items-center gap-1",children:f&&t.jsx("button",{type:"button","aria-label":`Remove ${g} from mosaic`,title:"Remove from mosaic",onClick:f,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-red-600/70 transition-colors text-base leading-none",children:"×"})}),o&&t.jsxs("div",{className:"flex flex-col items-center gap-1.5 my-auto",children:[(l||n)&&t.jsx("button",{type:"button",title:`Home${b?` (${b})`:""}`,onClick:w,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-white/15 transition-colors text-sm",children:"⌂"}),l&&t.jsx("button",{type:"button",title:"Back",onClick:N,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-white/15 transition-colors text-sm",children:"‹"}),l&&t.jsx("button",{type:"button",title:"Recent apps",onClick:v,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-white/15 transition-colors text-sm",children:"▢"})]}),o&&t.jsx("div",{className:"flex flex-col items-center gap-1",children:t.jsx("button",{type:"button",title:"Screenshot",onClick:u,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-white/15 transition-colors text-sm",children:"⎙"})})]})}const Ie={1:"1fr","2x1":"1fr 1fr","2x2":"1fr 1fr","3x2":"1fr 1fr 1fr"},De={1:"1fr","2x1":"1fr","2x2":"1fr 1fr","3x2":"1fr 1fr"},_e={1:1,"2x1":2,"2x2":4,"3x2":6};function Ae({layout:e,tiles:r,annotateMode:n,shape:l,color:b,onAnnotation:f,onRemove:w,onDropDevice:N}){const v=de(e,r.length),u=_e[v];r.length;const g=r.length,o=e==="auto"?Math.max(g,1):u,c=Math.max(0,o-g);return t.jsxs("div",{style:{display:"grid",gap:8,gridTemplateColumns:Ie[v],gridTemplateRows:De[v]},className:"h-full",children:[r.map(s=>t.jsx(Ce,{udid:s.udid,name:s.name,mjpegPort:s.mjpegPort,recordingId:s.recordingId,aspect:s.aspect,screenWidth:s.screenWidth,screenHeight:s.screenHeight,platform:s.platform,annotateMode:n,shape:l,color:b,onAnnotation:f,onRemove:w},s.udid)),Array.from({length:c},(s,x)=>t.jsx(Me,{onDropDevice:N},`empty-${x}`))]})}function Me({onDropDevice:e}){const[r,n]=m.useState(!1);return t.jsxs("div",{onDragOver:l=>{e&&(l.preventDefault(),l.dataTransfer.dropEffect="copy",r||n(!0))},onDragLeave:()=>n(!1),onDrop:l=>{if(n(!1),!e)return;l.preventDefault();const b=l.dataTransfer.getData("application/x-xenon-udid")||l.dataTransfer.getData("text/plain");b&&e(b)},className:`flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed transition-colors ${r?"border-emerald-500/60 bg-emerald-500/5":"border-[var(--border)] bg-[var(--surface-1,rgba(255,255,255,0.02))]"} text-[var(--text-dim)] min-h-[120px]`,children:[t.jsx("div",{className:`w-8 h-8 rounded-full flex items-center justify-center text-xl ${r?"bg-emerald-500/15 text-emerald-300":"bg-white/5 text-white/60"}`,children:"+"}),t.jsx("div",{className:"text-xs font-medium",children:"Drag device here"}),t.jsx("div",{className:"text-[10px] opacity-70",children:"or click one in the panel"})]})}const $="/xenon/api/recordings";class J extends Error{constructor(r){super(r.message??r.error),this.body=r}}async function Y(e,r){const n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:r?JSON.stringify(r):void 0});if(n.status===409)throw new J(await n.json());if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.json()}function Oe(e,r){return Y($,{udids:e,...r})}function $e(e){return Y(`${$}/${encodeURIComponent(e)}/stop`)}function q(e,r,n,l,b){return Y(`${$}/${encodeURIComponent(e)}/bookmark`,{recordingId:r,timecodeMs:n,label:l,note:b})}function Le(e,r){return Y(`${$}/${encodeURIComponent(e)}/annotation`,r)}function Be(e){return`${$}/${encodeURIComponent(e)}/bundle.zip`}function Pe(e){return`${$}/${encodeURIComponent(e)}/composite.mp4`}function Ue({selectedUdids:e}){const{state:r,dispatch:n}=me(),l=async()=>{if(!(r.recording||e.length===0))try{const o=await Oe(e),c={};for(const s of o.recordings)c[s.udid]=s.id;n({type:"START_RECORDING",groupId:o.groupId,startedAt:Date.now(),tileIds:c}),n({type:"SET_ERROR_BANNER",message:null})}catch(o){if(o instanceof J)if(o.body.error==="device_busy"){const c=(o.body.busyDevices??[]).map(s=>`${s.udid} (${s.reason})`).join(", ");n({type:"SET_ERROR_BANNER",message:`Cannot start — these devices are busy: ${c}`})}else n({type:"SET_ERROR_BANNER",message:`Server-wide recording cap reached (${o.body.active}/${o.body.limit}).`});else n({type:"SET_ERROR_BANNER",message:`Recording failed: ${o.message}`})}},b=async()=>{if(r.groupId)try{await $e(r.groupId)}catch(o){n({type:"SET_ERROR_BANNER",message:`Stop failed: ${o.message}`})}finally{n({type:"STOP_RECORDING"})}},f=async()=>{var x;if(!r.groupId||!r.recording)return;const o=window.prompt("Bookmark label?");if(!o)return;const c=r.startedAt?Date.now()-r.startedAt:0,s=(x=r.tiles.find(R=>R.recordingId))==null?void 0:x.recordingId;if(s)try{await q(r.groupId,s,c,o)}catch(R){n({type:"SET_ERROR_BANNER",message:`Bookmark failed: ${R.message}`})}},w=()=>n({type:"SET_ANNOTATE_MODE",enabled:!r.annotateMode}),N=!r.recording&&e.length>0,v=r.recording,u=r.groupId&&!r.recording,g=u&&r.tiles.length>=2;return t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs("button",{onClick:l,disabled:!N,className:"px-3 py-1.5 text-sm rounded bg-red-600 text-white disabled:opacity-40 disabled:cursor-not-allowed",children:["● ",e.length>1?"Record All":"Record"]}),t.jsx("button",{onClick:b,disabled:!v,className:"px-3 py-1.5 text-sm rounded border border-[var(--border)] disabled:opacity-40 disabled:cursor-not-allowed",children:"⏹ Stop"}),t.jsx("button",{onClick:f,disabled:!v,className:"px-3 py-1.5 text-sm rounded border border-[var(--border)] disabled:opacity-40 disabled:cursor-not-allowed",children:"🔖 Bookmark"}),t.jsx("button",{onClick:w,disabled:!r.recording,className:`px-3 py-1.5 text-sm rounded border ${r.annotateMode?"bg-[var(--accent,#3b82f6)] text-white border-transparent":"border-[var(--border)]"} disabled:opacity-40 disabled:cursor-not-allowed`,children:"✎ Annotate"}),g&&t.jsx("a",{href:Pe(r.groupId),className:"ml-2 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2,#1a1a1a)]",download:`mosaic-${r.groupId}.mp4`,children:"⤓ Composite mp4"}),u&&t.jsx("a",{href:Be(r.groupId),className:`${g?"ml-1":"ml-2"} px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2,#1a1a1a)]`,download:!0,children:"⤓ Proof bundle"})]})}function Ye({remainingSec:e,onContinue:r,onReleaseNow:n}){return t.jsx("div",{role:"dialog","aria-modal":"true","aria-labelledby":"idle-warning-title",className:"fixed inset-0 z-40 bg-black/60 flex items-center justify-center",children:t.jsxs("div",{className:"bg-[var(--bg)] border border-[var(--border)] rounded-lg w-full max-w-md p-6",children:[t.jsx("h3",{id:"idle-warning-title",className:"text-base font-semibold mb-2",children:"Are you still there?"}),t.jsxs("p",{className:"text-sm text-[var(--text-dim)] mb-4",children:["Your devices will be released in"," ",t.jsxs("span",{className:"text-[var(--text)] font-mono font-semibold",children:[e,"s"]})," due to inactivity. Click ",t.jsx("strong",{children:"Continue Session"})," to keep them locked."]}),t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx("button",{type:"button",onClick:n,className:"h-9 px-3 rounded-md border border-[var(--border)] text-sm text-[var(--text-dim)] hover:text-[var(--text)]",children:"Release now"}),t.jsx("button",{type:"button",autoFocus:!0,onClick:r,className:"h-9 px-4 rounded-md bg-[var(--green)] text-black text-sm font-medium",children:"Continue Session"})]})]})})}const F=["mousemove","mousedown","keydown","touchstart","wheel"];function We({idleAfterMs:e,warningSec:r,onWarning:n,onTimeout:l,enabled:b}){const[f,w]=m.useState(!1),[N,v]=m.useState(null),u=m.useRef(null),g=m.useRef(null),o=m.useRef(!1),c=m.useRef(n),s=m.useRef(l);c.current=n,s.current=l;function x(){u.current&&(clearTimeout(u.current),u.current=null),g.current&&(clearInterval(g.current),g.current=null)}function R(){o.current=!0,w(!0),v(r),c.current(r);let p=r;g.current=setInterval(()=>{p-=1,p<=0?(x(),o.current=!1,w(!1),v(null),s.current()):v(p)},1e3)}function i(){x(),o.current=!1,w(!1),v(null);const p=e-r*1e3;u.current=setTimeout(R,Math.max(0,p))}function d(){b&&i()}return m.useEffect(()=>{if(!b){x(),o.current=!1,w(!1),v(null);return}function p(){o.current||i()}return F.forEach(j=>window.addEventListener(j,p,{passive:!0})),i(),()=>{F.forEach(j=>window.removeEventListener(j,p)),x()}},[b,e,r]),{warning:f,remainingSec:N,reset:d}}const Xe=5*60*1e3,He=30;function z(e){if(!e)return"9 / 16";const r=Number(e.screenWidth),n=Number(e.screenHeight);if(Number.isFinite(r)&&Number.isFinite(n)&&r>0&&n>0)return`${r} / ${n}`;const l=(e.platform||"").toLowerCase();return l==="tvos"||l==="androidtv"||l==="android-tv"?"16 / 9":"9 / 16"}function Ke(e,r,n){return n?e===`manual_${n}_${r}`:!1}function Ge(e,r){if(e.busy)return e.session_id?e.session_id.startsWith("manual_")?Ke(e.session_id,e.udid,r)?"manual_self":"manual_other":"automation":"unknown"}function Fe(e,r){return{udid:e.udid,name:e.name,platform:e.platform,busy:e.busy,busyReason:Ge(e,r),mjpegServerPort:e.mjpegServerPort}}function Je(){const[e,r]=xe(),[n,l]=m.useState([]),[b,f]=m.useState(0),[w,N]=m.useState(null);m.useEffect(()=>{let i=!1;return fetch("/xenon/api/auth/me",{credentials:"include"}).then(d=>d.ok?d.json():null).then(d=>{!i&&(d!=null&&d.userId)&&N(d.userId)}).catch(()=>{}),()=>{i=!0}},[]),m.useEffect(()=>{let i=!1;const d=async()=>{try{const j=await T.getDevices();i||l(Array.isArray(j)?j:[])}catch{}};d();const p=window.setInterval(d,5e3);return()=>{i=!0,window.clearInterval(p)}},[b]),m.useEffect(()=>{let i=!1;return(async()=>{try{const d=await T.getDevices(),p=(Array.isArray(d)?d:[]).filter(y=>{var S;return y.busy&&((S=y.session_id)==null?void 0:S.startsWith("manual_"))});if(p.length===0)return;const O=(await Promise.all(p.map(async y=>{try{const S=await fetch(`/xenon/api/control/${encodeURIComponent(y.udid)}/stream/status`);if(!S.ok)return null;const E=await S.json();return(E==null?void 0:E.status)==="running"?y:null}catch{return null}}))).filter(y=>y!==null);if(i||O.length===0)return;const _=O.map(y=>{const S=Number(y.screenWidth),E=Number(y.screenHeight);return{udid:y.udid,name:y.name,mjpegPort:0,aspect:z(y),screenWidth:Number.isFinite(S)&&S>0?S:void 0,screenHeight:Number.isFinite(E)&&E>0?E:void 0,platform:y.platform}});r({type:"SET_TILES",tiles:_})}catch{}})(),()=>{i=!0}},[]),m.useEffect(()=>{const i=async d=>{var y,S;if(d.key!=="b"&&d.key!=="B")return;const p=(y=d.target)==null?void 0:y.tagName;if(p==="INPUT"||p==="TEXTAREA"||p==="SELECT"||!e.recording||!e.groupId)return;const j=window.prompt("Bookmark label?");if(!j)return;const O=e.startedAt?Date.now()-e.startedAt:0,_=(S=e.tiles.find(E=>E.recordingId))==null?void 0:S.recordingId;if(_)try{await q(e.groupId,_,O,j)}catch(E){r({type:"SET_ERROR_BANNER",message:`Bookmark failed: ${E.message}`})}};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[e.recording,e.groupId,e.startedAt,e.tiles,r]);const v=m.useMemo(()=>new Set(e.tiles.map(i=>i.udid)),[e.tiles]),u=m.useMemo(()=>n.map(i=>Fe(i,w)),[n,w]),g=i=>{const d=Number(i.screenWidth),p=Number(i.screenHeight);return{udid:i.udid,name:i.name,mjpegPort:0,aspect:z(i),screenWidth:Number.isFinite(d)&&d>0?d:void 0,screenHeight:Number.isFinite(p)&&p>0?p:void 0,platform:i.platform}},o=async i=>{if(e.tiles.some(j=>j.udid===i)){await c(i);return}if(e.recording){r({type:"SET_ERROR_BANNER",message:"Stop recording before changing the mosaic layout."});return}const p=n.find(j=>j.udid===i);p&&(r({type:"ADD_TILE",tile:g(p)}),fetch(`/xenon/api/control/${encodeURIComponent(i)}/stream/start`,{method:"POST"}).catch(()=>{}))},c=async i=>{r({type:"REMOVE_TILE",udid:i});try{await fetch(`/xenon/api/control/${encodeURIComponent(i)}/stream/stop`,{method:"POST"})}catch{}f(d=>d+1)},s=async(i,d)=>{if(e.groupId)try{await Le(e.groupId,{recordingId:i,timecodeMs:e.startedAt?Date.now()-e.startedAt:0,shape:d.shape,geometry:JSON.stringify(d.geometry),color:d.color,text:d.text})}catch(p){r({type:"SET_ERROR_BANNER",message:`Annotation failed: ${p.message}`})}},x=()=>{for(const i of e.tiles){const d=`/xenon/api/control/${encodeURIComponent(i.udid)}/stream/stop`;try{navigator.sendBeacon?navigator.sendBeacon(d):fetch(d,{method:"POST",keepalive:!0}).catch(()=>{})}catch{}}e.tiles.forEach(i=>r({type:"REMOVE_TILE",udid:i.udid}))},R=We({idleAfterMs:Xe,warningSec:He,enabled:e.tiles.length>0,onWarning:()=>{},onTimeout:()=>{x()}});return t.jsxs(V.Provider,{value:{state:e,dispatch:r},children:[t.jsxs("div",{className:"flex flex-col h-full p-4 gap-3",children:[t.jsxs("header",{className:"flex items-center justify-between gap-3",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("h1",{className:"text-base font-semibold",children:"Live Devices"}),t.jsx(ve,{value:e.layout,onChange:i=>r({type:"SET_LAYOUT",layout:i})})]}),t.jsx(Ue,{selectedUdids:e.tiles.map(i=>i.udid)})]}),e.errorBanner&&t.jsxs("div",{role:"alert",className:"text-sm rounded border border-red-500/40 bg-red-500/10 text-red-100 px-3 py-2 flex items-center gap-2",children:[t.jsx("span",{className:"flex-1",children:e.errorBanner}),t.jsx("button",{className:"text-xs opacity-80 hover:opacity-100",onClick:()=>r({type:"SET_ERROR_BANNER",message:null}),children:"Dismiss"})]}),t.jsxs("div",{className:"grid grid-cols-[260px_1fr] gap-3 flex-1 min-h-0",children:[t.jsxs("aside",{className:"flex flex-col gap-2 border border-[var(--border)] rounded p-3 overflow-y-auto min-h-0",children:[t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsx("span",{className:"text-xs uppercase tracking-wide text-[var(--text-dim)]",children:"Devices"}),t.jsx("button",{className:"text-xs underline opacity-70 hover:opacity-100",onClick:()=>f(i=>i+1),children:"Refresh"})]}),t.jsx(ge,{devices:u,inMosaic:v,onToggle:o}),t.jsx("p",{className:"mt-2 text-[11px] text-[var(--text-dim)] leading-relaxed",children:"Click a device to add it to the mosaic. Click again (or use the × on the tile) to remove it."})]}),t.jsx("main",{className:"border border-[var(--border)] rounded p-2 overflow-y-auto h-full min-h-0",children:t.jsx(Ae,{layout:e.layout,tiles:e.tiles,annotateMode:e.annotateMode,shape:e.shape,color:e.color,onAnnotation:s,onRemove:c,onDropDevice:o})})]})]}),R.warning&&R.remainingSec!==null&&t.jsx(Ye,{remainingSec:R.remainingSec,onContinue:R.reset,onReleaseNow:x})]})}export{Je as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as s}from"./index-
|
|
1
|
+
import{j as s}from"./index-CkwQBzCl.js";const i=({icon:e,title:m,description:t,action:a})=>s.jsxs("div",{className:"empty-state",children:[e&&s.jsx("div",{className:"empty-state-icon",children:e}),s.jsx("div",{className:"empty-state-title",children:m}),t&&s.jsx("div",{className:"empty-state-desc",children:t}),a&&s.jsx("div",{className:"empty-state-action",children:a})]});export{i as E};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as s}from"./index-
|
|
1
|
+
import{j as s}from"./index-CkwQBzCl.js";const r=({label:e,description:l,children:c,error:a,htmlFor:d})=>s.jsxs("div",{className:"fg",children:[s.jsx("label",{className:"fg-label",htmlFor:d,children:e}),l&&s.jsx("div",{className:"fg-desc",children:l}),s.jsx("div",{className:"fg-control",children:c}),a&&s.jsx("div",{className:"fg-error",children:a})]});export{r as F};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as i,j as h,h as at,R as xe,i as it,n as st}from"./index-BrVV0Kla.js";function me(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function De(...e){return t=>{let n=!1;const r=e.map(o=>{const a=me(o,t);return!n&&typeof a=="function"&&(n=!0),a});if(n)return()=>{for(let o=0;o<r.length;o++){const a=r[o];typeof a=="function"?a():me(e[o],null)}}}}function I(...e){return i.useCallback(De(...e),e)}function Oe(e){const t=ct(e),n=i.forwardRef((r,o)=>{const{children:a,...c}=r,s=i.Children.toArray(a),d=s.find(lt);if(d){const u=d.props.children,f=s.map(v=>v===d?i.Children.count(u)>1?i.Children.only(null):i.isValidElement(u)?u.props.children:null:v);return h.jsx(t,{...c,ref:o,children:i.isValidElement(u)?i.cloneElement(u,void 0,f):null})}return h.jsx(t,{...c,ref:o,children:a})});return n.displayName=`${e}.Slot`,n}function ct(e){const t=i.forwardRef((n,r)=>{const{children:o,...a}=n;if(i.isValidElement(o)){const c=ft(o),s=dt(a,o.props);return o.type!==i.Fragment&&(s.ref=r?De(r,c):c),i.cloneElement(o,s)}return i.Children.count(o)>1?i.Children.only(null):null});return t.displayName=`${e}.SlotClone`,t}var ut=Symbol("radix.slottable");function lt(e){return i.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===ut}function dt(e,t){const n={...t};for(const r in t){const o=e[r],a=t[r];/^on[A-Z]/.test(r)?o&&a?n[r]=(...s)=>{const d=a(...s);return o(...s),d}:o&&(n[r]=o):r==="style"?n[r]={...o,...a}:r==="className"&&(n[r]=[o,a].filter(Boolean).join(" "))}return{...e,...n}}function ft(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var vt=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],D=vt.reduce((e,t)=>{const n=Oe(`Primitive.${t}`),r=i.forwardRef((o,a)=>{const{asChild:c,...s}=o,d=c?n:t;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),h.jsx(d,{...s,ref:a})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function mt(e,t){e&&at.flushSync(()=>e.dispatchEvent(t))}function ht(e,t){const n=i.createContext(t),r=a=>{const{children:c,...s}=a,d=i.useMemo(()=>s,Object.values(s));return h.jsx(n.Provider,{value:d,children:c})};r.displayName=e+"Provider";function o(a){const c=i.useContext(n);if(c)return c;if(t!==void 0)return t;throw new Error(`\`${a}\` must be used within \`${e}\``)}return[r,o]}function pt(e,t=[]){let n=[];function r(a,c){const s=i.createContext(c),d=n.length;n=[...n,c];const u=v=>{var y;const{scope:m,children:g,...w}=v,l=((y=m==null?void 0:m[e])==null?void 0:y[d])||s,p=i.useMemo(()=>w,Object.values(w));return h.jsx(l.Provider,{value:p,children:g})};u.displayName=a+"Provider";function f(v,m){var l;const g=((l=m==null?void 0:m[e])==null?void 0:l[d])||s,w=i.useContext(g);if(w)return w;if(c!==void 0)return c;throw new Error(`\`${v}\` must be used within \`${a}\``)}return[u,f]}const o=()=>{const a=n.map(c=>i.createContext(c));return function(s){const d=(s==null?void 0:s[e])||a;return i.useMemo(()=>({[`__scope${e}`]:{...s,[e]:d}}),[s,d])}};return o.scopeName=e,[r,gt(o,...t)]}function gt(...e){const t=e[0];if(e.length===1)return t;const n=()=>{const r=e.map(o=>({useScope:o(),scopeName:o.scopeName}));return function(a){const c=r.reduce((s,{useScope:d,scopeName:u})=>{const v=d(a)[`__scope${u}`];return{...s,...v}},{});return i.useMemo(()=>({[`__scope${t.scopeName}`]:c}),[c])}};return n.scopeName=t.scopeName,n}function B(e){const t=i.useRef(e);return i.useEffect(()=>{t.current=e}),i.useMemo(()=>(...n)=>{var r;return(r=t.current)==null?void 0:r.call(t,...n)},[])}var U=globalThis!=null&&globalThis.document?i.useLayoutEffect:()=>{};function A(e,t,{checkForDefaultPrevented:n=!0}={}){return function(o){if(e==null||e(o),n===!1||!o.defaultPrevented)return t==null?void 0:t(o)}}function yt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e);i.useEffect(()=>{const r=o=>{o.key==="Escape"&&n(o)};return t.addEventListener("keydown",r,{capture:!0}),()=>t.removeEventListener("keydown",r,{capture:!0})},[n,t])}var Et="DismissableLayer",ce="dismissableLayer.update",bt="dismissableLayer.pointerDownOutside",Ct="dismissableLayer.focusOutside",he,Ae=i.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Te=i.forwardRef((e,t)=>{const{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:o,onFocusOutside:a,onInteractOutside:c,onDismiss:s,...d}=e,u=i.useContext(Ae),[f,v]=i.useState(null),m=(f==null?void 0:f.ownerDocument)??(globalThis==null?void 0:globalThis.document),[,g]=i.useState({}),w=I(t,E=>v(E)),l=Array.from(u.layers),[p]=[...u.layersWithOutsidePointerEventsDisabled].slice(-1),y=l.indexOf(p),b=f?l.indexOf(f):-1,C=u.layersWithOutsidePointerEventsDisabled.size>0,S=b>=y,R=Rt(E=>{const T=E.target,L=[...u.branches].some(W=>W.contains(T));!S||L||(o==null||o(E),c==null||c(E),E.defaultPrevented||s==null||s())},m),N=Nt(E=>{const T=E.target;[...u.branches].some(W=>W.contains(T))||(a==null||a(E),c==null||c(E),E.defaultPrevented||s==null||s())},m);return yt(E=>{b===u.layers.size-1&&(r==null||r(E),!E.defaultPrevented&&s&&(E.preventDefault(),s()))},m),i.useEffect(()=>{if(f)return n&&(u.layersWithOutsidePointerEventsDisabled.size===0&&(he=m.body.style.pointerEvents,m.body.style.pointerEvents="none"),u.layersWithOutsidePointerEventsDisabled.add(f)),u.layers.add(f),pe(),()=>{n&&u.layersWithOutsidePointerEventsDisabled.size===1&&(m.body.style.pointerEvents=he)}},[f,m,n,u]),i.useEffect(()=>()=>{f&&(u.layers.delete(f),u.layersWithOutsidePointerEventsDisabled.delete(f),pe())},[f,u]),i.useEffect(()=>{const E=()=>g({});return document.addEventListener(ce,E),()=>document.removeEventListener(ce,E)},[]),h.jsx(D.div,{...d,ref:w,style:{pointerEvents:C?S?"auto":"none":void 0,...e.style},onFocusCapture:A(e.onFocusCapture,N.onFocusCapture),onBlurCapture:A(e.onBlurCapture,N.onBlurCapture),onPointerDownCapture:A(e.onPointerDownCapture,R.onPointerDownCapture)})});Te.displayName=Et;var St="DismissableLayerBranch",wt=i.forwardRef((e,t)=>{const n=i.useContext(Ae),r=i.useRef(null),o=I(t,r);return i.useEffect(()=>{const a=r.current;if(a)return n.branches.add(a),()=>{n.branches.delete(a)}},[n.branches]),h.jsx(D.div,{...e,ref:o})});wt.displayName=St;function Rt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1),o=i.useRef(()=>{});return i.useEffect(()=>{const a=s=>{if(s.target&&!r.current){let d=function(){Me(bt,n,u,{discrete:!0})};const u={originalEvent:s};s.pointerType==="touch"?(t.removeEventListener("click",o.current),o.current=d,t.addEventListener("click",o.current,{once:!0})):d()}else t.removeEventListener("click",o.current);r.current=!1},c=window.setTimeout(()=>{t.addEventListener("pointerdown",a)},0);return()=>{window.clearTimeout(c),t.removeEventListener("pointerdown",a),t.removeEventListener("click",o.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function Nt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1);return i.useEffect(()=>{const o=a=>{a.target&&!r.current&&Me(Ct,n,{originalEvent:a},{discrete:!1})};return t.addEventListener("focusin",o),()=>t.removeEventListener("focusin",o)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function pe(){const e=new CustomEvent(ce);document.dispatchEvent(e)}function Me(e,t,n,{discrete:r}){const o=n.originalEvent.target,a=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&o.addEventListener(e,t,{once:!0}),r?mt(o,a):o.dispatchEvent(a)}var Pt=xe[" useId ".trim().toString()]||(()=>{}),xt=0;function ee(e){const[t,n]=i.useState(Pt());return U(()=>{n(r=>r??String(xt++))},[e]),e||(t?`radix-${t}`:"")}var Dt=xe[" useInsertionEffect ".trim().toString()]||U;function Ot({prop:e,defaultProp:t,onChange:n=()=>{},caller:r}){const[o,a,c]=At({defaultProp:t,onChange:n}),s=e!==void 0,d=s?e:o;{const f=i.useRef(e!==void 0);i.useEffect(()=>{const v=f.current;v!==s&&console.warn(`${r} is changing from ${v?"controlled":"uncontrolled"} to ${s?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),f.current=s},[s,r])}const u=i.useCallback(f=>{var v;if(s){const m=Tt(f)?f(e):f;m!==e&&((v=c.current)==null||v.call(c,m))}else a(f)},[s,e,a,c]);return[d,u]}function At({defaultProp:e,onChange:t}){const[n,r]=i.useState(e),o=i.useRef(n),a=i.useRef(t);return Dt(()=>{a.current=t},[t]),i.useEffect(()=>{var c;o.current!==n&&((c=a.current)==null||c.call(a,n),o.current=n)},[n,o]),[n,r,a]}function Tt(e){return typeof e=="function"}var te="focusScope.autoFocusOnMount",ne="focusScope.autoFocusOnUnmount",ge={bubbles:!1,cancelable:!0},Mt="FocusScope",Ie=i.forwardRef((e,t)=>{const{loop:n=!1,trapped:r=!1,onMountAutoFocus:o,onUnmountAutoFocus:a,...c}=e,[s,d]=i.useState(null),u=B(o),f=B(a),v=i.useRef(null),m=I(t,l=>d(l)),g=i.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;i.useEffect(()=>{if(r){let l=function(C){if(g.paused||!s)return;const S=C.target;s.contains(S)?v.current=S:O(v.current,{select:!0})},p=function(C){if(g.paused||!s)return;const S=C.relatedTarget;S!==null&&(s.contains(S)||O(v.current,{select:!0}))},y=function(C){if(document.activeElement===document.body)for(const R of C)R.removedNodes.length>0&&O(s)};document.addEventListener("focusin",l),document.addEventListener("focusout",p);const b=new MutationObserver(y);return s&&b.observe(s,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",l),document.removeEventListener("focusout",p),b.disconnect()}}},[r,s,g.paused]),i.useEffect(()=>{if(s){Ee.add(g);const l=document.activeElement;if(!s.contains(l)){const y=new CustomEvent(te,ge);s.addEventListener(te,u),s.dispatchEvent(y),y.defaultPrevented||(It(jt(Le(s)),{select:!0}),document.activeElement===l&&O(s))}return()=>{s.removeEventListener(te,u),setTimeout(()=>{const y=new CustomEvent(ne,ge);s.addEventListener(ne,f),s.dispatchEvent(y),y.defaultPrevented||O(l??document.body,{select:!0}),s.removeEventListener(ne,f),Ee.remove(g)},0)}}},[s,u,f,g]);const w=i.useCallback(l=>{if(!n&&!r||g.paused)return;const p=l.key==="Tab"&&!l.altKey&&!l.ctrlKey&&!l.metaKey,y=document.activeElement;if(p&&y){const b=l.currentTarget,[C,S]=Lt(b);C&&S?!l.shiftKey&&y===S?(l.preventDefault(),n&&O(C,{select:!0})):l.shiftKey&&y===C&&(l.preventDefault(),n&&O(S,{select:!0})):y===b&&l.preventDefault()}},[n,r,g.paused]);return h.jsx(D.div,{tabIndex:-1,...c,ref:m,onKeyDown:w})});Ie.displayName=Mt;function It(e,{select:t=!1}={}){const n=document.activeElement;for(const r of e)if(O(r,{select:t}),document.activeElement!==n)return}function Lt(e){const t=Le(e),n=ye(t,e),r=ye(t.reverse(),e);return[n,r]}function Le(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:r=>{const o=r.tagName==="INPUT"&&r.type==="hidden";return r.disabled||r.hidden||o?NodeFilter.FILTER_SKIP:r.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t}function ye(e,t){for(const n of e)if(!_t(n,{upTo:t}))return n}function _t(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t!==void 0&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1}function Ft(e){return e instanceof HTMLInputElement&&"select"in e}function O(e,{select:t=!1}={}){if(e&&e.focus){const n=document.activeElement;e.focus({preventScroll:!0}),e!==n&&Ft(e)&&t&&e.select()}}var Ee=kt();function kt(){let e=[];return{add(t){const n=e[0];t!==n&&(n==null||n.pause()),e=be(e,t),e.unshift(t)},remove(t){var n;e=be(e,t),(n=e[0])==null||n.resume()}}}function be(e,t){const n=[...e],r=n.indexOf(t);return r!==-1&&n.splice(r,1),n}function jt(e){return e.filter(t=>t.tagName!=="A")}var Wt="Portal",_e=i.forwardRef((e,t)=>{var s;const{container:n,...r}=e,[o,a]=i.useState(!1);U(()=>a(!0),[]);const c=n||o&&((s=globalThis==null?void 0:globalThis.document)==null?void 0:s.body);return c?it.createPortal(h.jsx(D.div,{...r,ref:t}),c):null});_e.displayName=Wt;function Bt(e,t){return i.useReducer((n,r)=>t[n][r]??n,e)}var q=e=>{const{present:t,children:n}=e,r=Ut(t),o=typeof n=="function"?n({present:r.isPresent}):i.Children.only(n),a=I(r.ref,$t(o));return typeof n=="function"||r.isPresent?i.cloneElement(o,{ref:a}):null};q.displayName="Presence";function Ut(e){const[t,n]=i.useState(),r=i.useRef(null),o=i.useRef(e),a=i.useRef("none"),c=e?"mounted":"unmounted",[s,d]=Bt(c,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return i.useEffect(()=>{const u=V(r.current);a.current=s==="mounted"?u:"none"},[s]),U(()=>{const u=r.current,f=o.current;if(f!==e){const m=a.current,g=V(u);e?d("MOUNT"):g==="none"||(u==null?void 0:u.display)==="none"?d("UNMOUNT"):d(f&&m!==g?"ANIMATION_OUT":"UNMOUNT"),o.current=e}},[e,d]),U(()=>{if(t){let u;const f=t.ownerDocument.defaultView??window,v=g=>{const l=V(r.current).includes(CSS.escape(g.animationName));if(g.target===t&&l&&(d("ANIMATION_END"),!o.current)){const p=t.style.animationFillMode;t.style.animationFillMode="forwards",u=f.setTimeout(()=>{t.style.animationFillMode==="forwards"&&(t.style.animationFillMode=p)})}},m=g=>{g.target===t&&(a.current=V(r.current))};return t.addEventListener("animationstart",m),t.addEventListener("animationcancel",v),t.addEventListener("animationend",v),()=>{f.clearTimeout(u),t.removeEventListener("animationstart",m),t.removeEventListener("animationcancel",v),t.removeEventListener("animationend",v)}}else d("ANIMATION_END")},[t,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:i.useCallback(u=>{r.current=u?getComputedStyle(u):null,n(u)},[])}}function V(e){return(e==null?void 0:e.animationName)||"none"}function $t(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var re=0;function Vt(){i.useEffect(()=>{const e=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",e[0]??Ce()),document.body.insertAdjacentElement("beforeend",e[1]??Ce()),re++,()=>{re===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(t=>t.remove()),re--}},[])}function Ce(){const e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var x=function(){return x=Object.assign||function(t){for(var n,r=1,o=arguments.length;r<o;r++){n=arguments[r];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(t[a]=n[a])}return t},x.apply(this,arguments)};function Fe(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]]);return n}function Kt(e,t,n){if(n||arguments.length===2)for(var r=0,o=t.length,a;r<o;r++)(a||!(r in t))&&(a||(a=Array.prototype.slice.call(t,0,r)),a[r]=t[r]);return e.concat(a||Array.prototype.slice.call(t))}var H="right-scroll-bar-position",z="width-before-scroll-bar",Gt="with-scroll-bars-hidden",Xt="--removed-body-scroll-bar-size";function oe(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}function Yt(e,t){var n=i.useState(function(){return{value:e,callback:t,facade:{get current(){return n.value},set current(r){var o=n.value;o!==r&&(n.value=r,n.callback(r,o))}}}})[0];return n.callback=t,n.facade}var Ht=typeof window<"u"?i.useLayoutEffect:i.useEffect,Se=new WeakMap;function zt(e,t){var n=Yt(null,function(r){return e.forEach(function(o){return oe(o,r)})});return Ht(function(){var r=Se.get(n);if(r){var o=new Set(r),a=new Set(e),c=n.current;o.forEach(function(s){a.has(s)||oe(s,null)}),a.forEach(function(s){o.has(s)||oe(s,c)})}Se.set(n,e)},[e]),n}function Zt(e){return e}function qt(e,t){t===void 0&&(t=Zt);var n=[],r=!1,o={read:function(){if(r)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return n.length?n[n.length-1]:e},useMedium:function(a){var c=t(a,r);return n.push(c),function(){n=n.filter(function(s){return s!==c})}},assignSyncMedium:function(a){for(r=!0;n.length;){var c=n;n=[],c.forEach(a)}n={push:function(s){return a(s)},filter:function(){return n}}},assignMedium:function(a){r=!0;var c=[];if(n.length){var s=n;n=[],s.forEach(a),c=n}var d=function(){var f=c;c=[],f.forEach(a)},u=function(){return Promise.resolve().then(d)};u(),n={push:function(f){c.push(f),u()},filter:function(f){return c=c.filter(f),n}}}};return o}function Qt(e){e===void 0&&(e={});var t=qt(null);return t.options=x({async:!0,ssr:!1},e),t}var ke=function(e){var t=e.sideCar,n=Fe(e,["sideCar"]);if(!t)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var r=t.read();if(!r)throw new Error("Sidecar medium not found");return i.createElement(r,x({},n))};ke.isSideCarExport=!0;function Jt(e,t){return e.useMedium(t),ke}var je=Qt(),ae=function(){},Q=i.forwardRef(function(e,t){var n=i.useRef(null),r=i.useState({onScrollCapture:ae,onWheelCapture:ae,onTouchMoveCapture:ae}),o=r[0],a=r[1],c=e.forwardProps,s=e.children,d=e.className,u=e.removeScrollBar,f=e.enabled,v=e.shards,m=e.sideCar,g=e.noRelative,w=e.noIsolation,l=e.inert,p=e.allowPinchZoom,y=e.as,b=y===void 0?"div":y,C=e.gapMode,S=Fe(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),R=m,N=zt([n,t]),E=x(x({},S),o);return i.createElement(i.Fragment,null,f&&i.createElement(R,{sideCar:je,removeScrollBar:u,shards:v,noRelative:g,noIsolation:w,inert:l,setCallbacks:a,allowPinchZoom:!!p,lockRef:n,gapMode:C}),c?i.cloneElement(i.Children.only(s),x(x({},E),{ref:N})):i.createElement(b,x({},E,{className:d,ref:N}),s))});Q.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Q.classNames={fullWidth:z,zeroRight:H};var en=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function tn(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=en();return t&&e.setAttribute("nonce",t),e}function nn(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function rn(e){var t=document.head||document.getElementsByTagName("head")[0];t.appendChild(e)}var on=function(){var e=0,t=null;return{add:function(n){e==0&&(t=tn())&&(nn(t,n),rn(t)),e++},remove:function(){e--,!e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}},an=function(){var e=on();return function(t,n){i.useEffect(function(){return e.add(t),function(){e.remove()}},[t&&n])}},We=function(){var e=an(),t=function(n){var r=n.styles,o=n.dynamic;return e(r,o),null};return t},sn={left:0,top:0,right:0,gap:0},ie=function(e){return parseInt(e||"",10)||0},cn=function(e){var t=window.getComputedStyle(document.body),n=t[e==="padding"?"paddingLeft":"marginLeft"],r=t[e==="padding"?"paddingTop":"marginTop"],o=t[e==="padding"?"paddingRight":"marginRight"];return[ie(n),ie(r),ie(o)]},un=function(e){if(e===void 0&&(e="margin"),typeof window>"u")return sn;var t=cn(e),n=document.documentElement.clientWidth,r=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,r-n+t[2]-t[0])}},ln=We(),j="data-scroll-locked",dn=function(e,t,n,r){var o=e.left,a=e.top,c=e.right,s=e.gap;return n===void 0&&(n="margin"),`
|
|
1
|
+
import{r as i,j as h,h as at,R as xe,i as it,n as st}from"./index-CkwQBzCl.js";function me(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function De(...e){return t=>{let n=!1;const r=e.map(o=>{const a=me(o,t);return!n&&typeof a=="function"&&(n=!0),a});if(n)return()=>{for(let o=0;o<r.length;o++){const a=r[o];typeof a=="function"?a():me(e[o],null)}}}}function I(...e){return i.useCallback(De(...e),e)}function Oe(e){const t=ct(e),n=i.forwardRef((r,o)=>{const{children:a,...c}=r,s=i.Children.toArray(a),d=s.find(lt);if(d){const u=d.props.children,f=s.map(v=>v===d?i.Children.count(u)>1?i.Children.only(null):i.isValidElement(u)?u.props.children:null:v);return h.jsx(t,{...c,ref:o,children:i.isValidElement(u)?i.cloneElement(u,void 0,f):null})}return h.jsx(t,{...c,ref:o,children:a})});return n.displayName=`${e}.Slot`,n}function ct(e){const t=i.forwardRef((n,r)=>{const{children:o,...a}=n;if(i.isValidElement(o)){const c=ft(o),s=dt(a,o.props);return o.type!==i.Fragment&&(s.ref=r?De(r,c):c),i.cloneElement(o,s)}return i.Children.count(o)>1?i.Children.only(null):null});return t.displayName=`${e}.SlotClone`,t}var ut=Symbol("radix.slottable");function lt(e){return i.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===ut}function dt(e,t){const n={...t};for(const r in t){const o=e[r],a=t[r];/^on[A-Z]/.test(r)?o&&a?n[r]=(...s)=>{const d=a(...s);return o(...s),d}:o&&(n[r]=o):r==="style"?n[r]={...o,...a}:r==="className"&&(n[r]=[o,a].filter(Boolean).join(" "))}return{...e,...n}}function ft(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var vt=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],D=vt.reduce((e,t)=>{const n=Oe(`Primitive.${t}`),r=i.forwardRef((o,a)=>{const{asChild:c,...s}=o,d=c?n:t;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),h.jsx(d,{...s,ref:a})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function mt(e,t){e&&at.flushSync(()=>e.dispatchEvent(t))}function ht(e,t){const n=i.createContext(t),r=a=>{const{children:c,...s}=a,d=i.useMemo(()=>s,Object.values(s));return h.jsx(n.Provider,{value:d,children:c})};r.displayName=e+"Provider";function o(a){const c=i.useContext(n);if(c)return c;if(t!==void 0)return t;throw new Error(`\`${a}\` must be used within \`${e}\``)}return[r,o]}function pt(e,t=[]){let n=[];function r(a,c){const s=i.createContext(c),d=n.length;n=[...n,c];const u=v=>{var y;const{scope:m,children:g,...w}=v,l=((y=m==null?void 0:m[e])==null?void 0:y[d])||s,p=i.useMemo(()=>w,Object.values(w));return h.jsx(l.Provider,{value:p,children:g})};u.displayName=a+"Provider";function f(v,m){var l;const g=((l=m==null?void 0:m[e])==null?void 0:l[d])||s,w=i.useContext(g);if(w)return w;if(c!==void 0)return c;throw new Error(`\`${v}\` must be used within \`${a}\``)}return[u,f]}const o=()=>{const a=n.map(c=>i.createContext(c));return function(s){const d=(s==null?void 0:s[e])||a;return i.useMemo(()=>({[`__scope${e}`]:{...s,[e]:d}}),[s,d])}};return o.scopeName=e,[r,gt(o,...t)]}function gt(...e){const t=e[0];if(e.length===1)return t;const n=()=>{const r=e.map(o=>({useScope:o(),scopeName:o.scopeName}));return function(a){const c=r.reduce((s,{useScope:d,scopeName:u})=>{const v=d(a)[`__scope${u}`];return{...s,...v}},{});return i.useMemo(()=>({[`__scope${t.scopeName}`]:c}),[c])}};return n.scopeName=t.scopeName,n}function B(e){const t=i.useRef(e);return i.useEffect(()=>{t.current=e}),i.useMemo(()=>(...n)=>{var r;return(r=t.current)==null?void 0:r.call(t,...n)},[])}var U=globalThis!=null&&globalThis.document?i.useLayoutEffect:()=>{};function A(e,t,{checkForDefaultPrevented:n=!0}={}){return function(o){if(e==null||e(o),n===!1||!o.defaultPrevented)return t==null?void 0:t(o)}}function yt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e);i.useEffect(()=>{const r=o=>{o.key==="Escape"&&n(o)};return t.addEventListener("keydown",r,{capture:!0}),()=>t.removeEventListener("keydown",r,{capture:!0})},[n,t])}var Et="DismissableLayer",ce="dismissableLayer.update",bt="dismissableLayer.pointerDownOutside",Ct="dismissableLayer.focusOutside",he,Ae=i.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Te=i.forwardRef((e,t)=>{const{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:o,onFocusOutside:a,onInteractOutside:c,onDismiss:s,...d}=e,u=i.useContext(Ae),[f,v]=i.useState(null),m=(f==null?void 0:f.ownerDocument)??(globalThis==null?void 0:globalThis.document),[,g]=i.useState({}),w=I(t,E=>v(E)),l=Array.from(u.layers),[p]=[...u.layersWithOutsidePointerEventsDisabled].slice(-1),y=l.indexOf(p),b=f?l.indexOf(f):-1,C=u.layersWithOutsidePointerEventsDisabled.size>0,S=b>=y,R=Rt(E=>{const T=E.target,L=[...u.branches].some(W=>W.contains(T));!S||L||(o==null||o(E),c==null||c(E),E.defaultPrevented||s==null||s())},m),N=Nt(E=>{const T=E.target;[...u.branches].some(W=>W.contains(T))||(a==null||a(E),c==null||c(E),E.defaultPrevented||s==null||s())},m);return yt(E=>{b===u.layers.size-1&&(r==null||r(E),!E.defaultPrevented&&s&&(E.preventDefault(),s()))},m),i.useEffect(()=>{if(f)return n&&(u.layersWithOutsidePointerEventsDisabled.size===0&&(he=m.body.style.pointerEvents,m.body.style.pointerEvents="none"),u.layersWithOutsidePointerEventsDisabled.add(f)),u.layers.add(f),pe(),()=>{n&&u.layersWithOutsidePointerEventsDisabled.size===1&&(m.body.style.pointerEvents=he)}},[f,m,n,u]),i.useEffect(()=>()=>{f&&(u.layers.delete(f),u.layersWithOutsidePointerEventsDisabled.delete(f),pe())},[f,u]),i.useEffect(()=>{const E=()=>g({});return document.addEventListener(ce,E),()=>document.removeEventListener(ce,E)},[]),h.jsx(D.div,{...d,ref:w,style:{pointerEvents:C?S?"auto":"none":void 0,...e.style},onFocusCapture:A(e.onFocusCapture,N.onFocusCapture),onBlurCapture:A(e.onBlurCapture,N.onBlurCapture),onPointerDownCapture:A(e.onPointerDownCapture,R.onPointerDownCapture)})});Te.displayName=Et;var St="DismissableLayerBranch",wt=i.forwardRef((e,t)=>{const n=i.useContext(Ae),r=i.useRef(null),o=I(t,r);return i.useEffect(()=>{const a=r.current;if(a)return n.branches.add(a),()=>{n.branches.delete(a)}},[n.branches]),h.jsx(D.div,{...e,ref:o})});wt.displayName=St;function Rt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1),o=i.useRef(()=>{});return i.useEffect(()=>{const a=s=>{if(s.target&&!r.current){let d=function(){Me(bt,n,u,{discrete:!0})};const u={originalEvent:s};s.pointerType==="touch"?(t.removeEventListener("click",o.current),o.current=d,t.addEventListener("click",o.current,{once:!0})):d()}else t.removeEventListener("click",o.current);r.current=!1},c=window.setTimeout(()=>{t.addEventListener("pointerdown",a)},0);return()=>{window.clearTimeout(c),t.removeEventListener("pointerdown",a),t.removeEventListener("click",o.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function Nt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1);return i.useEffect(()=>{const o=a=>{a.target&&!r.current&&Me(Ct,n,{originalEvent:a},{discrete:!1})};return t.addEventListener("focusin",o),()=>t.removeEventListener("focusin",o)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function pe(){const e=new CustomEvent(ce);document.dispatchEvent(e)}function Me(e,t,n,{discrete:r}){const o=n.originalEvent.target,a=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&o.addEventListener(e,t,{once:!0}),r?mt(o,a):o.dispatchEvent(a)}var Pt=xe[" useId ".trim().toString()]||(()=>{}),xt=0;function ee(e){const[t,n]=i.useState(Pt());return U(()=>{n(r=>r??String(xt++))},[e]),e||(t?`radix-${t}`:"")}var Dt=xe[" useInsertionEffect ".trim().toString()]||U;function Ot({prop:e,defaultProp:t,onChange:n=()=>{},caller:r}){const[o,a,c]=At({defaultProp:t,onChange:n}),s=e!==void 0,d=s?e:o;{const f=i.useRef(e!==void 0);i.useEffect(()=>{const v=f.current;v!==s&&console.warn(`${r} is changing from ${v?"controlled":"uncontrolled"} to ${s?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),f.current=s},[s,r])}const u=i.useCallback(f=>{var v;if(s){const m=Tt(f)?f(e):f;m!==e&&((v=c.current)==null||v.call(c,m))}else a(f)},[s,e,a,c]);return[d,u]}function At({defaultProp:e,onChange:t}){const[n,r]=i.useState(e),o=i.useRef(n),a=i.useRef(t);return Dt(()=>{a.current=t},[t]),i.useEffect(()=>{var c;o.current!==n&&((c=a.current)==null||c.call(a,n),o.current=n)},[n,o]),[n,r,a]}function Tt(e){return typeof e=="function"}var te="focusScope.autoFocusOnMount",ne="focusScope.autoFocusOnUnmount",ge={bubbles:!1,cancelable:!0},Mt="FocusScope",Ie=i.forwardRef((e,t)=>{const{loop:n=!1,trapped:r=!1,onMountAutoFocus:o,onUnmountAutoFocus:a,...c}=e,[s,d]=i.useState(null),u=B(o),f=B(a),v=i.useRef(null),m=I(t,l=>d(l)),g=i.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;i.useEffect(()=>{if(r){let l=function(C){if(g.paused||!s)return;const S=C.target;s.contains(S)?v.current=S:O(v.current,{select:!0})},p=function(C){if(g.paused||!s)return;const S=C.relatedTarget;S!==null&&(s.contains(S)||O(v.current,{select:!0}))},y=function(C){if(document.activeElement===document.body)for(const R of C)R.removedNodes.length>0&&O(s)};document.addEventListener("focusin",l),document.addEventListener("focusout",p);const b=new MutationObserver(y);return s&&b.observe(s,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",l),document.removeEventListener("focusout",p),b.disconnect()}}},[r,s,g.paused]),i.useEffect(()=>{if(s){Ee.add(g);const l=document.activeElement;if(!s.contains(l)){const y=new CustomEvent(te,ge);s.addEventListener(te,u),s.dispatchEvent(y),y.defaultPrevented||(It(jt(Le(s)),{select:!0}),document.activeElement===l&&O(s))}return()=>{s.removeEventListener(te,u),setTimeout(()=>{const y=new CustomEvent(ne,ge);s.addEventListener(ne,f),s.dispatchEvent(y),y.defaultPrevented||O(l??document.body,{select:!0}),s.removeEventListener(ne,f),Ee.remove(g)},0)}}},[s,u,f,g]);const w=i.useCallback(l=>{if(!n&&!r||g.paused)return;const p=l.key==="Tab"&&!l.altKey&&!l.ctrlKey&&!l.metaKey,y=document.activeElement;if(p&&y){const b=l.currentTarget,[C,S]=Lt(b);C&&S?!l.shiftKey&&y===S?(l.preventDefault(),n&&O(C,{select:!0})):l.shiftKey&&y===C&&(l.preventDefault(),n&&O(S,{select:!0})):y===b&&l.preventDefault()}},[n,r,g.paused]);return h.jsx(D.div,{tabIndex:-1,...c,ref:m,onKeyDown:w})});Ie.displayName=Mt;function It(e,{select:t=!1}={}){const n=document.activeElement;for(const r of e)if(O(r,{select:t}),document.activeElement!==n)return}function Lt(e){const t=Le(e),n=ye(t,e),r=ye(t.reverse(),e);return[n,r]}function Le(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:r=>{const o=r.tagName==="INPUT"&&r.type==="hidden";return r.disabled||r.hidden||o?NodeFilter.FILTER_SKIP:r.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t}function ye(e,t){for(const n of e)if(!_t(n,{upTo:t}))return n}function _t(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t!==void 0&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1}function Ft(e){return e instanceof HTMLInputElement&&"select"in e}function O(e,{select:t=!1}={}){if(e&&e.focus){const n=document.activeElement;e.focus({preventScroll:!0}),e!==n&&Ft(e)&&t&&e.select()}}var Ee=kt();function kt(){let e=[];return{add(t){const n=e[0];t!==n&&(n==null||n.pause()),e=be(e,t),e.unshift(t)},remove(t){var n;e=be(e,t),(n=e[0])==null||n.resume()}}}function be(e,t){const n=[...e],r=n.indexOf(t);return r!==-1&&n.splice(r,1),n}function jt(e){return e.filter(t=>t.tagName!=="A")}var Wt="Portal",_e=i.forwardRef((e,t)=>{var s;const{container:n,...r}=e,[o,a]=i.useState(!1);U(()=>a(!0),[]);const c=n||o&&((s=globalThis==null?void 0:globalThis.document)==null?void 0:s.body);return c?it.createPortal(h.jsx(D.div,{...r,ref:t}),c):null});_e.displayName=Wt;function Bt(e,t){return i.useReducer((n,r)=>t[n][r]??n,e)}var q=e=>{const{present:t,children:n}=e,r=Ut(t),o=typeof n=="function"?n({present:r.isPresent}):i.Children.only(n),a=I(r.ref,$t(o));return typeof n=="function"||r.isPresent?i.cloneElement(o,{ref:a}):null};q.displayName="Presence";function Ut(e){const[t,n]=i.useState(),r=i.useRef(null),o=i.useRef(e),a=i.useRef("none"),c=e?"mounted":"unmounted",[s,d]=Bt(c,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return i.useEffect(()=>{const u=V(r.current);a.current=s==="mounted"?u:"none"},[s]),U(()=>{const u=r.current,f=o.current;if(f!==e){const m=a.current,g=V(u);e?d("MOUNT"):g==="none"||(u==null?void 0:u.display)==="none"?d("UNMOUNT"):d(f&&m!==g?"ANIMATION_OUT":"UNMOUNT"),o.current=e}},[e,d]),U(()=>{if(t){let u;const f=t.ownerDocument.defaultView??window,v=g=>{const l=V(r.current).includes(CSS.escape(g.animationName));if(g.target===t&&l&&(d("ANIMATION_END"),!o.current)){const p=t.style.animationFillMode;t.style.animationFillMode="forwards",u=f.setTimeout(()=>{t.style.animationFillMode==="forwards"&&(t.style.animationFillMode=p)})}},m=g=>{g.target===t&&(a.current=V(r.current))};return t.addEventListener("animationstart",m),t.addEventListener("animationcancel",v),t.addEventListener("animationend",v),()=>{f.clearTimeout(u),t.removeEventListener("animationstart",m),t.removeEventListener("animationcancel",v),t.removeEventListener("animationend",v)}}else d("ANIMATION_END")},[t,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:i.useCallback(u=>{r.current=u?getComputedStyle(u):null,n(u)},[])}}function V(e){return(e==null?void 0:e.animationName)||"none"}function $t(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var re=0;function Vt(){i.useEffect(()=>{const e=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",e[0]??Ce()),document.body.insertAdjacentElement("beforeend",e[1]??Ce()),re++,()=>{re===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(t=>t.remove()),re--}},[])}function Ce(){const e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var x=function(){return x=Object.assign||function(t){for(var n,r=1,o=arguments.length;r<o;r++){n=arguments[r];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(t[a]=n[a])}return t},x.apply(this,arguments)};function Fe(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]]);return n}function Kt(e,t,n){if(n||arguments.length===2)for(var r=0,o=t.length,a;r<o;r++)(a||!(r in t))&&(a||(a=Array.prototype.slice.call(t,0,r)),a[r]=t[r]);return e.concat(a||Array.prototype.slice.call(t))}var H="right-scroll-bar-position",z="width-before-scroll-bar",Gt="with-scroll-bars-hidden",Xt="--removed-body-scroll-bar-size";function oe(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}function Yt(e,t){var n=i.useState(function(){return{value:e,callback:t,facade:{get current(){return n.value},set current(r){var o=n.value;o!==r&&(n.value=r,n.callback(r,o))}}}})[0];return n.callback=t,n.facade}var Ht=typeof window<"u"?i.useLayoutEffect:i.useEffect,Se=new WeakMap;function zt(e,t){var n=Yt(null,function(r){return e.forEach(function(o){return oe(o,r)})});return Ht(function(){var r=Se.get(n);if(r){var o=new Set(r),a=new Set(e),c=n.current;o.forEach(function(s){a.has(s)||oe(s,null)}),a.forEach(function(s){o.has(s)||oe(s,c)})}Se.set(n,e)},[e]),n}function Zt(e){return e}function qt(e,t){t===void 0&&(t=Zt);var n=[],r=!1,o={read:function(){if(r)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return n.length?n[n.length-1]:e},useMedium:function(a){var c=t(a,r);return n.push(c),function(){n=n.filter(function(s){return s!==c})}},assignSyncMedium:function(a){for(r=!0;n.length;){var c=n;n=[],c.forEach(a)}n={push:function(s){return a(s)},filter:function(){return n}}},assignMedium:function(a){r=!0;var c=[];if(n.length){var s=n;n=[],s.forEach(a),c=n}var d=function(){var f=c;c=[],f.forEach(a)},u=function(){return Promise.resolve().then(d)};u(),n={push:function(f){c.push(f),u()},filter:function(f){return c=c.filter(f),n}}}};return o}function Qt(e){e===void 0&&(e={});var t=qt(null);return t.options=x({async:!0,ssr:!1},e),t}var ke=function(e){var t=e.sideCar,n=Fe(e,["sideCar"]);if(!t)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var r=t.read();if(!r)throw new Error("Sidecar medium not found");return i.createElement(r,x({},n))};ke.isSideCarExport=!0;function Jt(e,t){return e.useMedium(t),ke}var je=Qt(),ae=function(){},Q=i.forwardRef(function(e,t){var n=i.useRef(null),r=i.useState({onScrollCapture:ae,onWheelCapture:ae,onTouchMoveCapture:ae}),o=r[0],a=r[1],c=e.forwardProps,s=e.children,d=e.className,u=e.removeScrollBar,f=e.enabled,v=e.shards,m=e.sideCar,g=e.noRelative,w=e.noIsolation,l=e.inert,p=e.allowPinchZoom,y=e.as,b=y===void 0?"div":y,C=e.gapMode,S=Fe(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),R=m,N=zt([n,t]),E=x(x({},S),o);return i.createElement(i.Fragment,null,f&&i.createElement(R,{sideCar:je,removeScrollBar:u,shards:v,noRelative:g,noIsolation:w,inert:l,setCallbacks:a,allowPinchZoom:!!p,lockRef:n,gapMode:C}),c?i.cloneElement(i.Children.only(s),x(x({},E),{ref:N})):i.createElement(b,x({},E,{className:d,ref:N}),s))});Q.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Q.classNames={fullWidth:z,zeroRight:H};var en=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function tn(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=en();return t&&e.setAttribute("nonce",t),e}function nn(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function rn(e){var t=document.head||document.getElementsByTagName("head")[0];t.appendChild(e)}var on=function(){var e=0,t=null;return{add:function(n){e==0&&(t=tn())&&(nn(t,n),rn(t)),e++},remove:function(){e--,!e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}},an=function(){var e=on();return function(t,n){i.useEffect(function(){return e.add(t),function(){e.remove()}},[t&&n])}},We=function(){var e=an(),t=function(n){var r=n.styles,o=n.dynamic;return e(r,o),null};return t},sn={left:0,top:0,right:0,gap:0},ie=function(e){return parseInt(e||"",10)||0},cn=function(e){var t=window.getComputedStyle(document.body),n=t[e==="padding"?"paddingLeft":"marginLeft"],r=t[e==="padding"?"paddingTop":"marginTop"],o=t[e==="padding"?"paddingRight":"marginRight"];return[ie(n),ie(r),ie(o)]},un=function(e){if(e===void 0&&(e="margin"),typeof window>"u")return sn;var t=cn(e),n=document.documentElement.clientWidth,r=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,r-n+t[2]-t[0])}},ln=We(),j="data-scroll-locked",dn=function(e,t,n,r){var o=e.left,a=e.top,c=e.right,s=e.gap;return n===void 0&&(n="margin"),`
|
|
2
2
|
.`.concat(Gt,` {
|
|
3
3
|
overflow: hidden `).concat(r,`;
|
|
4
4
|
padding-right: `).concat(s,"px ").concat(r,`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./index-
|
|
1
|
+
import{j as t}from"./index-CkwQBzCl.js";function r({segments:a,value:n,onChange:l,size:s="md"}){return t.jsx("div",{className:`seg seg-${s}`,role:"tablist",children:a.map(e=>t.jsxs("button",{role:"tab","aria-selected":e.value===n,className:`seg-btn${e.value===n?" seg-btn-active":""}`,onClick:()=>l(e.value),type:"button",children:[t.jsx("span",{children:e.label}),typeof e.count=="number"&&t.jsx("span",{className:"seg-count",children:e.count})]},e.value))})}export{r as S};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./index-
|
|
1
|
+
import{j as t}from"./index-CkwQBzCl.js";const x=({className:s,...a})=>t.jsx("table",{className:`tbl${s?" "+s:""}`,...a}),j=s=>t.jsx("thead",{...s}),c=s=>t.jsx("tbody",{...s}),e=s=>t.jsx("tr",{...s}),n=s=>t.jsx("th",{...s}),T=s=>t.jsx("td",{...s});export{x as T,j as a,e as b,n as c,c as d,T as e};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as p,m as A,r as l,X as m,j as e,s as N,v as k,y as E}from"./index-
|
|
1
|
+
import{g as p,m as A,r as l,X as m,j as e,s as N,v as k,y as E}from"./index-CkwQBzCl.js";/* empty css */import{S as T,A as z}from"./SettingCard-CRlStb6_.js";import{P as F}from"./page-header-BeUDGs-O.js";import{L as S}from"./lock-CqQvL12G.js";import{C as I}from"./circle-check-0COJnxUq.js";import{A as U}from"./activity-BhRPBZ3G.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as ie,r as a,j as e,v as F,K as L,p as ne}from"./index-BrVV0Kla.js";/* empty css */import{T as re,a as le,b as $,c as l,d as oe,e as o}from"./Table-B3EUgBi6.js";import{F as m}from"./FieldGroup-DE3u01Nu.js";import{P as z}from"./page-header-C0pnt4xz.js";import{M as O}from"./Modal-BJcFdiBP.js";import{S as ce}from"./shield-alert-BfoPJ8q_.js";import{P as g}from"./plus-BObE-_z6.js";import{T as de}from"./trash-2-CE5TRHb2.js";import{C as me}from"./check-BkT38An9.js";import{C as pe}from"./copy-CEcFYYHm.js";const H=["read","sessions","devices","admin"],M={"7d":"7 days","30d":"30 days","90d":"90 days","1y":"1 year",never:"No expiry"},he={"7d":7,"30d":30,"90d":90,"1y":365};function B(i){return i==="never"?null:new Date(Date.now()+he[i]*864e5).toISOString()}function U(i){if(!i)return"Never";const n=Date.now()-new Date(i).getTime();return n<6e4?"Just now":n<36e5?`${Math.floor(n/6e4)}m ago`:n<864e5?`${Math.floor(n/36e5)}h ago`:`${Math.floor(n/864e5)}d ago`}const Se=()=>{const{toast:i}=ie(),[n,v]=a.useState([]),[b,W]=a.useState([]),[Y,w]=a.useState(!0),[q,N]=a.useState(!1),[J,d]=a.useState(!1),[r,y]=a.useState(null),[k,C]=a.useState(null),[S,T]=a.useState(!1),[p,_]=a.useState(""),[j,A]=a.useState({read:!0,sessions:!0,devices:!1,admin:!1}),[I,R]=a.useState(300),[P,D]=a.useState(""),[h,E]=a.useState("30d"),[x,K]=a.useState(!1),X=s=>{var t;return s?((t=b.find(c=>c.id===s))==null?void 0:t.name)||s.slice(0,8):"Shared"},f=async()=>{w(!0);try{const[s,t]=await Promise.all([fetch("/xenon/api/apikeys",{credentials:"include"}),fetch("/xenon/api/teams",{credentials:"include"})]);if(s.status===403){N(!0),v([]);return}if(!s.ok)throw new Error(`HTTP ${s.status}`);v(await s.json()),t.ok&&W(await t.json()),N(!1)}catch(s){i(`Failed to load API keys: ${s.message}`,"error")}finally{w(!1)}};a.useEffect(()=>{f()},[]);const G=()=>{_(""),A({read:!0,sessions:!0,devices:!1,admin:!1}),R(300),D(""),E("30d")},Q=async()=>{const s=H.filter(t=>j[t]);if(!p.trim()){i("Key name is required","error");return}if(s.length===0){i("Select at least one scope","error");return}K(!0);try{const t=await fetch("/xenon/api/apikeys",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:p.trim(),scopes:s,rateLimit:I,teamId:P||null,expiresAt:B(h)})});if(!t.ok)throw new Error(`HTTP ${t.status}`);const c=await t.json();d(!1),G(),y({name:p.trim(),raw:c.key}),await f()}catch(t){i(`Create failed: ${t.message}`,"error")}finally{K(!1)}},V=async s=>{C(s);try{const t=await fetch(`/xenon/api/apikeys/${s}`,{method:"DELETE",credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);i("Key revoked","success"),await f()}catch(t){i(`Revoke failed: ${t.message}`,"error")}finally{C(null)}},Z=async s=>{try{await navigator.clipboard.writeText(s),T(!0),setTimeout(()=>T(!1),1500)}catch{i("Copy failed — select the text manually","error")}};if(Y)return e.jsxs("div",{className:"settings-loading",children:[e.jsx(F,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading API keys…"})]});if(q)return e.jsx("div",{className:"settings-container",children:e.jsx(z,{icon:ce,title:"API Keys",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to issue an admin key so you can manage access for other users."]})})});const ee=n.length,se=n.filter(s=>s.scopes.includes("admin")).length,te=n.filter(s=>s.lastUsedAt&&Date.now()-new Date(s.lastUsedAt).getTime()<864e5).length;return e.jsxs("div",{className:"settings-container",children:[e.jsx(z,{icon:L,title:"API Keys",subtitle:e.jsxs(e.Fragment,{children:["Issue scoped credentials for humans (dashboard login) and machines (CI, WebDriver clients via ",e.jsx("code",{children:"xenon:accessKey"}),"). Keys are shown only once at creation — copy the value before closing the dialog."]}),action:e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(g,{size:16}),e.jsx("span",{children:"Create new key"})]})}),e.jsxs("div",{className:"settings-content",children:[n.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ee}),e.jsx("div",{className:"stat-strip__label",children:"Total keys"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:se}),e.jsx("div",{className:"stat-strip__label",children:"Admin scope"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:te}),e.jsx("div",{className:"stat-strip__label",children:"Active in last 24h"})]})]}),n.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(L,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No API keys yet"}),e.jsx("p",{className:"empty-state__copy",children:"Issue your first key to authenticate WebDriver clients or CI pipelines. Keys are shown only once at creation — copy the value before closing the dialog."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(g,{size:16}),e.jsx("span",{children:"Create your first key"})]})]}):e.jsx("div",{className:"data-card",children:e.jsxs(re,{children:[e.jsx(le,{children:e.jsxs($,{children:[e.jsx(l,{children:"Name"}),e.jsx(l,{children:"Team"}),e.jsx(l,{children:"Scopes"}),e.jsx(l,{children:"Rate limit"}),e.jsx(l,{children:"Last used"}),e.jsx(l,{children:"Created"}),e.jsx(l,{children:"Expires"}),e.jsx(l,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(oe,{children:n.map(s=>e.jsxs($,{children:[e.jsxs(o,{children:[e.jsx("strong",{children:s.name}),e.jsx("div",{className:"row-meta-mono",children:s.id.slice(0,8)})]}),e.jsx(o,{children:e.jsx("span",{className:`pill-chip ${s.teamId?"pill-chip--team":"pill-chip--shared"}`,children:X(s.teamId)})}),e.jsx(o,{children:e.jsx("div",{className:"scope-chips",children:s.scopes.split(",").map(t=>{const c=t.trim(),ae=c==="admin";return e.jsx("span",{className:`pill-chip ${ae?"pill-chip--admin":"pill-chip--scope"}`,children:c},t)})})}),e.jsxs(o,{className:"row-mono",children:[s.rateLimit,"/min"]}),e.jsx(o,{className:"row-mono",children:U(s.lastUsedAt)}),e.jsx(o,{className:"row-mono",children:U(s.createdAt)}),e.jsx(o,{className:"row-mono",children:s.expiresAt?new Date(s.expiresAt).getTime()<=Date.now()?e.jsx("span",{style:{color:"var(--red)"},children:"expired"}):new Date(s.expiresAt).toLocaleDateString():"Never"}),e.jsx(o,{style:{textAlign:"right"},children:e.jsxs("button",{type:"button",className:"row-action row-action--danger",disabled:k===s.id,onClick:()=>{window.confirm(`Revoke "${s.name}"? Any client using this key will immediately fail.`)&&V(s.id)},children:[e.jsx(de,{size:13}),k===s.id?"Revoking…":"Revoke"]})})]},s.id))})]})})]}),e.jsx(O,{open:J,title:"Create API key",width:520,onClose:()=>d(!1),footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"reset-btn",onClick:()=>d(!1),disabled:x,children:"Cancel"}),e.jsxs("button",{className:"save-btn",onClick:Q,disabled:x,children:[x?e.jsx(F,{className:"animate-spin",size:18}):e.jsx(g,{size:18}),x?"Creating…":"Create key"]})]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column"},children:[e.jsx(m,{label:"Name",htmlFor:"apikey-name",children:e.jsx("input",{id:"apikey-name",type:"text",value:p,onChange:s=>_(s.target.value),placeholder:"alice-laptop, ci-main, etc.",style:u,autoFocus:!0})}),e.jsx(m,{label:"Scopes",description:e.jsxs(e.Fragment,{children:[e.jsx("code",{children:"admin"})," grants full access including API-key management."," ",e.jsx("code",{children:"sessions"})," is required for WebDriver ",e.jsx("code",{children:"xenon:accessKey"}),"."]}),children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:H.map(s=>e.jsxs("label",{style:xe,children:[e.jsx("input",{type:"checkbox",checked:j[s],onChange:t=>A({...j,[s]:t.target.checked})}),e.jsx("span",{children:s})]},s))})}),e.jsx(m,{label:"Rate limit (requests/min)",htmlFor:"apikey-ratelimit",children:e.jsx("input",{id:"apikey-ratelimit",type:"number",min:10,step:10,value:I,onChange:s=>R(parseInt(s.target.value)||300),style:u})}),e.jsx(m,{label:"Default team",description:e.jsxs(e.Fragment,{children:["Keys without a team can only reach shared-pool devices. Admins can override at session time via ",e.jsx("code",{children:"xenon:team"}),"."]}),htmlFor:"apikey-team",children:e.jsxs("select",{id:"apikey-team",value:P,onChange:s=>D(s.target.value),style:u,children:[e.jsx("option",{value:"",children:"No team (shared pool only)"}),b.map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))]})}),e.jsx(m,{label:"Expires after",description:h==="never"?"Key never expires. Rotate manually when needed.":`Key will stop working on ${new Date(B(h)).toLocaleDateString()}.`,htmlFor:"apikey-expiry",children:e.jsx("select",{id:"apikey-expiry",value:h,onChange:s=>E(s.target.value),style:u,children:Object.keys(M).map(s=>e.jsx("option",{value:s,children:M[s]},s))})})]})}),e.jsx(O,{open:!!r,title:r?`Key created: ${r.name}`:"",width:560,onClose:()=>y(null),closeOnOverlayClick:!1,footer:e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"save-btn",onClick:()=>r&&Z(r.raw),disabled:!r,children:[S?e.jsx(me,{size:18}):e.jsx(pe,{size:18}),S?"Copied":"Copy to clipboard"]}),e.jsx("button",{className:"reset-btn",onClick:()=>y(null),children:"I've saved it"})]}),children:r&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsxs("div",{style:{background:"var(--status-busy-bg)",border:"1px solid var(--status-busy-border)",borderRadius:6,padding:12,display:"flex",gap:8,alignItems:"flex-start"},children:[e.jsx(ne,{size:18,style:{flexShrink:0,marginTop:2}}),e.jsxs("div",{children:[e.jsx("strong",{children:"This key will not be shown again."})," Copy it now and store it in your password manager, CI secret store, or client config."]})]}),e.jsx("div",{style:{fontFamily:"monospace",padding:12,background:"rgba(0,0,0,0.3)",borderRadius:6,wordBreak:"break-all",fontSize:"0.9em"},children:r.raw})]})})]})},u={width:"100%",padding:"8px 12px",background:"rgba(0,0,0,0.3)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:6,color:"inherit",fontSize:"0.95em",boxSizing:"border-box"},xe={display:"flex",alignItems:"center",gap:6,padding:"6px 12px",background:"rgba(255,255,255,0.04)",borderRadius:6,cursor:"pointer",fontFamily:"monospace",fontSize:"0.9em"};export{Se as ApiKeys};
|
|
1
|
+
import{m as ie,r as a,j as e,v as F,K as L,p as ne}from"./index-CkwQBzCl.js";/* empty css */import{T as re,a as le,b as $,c as l,d as oe,e as o}from"./Table-CbmGiPJe.js";import{F as m}from"./FieldGroup-CGdoHDQ3.js";import{P as z}from"./page-header-BeUDGs-O.js";import{M as O}from"./Modal-OY-an2g6.js";import{S as ce}from"./shield-alert-Dm3Oz4Kc.js";import{P as g}from"./plus-BM5UAzcK.js";import{T as de}from"./trash-2-DUWA0N9n.js";import{C as me}from"./check-CV94AcJF.js";import{C as pe}from"./copy-DL_iD5Dh.js";const H=["read","sessions","devices","admin"],M={"7d":"7 days","30d":"30 days","90d":"90 days","1y":"1 year",never:"No expiry"},he={"7d":7,"30d":30,"90d":90,"1y":365};function B(i){return i==="never"?null:new Date(Date.now()+he[i]*864e5).toISOString()}function U(i){if(!i)return"Never";const n=Date.now()-new Date(i).getTime();return n<6e4?"Just now":n<36e5?`${Math.floor(n/6e4)}m ago`:n<864e5?`${Math.floor(n/36e5)}h ago`:`${Math.floor(n/864e5)}d ago`}const Se=()=>{const{toast:i}=ie(),[n,v]=a.useState([]),[b,W]=a.useState([]),[Y,w]=a.useState(!0),[q,N]=a.useState(!1),[J,d]=a.useState(!1),[r,y]=a.useState(null),[k,C]=a.useState(null),[S,T]=a.useState(!1),[p,_]=a.useState(""),[j,A]=a.useState({read:!0,sessions:!0,devices:!1,admin:!1}),[I,R]=a.useState(300),[P,D]=a.useState(""),[h,E]=a.useState("30d"),[x,K]=a.useState(!1),X=s=>{var t;return s?((t=b.find(c=>c.id===s))==null?void 0:t.name)||s.slice(0,8):"Shared"},f=async()=>{w(!0);try{const[s,t]=await Promise.all([fetch("/xenon/api/apikeys",{credentials:"include"}),fetch("/xenon/api/teams",{credentials:"include"})]);if(s.status===403){N(!0),v([]);return}if(!s.ok)throw new Error(`HTTP ${s.status}`);v(await s.json()),t.ok&&W(await t.json()),N(!1)}catch(s){i(`Failed to load API keys: ${s.message}`,"error")}finally{w(!1)}};a.useEffect(()=>{f()},[]);const G=()=>{_(""),A({read:!0,sessions:!0,devices:!1,admin:!1}),R(300),D(""),E("30d")},Q=async()=>{const s=H.filter(t=>j[t]);if(!p.trim()){i("Key name is required","error");return}if(s.length===0){i("Select at least one scope","error");return}K(!0);try{const t=await fetch("/xenon/api/apikeys",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:p.trim(),scopes:s,rateLimit:I,teamId:P||null,expiresAt:B(h)})});if(!t.ok)throw new Error(`HTTP ${t.status}`);const c=await t.json();d(!1),G(),y({name:p.trim(),raw:c.key}),await f()}catch(t){i(`Create failed: ${t.message}`,"error")}finally{K(!1)}},V=async s=>{C(s);try{const t=await fetch(`/xenon/api/apikeys/${s}`,{method:"DELETE",credentials:"include"});if(!t.ok)throw new Error(`HTTP ${t.status}`);i("Key revoked","success"),await f()}catch(t){i(`Revoke failed: ${t.message}`,"error")}finally{C(null)}},Z=async s=>{try{await navigator.clipboard.writeText(s),T(!0),setTimeout(()=>T(!1),1500)}catch{i("Copy failed — select the text manually","error")}};if(Y)return e.jsxs("div",{className:"settings-loading",children:[e.jsx(F,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading API keys…"})]});if(q)return e.jsx("div",{className:"settings-container",children:e.jsx(z,{icon:ce,title:"API Keys",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to issue an admin key so you can manage access for other users."]})})});const ee=n.length,se=n.filter(s=>s.scopes.includes("admin")).length,te=n.filter(s=>s.lastUsedAt&&Date.now()-new Date(s.lastUsedAt).getTime()<864e5).length;return e.jsxs("div",{className:"settings-container",children:[e.jsx(z,{icon:L,title:"API Keys",subtitle:e.jsxs(e.Fragment,{children:["Issue scoped credentials for humans (dashboard login) and machines (CI, WebDriver clients via ",e.jsx("code",{children:"xenon:accessKey"}),"). Keys are shown only once at creation — copy the value before closing the dialog."]}),action:e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(g,{size:16}),e.jsx("span",{children:"Create new key"})]})}),e.jsxs("div",{className:"settings-content",children:[n.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:ee}),e.jsx("div",{className:"stat-strip__label",children:"Total keys"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:se}),e.jsx("div",{className:"stat-strip__label",children:"Admin scope"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:te}),e.jsx("div",{className:"stat-strip__label",children:"Active in last 24h"})]})]}),n.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(L,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No API keys yet"}),e.jsx("p",{className:"empty-state__copy",children:"Issue your first key to authenticate WebDriver clients or CI pipelines. Keys are shown only once at creation — copy the value before closing the dialog."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(g,{size:16}),e.jsx("span",{children:"Create your first key"})]})]}):e.jsx("div",{className:"data-card",children:e.jsxs(re,{children:[e.jsx(le,{children:e.jsxs($,{children:[e.jsx(l,{children:"Name"}),e.jsx(l,{children:"Team"}),e.jsx(l,{children:"Scopes"}),e.jsx(l,{children:"Rate limit"}),e.jsx(l,{children:"Last used"}),e.jsx(l,{children:"Created"}),e.jsx(l,{children:"Expires"}),e.jsx(l,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(oe,{children:n.map(s=>e.jsxs($,{children:[e.jsxs(o,{children:[e.jsx("strong",{children:s.name}),e.jsx("div",{className:"row-meta-mono",children:s.id.slice(0,8)})]}),e.jsx(o,{children:e.jsx("span",{className:`pill-chip ${s.teamId?"pill-chip--team":"pill-chip--shared"}`,children:X(s.teamId)})}),e.jsx(o,{children:e.jsx("div",{className:"scope-chips",children:s.scopes.split(",").map(t=>{const c=t.trim(),ae=c==="admin";return e.jsx("span",{className:`pill-chip ${ae?"pill-chip--admin":"pill-chip--scope"}`,children:c},t)})})}),e.jsxs(o,{className:"row-mono",children:[s.rateLimit,"/min"]}),e.jsx(o,{className:"row-mono",children:U(s.lastUsedAt)}),e.jsx(o,{className:"row-mono",children:U(s.createdAt)}),e.jsx(o,{className:"row-mono",children:s.expiresAt?new Date(s.expiresAt).getTime()<=Date.now()?e.jsx("span",{style:{color:"var(--red)"},children:"expired"}):new Date(s.expiresAt).toLocaleDateString():"Never"}),e.jsx(o,{style:{textAlign:"right"},children:e.jsxs("button",{type:"button",className:"row-action row-action--danger",disabled:k===s.id,onClick:()=>{window.confirm(`Revoke "${s.name}"? Any client using this key will immediately fail.`)&&V(s.id)},children:[e.jsx(de,{size:13}),k===s.id?"Revoking…":"Revoke"]})})]},s.id))})]})})]}),e.jsx(O,{open:J,title:"Create API key",width:520,onClose:()=>d(!1),footer:e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"reset-btn",onClick:()=>d(!1),disabled:x,children:"Cancel"}),e.jsxs("button",{className:"save-btn",onClick:Q,disabled:x,children:[x?e.jsx(F,{className:"animate-spin",size:18}):e.jsx(g,{size:18}),x?"Creating…":"Create key"]})]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column"},children:[e.jsx(m,{label:"Name",htmlFor:"apikey-name",children:e.jsx("input",{id:"apikey-name",type:"text",value:p,onChange:s=>_(s.target.value),placeholder:"alice-laptop, ci-main, etc.",style:u,autoFocus:!0})}),e.jsx(m,{label:"Scopes",description:e.jsxs(e.Fragment,{children:[e.jsx("code",{children:"admin"})," grants full access including API-key management."," ",e.jsx("code",{children:"sessions"})," is required for WebDriver ",e.jsx("code",{children:"xenon:accessKey"}),"."]}),children:e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:8},children:H.map(s=>e.jsxs("label",{style:xe,children:[e.jsx("input",{type:"checkbox",checked:j[s],onChange:t=>A({...j,[s]:t.target.checked})}),e.jsx("span",{children:s})]},s))})}),e.jsx(m,{label:"Rate limit (requests/min)",htmlFor:"apikey-ratelimit",children:e.jsx("input",{id:"apikey-ratelimit",type:"number",min:10,step:10,value:I,onChange:s=>R(parseInt(s.target.value)||300),style:u})}),e.jsx(m,{label:"Default team",description:e.jsxs(e.Fragment,{children:["Keys without a team can only reach shared-pool devices. Admins can override at session time via ",e.jsx("code",{children:"xenon:team"}),"."]}),htmlFor:"apikey-team",children:e.jsxs("select",{id:"apikey-team",value:P,onChange:s=>D(s.target.value),style:u,children:[e.jsx("option",{value:"",children:"No team (shared pool only)"}),b.map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))]})}),e.jsx(m,{label:"Expires after",description:h==="never"?"Key never expires. Rotate manually when needed.":`Key will stop working on ${new Date(B(h)).toLocaleDateString()}.`,htmlFor:"apikey-expiry",children:e.jsx("select",{id:"apikey-expiry",value:h,onChange:s=>E(s.target.value),style:u,children:Object.keys(M).map(s=>e.jsx("option",{value:s,children:M[s]},s))})})]})}),e.jsx(O,{open:!!r,title:r?`Key created: ${r.name}`:"",width:560,onClose:()=>y(null),closeOnOverlayClick:!1,footer:e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"save-btn",onClick:()=>r&&Z(r.raw),disabled:!r,children:[S?e.jsx(me,{size:18}):e.jsx(pe,{size:18}),S?"Copied":"Copy to clipboard"]}),e.jsx("button",{className:"reset-btn",onClick:()=>y(null),children:"I've saved it"})]}),children:r&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsxs("div",{style:{background:"var(--status-busy-bg)",border:"1px solid var(--status-busy-border)",borderRadius:6,padding:12,display:"flex",gap:8,alignItems:"flex-start"},children:[e.jsx(ne,{size:18,style:{flexShrink:0,marginTop:2}}),e.jsxs("div",{children:[e.jsx("strong",{children:"This key will not be shown again."})," Copy it now and store it in your password manager, CI secret store, or client config."]})]}),e.jsx("div",{style:{fontFamily:"monospace",padding:12,background:"rgba(0,0,0,0.3)",borderRadius:6,wordBreak:"break-all",fontSize:"0.9em"},children:r.raw})]})})]})},u={width:"100%",padding:"8px 12px",background:"rgba(0,0,0,0.3)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:6,color:"inherit",fontSize:"0.95em",boxSizing:"border-box"},xe={display:"flex",alignItems:"center",gap:6,padding:"6px 12px",background:"rgba(255,255,255,0.04)",borderRadius:6,cursor:"pointer",fontFamily:"monospace",fontSize:"0.9em"};export{Se as ApiKeys};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as x,j as e,m as q,r,X as l,S,o as W,v as X,n as H}from"./index-
|
|
1
|
+
import{g as x,j as e,m as q,r,X as l,S,o as W,v as X,n as H}from"./index-CkwQBzCl.js";import{c as K,a as Z,P as J,B as D,U as Q,T as ee}from"./button-wz7ra9cW.js";import{P as se}from"./page-header-BeUDGs-O.js";import{C as ae}from"./check-CV94AcJF.js";import{C as te}from"./copy-DL_iD5Dh.js";import{Z as re}from"./zap-D8JQHaNH.js";import{D as ie}from"./download-aeG6Qqs8.js";import{T as ne}from"./trash-2-DUWA0N9n.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.apps-container{display:flex;flex-direction:column;height:100%;width:100%}.apps-registry-content{flex:1;overflow-y:auto;padding:var(--space-4) 24px;background:var(--bg)}.registry-table-header{display:grid;grid-template-columns:3fr 1fr 1fr 1.5fr 1.5fr;padding:12px 24px;border-bottom:2px solid var(--border);color:var(--text-dim);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;background:#0003;font-family:JetBrains Mono,monospace}.registry-list{display:flex;flex-direction:column}.artifact-row{display:grid;grid-template-columns:3fr 1fr 1fr 1.5fr 1.5fr;align-items:center;padding:12px 24px;background:#0000001a;border-bottom:1px solid var(--border);transition:all .2s ease;position:relative}.artifact-row:hover{background:#ffffff05}.artifact-row.active{background:#00ff880d;border-left:3px solid var(--green)}.col-app-info{display:flex;align-items:center;gap:16px;min-width:0}.app-platform-badge{width:32px;height:32px;background:#0006;border:1px solid var(--border);border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--text-dim)}.artifact-row.android .app-platform-badge{color:var(--green);border-color:#0f83}.artifact-row.ios .app-platform-badge{color:var(--text);border-color:var(--border)}.app-text-block{display:flex;flex-direction:column;min-width:0}.app-display-name{font-size:13px;font-weight:700;color:var(--text);font-family:Outfit,sans-serif;margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase}.app-package-id{font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-dim);opacity:.8;display:flex;align-items:center;gap:6px}.col-version{font-family:JetBrains Mono,monospace;font-size:11px;color:var(--green);font-weight:600}.col-size{font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-muted)}.col-timestamp{font-size:11px;color:var(--text-dim);font-family:JetBrains Mono,monospace;text-transform:uppercase}.col-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px}.instant-deploy-trigger{height:28px;background:#00ff880d;border:1px solid var(--green);border-radius:6px;padding:0 12px;display:flex;align-items:center;gap:8px;color:var(--green);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;transition:all .2s;cursor:pointer}.instant-deploy-trigger:hover:not(:disabled){background:var(--green);color:var(--bg);box-shadow:0 0 20px #0f83}.utility-icon-btn{width:28px;height:28px;background:#0000004d;border:1px solid var(--border);border-radius:6px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:all .2s}.utility-icon-btn:hover{border-color:var(--border);color:var(--text)}.utility-icon-btn.danger:hover{color:var(--status-error-fg)}.device-explorer-header-container{display:flex;justify-content:space-between;align-items:center;padding:12px 24px;background:#0f0f1a66;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid var(--border);z-index:100;gap:16px;flex-wrap:wrap}.device-explorer-header-left-container{display:flex;align-items:center;gap:24px;flex:1;min-width:0;flex-wrap:wrap}.device-explorer-header-right-container{display:flex;align-items:center;gap:12px}.device-explorer-header-filter-count{margin-left:8px}@media (max-width: 900px){.device-explorer-header-container{flex-direction:column;align-items:stretch;padding:12px 16px}.device-explorer-header-left-container{flex-direction:column;align-items:stretch;gap:12px}.device-explorer-header-left-container>*{width:100%;min-width:0}.device-explorer-header-right-container{justify-content:flex-end;flex-wrap:wrap}}.icon-btn-secondary{width:32px;height:32px;background:#ffffff08;border:1px solid var(--border);border-radius:6px;display:flex;align-items:center;justify-content:center;color:var(--text-dim);cursor:pointer;transition:all .2s ease}.icon-btn-secondary:hover{background:#ffffff14;color:var(--text);border-color:var(--border)}.deployment-flyout{position:absolute;top:50%;padding:6px;right:180px;transform:translateY(-50%);background:var(--surface);border:1px solid var(--green);border-radius:8px;box-shadow:0 10px 40px #0009;z-index:110;display:flex;gap:4px;animation:slideInRight .2s cubic-bezier(.16,1,.3,1)}@keyframes slideInRight{0%{opacity:0;transform:translateY(-50%) translate(10px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.target-device-select{height:32px;background:#00000040;border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:11px;font-weight:600;padding:0 12px;min-width:280px;outline:none;cursor:pointer;transition:all .2s ease;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center}.target-device-select:hover{border-color:var(--green);background-color:#0006}.target-device-select option{background:var(--surface);color:var(--text);padding:8px}.target-device-select.empty{display:flex;align-items:center;justify-content:center;padding:0 20px;height:32px;font-style:italic;opacity:.5;font-size:11px}.deploy-actions-group{display:flex;align-items:center;gap:6px}.confirm-deploy-btn{width:32px;height:32px;background:var(--green);border:none;border-radius:6px;display:flex;align-items:center;justify-content:center;color:#000;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.confirm-deploy-btn:hover:not(:disabled){background:var(--green-dim);transform:scale(1.05);box-shadow:0 0 15px var(--accent-subtle)}.confirm-deploy-btn:disabled{background:#ffffff1a;color:#fff3;cursor:not-allowed}.upload-overlay-technical{position:fixed;top:0;right:0;bottom:0;left:0;background:#020617d9;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);z-index:2000;display:flex;align-items:center;justify-content:center}.upload-card-technical{width:420px;background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:40px;text-align:center;box-shadow:0 30px 60px #0009}.processing-loader{width:40px;height:40px;border:2px solid rgba(34,197,94,.1);border-top-color:var(--green);border-radius:50%;margin:0 auto 20px;animation:spin 1s linear infinite}.empty-registry-technical{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:100px 20px;text-align:center;max-width:600px;margin:0 auto}.empty-icon-container{width:100px;height:100px;background:radial-gradient(circle,rgba(59,130,246,.1) 0%,transparent 70%);display:flex;align-items:center;justify-content:center;border-radius:50%;margin-bottom:24px}.empty-title{font-size:28px;font-weight:800;color:var(--text);margin-bottom:16px;letter-spacing:-.02em}.empty-description{font-size:14px;line-height:1.6;color:var(--text-muted);margin-bottom:40px}.empty-description code{background:#3b82f61a;padding:2px 6px;border-radius:4px;font-weight:600}.upload-trigger-massive{cursor:pointer;display:block}.massive-upload-content{display:flex;flex-direction:column;align-items:center;padding:30px 60px;background:var(--surface);border:1px solid var(--green);box-shadow:0 0 15px #00ff881a;border-radius:8px;color:var(--green);font-weight:700;font-size:16px;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 0 0 transparent}.massive-upload-content:hover{background:#3b82f60d;transform:translateY(-4px);box-shadow:0 10px 30px #3b82f626;border-style:solid}.massive-upload-content svg{transition:transform .3s ease}.massive-upload-content:hover svg{transform:translateY(-4px) scale(1.1)}.copy-hint{cursor:pointer;opacity:.4;transition:opacity .2s}.copy-hint:hover{opacity:1}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (min-width: 1401px){.apps-registry-content{padding:0 24px 24px}}.badge-base{display:inline-flex;align-items:center;gap:6px;border-radius:6px;border:1px solid transparent;padding:2px 8px;font-size:11px;font-weight:800;transition:all .2s ease;white-space:nowrap;text-transform:uppercase;letter-spacing:.05em;font-family:JetBrains Mono,monospace}.badge-variant-default{background:#0000004d;color:var(--text-dim);border-color:var(--border)}.badge-variant-success{background:#00ff880d;color:var(--green);border-color:#0f83}.badge-variant-warning{background:#ffc1070d;color:#ffc107;border-color:#ffc10733}.badge-variant-error{background:#ff4d4d0d;color:#ff4d4d;border-color:#ff4d4d33}.badge-variant-secondary{background:var(--surface);color:var(--text);border-color:var(--border)}.badge-variant-outline{background:transparent;color:var(--text-dim);border:1px solid var(--border)}.badge-variant-outline:hover{color:var(--text);border-color:var(--text-muted)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{g as F,j as e,o as E,k as
|
|
1
|
+
import{g as F,j as e,o as E,k as w,T as O,S as M,r as b,u as P,c as z,m as G,X}from"./index-CkwQBzCl.js";import{f as B,s as R,b as T,d as q,p as H,o as Q,S as V,h as J,a as K,u as W}from"./status-pill-outline-3FA5raqd.js";import{A as Y}from"./activity-BhRPBZ3G.js";import{C as Z}from"./circle-x-DGNoObyH.js";import{C as ee}from"./circle-check-0COJnxUq.js";import{C as te}from"./clock-DwtXByAH.js";import{D as se}from"./download-aeG6Qqs8.js";import{C as re}from"./chevron-right-_iIkyWqd.js";import{T as ae,M as ne}from"./tablet-CWU6hxZF.js";import"./useSocket-lsg6f_Dn.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const le=[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]],oe=F("refresh-ccw",le),ie={neutral:"bg-[var(--surface-2)] text-[var(--text-muted)] border-[var(--border)]",green:"bg-[var(--green)]/15 text-[var(--green)] border-[var(--green)]/30",red:"bg-[var(--red)]/15 text-[var(--red)] border-[var(--red)]/30",amber:"bg-[var(--amber)]/15 text-[var(--amber)] border-[var(--amber)]/30"},w=({value:t,tone:s="neutral"})=>e.jsx("span",{className:`inline-flex items-center justify-center min-w-[18px] h-[18px] px-1.5 rounded-full border text-[10px] font-mono font-medium ${ie[s]}`,children:t}),de={passed:{Icon:ee,label:"PASSED",tint:"text-[var(--green)]"},failed:{Icon:Z,label:"FAILED",tint:"text-[var(--red)]"},running:{Icon:Y,label:"RUNNING",tint:"text-[var(--amber)]"}},C=({kind:t,value:s})=>{const{Icon:r,label:i,tint:c}=de[t];return e.jsxs("div",{className:"flex-1 flex flex-col items-center gap-1 py-2 rounded-md border border-[var(--border)] bg-[var(--bg)]",children:[e.jsx(r,{className:`h-3.5 w-3.5 ${c}`}),e.jsx("span",{className:`text-[9px] font-mono font-semibold tracking-wider ${c}`,children:i}),e.jsx("span",{className:"text-sm font-semibold text-[var(--text)] tabular-nums",children:s})]})},I={all:"All time","24h":"Last 24 hours","7d":"Last 7 days","30d":"Last 30 days"},ce=({builds:t,selectedBuildId:s,onSelect:r,search:i,onSearchChange:c,timeFilter:x,onTimeFilterChange:m})=>{const l=t.filter(a=>{const d=(a.name??"")+" "+a.id;if(i&&!d.toLowerCase().includes(i.toLowerCase()))return!1;if(x!=="all"){const n={"24h":864e5,"7d":6048e5,"30d":2592e6},p=Date.parse(String(a.createdAt));if(!Number.isFinite(p)||Date.now()-p>n[x])return!1}return!0}),o=l.reduce((a,d)=>(a.passed+=d.passedCount||0,a.failed+=d.failedCount||0,a.running+=d.runningCount||0,a),{passed:0,failed:0,running:0});return e.jsxs("aside",{className:"w-[280px] shrink-0 border-r border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsxs("div",{className:"p-3 space-y-2 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"relative",children:[e.jsx(E,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("input",{type:"text",value:i,onChange:a=>c(a.target.value),placeholder:"Find builds…",className:"w-full h-8 pl-8 pr-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text)] placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--border-strong)]"})]}),e.jsx("select",{value:x,onChange:a=>m(a.target.value),className:"w-full h-8 px-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text-muted)]",children:Object.keys(I).map(a=>e.jsx("option",{value:a,children:I[a]},a))})]}),e.jsxs("div",{className:"p-3 flex items-stretch gap-2 border-b border-[var(--border)]",children:[e.jsx(C,{kind:"passed",value:o.passed}),e.jsx(C,{kind:"failed",value:o.failed}),e.jsx(C,{kind:"running",value:o.running})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto",children:[l.length===0&&e.jsx("div",{className:"px-4 py-8 text-center text-xs text-[var(--text-dim)]",children:"No builds match."}),l.map(a=>{const d=a.id===s;return e.jsxs("button",{type:"button",onClick:()=>r(a.id),className:`w-full text-left relative px-4 py-3 border-b border-[var(--border)] transition-colors ${d?"bg-[var(--surface-2)]":"hover:bg-[var(--surface-2)]/60"}`,children:[d&&e.jsx("span",{className:"absolute left-0 top-2 bottom-2 w-[3px] rounded-r bg-[var(--green)]"}),e.jsx("div",{className:"text-xs font-semibold text-[var(--text)] truncate",children:a.name||"Unnamed build"}),e.jsxs("div",{className:"mt-1 flex items-center gap-1 font-mono text-[9px] text-[var(--text-dim)]",children:[e.jsx(te,{className:"h-3 w-3"}),B(a.createdAt)]}),e.jsxs("div",{className:"mt-1.5 flex items-center gap-1.5",children:[a.passedCount>0&&e.jsx(w,{value:a.passedCount,tone:"green"}),a.failedCount>0&&e.jsx(w,{value:a.failedCount,tone:"red"}),a.runningCount>0&&e.jsx(w,{value:a.runningCount,tone:"amber"}),a.sessionCount===0&&e.jsx("span",{className:"text-[10px] font-mono text-[var(--text-dim)]",children:"empty"})]}),e.jsx("div",{className:"mt-1 font-mono text-[9px] text-[var(--text-dim)] truncate",children:R(a.id,10,4)})]},a.id)})]})]})},xe={neutral:"bg-[var(--text-dim)]",green:"bg-[var(--green)]",red:"bg-[var(--red)]",amber:"bg-[var(--amber)]",blue:"bg-[var(--blue)]"},N=({label:t,count:s,active:r,onClick:i,tone:c="neutral",bullet:x=!0})=>e.jsxs("button",{type:"button",onClick:i,"aria-pressed":r,className:`inline-flex items-center gap-2 h-8 px-3 rounded-md border text-[11px] font-semibold uppercase tracking-wider transition-colors cursor-pointer ${r?"bg-[var(--surface-2)] border-[var(--border-strong)] text-[var(--text)]":"bg-transparent border-transparent text-[var(--text-muted)] hover:text-[var(--text)] hover:bg-[var(--surface-2)]/50"}`,children:[x&&c!=="neutral"&&e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${xe[c]}`}),e.jsx("span",{children:t}),typeof s=="number"&&e.jsx("span",{className:"font-mono text-[10px] text-[var(--text-dim)]",children:s})]}),ue=({sessions:t,active:s,onChange:r,search:i,onSearchChange:c,totalMatching:x,totalUnfiltered:m})=>{const l=T(t);return e.jsxs("div",{className:"bg-[var(--surface)]",children:[e.jsxs("div",{className:"flex items-center gap-1.5 px-4 pt-3 pb-2",children:[e.jsx(N,{label:"ALL",count:l.all,active:s==="all",onClick:()=>r("all"),tone:"neutral",bullet:!1}),e.jsx(N,{label:"PASSED",count:l.passed,active:s==="passed",onClick:()=>r("passed"),tone:"green"}),e.jsx(N,{label:"FAILED",count:l.failed,active:s==="failed",onClick:()=>r("failed"),tone:"red"}),e.jsx(N,{label:"RUNNING",count:l.running,active:s==="running",onClick:()=>r("running"),tone:"amber"})]}),e.jsxs("div",{className:"flex items-center gap-4 px-4 pb-3 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"relative flex-1 max-w-xl",children:[e.jsx(E,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("input",{type:"text",value:i,onChange:o=>c(o.target.value),placeholder:"Search sessions by ID, name, or device…",className:"w-full h-8 pl-8 pr-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text)] placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--border-strong)]"})]}),e.jsxs("span",{className:"text-[10px] font-mono text-[var(--text-dim)] whitespace-nowrap",children:[x," of ",m," sessions"]})]})]})};function me(t){return(t.split("-")[0]||t).slice(0,8).toUpperCase()}const pe=({build:t,failedCount:s,selectedCount:r,onRetryFailed:i,onExport:c})=>{const x=s>0||r>0,[m,l]=y.useState(!1),o=y.useRef(null);y.useEffect(()=>{const d=n=>{o.current&&!o.current.contains(n.target)&&l(!1)};return document.addEventListener("mousedown",d),()=>document.removeEventListener("mousedown",d)},[]);const a=x?`Retry ${r||s} session${(r||s)===1?"":"s"}`:"No failed sessions to retry";return e.jsxs("header",{className:"flex items-start justify-between gap-4 px-4 py-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 text-[10px] uppercase tracking-widest text-[var(--text-dim)]",children:[e.jsx("span",{children:"Build"}),e.jsxs("span",{className:"font-mono text-[var(--green)]",title:t.id,children:["#",me(t.id)]})]}),e.jsx("h1",{className:"mt-0.5 text-sm font-semibold text-[var(--text)]",children:t.name||"Unnamed build"})]}),e.jsxs("div",{className:"flex items-center gap-2",ref:o,children:[e.jsxs("button",{type:"button",onClick:i,disabled:!x,title:a,className:"inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:[e.jsx(oe,{className:"h-3.5 w-3.5"}),"Retry failed"]}),e.jsxs("div",{className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>l(d=>!d),className:"inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors",children:[e.jsx(se,{className:"h-3.5 w-3.5"}),"Export"]}),m&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 w-40 rounded-md border border-[var(--border)] bg-[var(--surface)] shadow-lg overflow-hidden z-20",children:[e.jsx("button",{type:"button",onClick:()=>{l(!1),c("json")},className:"w-full text-left px-3 py-2 text-xs text-[var(--text)] hover:bg-[var(--surface-2)]",children:"Export as JSON"}),e.jsx("button",{type:"button",onClick:()=>{l(!1),c("csv")},className:"w-full text-left px-3 py-2 text-xs text-[var(--text)] hover:bg-[var(--surface-2)]",children:"Export as CSV"})]})]})]})]})};function fe({platform:t}){const s=(t||"").toLowerCase();return s.includes("tv")?e.jsx(O,{className:"h-3.5 w-3.5"}):s.includes("pad")||s.includes("tablet")?e.jsx(ae,{className:"h-3.5 w-3.5"}):s.includes("android")||s.includes("ios")?e.jsx(M,{className:"h-3.5 w-3.5"}):e.jsx(ne,{className:"h-3.5 w-3.5"})}function he(t){return t==="running"?{label:"RUNNING",tone:"running"}:t==="failed"?{label:"FAILED",tone:"failed"}:t==="ended"||t==="passed"?{label:"PASSED",tone:"passed"}:{label:t.toUpperCase(),tone:"offline"}}const ve=({session:t,selected:s,onToggleSelect:r,onOpen:i})=>{const c=t.status==="failed",x=he(t.status),m=q(t),l=c&&t.failure_reason?t.failure_reason:t.name??"";return e.jsxs("tr",{onClick:i,className:"group border-b border-[var(--border)] hover:bg-[var(--surface-2)] cursor-pointer transition-colors align-top",children:[e.jsx("td",{className:"px-3 py-3",onClick:o=>o.stopPropagation(),children:e.jsx("input",{type:"checkbox",checked:s,onChange:r,"aria-label":`Select session ${t.id}`})}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsxs("div",{className:"font-mono text-xs text-[var(--green)]",title:t.id,children:["#",R(t.id,14,4)]}),l&&e.jsx("div",{className:"mt-0.5 text-[11px] text-[var(--text-muted)] truncate max-w-[420px]",title:l,children:l})]}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs text-[var(--text)]",children:[e.jsx(fe,{platform:t.device_platform}),e.jsx("span",{className:"truncate max-w-[160px]",children:m})]}),t.node_id&&e.jsxs("div",{className:"mt-0.5 font-mono text-[10px] text-[var(--text-dim)]",children:["node-",t.node_id]})]}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsx("div",{className:"text-xs text-[var(--text)]",children:H(t)}),t.device_version&&e.jsx("div",{className:"mt-0.5 font-mono text-[10px] text-[var(--text-dim)]",children:Q(t)})]}),e.jsx("td",{className:"px-3 py-3",children:e.jsx(V,{label:x.label,tone:x.tone})}),e.jsx("td",{className:"px-3 py-3 font-mono text-[11px] text-[var(--text-muted)] whitespace-nowrap",children:B(t.startTime)}),e.jsx("td",{className:"px-3 py-3 font-mono text-[11px] text-[var(--text-muted)] whitespace-nowrap text-right",children:J(K(t))}),e.jsx("td",{className:"px-3 py-3 text-right",children:e.jsx(re,{className:"inline h-4 w-4 text-[var(--text-dim)] group-hover:text-[var(--text)]"})})]})};function be(t,s){return s==="all"?!0:s==="passed"?t.status==="ended"||t.status==="passed":s==="failed"?t.status==="failed":s==="running"?t.status==="running":!0}const ge=({sessions:t,statusFilter:s,searchQuery:r,selectedIds:i,onToggleSelect:c,onToggleSelectAll:x,onOpenRow:m,buildHasNoSessions:l})=>{const o=b.useMemo(()=>{const n=r.trim().toLowerCase();return t.filter(p=>!(!be(p,s)||n&&!(p.id+" "+(p.name??"")+" "+(p.device_name??"")+" "+(p.device_platform??"")+" "+(p.device_version??"")+" "+(p.node_id??"")).toLowerCase().includes(n)))},[t,s,r]);if(l)return e.jsx("div",{className:"px-4 py-12 text-center text-xs text-[var(--text-dim)]",children:"No sessions in this build yet. Trigger one from your test runner."});if(o.length===0)return e.jsx("div",{className:"px-4 py-12 text-center text-xs text-[var(--text-dim)]",children:"No sessions match the current filters."});const a=o.length>0&&o.every(n=>i.has(n.id)),d=o.some(n=>i.has(n.id));return e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("table",{className:"w-full text-left",children:[e.jsx("thead",{className:"sticky top-0 bg-[var(--surface)] border-b border-[var(--border)] z-10",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-3 py-2 w-[36px]",children:e.jsx("input",{type:"checkbox","aria-label":"Select all visible",checked:a,ref:n=>{n&&(n.indeterminate=d&&!a)},onChange:()=>x(o.map(n=>n.id))})}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Session"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Device · Node"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Platform"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Status"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Start Time"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium text-right",children:"Duration"}),e.jsx("th",{className:"px-3 py-2 w-[32px]"})]})}),e.jsx("tbody",{children:o.map(n=>e.jsx(ve,{session:n,selected:i.has(n.id),onToggleSelect:()=>c(n.id),onOpen:()=>m(n)},n.id))})]})})},Be=()=>{const t=P(),{buildId:s}=z(),r=W(),{toast:i}=G(),[c,x]=b.useState("all"),[m,l]=b.useState("all"),[o,a]=b.useState(""),[d,n]=b.useState(new Set);y.useEffect(()=>{s&&s!==r.selectedBuildId&&(r.selectBuild(s),n(new Set))},[s,r]);const p=u=>t(`/builds/${u}`),S=u=>t(`/builds/${r.selectedBuildId}/sessions/${u.id}`),A=b.useCallback(u=>{n(f=>{const h=new Set(f);return h.has(u)?h.delete(u):h.add(u),h})},[]),D=b.useCallback(u=>{n(f=>{const h=u.length>0&&u.every(v=>f.has(v)),g=new Set(f);return h?u.forEach(v=>g.delete(v)):u.forEach(v=>g.add(v)),g})},[]),k=r.builds.find(u=>u.id===r.selectedBuildId)||null,$=T(r.sessions),U=()=>{i("Bulk retry lands in a future release.","info")},_=async u=>{if(r.selectedBuildId)try{const f=d.size>0?Array.from(d):void 0,{blob:h,filename:g}=await X.exportBuild(r.selectedBuildId,u,f),v=URL.createObjectURL(h),j=document.createElement("a");j.href=v,j.download=g,document.body.appendChild(j),j.click(),document.body.removeChild(j),URL.revokeObjectURL(v);const L=f?f.length:"all";i(`Exported ${L} session${L===1?"":"s"} as ${u.toUpperCase()}.`,"success")}catch(f){const h=f instanceof Error?f.message:String(f);i(`Export failed: ${h}`,"error")}};return e.jsxs("div",{className:"flex h-full",children:[e.jsx(ce,{builds:r.builds,selectedBuildId:r.selectedBuildId,onSelect:p,search:r.searchQuery,onSearchChange:r.setSearchQuery,timeFilter:c,onTimeFilterChange:x}),e.jsx("section",{className:"flex-1 flex flex-col min-w-0",children:k?e.jsxs(e.Fragment,{children:[e.jsx(pe,{build:k,failedCount:$.failed,selectedCount:d.size,onRetryFailed:U,onExport:_}),e.jsx(ue,{sessions:r.sessions,active:m,onChange:l,search:o,onSearchChange:a,totalMatching:r.sessions.length,totalUnfiltered:r.sessions.length}),e.jsx(ge,{sessions:r.sessions,statusFilter:m,searchQuery:o,selectedIds:d,onToggleSelect:A,onToggleSelectAll:D,onOpenRow:S,buildHasNoSessions:r.sessions.length===0})]}):e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-[var(--text-dim)]",children:"Select a build from the left to see its sessions."})})]})};export{Be as BuildsPage,Be as default};
|
|
6
|
+
*/const le=[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]],oe=F("refresh-ccw",le),ie={neutral:"bg-[var(--surface-2)] text-[var(--text-muted)] border-[var(--border)]",green:"bg-[var(--green)]/15 text-[var(--green)] border-[var(--green)]/30",red:"bg-[var(--red)]/15 text-[var(--red)] border-[var(--red)]/30",amber:"bg-[var(--amber)]/15 text-[var(--amber)] border-[var(--amber)]/30"},y=({value:t,tone:s="neutral"})=>e.jsx("span",{className:`inline-flex items-center justify-center min-w-[18px] h-[18px] px-1.5 rounded-full border text-[10px] font-mono font-medium ${ie[s]}`,children:t}),de={passed:{Icon:ee,label:"PASSED",tint:"text-[var(--green)]"},failed:{Icon:Z,label:"FAILED",tint:"text-[var(--red)]"},running:{Icon:Y,label:"RUNNING",tint:"text-[var(--amber)]"}},C=({kind:t,value:s})=>{const{Icon:r,label:i,tint:c}=de[t];return e.jsxs("div",{className:"flex-1 flex flex-col items-center gap-1 py-2 rounded-md border border-[var(--border)] bg-[var(--bg)]",children:[e.jsx(r,{className:`h-3.5 w-3.5 ${c}`}),e.jsx("span",{className:`text-[9px] font-mono font-semibold tracking-wider ${c}`,children:i}),e.jsx("span",{className:"text-sm font-semibold text-[var(--text)] tabular-nums",children:s})]})},I={all:"All time","24h":"Last 24 hours","7d":"Last 7 days","30d":"Last 30 days"},ce=({builds:t,selectedBuildId:s,onSelect:r,search:i,onSearchChange:c,timeFilter:x,onTimeFilterChange:m})=>{const l=t.filter(a=>{const d=(a.name??"")+" "+a.id;if(i&&!d.toLowerCase().includes(i.toLowerCase()))return!1;if(x!=="all"){const n={"24h":864e5,"7d":6048e5,"30d":2592e6},p=Date.parse(String(a.createdAt));if(!Number.isFinite(p)||Date.now()-p>n[x])return!1}return!0}),o=l.reduce((a,d)=>(a.passed+=d.passedCount||0,a.failed+=d.failedCount||0,a.running+=d.runningCount||0,a),{passed:0,failed:0,running:0});return e.jsxs("aside",{className:"w-[280px] shrink-0 border-r border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsxs("div",{className:"p-3 space-y-2 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"relative",children:[e.jsx(E,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("input",{type:"text",value:i,onChange:a=>c(a.target.value),placeholder:"Find builds…",className:"w-full h-8 pl-8 pr-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text)] placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--border-strong)]"})]}),e.jsx("select",{value:x,onChange:a=>m(a.target.value),className:"w-full h-8 px-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text-muted)]",children:Object.keys(I).map(a=>e.jsx("option",{value:a,children:I[a]},a))})]}),e.jsxs("div",{className:"p-3 flex items-stretch gap-2 border-b border-[var(--border)]",children:[e.jsx(C,{kind:"passed",value:o.passed}),e.jsx(C,{kind:"failed",value:o.failed}),e.jsx(C,{kind:"running",value:o.running})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto",children:[l.length===0&&e.jsx("div",{className:"px-4 py-8 text-center text-xs text-[var(--text-dim)]",children:"No builds match."}),l.map(a=>{const d=a.id===s;return e.jsxs("button",{type:"button",onClick:()=>r(a.id),className:`w-full text-left relative px-4 py-3 border-b border-[var(--border)] transition-colors ${d?"bg-[var(--surface-2)]":"hover:bg-[var(--surface-2)]/60"}`,children:[d&&e.jsx("span",{className:"absolute left-0 top-2 bottom-2 w-[3px] rounded-r bg-[var(--green)]"}),e.jsx("div",{className:"text-xs font-semibold text-[var(--text)] truncate",children:a.name||"Unnamed build"}),e.jsxs("div",{className:"mt-1 flex items-center gap-1 font-mono text-[9px] text-[var(--text-dim)]",children:[e.jsx(te,{className:"h-3 w-3"}),B(a.createdAt)]}),e.jsxs("div",{className:"mt-1.5 flex items-center gap-1.5",children:[a.passedCount>0&&e.jsx(y,{value:a.passedCount,tone:"green"}),a.failedCount>0&&e.jsx(y,{value:a.failedCount,tone:"red"}),a.runningCount>0&&e.jsx(y,{value:a.runningCount,tone:"amber"}),a.sessionCount===0&&e.jsx("span",{className:"text-[10px] font-mono text-[var(--text-dim)]",children:"empty"})]}),e.jsx("div",{className:"mt-1 font-mono text-[9px] text-[var(--text-dim)] truncate",children:R(a.id,10,4)})]},a.id)})]})]})},xe={neutral:"bg-[var(--text-dim)]",green:"bg-[var(--green)]",red:"bg-[var(--red)]",amber:"bg-[var(--amber)]",blue:"bg-[var(--blue)]"},N=({label:t,count:s,active:r,onClick:i,tone:c="neutral",bullet:x=!0})=>e.jsxs("button",{type:"button",onClick:i,"aria-pressed":r,className:`inline-flex items-center gap-2 h-8 px-3 rounded-md border text-[11px] font-semibold uppercase tracking-wider transition-colors cursor-pointer ${r?"bg-[var(--surface-2)] border-[var(--border-strong)] text-[var(--text)]":"bg-transparent border-transparent text-[var(--text-muted)] hover:text-[var(--text)] hover:bg-[var(--surface-2)]/50"}`,children:[x&&c!=="neutral"&&e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${xe[c]}`}),e.jsx("span",{children:t}),typeof s=="number"&&e.jsx("span",{className:"font-mono text-[10px] text-[var(--text-dim)]",children:s})]}),ue=({sessions:t,active:s,onChange:r,search:i,onSearchChange:c,totalMatching:x,totalUnfiltered:m})=>{const l=T(t);return e.jsxs("div",{className:"bg-[var(--surface)]",children:[e.jsxs("div",{className:"flex items-center gap-1.5 px-4 pt-3 pb-2",children:[e.jsx(N,{label:"ALL",count:l.all,active:s==="all",onClick:()=>r("all"),tone:"neutral",bullet:!1}),e.jsx(N,{label:"PASSED",count:l.passed,active:s==="passed",onClick:()=>r("passed"),tone:"green"}),e.jsx(N,{label:"FAILED",count:l.failed,active:s==="failed",onClick:()=>r("failed"),tone:"red"}),e.jsx(N,{label:"RUNNING",count:l.running,active:s==="running",onClick:()=>r("running"),tone:"amber"})]}),e.jsxs("div",{className:"flex items-center gap-4 px-4 pb-3 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"relative flex-1 max-w-xl",children:[e.jsx(E,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("input",{type:"text",value:i,onChange:o=>c(o.target.value),placeholder:"Search sessions by ID, name, or device…",className:"w-full h-8 pl-8 pr-2 rounded-md bg-[var(--bg)] border border-[var(--border)] text-xs text-[var(--text)] placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--border-strong)]"})]}),e.jsxs("span",{className:"text-[10px] font-mono text-[var(--text-dim)] whitespace-nowrap",children:[x," of ",m," sessions"]})]})]})};function me(t){return(t.split("-")[0]||t).slice(0,8).toUpperCase()}const pe=({build:t,failedCount:s,selectedCount:r,onRetryFailed:i,onExport:c})=>{const x=s>0||r>0,[m,l]=w.useState(!1),o=w.useRef(null);w.useEffect(()=>{const d=n=>{o.current&&!o.current.contains(n.target)&&l(!1)};return document.addEventListener("mousedown",d),()=>document.removeEventListener("mousedown",d)},[]);const a=x?`Retry ${r||s} session${(r||s)===1?"":"s"}`:"No failed sessions to retry";return e.jsxs("header",{className:"flex items-start justify-between gap-4 px-4 py-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 text-[10px] uppercase tracking-widest text-[var(--text-dim)]",children:[e.jsx("span",{children:"Build"}),e.jsxs("span",{className:"font-mono text-[var(--green)]",title:t.id,children:["#",me(t.id)]})]}),e.jsx("h1",{className:"mt-0.5 text-sm font-semibold text-[var(--text)]",children:t.name||"Unnamed build"})]}),e.jsxs("div",{className:"flex items-center gap-2",ref:o,children:[e.jsxs("button",{type:"button",onClick:i,disabled:!x,title:a,className:"inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:[e.jsx(oe,{className:"h-3.5 w-3.5"}),"Retry failed"]}),e.jsxs("div",{className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>l(d=>!d),className:"inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors",children:[e.jsx(se,{className:"h-3.5 w-3.5"}),"Export"]}),m&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 w-40 rounded-md border border-[var(--border)] bg-[var(--surface)] shadow-lg overflow-hidden z-20",children:[e.jsx("button",{type:"button",onClick:()=>{l(!1),c("json")},className:"w-full text-left px-3 py-2 text-xs text-[var(--text)] hover:bg-[var(--surface-2)]",children:"Export as JSON"}),e.jsx("button",{type:"button",onClick:()=>{l(!1),c("csv")},className:"w-full text-left px-3 py-2 text-xs text-[var(--text)] hover:bg-[var(--surface-2)]",children:"Export as CSV"})]})]})]})]})};function fe({platform:t}){const s=(t||"").toLowerCase();return s.includes("tv")?e.jsx(O,{className:"h-3.5 w-3.5"}):s.includes("pad")||s.includes("tablet")?e.jsx(ae,{className:"h-3.5 w-3.5"}):s.includes("android")||s.includes("ios")?e.jsx(M,{className:"h-3.5 w-3.5"}):e.jsx(ne,{className:"h-3.5 w-3.5"})}function he(t){return t==="running"?{label:"RUNNING",tone:"running"}:t==="failed"?{label:"FAILED",tone:"failed"}:t==="ended"||t==="passed"?{label:"PASSED",tone:"passed"}:{label:t.toUpperCase(),tone:"offline"}}const ve=({session:t,selected:s,onToggleSelect:r,onOpen:i})=>{const c=t.status==="failed",x=he(t.status),m=q(t),l=c&&t.failure_reason?t.failure_reason:t.name??"";return e.jsxs("tr",{onClick:i,className:"group border-b border-[var(--border)] hover:bg-[var(--surface-2)] cursor-pointer transition-colors align-top",children:[e.jsx("td",{className:"px-3 py-3",onClick:o=>o.stopPropagation(),children:e.jsx("input",{type:"checkbox",checked:s,onChange:r,"aria-label":`Select session ${t.id}`})}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsxs("div",{className:"font-mono text-xs text-[var(--green)]",title:t.id,children:["#",R(t.id,14,4)]}),l&&e.jsx("div",{className:"mt-0.5 text-[11px] text-[var(--text-muted)] truncate max-w-[420px]",title:l,children:l})]}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-xs text-[var(--text)]",children:[e.jsx(fe,{platform:t.device_platform}),e.jsx("span",{className:"truncate max-w-[160px]",children:m})]}),t.node_id&&e.jsxs("div",{className:"mt-0.5 font-mono text-[10px] text-[var(--text-dim)]",children:["node-",t.node_id]})]}),e.jsxs("td",{className:"px-3 py-3",children:[e.jsx("div",{className:"text-xs text-[var(--text)]",children:H(t)}),t.device_version&&e.jsx("div",{className:"mt-0.5 font-mono text-[10px] text-[var(--text-dim)]",children:Q(t)})]}),e.jsx("td",{className:"px-3 py-3",children:e.jsx(V,{label:x.label,tone:x.tone})}),e.jsx("td",{className:"px-3 py-3 font-mono text-[11px] text-[var(--text-muted)] whitespace-nowrap",children:B(t.startTime)}),e.jsx("td",{className:"px-3 py-3 font-mono text-[11px] text-[var(--text-muted)] whitespace-nowrap text-right",children:J(K(t))}),e.jsx("td",{className:"px-3 py-3 text-right",children:e.jsx(re,{className:"inline h-4 w-4 text-[var(--text-dim)] group-hover:text-[var(--text)]"})})]})};function be(t,s){return s==="all"?!0:s==="passed"?t.status==="ended"||t.status==="passed":s==="failed"?t.status==="failed":s==="running"?t.status==="running":!0}const ge=({sessions:t,statusFilter:s,searchQuery:r,selectedIds:i,onToggleSelect:c,onToggleSelectAll:x,onOpenRow:m,buildHasNoSessions:l})=>{const o=b.useMemo(()=>{const n=r.trim().toLowerCase();return t.filter(p=>!(!be(p,s)||n&&!(p.id+" "+(p.name??"")+" "+(p.device_name??"")+" "+(p.device_platform??"")+" "+(p.device_version??"")+" "+(p.node_id??"")).toLowerCase().includes(n)))},[t,s,r]);if(l)return e.jsx("div",{className:"px-4 py-12 text-center text-xs text-[var(--text-dim)]",children:"No sessions in this build yet. Trigger one from your test runner."});if(o.length===0)return e.jsx("div",{className:"px-4 py-12 text-center text-xs text-[var(--text-dim)]",children:"No sessions match the current filters."});const a=o.length>0&&o.every(n=>i.has(n.id)),d=o.some(n=>i.has(n.id));return e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("table",{className:"w-full text-left table-fixed",children:[e.jsx("thead",{className:"sticky top-0 bg-[var(--surface)] border-b border-[var(--border)] z-10",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-3 py-2 w-[36px]",children:e.jsx("input",{type:"checkbox","aria-label":"Select all visible",checked:a,ref:n=>{n&&(n.indeterminate=d&&!a)},onChange:()=>x(o.map(n=>n.id))})}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Session"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium",children:"Device · Node"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium w-[108px]",children:"Platform"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium w-[104px]",children:"Status"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium w-[160px]",children:"Start Time"}),e.jsx("th",{className:"px-3 py-2 text-[10px] uppercase tracking-wider text-[var(--text-dim)] font-medium text-right w-[92px]",children:"Duration"}),e.jsx("th",{className:"px-3 py-2 w-[32px]"})]})}),e.jsx("tbody",{children:o.map(n=>e.jsx(ve,{session:n,selected:i.has(n.id),onToggleSelect:()=>c(n.id),onOpen:()=>m(n)},n.id))})]})})},Be=()=>{const t=P(),{buildId:s}=z(),r=W(),{toast:i}=G(),[c,x]=b.useState("all"),[m,l]=b.useState("all"),[o,a]=b.useState(""),[d,n]=b.useState(new Set);w.useEffect(()=>{s&&s!==r.selectedBuildId&&(r.selectBuild(s),n(new Set))},[s,r]);const p=u=>t(`/builds/${u}`),S=u=>t(`/builds/${r.selectedBuildId}/sessions/${u.id}`),A=b.useCallback(u=>{n(f=>{const h=new Set(f);return h.has(u)?h.delete(u):h.add(u),h})},[]),D=b.useCallback(u=>{n(f=>{const h=u.length>0&&u.every(v=>f.has(v)),g=new Set(f);return h?u.forEach(v=>g.delete(v)):u.forEach(v=>g.add(v)),g})},[]),k=r.builds.find(u=>u.id===r.selectedBuildId)||null,$=T(r.sessions),U=()=>{i("Bulk retry lands in a future release.","info")},_=async u=>{if(r.selectedBuildId)try{const f=d.size>0?Array.from(d):void 0,{blob:h,filename:g}=await X.exportBuild(r.selectedBuildId,u,f),v=URL.createObjectURL(h),j=document.createElement("a");j.href=v,j.download=g,document.body.appendChild(j),j.click(),document.body.removeChild(j),URL.revokeObjectURL(v);const L=f?f.length:"all";i(`Exported ${L} session${L===1?"":"s"} as ${u.toUpperCase()}.`,"success")}catch(f){const h=f instanceof Error?f.message:String(f);i(`Export failed: ${h}`,"error")}};return e.jsxs("div",{className:"flex h-full",children:[e.jsx(ce,{builds:r.builds,selectedBuildId:r.selectedBuildId,onSelect:p,search:r.searchQuery,onSearchChange:r.setSearchQuery,timeFilter:c,onTimeFilterChange:x}),e.jsx("section",{className:"flex-1 flex flex-col min-w-0",children:k?e.jsxs(e.Fragment,{children:[e.jsx(pe,{build:k,failedCount:$.failed,selectedCount:d.size,onRetryFailed:U,onExport:_}),e.jsx(ue,{sessions:r.sessions,active:m,onChange:l,search:o,onSearchChange:a,totalMatching:r.sessions.length,totalUnfiltered:r.sessions.length}),e.jsx(ge,{sessions:r.sessions,statusFilter:m,searchQuery:o,selectedIds:d,onToggleSelect:A,onToggleSelectAll:D,onOpenRow:S,buildHasNoSessions:r.sessions.length===0})]}):e.jsx("div",{className:"flex-1 flex items-center justify-center text-xs text-[var(--text-dim)]",children:"Select a build from the left to see its sessions."})})]})};export{Be as BuildsPage,Be as default};
|