const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContactsMapMapLibre-C4pjW3Kz.js","assets/index-C4inJ1rU.js","assets/consumer-registry-BEMotsU4.js","assets/link-scoring-BT92qwBN.js","assets/ConfirmModal-Dr1cpMpw.js","assets/variants-BxtUhUrZ.js","assets/git-branch-Dnk0SYSJ.js","assets/useMapViewStore-MJt-JUde.js","assets/index-BXWmGYBj.js","assets/index-CLVX1WuQ.js","assets/funnel-MRZBOee_.js","assets/plus-BvSKm1y6.js","assets/compass-BqGOlCkL.js","assets/zap-NBmxZJvi.js","assets/max-Cf6xo70m.js","assets/trash-2-1fU70LRT.js","assets/wifi-off-DcMGHQmj.js","assets/wifi-CrCnex2M.js","assets/circle-alert-CIOCr8DK.js","assets/clock-BOSF_clE.js","assets/chevron-right-CU8UihKL.js","assets/useReplayTick-BfUplIIt.js","assets/payload-detail-BWRHeO7M.js","assets/LightSparkline-CReUcxTn.js","assets/badge-colors-Dl76Mz8m.js","assets/map-pin-DlTTkXK_.js","assets/wrench-d23m0Iuc.js","assets/layer-D6BnwDKL.js","assets/node-types-chTBCezS.js","assets/BasemapLayer-zAPrA2Lm.js","assets/easing-C4vSIYXU.js","assets/usePipelineStore-BdsvnjJV.js","assets/PageLayout-CdGXajgM.js","assets/listbox-C-kqERsa.js","assets/element-movement-Dl45gerR.js","assets/floating-4TW7J4UF.js","assets/use-text-value-BO4BQQts.js","assets/frozen-BB9d2dXD.js","assets/TimeRangeStepper-DNUdgVzA.js","assets/MqttModeBadge-BTwynmjt.js","assets/chat-utils-C6kvX8nY.js","assets/SignalIndicator-BTMFmuDD.js","assets/CollisionExplorerModal-D4h1t6K4.js","assets/share-2-CGZnW2u_.js","assets/map-pin-off-lllWd_C7.js","assets/activity-Q-NGsRUt.js","assets/target-C8oxWH8W.js","assets/search-qUivGgU1.js","assets/index-DuWodFP7.css","assets/maplibre-gl-B1CfjdFi.css","assets/ContactsMapMapLibre-BwWOEply.css"])))=>i.map(i=>d[i]);
import{e as xe,at as cs,j as e,r as n,_ as is,cs as He,ct as Oe,aq as U,cu as ls,a4 as Ce,cv as ds,cw as me,R as de,bX as Ie,c4 as ms,aw as De,cx as ye,a6 as ze,cy as xs,ae as us,cz as ps,cA as hs,cB as fs,ad as gs,cC as js,cD as bs,af as ys,ax as Ns,ag as Ne,cE as vs,cF as ws,bG as Cs,cG as ks,bF as ee,cH as $e,a2 as Ms,I as Ss,bK as Ps,c as we}from"./index-C4inJ1rU.js";import{useDiscoveredNodes as Rs}from"./usePipelineStore-BdsvnjJV.js";import{c as ke}from"./node-types-chTBCezS.js";import{P as _s,a as Ls,B as Ts}from"./PageLayout-CdGXajgM.js";import{L as $s,a as le}from"./listbox-C-kqERsa.js";import{T as Fe}from"./TimeRangeStepper-DNUdgVzA.js";import{M as Fs}from"./MqttModeBadge-BTwynmjt.js";import{u as Es,e as Hs,f as Os,r as Is}from"./consumer-registry-BEMotsU4.js";import{e as Ds,g as zs,a as Bs}from"./chat-utils-C6kvX8nY.js";import{b as As}from"./SignalIndicator-BTMFmuDD.js";import{C as qs}from"./CollisionExplorerModal-D4h1t6K4.js";import{S as Vs}from"./share-2-CGZnW2u_.js";import{M as Gs}from"./map-pin-off-lllWd_C7.js";import{A as Be}from"./activity-Q-NGsRUt.js";import{T as Us}from"./target-C8oxWH8W.js";import{T as Ws}from"./trash-2-1fU70LRT.js";import{C as Qs}from"./ConfirmModal-Dr1cpMpw.js";import{M as Xs}from"./map-pin-DlTTkXK_.js";import{S as Ks}from"./search-qUivGgU1.js";import{C as Zs}from"./clock-BOSF_clE.js";/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const Js=[["path",{d:"m21 16-4 4-4-4",key:"f6ql7i"}],["path",{d:"M17 20V4",key:"1ejh1v"}],["path",{d:"m3 8 4-4 4 4",key:"11wl7u"}],["path",{d:"M7 4v16",key:"1glfcx"}]],Ys=xe("arrow-up-down",Js);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const et=[["path",{d:"M4 12V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2",key:"jrl274"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 16h2v6",key:"1bxocy"}],["path",{d:"M10 22h4",key:"ceow96"}],["rect",{x:"2",y:"16",width:"4",height:"6",rx:"2",key:"r45zd0"}]],st=xe("file-digit",et);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const tt=[["path",{d:"M2 5h20",key:"1fs1ex"}],["path",{d:"M6 12h12",key:"8npq4p"}],["path",{d:"M9 19h6",key:"456am0"}]],at=xe("list-filter",tt);/**
 * @license lucide-react v0.559.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */const nt=[["path",{d:"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z",key:"icamh8"}],["path",{d:"m14.5 12.5 2-2",key:"inckbg"}],["path",{d:"m11.5 9.5 2-2",key:"fmmyf7"}],["path",{d:"m8.5 6.5 2-2",key:"vc6u1g"}],["path",{d:"m17.5 15.5 2-2",key:"wo5hmg"}]],Ae=xe("ruler",nt);class rt extends n.Component{constructor(l){super(l),this.state={hasError:!1}}static getDerivedStateFromError(l){return{hasError:!0,error:l}}render(){var l;return this.state.hasError?e.jsx("div",{className:"map-container-16-9 flex items-center justify-center rounded-2xl surface-base",role:"alert","aria-live":"assertive",children:e.jsxs("div",{className:"text-center text-fg-muted p-4",children:[e.jsx("p",{className:"text-lg mb-2",children:"Map failed to load"}),e.jsx("p",{className:"text-sm text-fg-muted",children:((l=this.state.error)==null?void 0:l.message)||"Unknown error"}),e.jsx("p",{className:"text-xs text-fg-muted mt-2",children:"Try refreshing the page or check your browser's WebGL support."})]})}):this.props.children}}const ot=n.lazy(()=>is(()=>import("./ContactsMapMapLibre-C4pjW3Kz.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50]))),Ee=()=>e.jsx("div",{className:"map-container-16-9 flex items-center justify-center rounded-2xl surface-base",role:"status","aria-live":"polite","aria-label":"Loading map",children:e.jsxs("div",{className:"text-fg-muted flex items-center gap-3",children:[e.jsx("div",{className:"w-5 h-5 border-2 border-sys-blue border-t-transparent rounded-full animate-spin","aria-hidden":"true"}),e.jsx("span",{children:"Loading map..."})]})});function ct({neighbors:o,localNode:l,localHash:g,onRemoveNode:u,selectedNodeHash:j,onNodeSelected:N,highlightedEdgeKey:c,highlightedGhost:T}){return cs()===!1?e.jsx(Ee,{}):e.jsx(rt,{children:e.jsx(n.Suspense,{fallback:e.jsx(Ee,{}),children:e.jsx(ot,{neighbors:o,localNode:l,localHash:g,onRemoveNode:u,selectedNodeHash:j,onNodeSelected:N,highlightedEdgeKey:c,highlightedGhost:T})})})}function it({hash:o,className:l="",size:g="sm",collisionInfo:u,isViterbiResolved:j}){const N=He(),c=Oe(),[T,$]=n.useState(!1),w=n.useMemo(()=>U(o),[o]),p=n.useMemo(()=>u!==void 0?u:w?N.find(P=>P.prefix===w)??null:null,[w,N,u]),C=j??(c.totalPaths>0&&c.avgPathConfidence>=.7),z=n.useCallback(P=>{P.preventDefault(),P.stopPropagation(),$(!0)},[]),B=n.useCallback(()=>{$(!1)},[]);if(!p)return null;const A=g==="sm"?"w-3.5 h-3.5":"w-4 h-4",q=C?"text-sys-cyan hover:text-sys-cyan hover:bg-sys-cyan/10 focus:ring-sys-cyan/50":"text-signal-fair hover:text-sys-indigo hover:bg-signal-fair/10 focus:ring-signal-fair/50",S=C?`Prefix conflict resolved by Viterbi HMM (${(c.avgPathConfidence*100).toFixed(0)}% confidence)`:`Prefix conflict: ${p.candidateCount} nodes share prefix "${w}"`;return e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:z,className:`inline-flex items-center justify-center p-0.5 rounded focus:outline-none focus:ring-2 transition-colors cursor-pointer touch-manipulation ${q} ${l}`,title:S,"aria-label":`View prefix conflict for ${w}${C?" (Viterbi resolved)":""}`,children:C?e.jsxs("span",{className:"relative",children:[e.jsx(ls,{className:A}),e.jsx(Ce,{className:"absolute -bottom-0.5 -right-0.5 w-2 h-2 text-sys-green"})]}):e.jsx(st,{className:A})}),T&&e.jsx(qs,{isOpen:!0,prefix:p.prefix,candidateHashes:p.candidateHashes,onClose:B})]})}const lt=n.memo(it),qe=[{target:"Contacts",fn:"name",minStage:1,when:Hs},{target:"Contacts",fn:"traceLinks.directed",minStage:2,when:Os}];Is(qe);function dt(o){return o<1e3?`${Math.round(o)}m`:`${(o/1e3).toFixed(1)}km`}function mt({hash:o,contact:l,isHub:g,isNeighbor:u,distance:j,centrality:N,neighborSignal:c,collisionInfo:T,isViterbiResolved:$,pingingHash:w,pingResult:p,pingError:C,isMobile:z,metaSummary:B,metaTooltip:A,onRowClick:q,onPing:S,onRemove:P}){Es(qe);const R=l.latitude&&l.longitude&&l.latitude!==0&&l.longitude!==0,H=l.node_name||l.name||"Unknown",O=u&&c,se=ke(l),{isRepeater:v,isCompanion:W,isRoomServer:_,isClient:Q,label:b}=se,te=u?`${b} — Direct RF contact (zero-hop neighbor)`:`${b} — Flood routing (multi-hop via mesh)`,ae=n.useCallback(()=>q(o),[q,o]);return e.jsxs("div",{className:`contacts-grid-row ${g?"bg-sys-amber/5 border-l-2 border-l-sys-amber":""} ${R?"cursor-pointer":""}`,onClick:ae,children:[e.jsxs("div",{className:"contacts-col-node flex items-center gap-2 min-w-0",children:[O&&(c==null?void 0:c.avgSnr)!==null?e.jsx("div",{className:`w-2 h-2 rounded-full flex-shrink-0 self-center ${ds(c.avgSnr)}`}):e.jsx("div",{className:"w-2 flex-shrink-0"}),e.jsx("div",{className:"w-6 h-6 flex items-center justify-center flex-shrink-0",title:te,children:(()=>{if(_&&v)return e.jsxs("div",{className:"relative w-5 h-5",children:[e.jsx(me,{className:"w-5 h-5 absolute inset-0 text-sys-pink"}),e.jsx(Vs,{className:"w-2.5 h-2.5 absolute -bottom-0.5 -right-0.5 text-sys-teal"})]});if(_)return e.jsx(me,{className:"w-5 h-5 text-sys-pink"});if(v)return e.jsx("div",{className:"w-5 h-5 rounded-full flex items-center justify-center ring-[1.5px] ring-sys-blue",children:e.jsx(de,{className:"w-3.5 h-3.5 text-sys-blue"})});if((W||Q)&&H!=="Unknown"){const{emoji:F,cleanName:ue}=Ds(H);return e.jsx("div",{className:"w-6 h-6 clay-avatar",style:{"--avatar-color":zs(ue)},children:F?e.jsx("span",{className:"text-sm leading-none",children:F}):e.jsx("span",{className:"text-white text-[9px] font-bold tracking-tighter",children:Bs(H)})})}return e.jsx("div",{className:"w-6 h-6 rounded-full flex items-center justify-center bg-zinc-500/20",children:e.jsx(Ie,{className:"w-3.5 h-3.5 text-sys-amber"})})})()}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5 overflow-hidden",children:[e.jsx("span",{className:"roster-title truncate",title:H,children:H}),u&&e.jsx("span",{className:"contact-tag contact-tag--nbr",children:"NBR"}),g&&e.jsx("span",{className:"contact-tag contact-tag--hub",children:"HUB"}),v&&e.jsx("span",{className:"contact-tag contact-tag--rpt",children:"RPT"}),_&&e.jsx("span",{className:"contact-tag contact-tag--room",children:"ROOM"}),W&&e.jsx("span",{className:"contact-tag contact-tag--comp",children:"COMP"}),Q&&e.jsx("span",{className:"contact-tag contact-tag--client",children:"CLIENT"}),z&&e.jsx("span",{className:"contact-tag contact-tag--mobile",children:"MOB"}),!R&&e.jsx(Gs,{className:"w-3 h-3 flex-shrink-0 text-fg-muted/50"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 mt-0.5",children:[e.jsx(ms,{copy:!0,size:"compact",truncate:[8,6],children:o}),e.jsx(lt,{hash:o,collisionInfo:T,isViterbiResolved:$}),B&&e.jsx("span",{className:"contact-meta",title:A,children:B})]})]})]}),e.jsxs("div",{className:"contacts-col-signal flex items-center justify-end gap-2",children:[O&&(c==null?void 0:c.avgRssi)!==null&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(As,{rssi:c.avgRssi,className:"w-3.5 h-3.5"}),e.jsx("span",{className:"type-data-xs text-fg-muted",children:Math.round(c.avgRssi)})]}),O&&(c==null?void 0:c.avgSnr)!==null&&e.jsxs("span",{className:"type-data-xs text-fg-muted",children:[c.avgSnr.toFixed(1)," dB"]})]}),e.jsx("div",{className:"contacts-col-distance flex items-center justify-end gap-1 text-fg-muted",children:j!=null&&e.jsxs(e.Fragment,{children:[e.jsx(Ae,{className:"w-3 h-3"}),e.jsx("span",{className:"type-data-xs",children:dt(j)})]})}),e.jsx("div",{className:"contacts-col-centrality flex items-center justify-end gap-1",children:N>0&&e.jsxs(e.Fragment,{children:[e.jsx(Be,{className:"w-3 h-3 text-sys-indigo"}),e.jsxs("span",{className:"type-data-xs text-fg-muted",children:[(N*100).toFixed(0),"%"]})]})}),e.jsx("div",{className:"contacts-col-seen flex items-center justify-end",children:e.jsx("span",{className:"type-data-xs text-fg-primary whitespace-nowrap",children:l.last_seen?De(l.last_seen):"—"})}),e.jsxs("div",{className:"contacts-col-actions flex items-center justify-end gap-1",children:[u&&e.jsx(e.Fragment,{children:p?e.jsxs("div",{className:`flex items-center gap-1 ${ye(p)?"text-sys-green":"text-fg-muted"}`,title:`RTT: ${p.rtt_ms.toFixed(0)}ms${ye(p)?` · SNR: ${p.snr_db.toFixed(1)}dB · RSSI: ${p.rssi}dBm`:""}`,children:[e.jsx(Ce,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"type-data-xs hidden sm:inline",children:ye(p)?`${p.snr_db.toFixed(1)}dB`:`${(p.rtt_ms/1e3).toFixed(1)}s`})]}):C?e.jsxs("span",{className:"text-sys-red text-xs font-medium",title:C,children:[e.jsx("span",{className:"hidden sm:inline",children:C}),e.jsx("span",{className:"sm:hidden",children:"✗"})]}):e.jsx("button",{onClick:F=>S(o,F),disabled:w!==null,className:"p-1 sm:p-1.5 radius-inner text-fg-muted/50 hover:text-sys-blue hover:bg-sys-blue/10 transition-base disabled:opacity-50 disabled:cursor-not-allowed",title:"Ping neighbor for updated signal info",children:w===o?e.jsx(ze,{className:"w-3.5 h-3.5 sm:w-4 sm:h-4 animate-spin"}):e.jsx(Us,{className:"w-3.5 h-3.5 sm:w-4 sm:h-4"})})}),e.jsx("button",{onClick:F=>{F.stopPropagation(),P(o,H)},className:"p-1 sm:p-1.5 radius-inner text-fg-muted/50 hover:text-sys-red hover:bg-sys-red/10 transition-base",title:"Remove contact",children:e.jsx(Ws,{className:"w-3.5 h-3.5 sm:w-4 sm:h-4"})})]})]})}const xt=n.memo(mt),ut=6371e3,pt=[{field:"lastHeard",icon:Zs,label:"Recent"},{field:"distance",icon:Ae,label:"Distance"},{field:"centrality",icon:Be,label:"Centrality"}];function ht(o){switch(o){case"room_server":return"room";case"repeater":return"repeater";case"companion":return"companion";case"unknown":return"companion"}}function ft(o){const l=ke(o);return ht(l.type)}function ve(o,l){const{color:g="primary",border:u=!1}=l??{};return we("flex items-center gap-1.5 px-2 py-1.5 text-sm radius-inner transition-base",o?g==="success"?"bg-sys-green/20 text-sys-green":"bg-sys-blue/20 text-sys-blue":"text-fg-muted hover:text-fg-secondary hover-bg",u&&(o?g==="success"?"border border-sys-green/30":"border border-sys-blue/30":"border border-transparent"))}function gt(o,l,g,u){const j=(g-o)*Math.PI/180,N=(u-l)*Math.PI/180,c=Math.sin(j/2)*Math.sin(j/2)+Math.cos(o*Math.PI/180)*Math.cos(g*Math.PI/180)*Math.sin(N/2)*Math.sin(N/2),T=2*Math.atan2(Math.sqrt(c),Math.sqrt(1-c));return ut*T}function jt(){var Le,Te;const{stats:o}=xs(),l=us(),g=ps(),u=hs(),j=fs(),N=gs(),c=js(),T=bs(),$=ys(),w=Ns(),p=Ne[$],C=He(),z=Oe(),B=vs(),A=z.totalPaths>0&&z.avgPathConfidence>=.7,q=n.useMemo(()=>{const s=new Map;for(const a of C)s.set(a.prefix,a);return s},[C]),[S,P]=n.useState(null),[R,H]=n.useState("lastHeard"),[O,se]=n.useState("desc"),[v,W]=n.useState(""),[_,Q]=n.useState(!1),[b,te]=n.useState(new Set),[ae,F]=n.useState(!1),[ue,Me]=n.useState(null),[pe,Se]=n.useState(null),[Ve,he]=n.useState(new Map),[Ge,X]=n.useState(new Map),[k,Ue]=n.useState(25),[V,ne]=n.useState(25),fe=n.useRef(null),K=n.useMemo(()=>(o==null?void 0:o.neighbors)??{},[o==null?void 0:o.neighbors]),ge=Rs(),re=n.useMemo(()=>{if(ge.size===0)return K;const s=new Set;for(const t of Object.keys(K))s.add((t.startsWith("0x")?t.slice(2):t).toLowerCase());let a=null;for(const[t,r]of ge){const i=(t.startsWith("0x")?t.slice(2):t).toLowerCase();s.has(i)||(a||(a={...K}),a[t]={last_seen:r.lastSeen,name:r.name??void 0,node_name:r.name??void 0,latitude:r.latitude,longitude:r.longitude,is_repeater:r.nodeType==="repeater",contact_type:r.nodeType==="repeater"?"Repeater":r.nodeType==="companion"?"Companion":r.nodeType==="room_server"?"Room Server":void 0})}return a??K},[K,ge]),I=n.useMemo(()=>{const a=Date.now()/1e3-p.minutes*60;return Object.fromEntries(Object.entries(re).filter(([t,r])=>l.has(t)?!1:(r.last_seen??0)>=a))},[re,l,p.minutes]),L=ws(),D=o==null?void 0:o.local_hash,We=n.useMemo(()=>{const s=new Map;if(!D||c.size===0)return s;for(const[a,t]of c)if(a.endsWith(`→${D}`)&&t.hops.length>1){const r=a.split("→")[0],i=t.hops[t.hops.length-1];s.set(r,i)}return s},[c,D]),Qe=n.useMemo(()=>{const s=new Map;if(!D||c.size===0)return s;const a=new Map;for(const[t,r]of Object.entries(re)){const i=(t.startsWith("0x")?t.slice(2):t).toLowerCase();a.set(i,r)}for(const[t,r]of c){if(!t.endsWith(`→${D}`)||r.hops.length===0)continue;const i=t.split("→")[0],d=r.hops[0];let h=null;for(const[f,y]of a)if(f.startsWith(d.toLowerCase())){h=y.node_name??y.name??null;break}s.set(i,{prefix:d,name:h,hopCount:r.hopCount})}return s},[c,D,re]),oe=n.useMemo(()=>{const s=new Map;if(!(L!=null&&L.latitude)||!(L!=null&&L.longitude))return s;for(const[a,t]of Object.entries(I))t.latitude&&t.longitude&&t.latitude!==0&&t.longitude!==0?s.set(a,gt(L.latitude,L.longitude,t.latitude,t.longitude)):s.set(a,null);return s},[I,L]),{neighborHashSet:ce,neighborSignalMap:Xe}=n.useMemo(()=>{const s=new Set,a=new Map;for(const t of N)s.add(t.hash),a.set(t.hash,{avgRssi:t.avgRssi,avgSnr:t.avgSnr});return{neighborHashSet:s,neighborSignalMap:a}},[N]),Pe=n.useMemo(()=>{const s=v.toLowerCase().trim(),a=s==="neighbor"||s==="neighbors",t=_||a,r=b.size>0;return Object.fromEntries(Object.entries(I).filter(([i,d])=>{if(r){const y=ft(d);if(!b.has(y))return!1}if(t&&!ce.has(i))return!1;if(a||!s)return!0;const h=(d.node_name||d.name||"").toLowerCase(),f=U(i).toLowerCase();return h.includes(s)||f.includes(s)||i.toLowerCase().includes(s)}))},[I,v,_,ce,b]),x=n.useMemo(()=>{const s=Object.entries(Pe),a=v.toLowerCase().trim(),t=/^[0-9a-f]{2}(?:[0-9a-f]{2}){0,2}$/i.test(a);return s.sort(([r,i],[d,h])=>{if(t){const y=U(r).toLowerCase(),E=U(d).toLowerCase(),M=y===a,G=E===a;if(M&&!G)return-1;if(G&&!M)return 1}let f=0;switch(R){case"lastHeard":f=(i.last_seen||0)-(h.last_seen||0);break;case"distance":{const y=oe.get(r)??null,E=oe.get(d)??null;y===null&&E===null?f=0:y===null?f=1:E===null?f=-1:f=y-E;break}case"centrality":{const y=j.get(r)||0,E=j.get(d)||0;f=y-E;break}}return O==="desc"?-f:f})},[Pe,R,O,oe,j,v]),m=n.useMemo(()=>{let s=0,a=0,t=0,r=0,i=0;for(const[,d]of x){const h=ke(d),f=d.latitude&&d.longitude&&d.latitude!==0&&d.longitude!==0;switch(h.type){case"room_server":t++;break;case"repeater":a++;break;case"companion":s++;break;case"unknown":i++;break}f&&r++}return{companions:s,repeaters:a,roomServers:t,total:x.length,withLocation:r,unknown:i}},[x]),Ke=n.useMemo(()=>new Set(u),[u]),Re=n.useMemo(()=>k===0?x:x.slice(0,V),[x,V,k]);n.useEffect(()=>{ne(k||x.length)},[R,O,v,_,b,k,x.length]),n.useEffect(()=>{const s=a=>{a.target.closest("[data-dropdown]")||F(!1)};return document.addEventListener("click",s),()=>document.removeEventListener("click",s)},[]),n.useEffect(()=>{if(k===0)return;const s=new IntersectionObserver(a=>{a[0].isIntersecting&&V<x.length&&ne(t=>Math.min(t+k,x.length))},{threshold:.1,rootMargin:"100px"});return fe.current&&s.observe(fe.current),()=>s.disconnect()},[k,V,x.length]);const Ze=n.useCallback(s=>{Ue(s),ne(s||x.length)},[x.length]),Je=n.useCallback(s=>{R===s?se(a=>a==="desc"?"asc":"desc"):(H(s),se("desc"))},[R]),Ye=n.useCallback(s=>{const a=I[s];a!=null&&a.latitude&&(a!=null&&a.longitude)&&a.latitude!==0&&a.longitude!==0&&Me(s)},[I]),es=n.useCallback(()=>{Me(null)},[]),ss=n.useCallback((s,a)=>{P({hash:s,name:a})},[]),_e=Cs((Te=(Le=o==null?void 0:o.config)==null?void 0:Le.mesh)==null?void 0:Te.path_hash_mode),ts=n.useCallback(async(s,a)=>{if(a.stopPropagation(),!pe){Se(s),he(t=>{const r=new Map(t);return r.delete(s),r}),X(t=>{const r=new Map(t);return r.delete(s),r});try{const r=`0x${U(s,_e)}`,i=await ks(r,30);i.success&&i.data?(he(d=>new Map(d).set(s,i.data)),setTimeout(()=>{he(d=>{const h=new Map(d);return h.delete(s),h})},1e4)):(X(d=>new Map(d).set(s,i.error||"Ping failed")),setTimeout(()=>{X(d=>{const h=new Map(d);return h.delete(s),h})},5e3))}catch(t){const r=t instanceof Error?t.message:"Ping failed";X(i=>new Map(i).set(s,r)),setTimeout(()=>{X(i=>{const d=new Map(i);return d.delete(s),d})},5e3)}finally{Se(null)}}},[pe,_e]);return e.jsxs(_s,{children:[e.jsx(Ls,{title:"Contacts",icon:e.jsx(ee,{}),subtitle:e.jsx(Fs,{}),controls:e.jsxs("div",{className:"flex items-center gap-3 sm:gap-5",children:[e.jsxs("div",{className:"hidden sm:flex items-center gap-4",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-xs text-fg-muted",children:"Total:"}),e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:`${m.total} discovered node${m.total!==1?"s":""} on the mesh network`,children:[e.jsx(ee,{className:"w-3.5 h-3.5 text-fg-secondary"}),e.jsx("span",{children:m.total})]})]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-xs text-fg-muted",children:"Types:"}),m.repeaters>0&&e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:"Repeaters",children:[e.jsx(de,{className:"w-3.5 h-3.5 text-sys-blue"}),e.jsx("span",{children:m.repeaters})]}),m.companions>0&&e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:"Companions",children:[e.jsx($e,{className:"w-3.5 h-3.5 text-fg-muted"}),e.jsx("span",{children:m.companions})]}),m.roomServers>0&&e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:"Room Servers",children:[e.jsx(me,{className:"w-3.5 h-3.5 text-sys-pink"}),e.jsx("span",{children:m.roomServers})]}),m.withLocation>0&&e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:"With GPS location",children:[e.jsx(Xs,{className:"w-3.5 h-3.5 text-sys-green"}),e.jsx("span",{children:m.withLocation})]}),m.unknown>0&&e.jsxs("span",{className:"data-box flex items-center gap-1.5 cursor-default",title:"Unknown type",children:[e.jsx(Ie,{className:"w-3.5 h-3.5 text-sys-amber"}),e.jsx("span",{children:m.unknown})]})]})]}),e.jsxs("div",{className:"flex sm:hidden items-center gap-1.5",children:[e.jsxs("span",{className:"data-box !px-1.5 !py-0.5 !text-[10px] flex items-center gap-1",children:[e.jsx(ee,{className:"w-3 h-3 text-fg-secondary"}),e.jsx("span",{children:m.total})]}),m.repeaters>0&&e.jsxs("span",{className:"data-box !px-1.5 !py-0.5 !text-[10px] flex items-center gap-1",children:[e.jsx(de,{className:"w-3 h-3 text-sys-blue"}),e.jsx("span",{children:m.repeaters})]}),m.companions>0&&e.jsxs("span",{className:"data-box !px-1.5 !py-0.5 !text-[10px] flex items-center gap-1",children:[e.jsx($e,{className:"w-3 h-3 text-fg-muted"}),e.jsx("span",{children:m.companions})]}),m.roomServers>0&&e.jsxs("span",{className:"data-box !px-1.5 !py-0.5 !text-[10px] flex items-center gap-1",children:[e.jsx(me,{className:"w-3 h-3 text-sys-pink"}),e.jsx("span",{children:m.roomServers})]}),e.jsx(Fe,{ranges:Ne,selectedIndex:$,onSelect:w,size:"sm"})]}),e.jsx("div",{className:"hidden sm:block",children:e.jsx(Fe,{ranges:Ne,selectedIndex:$,onSelect:w})})]})}),e.jsxs(Ts,{children:[e.jsx(ct,{neighbors:I,localNode:L??void 0,localHash:D,onRemoveNode:g,selectedNodeHash:ue,onNodeSelected:es}),e.jsxs(Ms,{noPadding:!0,children:[e.jsxs("div",{className:"flex items-center gap-1.5 sm:gap-2 px-3 sm:px-4 py-2.5 border-b border-edge-subtle",children:[e.jsx("span",{className:"icon-md flex items-center justify-center text-icon-card-title flex-shrink-0",children:e.jsx(ee,{})}),e.jsx("span",{className:"type-micro flex-shrink-0 mr-auto hidden sm:block",children:"Discovered Contacts"}),e.jsx(Ss,{type:"search",size:"sm",value:v,onChange:s=>W(s.target.value),placeholder:"Search...",leadingIcon:e.jsx(Ks,{className:"w-3.5 h-3.5"}),trailingIcon:v?e.jsx("button",{onClick:()=>{W(""),(v.toLowerCase().trim()==="neighbor"||v.toLowerCase().trim()==="neighbors")&&Q(!1)},className:"text-fg-muted hover:text-fg-secondary",children:e.jsx(Ps,{className:"w-3 h-3"})}):void 0,className:"w-24 sm:w-32 xl:w-44","aria-label":"Search contacts"}),e.jsx("div",{className:"h-4 w-px bg-border-subtle flex-shrink-0"}),e.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[e.jsxs("div",{className:"relative","data-dropdown":!0,children:[e.jsxs("button",{onClick:()=>F(!ae),className:ve(b.size>0,{border:!0}),title:"Filter by contact type",children:[e.jsx(at,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"hidden xl:inline",children:"Filter"}),b.size>0&&e.jsx("span",{className:"tabular-nums text-xs bg-sys-blue/30 px-1 rounded",children:b.size})]}),ae&&e.jsxs("div",{className:"absolute right-0 top-full mt-1 z-50 surface-elevated radius-inner py-1 min-w-[140px]",children:[[{key:"repeater",label:"Repeaters"},{key:"companion",label:"Companions"},{key:"room",label:"Rooms"}].map(({key:s,label:a})=>e.jsxs("button",{onClick:()=>{te(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},className:"w-full px-3 py-1.5 text-sm text-left hover-bg transition-base flex items-center gap-2",children:[e.jsx("span",{className:we("w-4 h-4 flex items-center justify-center radius-badge border",b.has(s)?"bg-sys-blue border-sys-blue text-white":"border-edge-subtle"),children:b.has(s)&&e.jsx(Ce,{className:"w-3 h-3"})}),e.jsx("span",{className:b.has(s)?"text-fg-primary":"text-fg-secondary",children:a})]},s)),b.size>0&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"border-t border-edge-subtle my-1"}),e.jsx("button",{onClick:()=>te(new Set),className:"w-full px-3 py-1.5 text-sm text-left text-fg-muted hover:text-fg-secondary hover-bg transition-base",children:"Clear filters"})]})]})]}),ce.size>0&&e.jsxs("button",{onClick:()=>Q(!_),className:ve(_,{color:"success",border:!0}),title:_?"Show all contacts":"Show only MeshCore neighbors (direct RF contact)",children:[e.jsx(de,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"hidden xl:inline",children:"Neighbors"})]})]}),e.jsx("div",{className:"h-4 w-px bg-border-subtle flex-shrink-0"}),e.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[pt.map(({field:s,icon:a,label:t})=>e.jsxs("button",{onClick:()=>Je(s),className:ve(R===s),title:`Sort by ${t.toLowerCase()}`,children:[e.jsx(a,{className:"w-3.5 h-3.5"}),e.jsx("span",{className:"hidden xl:inline",children:t}),R===s&&e.jsx(Ys,{className:we("w-3 h-3",O==="asc"&&"rotate-180")})]},s)),e.jsx("div",{className:"h-4 w-px bg-border-subtle"}),e.jsxs($s,{value:k,onChange:Ze,className:"w-auto min-w-[50px] [&_button]:py-1 [&_button]:px-2 [&_button]:text-xs [&_button]:min-h-0","aria-label":"Items per page",children:[e.jsx(le,{value:25,children:"25"}),e.jsx(le,{value:50,children:"50"}),e.jsx(le,{value:100,children:"100"}),e.jsx(le,{value:0,children:"All"})]})]})]}),x.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"hidden sm:grid contacts-grid-header border-b border-edge-subtle/50 px-3 py-2 type-micro text-fg-muted",children:[e.jsx("div",{className:"contacts-col-node",children:"Node"}),e.jsx("div",{className:"contacts-col-signal text-right",children:"Signal"}),e.jsx("div",{className:"contacts-col-distance text-right",children:"Distance"}),e.jsx("div",{className:"contacts-col-centrality text-right",children:"Centrality"}),e.jsx("div",{className:"contacts-col-seen text-right",children:"Last Seen"}),e.jsx("div",{className:"contacts-col-actions"})]}),e.jsx("div",{className:"divide-y divide-edge-subtle/30",style:{contain:"layout paint"},children:Re.map(([s,a])=>{const t=U(s),r=Ke.has(s),i=ce.has(s),d=oe.get(s)??null,h=j.get(s)||0,f=i?Xe.get(s):void 0,y=t?q.get(t)??null:null,E=T.has(s),M=i?null:Qe.get(s)??null,G=We.get(s)??null,je=B.get(s);let Z=null;if(je&&je.length>0){const ie=je.reduce((rs,os)=>rs+os.count,0);ie>0&&(Z=ie/24)}const be=a.first_seen?De(a.first_seen).replace(/ ago$/i,""):null,J=[],Y=[];if(M){const ie=M.name??M.prefix;J.push(`→${ie} +${M.hopCount}`),Y.push(`Gateway: ${M.name??M.prefix} (${M.hopCount} hop${M.hopCount!==1?"s":""})`)}G&&(J.push(`↙${G}`),Y.push(`Last forwarder: ${G}`)),Z!==null&&(J.push(`${Z<1?"<1":Math.round(Z)}/hr`),Y.push(`Packet rate: ${Z.toFixed(1)}/hr`)),be&&(J.push(be),Y.push(`First seen: ${be} ago`));const as=J.join(" · "),ns=Y.join(`
`);return e.jsx(xt,{hash:s,contact:a,isHub:r,isNeighbor:i,distance:d,centrality:h,neighborSignal:f,collisionInfo:y,isViterbiResolved:A,pingingHash:pe,pingResult:Ve.get(s),pingError:Ge.get(s),isMobile:E,metaSummary:as,metaTooltip:ns,onRowClick:Ye,onPing:ts,onRemove:ss},s)})}),k>0&&V<x.length&&e.jsxs("div",{ref:fe,className:"flex items-center justify-center py-4 text-fg-muted",children:[e.jsx(ze,{className:"w-4 h-4 animate-spin mr-2"}),e.jsx("span",{className:"text-xs",children:"Loading more..."})]}),e.jsxs("div",{className:"flex items-center justify-between px-3 py-2 border-t border-edge-subtle/50 text-xs text-fg-muted",children:[e.jsxs("span",{className:"tabular-nums",children:["Showing ",Re.length," of ",x.length]}),k>0&&V<x.length&&e.jsx("button",{onClick:()=>ne(s=>Math.min(s+k,x.length)),className:"text-sys-blue hover:text-sys-blue/80 transition-base",children:"Load more"})]})]}):e.jsxs("div",{className:"roster-empty",children:[e.jsx(ee,{className:"roster-empty-icon"}),e.jsx("div",{className:"type-label text-fg-secondary",children:"No Contacts Discovered"}),e.jsx("div",{className:"type-data-xs text-fg-muted mt-1",children:"Contacts will appear here as they advertise on the mesh network."})]})]})]}),e.jsx(Qs,{isOpen:!!S,title:"Remove Contact",message:`Remove ${(S==null?void 0:S.name)||"this contact"} from the contacts list? The node will reappear if it advertises again.`,confirmLabel:"Remove",cancelLabel:"Cancel",variant:"danger",onConfirm:()=>{S&&g(S.hash),P(null)},onCancel:()=>P(null)})]})}const Dt=Object.freeze(Object.defineProperty({__proto__:null,default:jt},Symbol.toStringTag,{value:"Module"}));export{Dt as C,lt as P,Ae as R};
