const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContactsMapMapLibre-ry1U_kIq.js","assets/index-BuFgUdF6.js","assets/consumer-registry-YGO4kl9s.js","assets/link-scoring-DMBYgePn.js","assets/ConfirmModal-nA8_-uZY.js","assets/variants-DM-hs1OK.js","assets/git-branch-CfbKq2-d.js","assets/database-6NHqXCMW.js","assets/useMapViewStore-CYTMhi1e.js","assets/index-tC-yebOi.js","assets/index-CjY609r3.js","assets/target-DIUvz3Tq.js","assets/funnel-DqVoB6_M.js","assets/plus-DzDLhCtU.js","assets/compass-DF0afhxw.js","assets/zap-CcGk7ixp.js","assets/max-2s8xWRMa.js","assets/trash-2-BxJacC3X.js","assets/wifi-off-UIVfR54a.js","assets/wifi-i97D3b-F.js","assets/circle-alert-DzBa7wxQ.js","assets/clock-CiO_tPRQ.js","assets/chevron-right-Bn33xBBB.js","assets/useReplayTick-5QafLbi4.js","assets/payload-detail-C-jD4akC.js","assets/LightSparkline-D-p7t3p_.js","assets/badge-colors-Dl76Mz8m.js","assets/map-pin-DUIK7gpx.js","assets/node-types-DgK-t_34.js","assets/BasemapLayer-9KgDoniZ.js","assets/easing-DkQiIJc0.js","assets/usePipelineStore-Chyk9TCr.js","assets/PageLayout-DKfh0Blq.js","assets/listbox-CJH36T5I.js","assets/element-movement-BCAtukIF.js","assets/use-text-value-CNy_lL-R.js","assets/frozen-CKj5jrk2.js","assets/MqttModeBadge-BeRzf62U.js","assets/chat-utils-DXcrFuPC.js","assets/SignalIndicator-DlCNJ53K.js","assets/CollisionExplorerModal-ggc1GI4m.js","assets/share-2-Rt2CcEoP.js","assets/circle-question-mark-NwPFAIxO.js","assets/map-pin-off-MHnLeyVX.js","assets/activity-CU9M_dkq.js","assets/search-s6rZk7pl.js","assets/index-C9lzYVvf.css","assets/maplibre-gl-B1CfjdFi.css","assets/ContactsMapMapLibre-BwWOEply.css"])))=>i.map(i=>d[i]);
import{e as xe,ar as cs,j as e,r as n,_ as is,cp as He,cq as Ie,ao as W,a0 as Ce,cr as ls,cs as me,aa as de,c3 as ds,az as Oe,ct as ye,a2 as ze,cu as ms,ac as xs,cv as us,cw as ps,cx as hs,ab as fs,cy as gs,cz as js,ad as bs,aA as ys,ae as Ne,cA as Ns,cB as vs,cC as ws,cD as Cs,bI as ee,cE as $e,Y as ks,I as Ms,bM as Ss,c as we}from"./index-BuFgUdF6.js";import{useDiscoveredNodes as Ps}from"./usePipelineStore-Chyk9TCr.js";import{c as ke}from"./node-types-DgK-t_34.js";import{P as _s,a as Rs,B as Ls}from"./PageLayout-DKfh0Blq.js";import{L as Ts,a as le}from"./listbox-CJH36T5I.js";import{T as Fe,M as $s}from"./MqttModeBadge-BeRzf62U.js";import{u as Fs,e as Es,f as Hs,r as Is}from"./consumer-registry-YGO4kl9s.js";import{e as Os,g as zs,a as Ds}from"./chat-utils-DXcrFuPC.js";import{b as Bs}from"./SignalIndicator-DlCNJ53K.js";import{C as As}from"./CollisionExplorerModal-ggc1GI4m.js";import{E as qs,T as Vs}from"./target-DIUvz3Tq.js";import{S as Us}from"./share-2-Rt2CcEoP.js";import{C as De}from"./circle-question-mark-NwPFAIxO.js";import{M as Ws}from"./map-pin-off-MHnLeyVX.js";import{A as Be}from"./activity-CU9M_dkq.js";import{T as Gs}from"./trash-2-BxJacC3X.js";import{C as Qs}from"./ConfirmModal-nA8_-uZY.js";import{M as Xs}from"./map-pin-DUIK7gpx.js";import{S as Ys}from"./search-s6rZk7pl.js";import{C as Zs}from"./clock-CiO_tPRQ.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"}]],Ks=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-ry1U_kIq.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]))),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=Ie(),[T,$]=n.useState(!1),w=n.useMemo(()=>W(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),D=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:D,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(qs,{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(As,{isOpen:!0,prefix:p.prefix,candidateHashes:p.candidateHashes,onClose:B})]})}const lt=n.memo(it),qe=[{target:"Contacts",fn:"name",minStage:1,when:Es},{target:"Contacts",fn:"traceLinks.directed",minStage:2,when:Hs}];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:D,metaSummary:B,metaTooltip:A,onRowClick:q,onPing:S,onRemove:P}){Fs(qe);const _=l.latitude&&l.longitude&&l.latitude!==0&&l.longitude!==0,H=l.node_name||l.name||"Unknown",I=u&&c,se=ke(l),{isRepeater:v,isCompanion:G,isRoomServer:R,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":""} ${_?"cursor-pointer":""}`,onClick:ae,children:[e.jsxs("div",{className:"contacts-col-node flex items-center gap-2 min-w-0",children:[I&&(c==null?void 0:c.avgSnr)!==null?e.jsx("div",{className:`w-2 h-2 rounded-full flex-shrink-0 self-center ${ls(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(R&&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(Us,{className:"w-2.5 h-2.5 absolute -bottom-0.5 -right-0.5 text-sys-teal"})]});if(R)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((G||Q)&&H!=="Unknown"){const{emoji:F,cleanName:ue}=Os(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:Ds(H)})})}return e.jsx("div",{className:"w-6 h-6 rounded-full flex items-center justify-center bg-zinc-500/20",children:e.jsx(De,{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"}),R&&e.jsx("span",{className:"contact-tag contact-tag--room",children:"ROOM"}),G&&e.jsx("span",{className:"contact-tag contact-tag--comp",children:"COMP"}),Q&&e.jsx("span",{className:"contact-tag contact-tag--client",children:"CLIENT"}),D&&e.jsx("span",{className:"contact-tag contact-tag--mobile",children:"MOB"}),!_&&e.jsx(Ws,{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(ds,{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:[I&&(c==null?void 0:c.avgRssi)!==null&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Bs,{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)})]}),I&&(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?Oe(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(Vs,{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(Gs,{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}=ms(),l=xs(),g=us(),u=ps(),j=hs(),N=fs(),c=gs(),T=js(),$=bs(),w=ys(),p=Ne[$],C=He(),D=Ie(),B=Ns(),A=D.totalPaths>0&&D.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),[_,H]=n.useState("lastHeard"),[I,se]=n.useState("desc"),[v,G]=n.useState(""),[R,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),[Ue,X]=n.useState(new Map),[k,We]=n.useState(25),[V,ne]=n.useState(25),fe=n.useRef(null),Y=n.useMemo(()=>(o==null?void 0:o.neighbors)??{},[o==null?void 0:o.neighbors]),ge=Ps(),re=n.useMemo(()=>{if(ge.size===0)return Y;const s=new Set;for(const t of Object.keys(Y))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={...Y}),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??Y},[Y,ge]),O=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=vs(),z=o==null?void 0:o.local_hash,Ge=n.useMemo(()=>{const s=new Map;if(!z||c.size===0)return s;for(const[a,t]of c)if(a.endsWith(`→${z}`)&&t.hops.length>1){const r=a.split("→")[0],i=t.hops[t.hops.length-1];s.set(r,i)}return s},[c,z]),Qe=n.useMemo(()=>{const s=new Map;if(!z||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(`→${z}`)||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,z,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(O))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},[O,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=R||a,r=b.size>0;return Object.fromEntries(Object.entries(O).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=W(i).toLowerCase();return h.includes(s)||f.includes(s)||i.toLowerCase().includes(s)}))},[O,v,R,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=W(r).toLowerCase(),E=W(d).toLowerCase(),M=y===a,U=E===a;if(M&&!U)return-1;if(U&&!M)return 1}let f=0;switch(_){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 I==="desc"?-f:f})},[Pe,_,I,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]),Ye=n.useMemo(()=>new Set(u),[u]),_e=n.useMemo(()=>k===0?x:x.slice(0,V),[x,V,k]);n.useEffect(()=>{ne(k||x.length)},[_,I,v,R,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=>{We(s),ne(s||x.length)},[x.length]),Je=n.useCallback(s=>{_===s?se(a=>a==="desc"?"asc":"desc"):(H(s),se("desc"))},[_]),Ke=n.useCallback(s=>{const a=O[s];a!=null&&a.latitude&&(a!=null&&a.longitude)&&a.latitude!==0&&a.longitude!==0&&Me(s)},[O]),es=n.useCallback(()=>{Me(null)},[]),ss=n.useCallback((s,a)=>{P({hash:s,name:a})},[]),Re=ws((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${W(s,Re)}`,i=await Cs(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,Re]);return e.jsxs(_s,{children:[e.jsx(Rs,{title:"Contacts",icon:e.jsx(ee,{}),subtitle:e.jsx($s,{}),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(De,{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(Ls,{children:[e.jsx(ct,{neighbors:O,localNode:L??void 0,localHash:z,onRemoveNode:g,selectedNodeHash:ue,onNodeSelected:es}),e.jsxs(ks,{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(Ms,{type:"search",size:"sm",value:v,onChange:s=>G(s.target.value),placeholder:"Search...",leadingIcon:e.jsx(Ys,{className:"w-3.5 h-3.5"}),trailingIcon:v?e.jsx("button",{onClick:()=>{G(""),(v.toLowerCase().trim()==="neighbor"||v.toLowerCase().trim()==="neighbors")&&Q(!1)},className:"text-fg-muted hover:text-fg-secondary",children:e.jsx(Ss,{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(!R),className:ve(R,{color:"success",border:!0}),title:R?"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(_===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}),_===s&&e.jsx(Ks,{className:we("w-3 h-3",I==="asc"&&"rotate-180")})]},s)),e.jsx("div",{className:"h-4 w-px bg-border-subtle"}),e.jsxs(Ts,{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:_e.map(([s,a])=>{const t=W(s),r=Ye.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,U=Ge.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?Oe(a.first_seen).replace(/ ago$/i,""):null,J=[],K=[];if(M){const ie=M.name??M.prefix;J.push(`→${ie} +${M.hopCount}`),K.push(`Gateway: ${M.name??M.prefix} (${M.hopCount} hop${M.hopCount!==1?"s":""})`)}U&&(J.push(`↙${U}`),K.push(`Last forwarder: ${U}`)),Z!==null&&(J.push(`${Z<1?"<1":Math.round(Z)}/hr`),K.push(`Packet rate: ${Z.toFixed(1)}/hr`)),be&&(J.push(be),K.push(`First seen: ${be} ago`));const as=J.join(" · "),ns=K.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:Ue.get(s),isMobile:E,metaSummary:as,metaTooltip:ns,onRowClick:Ke,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 ",_e.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 zt=Object.freeze(Object.defineProperty({__proto__:null,default:jt},Symbol.toStringTag,{value:"Module"}));export{zt as C,lt as P,Ae as R};
