diff --git a/frontend/dist/VERSION b/frontend/dist/VERSION index 7486fdbc..f38fc539 100644 --- a/frontend/dist/VERSION +++ b/frontend/dist/VERSION @@ -1 +1 @@ -0.7.2 +0.7.3 diff --git a/frontend/dist/assets/Contacts-BmRuXfkt.js b/frontend/dist/assets/Contacts-g8mARlhw.js similarity index 95% rename from frontend/dist/assets/Contacts-BmRuXfkt.js rename to frontend/dist/assets/Contacts-g8mARlhw.js index 2d9991ca..7ec4e6e4 100644 --- a/frontend/dist/assets/Contacts-BmRuXfkt.js +++ b/frontend/dist/assets/Contacts-g8mARlhw.js @@ -1,2 +1,2 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContactsMapMapLibre-CJeu6v4R.js","assets/index-CV7v97nI.js","assets/recharts-bmHCCfxU.js","assets/maplibre-gl-CFO9X1Ek.js","assets/index-Bmz50KcY.css","assets/maplibre-gl-DPqA1aeF.js","assets/maplibre-gl-B1CfjdFi.css","assets/HashBadge-B-tp-R60.js","assets/loader-circle-nWyQmXVo.js","assets/info-B98xpn6R.js","assets/house-DIgfF7wb.js","assets/refresh-cw-DPnajVcG.js","assets/trending-up-Cxmt7mo3.js","assets/SignalIndicator-2MpYmE16.js","assets/triangle-alert-CxqtdCr5.js","assets/zap-DSYoS0xt.js","assets/activity-3Vz0t4n3.js","assets/PageLayout-M3WtUa6t.js","assets/users-DTJBXVif.js"])))=>i.map(i=>d[i]); -import{c as e,j as t,_ as s,w as a,v as n,X as r,x as l,y as i,z as c,A as o,B as d,E as h,F as m,f as x,R as u,C as p,G as g}from"./index-CV7v97nI.js";import{b,g as j,c as y,d as v,h as f,T as N,f as w,e as k,L as C}from"./recharts-bmHCCfxU.js";import{a as M}from"./SignalIndicator-2MpYmE16.js";import{T as S}from"./triangle-alert-CxqtdCr5.js";import{T as H,Z as L,M as _}from"./zap-DSYoS0xt.js";import{A as E}from"./activity-3Vz0t4n3.js";import{T as $,N as R}from"./trending-up-Cxmt7mo3.js";import{M as A,H as P}from"./HashBadge-B-tp-R60.js";import{P as T,a as O,C as z,b as F}from"./PageLayout-M3WtUa6t.js";import{U as q}from"./users-DTJBXVif.js";const K=e("arrow-left-right",[["path",{d:"M8 3 4 7l4 4",key:"9rb6wj"}],["path",{d:"M4 7h16",key:"6tx8e3"}],["path",{d:"m16 21 4-4-4-4",key:"siv7j2"}],["path",{d:"M20 17H4",key:"h6l3hr"}]]),D=e("arrow-up-down",[["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"}]]),B=e("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]),W=e("git-branch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]),I=e("messages-square",[["path",{d:"M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z",key:"1n2ejm"}],["path",{d:"M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1",key:"1qfcsi"}]]),V=e("monitor-smartphone",[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8",key:"10dyio"}],["path",{d:"M10 19v-3.96 3.15",key:"1irgej"}],["path",{d:"M7 19h5",key:"qswx4l"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2",key:"1egngj"}]]),U=e("ruler",[["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"}]]),G=e("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]),Z=e("share-2",[["circle",{cx:"18",cy:"5",r:"3",key:"gq8acd"}],["circle",{cx:"6",cy:"12",r:"3",key:"w7nqdw"}],["circle",{cx:"18",cy:"19",r:"3",key:"1xt0gg"}],["line",{x1:"8.59",x2:"15.42",y1:"13.51",y2:"17.49",key:"47mynk"}],["line",{x1:"15.41",x2:"8.59",y1:"6.51",y2:"10.49",key:"1n3mei"}]]),Y=e("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);class J extends b.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}render(){var e;return this.state.hasError?t.jsx("div",{className:"glass-card h-[400px] flex items-center justify-center",children:t.jsxs("div",{className:"text-center text-white/50 p-4",children:[t.jsx("p",{className:"text-lg mb-2",children:"Map failed to load"}),t.jsx("p",{className:"text-sm text-white/30",children:(null==(e=this.state.error)?void 0:e.message)||"Unknown error"})]})}):this.props.children}}const Q=b.lazy(()=>s(()=>import("./ContactsMapMapLibre-CJeu6v4R.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18])));function X({neighbors:e,localNode:s,localHash:a,onRemoveNode:n,selectedNodeHash:r,onNodeSelected:l,highlightedEdgeKey:i}){return t.jsx(J,{children:t.jsx(b.Suspense,{fallback:t.jsx("div",{className:"glass-card h-[500px] flex items-center justify-center",children:t.jsx("div",{className:"text-white/50",children:"Loading map..."})}),children:t.jsx(Q,{neighbors:e,localNode:s,localHash:a,onRemoveNode:n,selectedNodeHash:r,onNodeSelected:l,highlightedEdgeKey:i})})})}function ee(e){return e>=.7?"text-accent-success":e>=.5?"text-accent-secondary":e>=.3?"text-signal-poor":"text-accent-danger"}function te(e){return`${Math.round(100*e)}%`}const se=b.memo(function({path:e,isHighlighted:s,onHighlight:a}){const n=function(e){return e>.2?{icon:t.jsx($,{className:"w-3 h-3"}),color:"text-accent-success"}:e<-.2?{icon:t.jsx(H,{className:"w-3 h-3"}),color:"text-accent-danger"}:{icon:t.jsx(_,{className:"w-3 h-3"}),color:"text-text-muted"}}(e.observationTrend),r=e.weakestLinkKey&&e.weakestLinkConfidence<.5;return t.jsxs("div",{className:"flex items-center gap-3 p-2 rounded-md transition-colors cursor-pointer "+(s?"bg-accent-primary/20 border border-accent-primary/40":"hover:bg-white/5"),onClick:()=>a(s?null:e.weakestLinkKey),children:[t.jsx("div",{className:"flex-shrink-0 w-12 text-center py-1 rounded-md "+(l=e.healthScore,l>=.7?"bg-accent-success/10":l>=.5?"bg-accent-secondary/10":l>=.3?"bg-signal-poor/10":"bg-accent-danger/10"),children:t.jsx("span",{className:`text-xs font-semibold tabular-nums ${ee(e.healthScore)}`,children:te(e.healthScore)})}),t.jsx("div",{className:"flex-1 flex items-center gap-0.5 overflow-x-auto min-w-0",children:e.hops.map((s,a)=>{var n;return t.jsxs("span",{className:"flex items-center",children:[t.jsx("span",{className:"text-[10px] font-mono px-1.5 py-0.5 rounded "+(r&&(null==(n=e.weakestLinkKey)?void 0:n.includes(s))?"bg-accent-danger/20 text-accent-danger":"bg-white/10 text-text-secondary"),children:s}),al.slice(0,e),[l,e]),d=b.useMemo(()=>0===l.length?null:{avgHealth:l.reduce((e,t)=>e+t.healthScore,0)/l.length,declining:l.filter(e=>e.observationTrend<-.2).length,weakLinks:l.filter(e=>e.weakestLinkConfidence<.5).length},[l]),h=e=>{null==s||s(e)};return 0===l.length?null:t.jsxs("div",{className:"chart-container",children:[t.jsxs("button",{onClick:()=>c(!i),className:"w-full chart-header hover:bg-white/5 transition-colors rounded-t-lg cursor-pointer",children:[t.jsxs("div",{className:"chart-title",children:[t.jsx(W,{className:"chart-title-icon"}),"Path Health",t.jsxs("span",{className:"ml-2 text-[10px] font-normal text-text-muted",children:["(",l.length," paths)"]})]}),t.jsxs("div",{className:"flex items-center gap-3",children:[d&&t.jsxs("div",{className:"flex items-center gap-3 text-[10px]",children:[t.jsxs("span",{className:`tabular-nums ${ee(d.avgHealth)}`,children:["Avg: ",te(d.avgHealth)]}),d.weakLinks>0&&t.jsxs("span",{className:"text-accent-danger flex items-center gap-1",children:[t.jsx(S,{className:"w-3 h-3"}),d.weakLinks," weak"]}),d.declining>0&&t.jsxs("span",{className:"text-signal-poor flex items-center gap-1",children:[t.jsx(H,{className:"w-3 h-3"}),d.declining," declining"]})]}),i?t.jsx(B,{className:"w-4 h-4 text-text-muted"}):t.jsx(n,{className:"w-4 h-4 text-text-muted"})]})]}),i&&t.jsxs("div",{className:"p-3 pt-0 space-y-1",children:[t.jsxs("div",{className:"flex items-center gap-4 text-[10px] text-text-muted pb-2 border-b border-white/5",children:[t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-success"})," Healthy (≥70%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-secondary"})," Fair (50-70%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-signal-poor"})," Weak (30-50%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-danger"})," Critical (<30%)"]})]}),t.jsx("div",{className:"space-y-1 max-h-64 overflow-y-auto",children:o.map(e=>t.jsx(se,{path:e,isHighlighted:r===e.weakestLinkKey,onHighlight:h},e.pathKey))}),l.length>e&&t.jsxs("div",{className:"text-center text-[10px] text-text-muted pt-2",children:["Showing top ",e," of ",l.length," paths"]})]})]})}),ne=b.memo(function({isOpen:e,title:s="Confirm",message:a,confirmLabel:n="Confirm",cancelLabel:l="Cancel",variant:i="default",onConfirm:c,onCancel:o}){if(b.useEffect(()=>{if(!e)return;const t=e=>{"Escape"===e.key&&o()};window.addEventListener("keydown",t);const s=document.body.style.overflow,a=document.body.style.position,n=document.body.style.width,r=document.body.style.top,l=window.scrollY;return document.body.style.overflow="hidden",document.body.style.position="fixed",document.body.style.width="100%",document.body.style.top=`-${l}px`,()=>{window.removeEventListener("keydown",t),document.body.style.overflow=s,document.body.style.position=a,document.body.style.width=n,document.body.style.top=r,window.scrollTo(0,l)}},[e,o]),!e)return null;const d={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:bg-red-600"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:bg-yellow-600 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:bg-violet-500 text-bg-body"}}[i];return j.createPortal(t.jsx("div",{className:"fixed inset-0 bg-black/40 backdrop-blur-md z-[10010] flex items-end sm:items-center justify-center",onClick:o,role:"dialog","aria-modal":"true","aria-labelledby":"confirm-modal-title",children:t.jsxs("div",{className:y("glass-card w-full max-w-sm overflow-hidden","sm:mx-4 sm:rounded-xl","rounded-t-2xl rounded-b-none sm:rounded-b-xl","pb-safe"),onClick:e=>e.stopPropagation(),children:[t.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-border-subtle",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:y("p-2 rounded-lg bg-bg-subtle",d.icon),children:t.jsx(S,{className:"w-5 h-5"})}),t.jsx("h3",{id:"confirm-modal-title",className:"text-base font-semibold text-text-primary",children:s})]}),t.jsx("button",{onClick:o,className:"p-2 rounded-lg text-text-muted hover:text-text-primary hover:bg-bg-subtle transition-colors",children:t.jsx(r,{className:"w-5 h-5"})})]}),t.jsx("div",{className:"p-4",children:t.jsx("p",{className:"text-sm text-text-secondary",children:a})}),t.jsxs("div",{className:"flex gap-3 p-4 pt-0",children:[t.jsx("button",{onClick:o,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:l}),t.jsx("button",{onClick:c,className:y("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",d.button),children:n})]})]})}),document.body)}),re="var(--signal-critical)",le="var(--signal-poor)",ie="var(--signal-fair)",ce="var(--signal-good)",oe="var(--signal-excellent)",de="var(--text-muted)";function he({active:e,payload:s}){if(!e||!s||!s.length)return null;const a=s[0].payload,n=new Date(a.timestamp),r=`${(n.getMonth()+1).toString().padStart(2,"0")}/${n.getDate().toString().padStart(2,"0")}`;return t.jsxs("div",{className:"bg-bg-surface/95 border border-border-subtle rounded px-1.5 py-0.5 text-[10px] shadow-lg",children:[t.jsx("span",{className:"text-text-muted",children:r}),t.jsx("span",{className:"ml-1.5 font-semibold tabular-nums",children:a.count})]})}function me({nodeHash:e,width:s=60,height:a=20,color:n,showArea:r=!0,showTooltip:c=!1,className:o=""}){const d=l(e),h=i(),m=n??(d.length>0?function(e){if(0===e.length)return re;const t=e.slice(-4),s=t.reduce((e,t)=>e+t.count,0),a=s/t.length,n=e.reduce((e,t)=>e+t.count,0)/e.length;if(0===s)return re;if(n>0){const e=a/n;return e>=1.2?oe:e>=.8?ce:e>=.4?ie:e>=.1?le:re}return s>=10?oe:s>=5?ce:s>=2?ie:s>=1?le:re}(d):de),x={width:s,height:a};if(d.length<2){const e="number"==typeof s?s:60,n=h?de:re;return t.jsx("div",{className:`flex items-center justify-center ${o}`,style:{...x,color:n},children:t.jsx("svg",{width:"100%",height:a,viewBox:`0 0 ${e} ${a}`,preserveAspectRatio:"none",children:t.jsx("line",{x1:4,y1:a/2,x2:e-4,y2:a/2,stroke:"currentColor",strokeWidth:1.5,strokeDasharray:"3,2",className:h?"animate-pulse":""})})})}const u=`sparkline-gradient-${e.slice(-6)}`;return t.jsx("div",{className:o,style:x,children:t.jsx(v,{width:"100%",height:"100%",children:r?t.jsxs(f,{data:d,margin:{top:1,right:1,bottom:1,left:1},children:[t.jsx("defs",{children:t.jsxs("linearGradient",{id:u,x1:"0",y1:"0",x2:"0",y2:"1",children:[t.jsx("stop",{offset:"0%",stopColor:m,stopOpacity:.35}),t.jsx("stop",{offset:"100%",stopColor:m,stopOpacity:.05})]})}),c&&t.jsx(N,{content:t.jsx(he,{}),cursor:{stroke:"rgba(255,255,255,0.2)",strokeWidth:1}}),t.jsx(w,{type:"monotone",dataKey:"count",stroke:"none",fill:`url(#${u})`,isAnimationActive:!1}),t.jsx(k,{type:"monotone",dataKey:"count",stroke:m,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]}):t.jsxs(C,{data:d,margin:{top:1,right:1,bottom:1,left:1},children:[c&&t.jsx(N,{content:t.jsx(he,{}),cursor:{stroke:"rgba(255,255,255,0.2)",strokeWidth:1}}),t.jsx(k,{type:"monotone",dataKey:"count",stroke:m,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]})})})}function xe(e,t,s,a){const n=(s-e)*Math.PI/180,r=(a-t)*Math.PI/180,l=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e*Math.PI/180)*Math.cos(s*Math.PI/180)*Math.sin(r/2)*Math.sin(r/2);return 2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l))*6371e3}const ue=Object.freeze(Object.defineProperty({__proto__:null,default:function(){const{stats:e}=c(),s=o(),a=d(),n=h(),l=m(),i=x(),[j,y]=b.useState(null),[v,f]=b.useState("lastHeard"),[N,w]=b.useState("desc"),[k,C]=b.useState(""),[S,H]=b.useState(!1),[L,_]=b.useState(null),[$,B]=b.useState(null),W=b.useMemo(()=>(null==e?void 0:e.neighbors)??{},[null==e?void 0:e.neighbors]),J=b.useMemo(()=>Object.fromEntries(Object.entries(W).filter(([e])=>!s.has(e))),[W,s]),Q=b.useMemo(()=>{var t;return(null==(t=null==e?void 0:e.config)?void 0:t.repeater)?{latitude:e.config.repeater.latitude,longitude:e.config.repeater.longitude,name:e.config.node_name||"Local Node"}:void 0},[e]),ee=null==e?void 0:e.local_hash,te=b.useMemo(()=>{const e=new Map;if(!(null==Q?void 0:Q.latitude)||!(null==Q?void 0:Q.longitude))return e;for(const[t,s]of Object.entries(J))s.latitude&&s.longitude&&0!==s.latitude&&0!==s.longitude?e.set(t,xe(Q.latitude,Q.longitude,s.latitude,s.longitude)):e.set(t,null);return e},[J,Q]),{neighborHashSet:se,neighborSignalMap:re}=b.useMemo(()=>{const e=new Set,t=new Map;for(const s of i)e.add(s.hash),t.set(s.hash,{avgRssi:s.avgRssi,avgSnr:s.avgSnr});return{neighborHashSet:e,neighborSignalMap:t}},[i]),le=b.useMemo(()=>{const e=k.toLowerCase().trim(),t="neighbor"===e||"neighbors"===e,s=S||t;return Object.fromEntries(Object.entries(J).filter(([a,n])=>{if(s&&!se.has(a))return!1;if(t)return!0;if(!e)return!0;const r=(n.node_name||n.name||"").toLowerCase(),l=a.slice(2,4).toLowerCase();return r.includes(e)||l.includes(e)||a.toLowerCase().includes(e)}))},[J,k,S,se]),ie=b.useMemo(()=>Object.entries(le).sort(([e,t],[s,a])=>{let n=0;switch(v){case"lastHeard":n=(t.last_seen||0)-(a.last_seen||0);break;case"distance":{const t=te.get(e)??null,a=te.get(s)??null;n=null===t&&null===a?0:null===t?1:null===a?-1:t-a;break}case"centrality":n=(l.get(e)||0)-(l.get(s)||0)}return"desc"===N?-n:n}),[le,v,N,te,l]),ce=ie.filter(([,e])=>e.latitude&&e.longitude&&0!==e.latitude&&0!==e.longitude).length,oe=b.useMemo(()=>new Set(n),[n]),de=b.useCallback(e=>{v===e?w(e=>"desc"===e?"asc":"desc"):(f(e),w("desc"))},[v]),he=b.useCallback(e=>{const t=J[e];(null==t?void 0:t.latitude)&&(null==t?void 0:t.longitude)&&0!==t.latitude&&0!==t.longitude&&_(e)},[J]),ue=b.useCallback(()=>{_(null)},[]);return t.jsxs(T,{children:[t.jsx(O,{title:"Contacts",icon:t.jsx(q,{}),controls:t.jsxs("div",{className:"flex items-baseline gap-3 sm:gap-4",children:[t.jsxs("span",{className:"roster-title tabular-nums",children:[ie.length," node",1!==ie.length?"s":""]}),ce>0&&t.jsxs("span",{className:"roster-title flex items-baseline gap-1.5 tabular-nums",children:[t.jsx(A,{className:"w-3.5 h-3.5 relative top-[2px]"}),ce," with location"]})]})}),t.jsx("div",{className:"relative",children:t.jsx(X,{neighbors:J,localNode:Q,localHash:ee,onRemoveNode:a,selectedNodeHash:L,onNodeSelected:ue,highlightedEdgeKey:$})}),t.jsx(ae,{maxPaths:10,highlightedEdge:$,onHighlightEdge:B}),t.jsxs(z,{noPadding:!0,children:[t.jsx(F,{listHeader:!0,icon:t.jsx(q,{className:"icon-sm"}),title:"Discovered Contacts",actions:t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[se.size>0&&t.jsxs("button",{onClick:()=>H(!S),className:"flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] order-1 sm:order-1 "+(S?"bg-accent-success/20 text-accent-success border border-accent-success/30":"text-text-muted hover:text-text-secondary hover:bg-white/5 border border-transparent"),title:S?"Show all contacts":"Show only MeshCore neighbors (direct RF contact)",children:[t.jsx(u,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Neighbors"}),t.jsx("span",{className:"sm:hidden",children:se.size}),S&&t.jsx("span",{className:"text-[10px] font-semibold tabular-nums",children:se.size})]}),t.jsxs("div",{className:"relative order-2 sm:order-2",children:[t.jsx(G,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-text-muted"}),t.jsx("input",{type:"text",value:k,onChange:e=>C(e.target.value),placeholder:"Search...",className:"w-28 sm:w-32 pl-7 pr-7 py-1.5 text-xs bg-white/5 border border-white/10 rounded-lg text-text-primary placeholder:text-text-muted focus:outline-none focus:border-accent-primary/50"}),k&&t.jsx("button",{onClick:()=>{C(""),"neighbor"!==k.toLowerCase().trim()&&"neighbors"!==k.toLowerCase().trim()||H(!1)},className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-muted hover:text-text-secondary p-0.5",children:t.jsx(r,{className:"w-3.5 h-3.5"})})]}),t.jsxs("div",{className:"flex items-center gap-1 order-1 sm:order-2",children:[t.jsxs("button",{onClick:()=>de("lastHeard"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("lastHeard"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by last heard",children:[t.jsx(p,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Recent"}),"lastHeard"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]}),t.jsxs("button",{onClick:()=>de("distance"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("distance"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by distance",children:[t.jsx(U,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Distance"}),"distance"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]}),t.jsxs("button",{onClick:()=>de("centrality"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("centrality"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by network centrality",children:[t.jsx(E,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Centrality"}),"centrality"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]})]})]})}),ie.length>0?t.jsx("div",{className:"roster-list",children:ie.map(([e,s],a)=>{var n,r;const i=s.latitude&&s.longitude&&0!==s.latitude&&0!==s.longitude,c=s.node_name||s.name||"Unknown",o=oe.has(e),d=se.has(e),h=te.get(e),m=l.get(e)||0,x=d?re.get(e):void 0,u=d&&x;return t.jsxs("div",{children:[t.jsxs("div",{className:`roster-row ${o?"bg-amber-500/5 border-l-2 border-l-amber-400":""} ${i?"cursor-pointer hover:bg-white/[0.02]":""}`,onClick:()=>he(e),children:[t.jsxs("div",{className:"relative flex-shrink-0",children:[t.jsx("div",{className:"roster-icon",children:(()=>{var e;const a=null==(e=s.contact_type)?void 0:e.toLowerCase(),n="room server"===a||"room_server"===a||"room"===a||"server"===a,r="companion"===a||"client"===a||"cli"===a,l=s.is_repeater||"repeater"===a||"rep"===a,i="#4338CA",c="#F59E0B";return n&&l?t.jsxs("div",{className:"relative w-5 h-5",children:[t.jsx(I,{className:"w-5 h-5 absolute inset-0",style:{color:c}}),t.jsx(Z,{className:"w-2.5 h-2.5 absolute -bottom-0.5 -right-0.5",style:{color:i}})]}):n?t.jsx(I,{className:"w-5 h-5",style:{color:c}}):r?t.jsx(V,{className:"w-5 h-5 text-text-muted"}):l?d?t.jsx(K,{className:"w-5 h-5 text-accent-success"}):t.jsx(Z,{className:"w-5 h-5",style:{color:i}}):t.jsx(V,{className:"w-5 h-5 text-text-muted"})})()}),u&&null!==(null==x?void 0:x.avgSnr)&&t.jsx("div",{className:`absolute -top-0.5 -right-0.5 w-2.5 h-2.5 rounded-full ${b=x.avgSnr,void 0===b?"bg-[var(--signal-unknown)]":b>=5?"bg-[var(--signal-excellent)]":b>=0?"bg-[var(--signal-good)]":b>=-5?"bg-[var(--signal-fair)]":b>=-10?"bg-[var(--signal-poor)]":"bg-[var(--signal-critical)]"} border-2 border-bg-surface`})]}),t.jsxs("div",{className:"roster-content min-w-0 flex-1",children:[t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[t.jsx("span",{className:"roster-title",children:c}),d&&t.jsx("span",{className:"type-badge px-1.5 py-0.5 rounded",style:{backgroundColor:"rgba(57, 217, 138, 0.2)",color:"#39D98A"},children:"NBR"}),o&&t.jsxs("span",{className:"type-badge px-1.5 py-0.5 rounded flex items-center gap-1",style:{backgroundColor:"rgba(251, 191, 36, 0.2)",color:"#FBBF24"},children:[t.jsx(R,{className:"w-3 h-3"}),"HUB"]}),(s.is_repeater||"repeater"===(null==(n=s.contact_type)?void 0:n.toLowerCase())||"rep"===(null==(r=s.contact_type)?void 0:r.toLowerCase()))&&t.jsx("span",{className:"pill-tag",children:"RPT"})]}),t.jsx("div",{className:"hidden md:block",children:t.jsx(P,{hash:e,size:"sm",full:!0})}),t.jsx("div",{className:"md:hidden",children:t.jsx(P,{hash:e,size:"sm",prefixLength:8,suffixLength:6})})]}),t.jsxs("div",{className:"roster-metrics flex-shrink-0",children:[u&&null!==(null==x?void 0:x.avgRssi)&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(M,{rssi:x.avgRssi,className:"w-3.5 h-3.5"}),t.jsx("span",{className:"type-data-xs tabular-nums",children:Math.round(x.avgRssi)})]}),u&&null!==(null==x?void 0:x.avgSnr)&&t.jsx("div",{className:"flex items-center gap-1.5",children:t.jsxs("span",{className:"type-data-xs tabular-nums",children:[x.avgSnr.toFixed(1)," dB"]})}),null!=h&&t.jsxs("div",{className:"flex items-center gap-1 text-accent-tertiary",children:[t.jsx(U,{className:"w-3 h-3"}),t.jsx("span",{className:"type-data-xs tabular-nums",children:(p=h,p<1e3?`${Math.round(p)}m`:`${(p/1e3).toFixed(1)}km`)})]}),m>0&&t.jsxs("div",{className:"flex items-center gap-1 text-amber-400/70",children:[t.jsx(E,{className:"w-3 h-3"}),t.jsxs("span",{className:"type-data-xs tabular-nums",children:[(100*m).toFixed(0),"%"]})]}),t.jsx("div",{className:"hidden sm:block",children:t.jsx(me,{nodeHash:e,width:48,height:16})})]}),t.jsx("div",{className:"roster-metric flex-shrink-0",children:s.last_seen?g(s.last_seen):"—"}),t.jsx("button",{onClick:t=>{t.stopPropagation(),y({hash:e,name:c})},className:"ml-2 p-1.5 rounded-lg text-text-muted/50 hover:text-red-400 hover:bg-red-500/10 transition-colors flex-shrink-0",title:"Remove contact",children:t.jsx(Y,{className:"w-4 h-4"})})]}),a{j&&a(j.hash),y(null)},onCancel:()=>y(null)})]})}},Symbol.toStringTag,{value:"Module"}));export{ne as C,W as G,I as M,me as N,Y as T,ue as a}; +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ContactsMapMapLibre-DdUR4fAK.js","assets/index-B6uaIH4a.js","assets/recharts-bmHCCfxU.js","assets/maplibre-gl-CFO9X1Ek.js","assets/index-Bmz50KcY.css","assets/maplibre-gl-Cc9pteRd.js","assets/maplibre-gl-B1CfjdFi.css","assets/HashBadge-BouKPZm3.js","assets/loader-circle-BKbDVUFx.js","assets/info-BEK92J4-.js","assets/house-jkSBVqNP.js","assets/refresh-cw-DbDdP20L.js","assets/trending-up-BoIqo0NL.js","assets/SignalIndicator-B_Pu6fZk.js","assets/triangle-alert-B_JcGGdg.js","assets/zap-C9mGS9M1.js","assets/activity-BuX4vAF7.js","assets/PageLayout-Can3a9Qu.js","assets/users-sQCP36TR.js"])))=>i.map(i=>d[i]); +import{c as e,j as t,_ as s,w as a,v as n,X as r,x as l,y as i,z as c,A as o,B as d,E as h,F as m,f as x,R as u,C as p,G as g}from"./index-B6uaIH4a.js";import{b,g as j,c as y,d as v,h as f,T as N,f as w,e as k,L as C}from"./recharts-bmHCCfxU.js";import{a as M}from"./SignalIndicator-B_Pu6fZk.js";import{T as S}from"./triangle-alert-B_JcGGdg.js";import{T as H,Z as L,M as _}from"./zap-C9mGS9M1.js";import{A as E}from"./activity-BuX4vAF7.js";import{T as $,N as R}from"./trending-up-BoIqo0NL.js";import{M as A,H as P}from"./HashBadge-BouKPZm3.js";import{P as T,a as O,C as z,b as F}from"./PageLayout-Can3a9Qu.js";import{U as q}from"./users-sQCP36TR.js";const K=e("arrow-left-right",[["path",{d:"M8 3 4 7l4 4",key:"9rb6wj"}],["path",{d:"M4 7h16",key:"6tx8e3"}],["path",{d:"m16 21 4-4-4-4",key:"siv7j2"}],["path",{d:"M20 17H4",key:"h6l3hr"}]]),D=e("arrow-up-down",[["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"}]]),B=e("chevron-up",[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]]),W=e("git-branch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]),I=e("messages-square",[["path",{d:"M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z",key:"1n2ejm"}],["path",{d:"M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1",key:"1qfcsi"}]]),V=e("monitor-smartphone",[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8",key:"10dyio"}],["path",{d:"M10 19v-3.96 3.15",key:"1irgej"}],["path",{d:"M7 19h5",key:"qswx4l"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2",key:"1egngj"}]]),U=e("ruler",[["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"}]]),G=e("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]),Z=e("share-2",[["circle",{cx:"18",cy:"5",r:"3",key:"gq8acd"}],["circle",{cx:"6",cy:"12",r:"3",key:"w7nqdw"}],["circle",{cx:"18",cy:"19",r:"3",key:"1xt0gg"}],["line",{x1:"8.59",x2:"15.42",y1:"13.51",y2:"17.49",key:"47mynk"}],["line",{x1:"15.41",x2:"8.59",y1:"6.51",y2:"10.49",key:"1n3mei"}]]),Y=e("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);class J extends b.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}render(){var e;return this.state.hasError?t.jsx("div",{className:"glass-card h-[400px] flex items-center justify-center",children:t.jsxs("div",{className:"text-center text-white/50 p-4",children:[t.jsx("p",{className:"text-lg mb-2",children:"Map failed to load"}),t.jsx("p",{className:"text-sm text-white/30",children:(null==(e=this.state.error)?void 0:e.message)||"Unknown error"})]})}):this.props.children}}const Q=b.lazy(()=>s(()=>import("./ContactsMapMapLibre-DdUR4fAK.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18])));function X({neighbors:e,localNode:s,localHash:a,onRemoveNode:n,selectedNodeHash:r,onNodeSelected:l,highlightedEdgeKey:i}){return t.jsx(J,{children:t.jsx(b.Suspense,{fallback:t.jsx("div",{className:"glass-card h-[500px] flex items-center justify-center",children:t.jsx("div",{className:"text-white/50",children:"Loading map..."})}),children:t.jsx(Q,{neighbors:e,localNode:s,localHash:a,onRemoveNode:n,selectedNodeHash:r,onNodeSelected:l,highlightedEdgeKey:i})})})}function ee(e){return e>=.7?"text-accent-success":e>=.5?"text-accent-secondary":e>=.3?"text-signal-poor":"text-accent-danger"}function te(e){return`${Math.round(100*e)}%`}const se=b.memo(function({path:e,isHighlighted:s,onHighlight:a}){const n=function(e){return e>.2?{icon:t.jsx($,{className:"w-3 h-3"}),color:"text-accent-success"}:e<-.2?{icon:t.jsx(H,{className:"w-3 h-3"}),color:"text-accent-danger"}:{icon:t.jsx(_,{className:"w-3 h-3"}),color:"text-text-muted"}}(e.observationTrend),r=e.weakestLinkKey&&e.weakestLinkConfidence<.5;return t.jsxs("div",{className:"flex items-center gap-3 p-2 rounded-md transition-colors cursor-pointer "+(s?"bg-accent-primary/20 border border-accent-primary/40":"hover:bg-white/5"),onClick:()=>a(s?null:e.weakestLinkKey),children:[t.jsx("div",{className:"flex-shrink-0 w-12 text-center py-1 rounded-md "+(l=e.healthScore,l>=.7?"bg-accent-success/10":l>=.5?"bg-accent-secondary/10":l>=.3?"bg-signal-poor/10":"bg-accent-danger/10"),children:t.jsx("span",{className:`text-xs font-semibold tabular-nums ${ee(e.healthScore)}`,children:te(e.healthScore)})}),t.jsx("div",{className:"flex-1 flex items-center gap-0.5 overflow-x-auto min-w-0",children:e.hops.map((s,a)=>{var n;return t.jsxs("span",{className:"flex items-center",children:[t.jsx("span",{className:"text-[10px] font-mono px-1.5 py-0.5 rounded "+(r&&(null==(n=e.weakestLinkKey)?void 0:n.includes(s))?"bg-accent-danger/20 text-accent-danger":"bg-white/10 text-text-secondary"),children:s}),al.slice(0,e),[l,e]),d=b.useMemo(()=>0===l.length?null:{avgHealth:l.reduce((e,t)=>e+t.healthScore,0)/l.length,declining:l.filter(e=>e.observationTrend<-.2).length,weakLinks:l.filter(e=>e.weakestLinkConfidence<.5).length},[l]),h=e=>{null==s||s(e)};return 0===l.length?null:t.jsxs("div",{className:"chart-container",children:[t.jsxs("button",{onClick:()=>c(!i),className:"w-full chart-header hover:bg-white/5 transition-colors rounded-t-lg cursor-pointer",children:[t.jsxs("div",{className:"chart-title",children:[t.jsx(W,{className:"chart-title-icon"}),"Path Health",t.jsxs("span",{className:"ml-2 text-[10px] font-normal text-text-muted",children:["(",l.length," paths)"]})]}),t.jsxs("div",{className:"flex items-center gap-3",children:[d&&t.jsxs("div",{className:"flex items-center gap-3 text-[10px]",children:[t.jsxs("span",{className:`tabular-nums ${ee(d.avgHealth)}`,children:["Avg: ",te(d.avgHealth)]}),d.weakLinks>0&&t.jsxs("span",{className:"text-accent-danger flex items-center gap-1",children:[t.jsx(S,{className:"w-3 h-3"}),d.weakLinks," weak"]}),d.declining>0&&t.jsxs("span",{className:"text-signal-poor flex items-center gap-1",children:[t.jsx(H,{className:"w-3 h-3"}),d.declining," declining"]})]}),i?t.jsx(B,{className:"w-4 h-4 text-text-muted"}):t.jsx(n,{className:"w-4 h-4 text-text-muted"})]})]}),i&&t.jsxs("div",{className:"p-3 pt-0 space-y-1",children:[t.jsxs("div",{className:"flex items-center gap-4 text-[10px] text-text-muted pb-2 border-b border-white/5",children:[t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-success"})," Healthy (≥70%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-secondary"})," Fair (50-70%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-signal-poor"})," Weak (30-50%)"]}),t.jsxs("span",{className:"flex items-center gap-1",children:[t.jsx("span",{className:"w-2 h-2 rounded-full bg-accent-danger"})," Critical (<30%)"]})]}),t.jsx("div",{className:"space-y-1 max-h-64 overflow-y-auto",children:o.map(e=>t.jsx(se,{path:e,isHighlighted:r===e.weakestLinkKey,onHighlight:h},e.pathKey))}),l.length>e&&t.jsxs("div",{className:"text-center text-[10px] text-text-muted pt-2",children:["Showing top ",e," of ",l.length," paths"]})]})]})}),ne=b.memo(function({isOpen:e,title:s="Confirm",message:a,confirmLabel:n="Confirm",cancelLabel:l="Cancel",variant:i="default",onConfirm:c,onCancel:o}){if(b.useEffect(()=>{if(!e)return;const t=e=>{"Escape"===e.key&&o()};window.addEventListener("keydown",t);const s=document.body.style.overflow,a=document.body.style.position,n=document.body.style.width,r=document.body.style.top,l=window.scrollY;return document.body.style.overflow="hidden",document.body.style.position="fixed",document.body.style.width="100%",document.body.style.top=`-${l}px`,()=>{window.removeEventListener("keydown",t),document.body.style.overflow=s,document.body.style.position=a,document.body.style.width=n,document.body.style.top=r,window.scrollTo(0,l)}},[e,o]),!e)return null;const d={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:bg-red-600"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:bg-yellow-600 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:bg-violet-500 text-bg-body"}}[i];return j.createPortal(t.jsx("div",{className:"fixed inset-0 bg-black/40 backdrop-blur-md z-[10010] flex items-end sm:items-center justify-center",onClick:o,role:"dialog","aria-modal":"true","aria-labelledby":"confirm-modal-title",children:t.jsxs("div",{className:y("glass-card w-full max-w-sm overflow-hidden","sm:mx-4 sm:rounded-xl","rounded-t-2xl rounded-b-none sm:rounded-b-xl","pb-safe"),onClick:e=>e.stopPropagation(),children:[t.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-border-subtle",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx("div",{className:y("p-2 rounded-lg bg-bg-subtle",d.icon),children:t.jsx(S,{className:"w-5 h-5"})}),t.jsx("h3",{id:"confirm-modal-title",className:"text-base font-semibold text-text-primary",children:s})]}),t.jsx("button",{onClick:o,className:"p-2 rounded-lg text-text-muted hover:text-text-primary hover:bg-bg-subtle transition-colors",children:t.jsx(r,{className:"w-5 h-5"})})]}),t.jsx("div",{className:"p-4",children:t.jsx("p",{className:"text-sm text-text-secondary",children:a})}),t.jsxs("div",{className:"flex gap-3 p-4 pt-0",children:[t.jsx("button",{onClick:o,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:l}),t.jsx("button",{onClick:c,className:y("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",d.button),children:n})]})]})}),document.body)}),re="var(--signal-critical)",le="var(--signal-poor)",ie="var(--signal-fair)",ce="var(--signal-good)",oe="var(--signal-excellent)",de="var(--text-muted)";function he({active:e,payload:s}){if(!e||!s||!s.length)return null;const a=s[0].payload,n=new Date(a.timestamp),r=`${(n.getMonth()+1).toString().padStart(2,"0")}/${n.getDate().toString().padStart(2,"0")}`;return t.jsxs("div",{className:"bg-bg-surface/95 border border-border-subtle rounded px-1.5 py-0.5 text-[10px] shadow-lg",children:[t.jsx("span",{className:"text-text-muted",children:r}),t.jsx("span",{className:"ml-1.5 font-semibold tabular-nums",children:a.count})]})}function me({nodeHash:e,width:s=60,height:a=20,color:n,showArea:r=!0,showTooltip:c=!1,className:o=""}){const d=l(e),h=i(),m=n??(d.length>0?function(e){if(0===e.length)return re;const t=e.slice(-4),s=t.reduce((e,t)=>e+t.count,0),a=s/t.length,n=e.reduce((e,t)=>e+t.count,0)/e.length;if(0===s)return re;if(n>0){const e=a/n;return e>=1.2?oe:e>=.8?ce:e>=.4?ie:e>=.1?le:re}return s>=10?oe:s>=5?ce:s>=2?ie:s>=1?le:re}(d):de),x={width:s,height:a};if(d.length<2){const e="number"==typeof s?s:60,n=h?de:re;return t.jsx("div",{className:`flex items-center justify-center ${o}`,style:{...x,color:n},children:t.jsx("svg",{width:"100%",height:a,viewBox:`0 0 ${e} ${a}`,preserveAspectRatio:"none",children:t.jsx("line",{x1:4,y1:a/2,x2:e-4,y2:a/2,stroke:"currentColor",strokeWidth:1.5,strokeDasharray:"3,2",className:h?"animate-pulse":""})})})}const u=`sparkline-gradient-${e.slice(-6)}`;return t.jsx("div",{className:o,style:x,children:t.jsx(v,{width:"100%",height:"100%",children:r?t.jsxs(f,{data:d,margin:{top:1,right:1,bottom:1,left:1},children:[t.jsx("defs",{children:t.jsxs("linearGradient",{id:u,x1:"0",y1:"0",x2:"0",y2:"1",children:[t.jsx("stop",{offset:"0%",stopColor:m,stopOpacity:.35}),t.jsx("stop",{offset:"100%",stopColor:m,stopOpacity:.05})]})}),c&&t.jsx(N,{content:t.jsx(he,{}),cursor:{stroke:"rgba(255,255,255,0.2)",strokeWidth:1}}),t.jsx(w,{type:"monotone",dataKey:"count",stroke:"none",fill:`url(#${u})`,isAnimationActive:!1}),t.jsx(k,{type:"monotone",dataKey:"count",stroke:m,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]}):t.jsxs(C,{data:d,margin:{top:1,right:1,bottom:1,left:1},children:[c&&t.jsx(N,{content:t.jsx(he,{}),cursor:{stroke:"rgba(255,255,255,0.2)",strokeWidth:1}}),t.jsx(k,{type:"monotone",dataKey:"count",stroke:m,strokeWidth:1.5,dot:!1,isAnimationActive:!1})]})})})}function xe(e,t,s,a){const n=(s-e)*Math.PI/180,r=(a-t)*Math.PI/180,l=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e*Math.PI/180)*Math.cos(s*Math.PI/180)*Math.sin(r/2)*Math.sin(r/2);return 2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l))*6371e3}const ue=Object.freeze(Object.defineProperty({__proto__:null,default:function(){const{stats:e}=c(),s=o(),a=d(),n=h(),l=m(),i=x(),[j,y]=b.useState(null),[v,f]=b.useState("lastHeard"),[N,w]=b.useState("desc"),[k,C]=b.useState(""),[S,H]=b.useState(!1),[L,_]=b.useState(null),[$,B]=b.useState(null),W=b.useMemo(()=>(null==e?void 0:e.neighbors)??{},[null==e?void 0:e.neighbors]),J=b.useMemo(()=>Object.fromEntries(Object.entries(W).filter(([e])=>!s.has(e))),[W,s]),Q=b.useMemo(()=>{var t;return(null==(t=null==e?void 0:e.config)?void 0:t.repeater)?{latitude:e.config.repeater.latitude,longitude:e.config.repeater.longitude,name:e.config.node_name||"Local Node"}:void 0},[e]),ee=null==e?void 0:e.local_hash,te=b.useMemo(()=>{const e=new Map;if(!(null==Q?void 0:Q.latitude)||!(null==Q?void 0:Q.longitude))return e;for(const[t,s]of Object.entries(J))s.latitude&&s.longitude&&0!==s.latitude&&0!==s.longitude?e.set(t,xe(Q.latitude,Q.longitude,s.latitude,s.longitude)):e.set(t,null);return e},[J,Q]),{neighborHashSet:se,neighborSignalMap:re}=b.useMemo(()=>{const e=new Set,t=new Map;for(const s of i)e.add(s.hash),t.set(s.hash,{avgRssi:s.avgRssi,avgSnr:s.avgSnr});return{neighborHashSet:e,neighborSignalMap:t}},[i]),le=b.useMemo(()=>{const e=k.toLowerCase().trim(),t="neighbor"===e||"neighbors"===e,s=S||t;return Object.fromEntries(Object.entries(J).filter(([a,n])=>{if(s&&!se.has(a))return!1;if(t)return!0;if(!e)return!0;const r=(n.node_name||n.name||"").toLowerCase(),l=a.slice(2,4).toLowerCase();return r.includes(e)||l.includes(e)||a.toLowerCase().includes(e)}))},[J,k,S,se]),ie=b.useMemo(()=>Object.entries(le).sort(([e,t],[s,a])=>{let n=0;switch(v){case"lastHeard":n=(t.last_seen||0)-(a.last_seen||0);break;case"distance":{const t=te.get(e)??null,a=te.get(s)??null;n=null===t&&null===a?0:null===t?1:null===a?-1:t-a;break}case"centrality":n=(l.get(e)||0)-(l.get(s)||0)}return"desc"===N?-n:n}),[le,v,N,te,l]),ce=ie.filter(([,e])=>e.latitude&&e.longitude&&0!==e.latitude&&0!==e.longitude).length,oe=b.useMemo(()=>new Set(n),[n]),de=b.useCallback(e=>{v===e?w(e=>"desc"===e?"asc":"desc"):(f(e),w("desc"))},[v]),he=b.useCallback(e=>{const t=J[e];(null==t?void 0:t.latitude)&&(null==t?void 0:t.longitude)&&0!==t.latitude&&0!==t.longitude&&_(e)},[J]),ue=b.useCallback(()=>{_(null)},[]);return t.jsxs(T,{children:[t.jsx(O,{title:"Contacts",icon:t.jsx(q,{}),controls:t.jsxs("div",{className:"flex items-baseline gap-3 sm:gap-4",children:[t.jsxs("span",{className:"roster-title tabular-nums",children:[ie.length," node",1!==ie.length?"s":""]}),ce>0&&t.jsxs("span",{className:"roster-title flex items-baseline gap-1.5 tabular-nums",children:[t.jsx(A,{className:"w-3.5 h-3.5 relative top-[2px]"}),ce," with location"]})]})}),t.jsx("div",{className:"relative",children:t.jsx(X,{neighbors:J,localNode:Q,localHash:ee,onRemoveNode:a,selectedNodeHash:L,onNodeSelected:ue,highlightedEdgeKey:$})}),t.jsx(ae,{maxPaths:10,highlightedEdge:$,onHighlightEdge:B}),t.jsxs(z,{noPadding:!0,children:[t.jsx(F,{listHeader:!0,icon:t.jsx(q,{className:"icon-sm"}),title:"Discovered Contacts",actions:t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[se.size>0&&t.jsxs("button",{onClick:()=>H(!S),className:"flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] order-1 sm:order-1 "+(S?"bg-accent-success/20 text-accent-success border border-accent-success/30":"text-text-muted hover:text-text-secondary hover:bg-white/5 border border-transparent"),title:S?"Show all contacts":"Show only MeshCore neighbors (direct RF contact)",children:[t.jsx(u,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Neighbors"}),t.jsx("span",{className:"sm:hidden",children:se.size}),S&&t.jsx("span",{className:"text-[10px] font-semibold tabular-nums",children:se.size})]}),t.jsxs("div",{className:"relative order-2 sm:order-2",children:[t.jsx(G,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-text-muted"}),t.jsx("input",{type:"text",value:k,onChange:e=>C(e.target.value),placeholder:"Search...",className:"w-28 sm:w-32 pl-7 pr-7 py-1.5 text-xs bg-white/5 border border-white/10 rounded-lg text-text-primary placeholder:text-text-muted focus:outline-none focus:border-accent-primary/50"}),k&&t.jsx("button",{onClick:()=>{C(""),"neighbor"!==k.toLowerCase().trim()&&"neighbors"!==k.toLowerCase().trim()||H(!1)},className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-muted hover:text-text-secondary p-0.5",children:t.jsx(r,{className:"w-3.5 h-3.5"})})]}),t.jsxs("div",{className:"flex items-center gap-1 order-1 sm:order-2",children:[t.jsxs("button",{onClick:()=>de("lastHeard"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("lastHeard"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by last heard",children:[t.jsx(p,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Recent"}),"lastHeard"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]}),t.jsxs("button",{onClick:()=>de("distance"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("distance"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by distance",children:[t.jsx(U,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Distance"}),"distance"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]}),t.jsxs("button",{onClick:()=>de("centrality"),className:"flex items-center gap-1 px-2.5 py-1.5 text-xs rounded-lg transition-colors min-h-[32px] "+("centrality"===v?"bg-accent-primary/20 text-accent-primary":"text-text-muted hover:text-text-secondary hover:bg-white/5"),title:"Sort by network centrality",children:[t.jsx(E,{className:"w-3.5 h-3.5"}),t.jsx("span",{className:"hidden sm:inline",children:"Centrality"}),"centrality"===v&&t.jsx(D,{className:"w-3 h-3 "+("asc"===N?"rotate-180":"")})]})]})]})}),ie.length>0?t.jsx("div",{className:"roster-list",children:ie.map(([e,s],a)=>{var n,r;const i=s.latitude&&s.longitude&&0!==s.latitude&&0!==s.longitude,c=s.node_name||s.name||"Unknown",o=oe.has(e),d=se.has(e),h=te.get(e),m=l.get(e)||0,x=d?re.get(e):void 0,u=d&&x;return t.jsxs("div",{children:[t.jsxs("div",{className:`roster-row ${o?"bg-amber-500/5 border-l-2 border-l-amber-400":""} ${i?"cursor-pointer hover:bg-white/[0.02]":""}`,onClick:()=>he(e),children:[t.jsxs("div",{className:"relative flex-shrink-0",children:[t.jsx("div",{className:"roster-icon",children:(()=>{var e;const a=null==(e=s.contact_type)?void 0:e.toLowerCase(),n="room server"===a||"room_server"===a||"room"===a||"server"===a,r="companion"===a||"client"===a||"cli"===a,l=s.is_repeater||"repeater"===a||"rep"===a,i="#4338CA",c="#F59E0B";return n&&l?t.jsxs("div",{className:"relative w-5 h-5",children:[t.jsx(I,{className:"w-5 h-5 absolute inset-0",style:{color:c}}),t.jsx(Z,{className:"w-2.5 h-2.5 absolute -bottom-0.5 -right-0.5",style:{color:i}})]}):n?t.jsx(I,{className:"w-5 h-5",style:{color:c}}):r?t.jsx(V,{className:"w-5 h-5 text-text-muted"}):l?d?t.jsx(K,{className:"w-5 h-5 text-accent-success"}):t.jsx(Z,{className:"w-5 h-5",style:{color:i}}):t.jsx(V,{className:"w-5 h-5 text-text-muted"})})()}),u&&null!==(null==x?void 0:x.avgSnr)&&t.jsx("div",{className:`absolute -top-0.5 -right-0.5 w-2.5 h-2.5 rounded-full ${b=x.avgSnr,void 0===b?"bg-[var(--signal-unknown)]":b>=5?"bg-[var(--signal-excellent)]":b>=0?"bg-[var(--signal-good)]":b>=-5?"bg-[var(--signal-fair)]":b>=-10?"bg-[var(--signal-poor)]":"bg-[var(--signal-critical)]"} border-2 border-bg-surface`})]}),t.jsxs("div",{className:"roster-content min-w-0 flex-1",children:[t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[t.jsx("span",{className:"roster-title",children:c}),d&&t.jsx("span",{className:"type-badge px-1.5 py-0.5 rounded",style:{backgroundColor:"rgba(57, 217, 138, 0.2)",color:"#39D98A"},children:"NBR"}),o&&t.jsxs("span",{className:"type-badge px-1.5 py-0.5 rounded flex items-center gap-1",style:{backgroundColor:"rgba(251, 191, 36, 0.2)",color:"#FBBF24"},children:[t.jsx(R,{className:"w-3 h-3"}),"HUB"]}),(s.is_repeater||"repeater"===(null==(n=s.contact_type)?void 0:n.toLowerCase())||"rep"===(null==(r=s.contact_type)?void 0:r.toLowerCase()))&&t.jsx("span",{className:"pill-tag",children:"RPT"})]}),t.jsx("div",{className:"hidden md:block",children:t.jsx(P,{hash:e,size:"sm",full:!0})}),t.jsx("div",{className:"md:hidden",children:t.jsx(P,{hash:e,size:"sm",prefixLength:8,suffixLength:6})})]}),t.jsxs("div",{className:"roster-metrics flex-shrink-0",children:[u&&null!==(null==x?void 0:x.avgRssi)&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(M,{rssi:x.avgRssi,className:"w-3.5 h-3.5"}),t.jsx("span",{className:"type-data-xs tabular-nums",children:Math.round(x.avgRssi)})]}),u&&null!==(null==x?void 0:x.avgSnr)&&t.jsx("div",{className:"flex items-center gap-1.5",children:t.jsxs("span",{className:"type-data-xs tabular-nums",children:[x.avgSnr.toFixed(1)," dB"]})}),null!=h&&t.jsxs("div",{className:"flex items-center gap-1 text-accent-tertiary",children:[t.jsx(U,{className:"w-3 h-3"}),t.jsx("span",{className:"type-data-xs tabular-nums",children:(p=h,p<1e3?`${Math.round(p)}m`:`${(p/1e3).toFixed(1)}km`)})]}),m>0&&t.jsxs("div",{className:"flex items-center gap-1 text-amber-400/70",children:[t.jsx(E,{className:"w-3 h-3"}),t.jsxs("span",{className:"type-data-xs tabular-nums",children:[(100*m).toFixed(0),"%"]})]}),t.jsx("div",{className:"hidden sm:block",children:t.jsx(me,{nodeHash:e,width:48,height:16})})]}),t.jsx("div",{className:"roster-metric flex-shrink-0",children:s.last_seen?g(s.last_seen):"—"}),t.jsx("button",{onClick:t=>{t.stopPropagation(),y({hash:e,name:c})},className:"ml-2 p-1.5 rounded-lg text-text-muted/50 hover:text-red-400 hover:bg-red-500/10 transition-colors flex-shrink-0",title:"Remove contact",children:t.jsx(Y,{className:"w-4 h-4"})})]}),a{j&&a(j.hash),y(null)},onCancel:()=>y(null)})]})}},Symbol.toStringTag,{value:"Module"}));export{ne as C,W as G,I as M,me as N,Y as T,ue as a}; diff --git a/frontend/dist/assets/ContactsMapMapLibre-CJeu6v4R.js b/frontend/dist/assets/ContactsMapMapLibre-CJeu6v4R.js deleted file mode 100644 index 8f07cce9..00000000 --- a/frontend/dist/assets/ContactsMapMapLibre-CJeu6v4R.js +++ /dev/null @@ -1 +0,0 @@ -import{c as e,j as t,G as n,af as r,ag as o,f as a,ah as s}from"./index-CV7v97nI.js";import{b as i,g as l,c as u,r as c}from"./recharts-bmHCCfxU.js";import{a as d,P as p,S as h,L as f,u as m,M as g,N as x,b}from"./maplibre-gl-DPqA1aeF.js";import{G as y,N as v,T as k,M as w,C as S}from"./Contacts-BmRuXfkt.js";import{a as C,C as j}from"./HashBadge-B-tp-R60.js";import{L as N}from"./loader-circle-nWyQmXVo.js";import{I as E}from"./info-B98xpn6R.js";import{H as F}from"./house-DIgfF7wb.js";import{R as M}from"./refresh-cw-DPnajVcG.js";import{N as R}from"./trending-up-Cxmt7mo3.js";import"./maplibre-gl-CFO9X1Ek.js";import"./SignalIndicator-2MpYmE16.js";import"./triangle-alert-CxqtdCr5.js";import"./zap-DSYoS0xt.js";import"./activity-3Vz0t4n3.js";import"./PageLayout-M3WtUa6t.js";import"./users-DTJBXVif.js";const T=e("chart-no-axes-column",[["path",{d:"M5 21v-6",key:"1hz6c0"}],["path",{d:"M12 21V3",key:"1lcnhd"}],["path",{d:"M19 21V9",key:"unv183"}]]),P=e("chevrons-left-right-ellipsis",[["path",{d:"M12 12h.01",key:"1mp3jc"}],["path",{d:"M16 12h.01",key:"1l6xoz"}],["path",{d:"m17 7 5 5-5 5",key:"1xlxn0"}],["path",{d:"m7 7-5 5 5 5",key:"19njba"}],["path",{d:"M8 12h.01",key:"czm47f"}]]),_=e("database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]),D=e("download",[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]]),H=e("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]),$=e("maximize-2",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"m21 3-7 7",key:"1l2asr"}],["path",{d:"m3 21 7-7",key:"tjx5ai"}],["path",{d:"M9 21H3v-6",key:"wtvkvv"}]]),I=e("minimize-2",[["path",{d:"m14 10 7-7",key:"oa77jy"}],["path",{d:"M20 10h-6V4",key:"mjg0md"}],["path",{d:"m3 21 7-7",key:"tjx5ai"}],["path",{d:"M4 14h6v6",key:"rmj7iw"}]]);function z(e,t){const n=Math.max(5,Math.min(e,300)),r=Math.log(5),o=Math.log(300);return 1+(Math.log(n)-r)/(o-r)*5}const L="#4338CA";function A({label:e,icon:n,status:r,detail:o}){return t.jsxs("div",{className:u("flex items-center gap-3 py-3 px-4 rounded-xl transition-all duration-300","active"===r&&"bg-[#4338CA]/10","complete"===r&&"bg-accent-success/10","pending"===r&&"opacity-40"),children:[t.jsx("div",{className:u("w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 transition-all duration-300","active"===r&&"bg-[#4338CA]/20","complete"===r&&"bg-accent-success/20","pending"===r&&"bg-white/5"),children:"complete"===r?t.jsx(C,{className:"w-4 h-4 text-accent-success"}):"active"===r?t.jsx(N,{className:"w-4 h-4 animate-spin",style:{color:L}}):t.jsx("span",{className:"text-text-muted",children:n})}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("div",{className:u("text-sm font-medium transition-colors","active"===r&&"text-[#4338CA]","complete"===r&&"text-accent-success","pending"===r&&"text-text-muted"),children:e}),o&&"pending"!==r&&t.jsx("div",{className:"text-xs text-text-muted mt-0.5 truncate",children:o})]})]})}const B=i.memo(function({isOpen:e,currentStep:n,packetCount:r,onClose:o}){if(i.useEffect(()=>{if(!e)return;const t=e=>{"Escape"===e.key&&o&&o()};window.addEventListener("keydown",t);const n=document.body.style.overflow,r=document.body.style.position,a=document.body.style.width,s=document.body.style.top,i=window.scrollY;return document.body.style.overflow="hidden",document.body.style.position="fixed",document.body.style.width="100%",document.body.style.top=`-${i}px`,()=>{window.removeEventListener("keydown",t),document.body.style.overflow=n,document.body.style.position=r,document.body.style.width=a,document.body.style.top=s,window.scrollTo(0,i)}},[e,o]),!e)return null;const a="complete"===n,s=e=>{const t=["fetching","analyzing","building","complete"],r=t.indexOf(n),o=t.indexOf(e);return o0?`${r.toLocaleString()} packets`:"Loading database..."}),t.jsx(A,{label:"Analyzing Database",icon:t.jsx(_,{className:"w-4 h-4"}),status:s("analyzing"),detail:"Processing packet paths"}),t.jsx(A,{label:"Building Topology",icon:t.jsx(y,{className:"w-4 h-4"}),status:s("building"),detail:"Computing mesh edges"})]}),t.jsx("p",{className:"text-xs text-text-muted text-center mt-5",children:"This may take a few seconds..."})]})})]}),document.body)}),O="#4338CA",V="#FBBF24",q="#6366F1",W="#F97316",U="#F59E0B",Z="#FBBF24",K="#4B5563",G="#6B7280",X="#374151",Y="#5EEAD4",J="#6366F1",Q="#9CA3AF",ee="#6B7280",te="#FBBF24",ne=2e3;function re({text:e}){return t.jsxs("span",{className:"group relative cursor-help",children:[t.jsx(E,{className:"w-3 h-3 text-text-muted"}),t.jsx("div",{className:"absolute bottom-full left-0 mb-1 hidden group-hover:block w-44 p-2 text-[10px] leading-tight rounded-lg z-10",style:{background:"rgba(20, 20, 22, 0.98)",border:"1px solid rgba(140, 160, 200, 0.3)"},children:e})]})}function oe(e){const t=new Date(1e3*e);return`${(t.getMonth()+1).toString().padStart(2,"0")}/${t.getDate().toString().padStart(2,"0")}`}function ae({hash:e,hashPrefix:r,name:o,isHub:a,isZeroHop:s,isMobile:l,isRoomServer:u,isStale:c,lastSeenTimestamp:d,centrality:p,affinity:h,meanSnr:f,meanRssi:m,neighbor:g,onRemove:x,txDelayRec:b}){var y,w;const[S,N]=i.useState(!1),E=s?"Direct":(null==h?void 0:h.typicalHopPosition)?`${h.typicalHopPosition}-hop`:null,F=[{label:"Packets",value:(null==h?void 0:h.frequency)||0},{label:"Adverts",value:g.advert_count||0}];s&&void 0!==f?F.push({label:"SNR",value:`${f.toFixed(1)} dB`}):a&&p>0&&F.push({label:"Centrality",value:`${(100*p).toFixed(0)}%`,highlight:!0}),s&&void 0!==m&&F.push({label:"RSSI",value:`${Math.round(m)} dBm`});const M=b&&!b.insufficientData;return t.jsxs("div",{className:"w-[220px] pr-3",children:[t.jsx("div",{className:"text-[14px] font-semibold text-text-primary leading-snug truncate mb-0.5",children:o}),t.jsxs("div",{className:"flex items-center gap-1 flex-wrap mb-1.5",children:[t.jsx("code",{className:"font-mono text-[10px] text-text-muted/70 bg-white/5 px-1 py-px rounded",children:r}),t.jsx("button",{onClick:()=>{navigator.clipboard.writeText(e),N(!0),setTimeout(()=>N(!1),1500)},className:"p-0.5 hover:bg-white/10 rounded transition-colors",title:"Copy full hash",children:S?t.jsx(C,{className:"w-2.5 h-2.5 text-accent-success"}):t.jsx(j,{className:"w-2.5 h-2.5 text-text-muted/50"})}),a&&t.jsx("span",{className:"px-1 py-px text-[8px] font-bold uppercase rounded",style:{backgroundColor:"#FBBF24",color:"#000"},children:"Hub"}),E&&t.jsx("span",{className:"px-1 py-px text-[8px] font-bold uppercase rounded",style:{backgroundColor:s?Z:"rgba(255,255,255,0.08)",color:s?"#000":"rgba(255,255,255,0.5)"},children:E}),l&&t.jsx("span",{className:"px-1 py-px text-[8px] font-bold uppercase rounded bg-orange-500/25 text-orange-300",children:"Mobile"}),g.is_repeater&&t.jsx("span",{className:"px-1 py-px text-[8px] font-bold uppercase rounded bg-cyan-500/20 text-cyan-400",children:"Rptr"}),u&&t.jsx("span",{className:"px-1 py-px text-[8px] font-bold uppercase rounded bg-amber-500/25 text-amber-400",children:"Room"}),c&&d&&t.jsxs("span",{className:"px-1 py-px text-[8px] font-medium rounded bg-gray-500/30 text-gray-300",title:"Neighbor not heard in 7+ days",children:["Idle ",oe(d)]})]}),t.jsxs("div",{className:"text-[10px] text-text-muted/60 mb-2 leading-tight",children:[t.jsx("span",{children:n(g.last_seen)}),(null==h?void 0:h.distanceMeters)&&t.jsxs("span",{className:"font-medium text-text-muted/80",children:[" · ",(R=h.distanceMeters,null===R?"—":R<1e3?`${Math.round(R)}m`:`${(R/1e3).toFixed(1)}km`)]}),g.latitude&&g.longitude&&0!==g.latitude&&0!==g.longitude&&t.jsxs("span",{className:"font-mono text-[9px]",children:[" · ",g.latitude.toFixed(4),", ",g.longitude.toFixed(4)]})]}),t.jsx("div",{className:"mb-2",children:t.jsx(v,{nodeHash:e,width:"100%",height:28,showArea:!0,showTooltip:!0})}),t.jsx("div",{className:"grid grid-cols-2 gap-x-4 gap-y-0.5 text-[11px] mb-2",children:F.map((e,n)=>t.jsxs("div",{className:"flex justify-between",children:[t.jsx("span",{className:"text-text-muted/50",children:e.label}),t.jsx("span",{className:"font-semibold tabular-nums "+("highlight"in e&&e.highlight?"text-amber-400":""),children:e.value})]},n))}),(M||x)&&t.jsxs("div",{className:"flex items-center justify-between gap-2 pt-1.5 border-t border-white/5",children:[M?t.jsxs("div",{className:"flex flex-col gap-0.5 text-[10px] text-text-muted/60",children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("span",{className:"uppercase text-[8px] font-semibold tracking-wide text-text-muted/40",children:"TX"}),void 0!==b.floodSlots?t.jsxs(t.Fragment,{children:[t.jsxs("span",{children:["F ",t.jsxs("span",{className:"font-semibold tabular-nums "+("low"===b.dataConfidence?"text-amber-400/50":"text-amber-400"),children:[null==(y=b.floodDelaySec)?void 0:y.toFixed(1),"s"]}),t.jsxs("span",{className:"text-text-muted/40",children:[" (",b.floodSlots,")"]})]}),t.jsxs("span",{children:["D ",t.jsxs("span",{className:"font-semibold tabular-nums "+("low"===b.dataConfidence?"text-amber-400/50":"text-amber-400"),children:[null==(w=b.directDelaySec)?void 0:w.toFixed(1),"s"]}),t.jsxs("span",{className:"text-text-muted/40",children:[" (",b.directSlots,")"]})]})]}):t.jsxs(t.Fragment,{children:[t.jsxs("span",{children:["F ",t.jsx("span",{className:"font-semibold text-amber-400 tabular-nums",children:b.txDelayFactor.toFixed(2)})]}),t.jsxs("span",{children:["D ",t.jsx("span",{className:"font-semibold text-amber-400 tabular-nums",children:b.directTxDelayFactor.toFixed(2)})]})]}),"low"===b.dataConfidence&&t.jsx("span",{className:"text-[9px] text-amber-500",title:"Low confidence - limited data or asymmetric traffic",children:"⚠️"}),"high"===b.dataConfidence&&t.jsx("span",{className:"text-[9px] text-green-400",title:"High confidence - good bidirectional visibility",children:"✓"})]}),t.jsxs("div",{className:"flex items-center gap-1",children:[b.networkRole&&t.jsx("span",{className:"text-[9px] text-text-muted/40 capitalize",children:b.networkRole}),void 0!==b.observationSymmetry&&t.jsxs("span",{className:"text-[9px] "+(b.observationSymmetry>=.5?"text-green-400/60":b.observationSymmetry<.3?"text-amber-500/60":"text-text-muted/40"),title:`Edge symmetry: ${Math.round(100*b.observationSymmetry)}% bidirectional`,children:[b.observationSymmetry>=.5?"↔":b.observationSymmetry<.3?"→":"⇄",Math.round(100*b.observationSymmetry),"%"]})]})]}):t.jsx("div",{}),x&&t.jsx("button",{onClick:x,className:"flex items-center gap-0.5 p-1 text-[10px] text-text-muted/30 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",title:"Remove from contacts",children:t.jsx(k,{className:"w-3 h-3"})})]})]});var R}function se({showTopology:e,validatedPolylineCount:n,filteredNeighborCount:r,hasLocalNode:o,meshTopology:a,zeroHopNeighbors:s,neighborsWithLocation:i}){return t.jsxs("div",{className:"absolute bottom-4 left-4 z-[600] text-xs",style:{background:"rgba(20, 20, 22, 0.95)",borderRadius:"0.75rem",padding:"0.625rem",border:"1px solid rgba(140, 160, 200, 0.2)",maxWidth:"150px"},children:[t.jsxs("div",{className:"text-text-secondary font-medium mb-1.5 flex items-center gap-1",children:["Nodes",t.jsx(re,{text:"Node type shown by shape/color. Yellow outer ring = direct RF neighbor."})]}),t.jsxs("div",{className:"flex flex-col gap-1",children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("div",{className:"w-3 h-3 rounded-full flex-shrink-0",style:{background:"transparent",border:`3px solid ${O}`,boxSizing:"border-box"}}),t.jsx("span",{className:"text-text-muted",children:"Node"})]}),t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("div",{className:"w-3 h-3 rounded-full flex-shrink-0",style:{backgroundColor:q}}),t.jsx("span",{className:"text-text-muted",children:"Hub"})]}),t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(F,{className:"w-3 h-3 flex-shrink-0",style:{color:V},strokeWidth:2.5}),t.jsx("span",{className:"text-text-muted",children:"Local"})]}),(l=i,l.some(([,e])=>{var t;const n=null==(t=e.contact_type)?void 0:t.toLowerCase();return"room server"===n||"room_server"===n||"room"===n||"server"===n})&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(w,{className:"w-3 h-3 flex-shrink-0",style:{color:U},strokeWidth:2.5}),t.jsx("span",{className:"text-text-muted",children:"Room"})]})),a.mobileNodes.length>0&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("div",{className:"w-3 h-3 rounded-full flex-shrink-0",style:{background:"transparent",border:`3px solid ${W}`,boxSizing:"border-box"}}),t.jsx("span",{className:"text-text-muted",children:"Mobile"})]}),s.size>0&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsxs("div",{className:"relative w-4 h-4 flex-shrink-0",children:[t.jsx("div",{className:"absolute inset-0 rounded-full",style:{background:"transparent",border:`1px solid ${Z}`,boxSizing:"border-box",opacity:.8}}),t.jsx("div",{className:"absolute rounded-full",style:{top:"4px",left:"4px",width:"8px",height:"8px",background:"transparent",border:`2px solid ${O}`,boxSizing:"border-box"}})]}),t.jsx("span",{className:"text-text-muted",children:"Neighbor"})]})]}),s.size>0&&t.jsx("div",{className:"mt-1.5 pt-1.5 border-t border-white/10",children:t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("div",{className:"flex-shrink-0",style:{width:"14px",height:"2px",backgroundImage:`repeating-linear-gradient(90deg, ${ee} 0, ${ee} 3px, transparent 3px, transparent 5px)`,borderRadius:"1px"}}),t.jsx("span",{className:"text-text-muted",children:"Neighbor"}),t.jsx(re,{text:"Dashed gray → yellow on hover. Direct RF contact with local."})]})}),e&&n>0&&t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"text-text-secondary font-medium mt-2 pt-2 border-t border-white/10 mb-1 flex items-center gap-1",children:["Topology",t.jsx(re,{text:"Links with 5+ validations. Thickness = relative strength."})]}),t.jsxs("div",{className:"flex flex-col gap-0.5 text-text-muted",children:[t.jsxs("div",{className:"flex justify-between tabular-nums",children:[t.jsx("span",{children:"Nodes"}),t.jsx("span",{className:"text-text-secondary",children:r+(o?1:0)})]}),t.jsxs("div",{className:"flex justify-between tabular-nums",children:[t.jsx("span",{children:"Links"}),t.jsx("span",{className:"text-text-secondary",children:n})]}),a.hubNodes.length>0&&t.jsxs("div",{className:"flex justify-between tabular-nums",children:[t.jsx("span",{children:"Hubs"}),t.jsx("span",{style:{color:q},children:a.hubNodes.length})]})]}),t.jsxs("div",{className:"flex flex-col gap-1 mt-1.5 pt-1.5 border-t border-white/10",children:[t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx("div",{className:"flex-shrink-0",style:{width:"14px",height:"3px",backgroundColor:K,borderRadius:"1px"}}),t.jsx("span",{className:"text-text-muted",children:"Link"}),t.jsx(re,{text:"Gray at rest. Hover to reveal type (teal=direct, indigo=loop)."})]}),a.loops.length>0&&t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsxs("div",{className:"flex-shrink-0 flex flex-col gap-0.5",style:{width:"14px"},children:[t.jsx("div",{style:{height:"2px",backgroundColor:K,borderRadius:"1px"}}),t.jsx("div",{style:{height:"2px",backgroundColor:K,borderRadius:"1px"}})]}),t.jsx("span",{className:"text-text-muted",children:"Redundant"})]})]}),a.loops.length>0&&t.jsx("div",{className:"mt-1.5 pt-1.5 border-t border-white/10",children:t.jsxs("div",{className:"flex items-center gap-1.5",children:[t.jsx(M,{className:"w-3 h-3 flex-shrink-0",style:{color:J}}),t.jsxs("div",{className:"flex flex-col",children:[t.jsxs("span",{style:{color:J},className:"font-medium",children:[a.loops.length," ",1===a.loops.length?"Loop":"Loops"]}),t.jsx("span",{className:"text-text-muted text-[10px] leading-tight",children:"Redundant paths"})]})]})})]})]});var l}const ie={background:"rgba(20, 20, 22, 0.95)",borderRadius:"0.75rem",border:"1px solid rgba(140, 160, 200, 0.2)"},le=(e,t=.4)=>({background:e,borderRadius:"0.75rem",border:`1px solid ${e.replace(/[\d.]+\)$/,`${t})`)}`});function ue({isDeepLoading:e,showDeepAnalysisModal:n,onDeepAnalysis:r,showTopology:o,onToggleTopology:a,hasValidatedPolylines:s,soloHubs:i,onToggleSoloHubs:l,hasHubNodes:u,soloDirect:c,onToggleSoloDirect:d,hasZeroHopNeighbors:p,isFullscreen:h,onToggleFullscreen:f}){return t.jsxs("div",{className:"absolute top-4 right-4 z-[600] flex gap-2",children:[t.jsxs("button",{onClick:r,disabled:e||n,className:"px-3 py-2 flex items-center gap-2 transition-colors hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",style:ie,title:"Deep Analysis - Load full packet history and rebuild topology",children:[t.jsx("span",{className:"text-xs font-medium text-text-primary",children:"Deep Analysis"}),t.jsx(T,{className:"w-4 h-4 text-accent-primary"})]}),s&&t.jsx("button",{onClick:a,className:"p-2 transition-colors hover:bg-white/10",style:o?le("rgba(74, 222, 128, 0.2)"):ie,title:o?"Hide topology lines":"Show topology lines",children:o?t.jsx(y,{className:"w-4 h-4 text-green-400"}):t.jsx(H,{className:"w-4 h-4 text-text-secondary"})}),u&&t.jsx("button",{onClick:l,className:"p-2 transition-colors hover:bg-white/10",style:i?{...ie,background:"rgba(251, 191, 36, 0.25)",border:"1px solid rgba(251, 191, 36, 0.5)"}:ie,title:i?"Show all nodes":"Solo hubs & connections",children:t.jsx(R,{className:"w-4 h-4 "+(i?"text-amber-400":"text-text-secondary")})}),p&&t.jsx("button",{onClick:d,className:"p-2 transition-colors hover:bg-white/10",style:c?{...ie,background:"rgba(67, 56, 202, 0.35)",border:"1px solid rgba(67, 56, 202, 0.6)"}:ie,title:c?"Show all nodes":"Solo direct (0-hop) nodes",children:t.jsx(P,{className:"w-4 h-4 "+(c?"text-indigo-400":"text-text-secondary")})}),t.jsx("button",{onClick:f,className:"p-2 transition-colors hover:bg-white/10",style:ie,title:h?"Exit fullscreen":"Fullscreen",children:h?t.jsx(I,{className:"w-4 h-4 text-text-secondary"}):t.jsx($,{className:"w-4 h-4 text-text-secondary"})})]})}function ce(e){return e<.5?4*e*e*e:1-Math.pow(-2*e+2,3)/2}function de(e){return e<.5?4*e*e*e:1-Math.pow(-2*e+2,3)/2}var pe,he={},fe={};var me,ge,xe={};var be,ye,ve=(ge||(ge=1,be=function(){if(pe)return fe;pe=1;var e=c();function t(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n