@herongxhr/network-status
Version:
A Vue 3 composable and component for monitoring network status.
2 lines (1 loc) • 5.83 kB
JavaScript
(function(f,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(f=typeof globalThis<"u"?globalThis:f||self,e(f.NetworkStatus={},f.Vue))})(this,function(f,e){"use strict";function T(u={}){const{initialStatus:m=0,checkUrl:a,alertPosition:y="bottom-right",statusTexts:p=["No Signal","Very Weak","Weak","Good","Excellent"],alertMessages:d=["You are offline!","Network signal is lost!","Network signal is very weak!"],checkInterval:S=8e3,decimalPlaces:h=0}=u,C=e.computed(()=>a||(console.warn("No checkUrl provided. Using current host as default. For accurate network detection, please specify a custom URL (e.g., a health check endpoint)."),`${window.location.origin}/`)),s=e.ref(m),i=e.ref(0),r=e.ref(!1);let t,n;const c=e.computed(()=>i.value.toFixed(Math.max(0,h))),l=e.computed(()=>{const o=Math.max(0,Math.min(4,Math.round(s.value)));return Array.from({length:4},(E,w)=>w<o)}),N=e.computed(()=>{const o=s.value;return p[o]}),B=e.computed(()=>{if(!navigator.onLine)return d[0];const o=s.value;return o===0?d[1]:o===1?d[2]:""}),g=async()=>{if(!navigator.onLine){s.value=0,i.value=0;return}try{const o=performance.now();if(!(await fetch(C.value,{method:"HEAD",cache:"no-store"})).ok)throw new Error("Response not OK");const w=performance.now();i.value=w-o;const k=i.value;k>1e3?s.value=0:k>500?s.value=1:k>300?s.value=2:k>200?s.value=3:s.value=4}catch{s.value=0,i.value=0}},z=()=>{r.value=!1,t&&clearTimeout(t)};return e.onMounted(()=>{g(),n=setInterval(g,S),window.addEventListener("online",g),window.addEventListener("offline",()=>{s.value=0,i.value=0,r.value=!0,t=setTimeout(()=>{r.value=!1},3e3)})}),e.onUnmounted(()=>{n&&clearInterval(n),window.removeEventListener("online",g),window.removeEventListener("offline",()=>{s.value=0})}),e.watch(()=>s.value,o=>{o<=1||!navigator.onLine?(r.value=!0,t=setTimeout(()=>{r.value=!1},3e3)):(r.value=!1,t&&clearTimeout(t))}),{networkStatus:s,latency:i,formattedLatency:c,signalBars:l,statusText:N,showAlert:r,alertMessage:B,checkNetworkStatus:g,closeAlert:z,alertPosition:y}}const x=((u,m)=>{const a=u.__vccOpts||u;for(const[y,p]of m)a[y]=p;return a})(e.defineComponent({__name:"NetworkStatusTemplate",props:{position:{default:"top-right"},positionOffset:{default:"1rem"},containerClass:{default:"h-4 flex items-center gap-2 rounded text-xs"},containerStyle:{},signalBarsContainerClass:{default:"h-full py-[2px] flex items-end gap-[2px]"},signalBarsContainerStyle:{},signalBarClass:{default:"transition-all duration-300 flex-none"},signalBarStyle:{},statusTextContainerClass:{default:"flex flex-col"},statusTextContainerStyle:{},statusTextClass:{default:"h-full flex items-center text-gray-900 dark:text-gray-100"},statusTextStyle:{},latencyTextClass:{default:"text-xs text-gray-600 dark:text-gray-400"},latencyTextStyle:{},alertClass:{default:"p-2 rounded"},alertStyle:{},alertMessageClass:{default:""},alertMessageStyle:{},closeButtonClass:{default:"absolute top-1 right-1 w-4 h-4 bg-transparent border-none cursor-pointer"},closeButtonStyle:{},statusTexts:{default:()=>["No Signal","Very Weak","Weak","Good","Excellent"]},alertMessages:{default:()=>["You are offline!","Network signal is lost!","Network signal is very weak!"]},checkUrl:{default:void 0},checkInterval:{default:5e3}},setup(u){const m=t=>{const[n,c]=t.split("-"),l={};return n==="top"?l.top=a.positionOffset:n==="bottom"&&(l.bottom=a.positionOffset),c==="left"?l.left=a.positionOffset:c==="right"?l.right=a.positionOffset:c==="center"&&(l.left="50%",l.transform="translateX(-50%)"),l},a=u,{networkStatus:y,formattedLatency:p,signalBars:d,statusText:S,showAlert:h,alertMessage:C,closeAlert:s,alertPosition:i}=T({initialStatus:0,checkUrl:a.checkUrl,alertPosition:a.position,statusTexts:a.statusTexts,alertMessages:a.alertMessages,checkInterval:a.checkInterval}),r=e.computed(()=>{const t=y.value;return t===0?"#6b7280":t<=1?"#ef4444":t===2?"#eab308":t===3?"#22c55e":"#46cd7c"});return(t,n)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass([t.containerClass]),style:e.normalizeStyle(t.containerStyle)},[e.createElementVNode("div",{class:e.normalizeClass([t.statusTextClass]),style:e.normalizeStyle(t.statusTextStyle)},e.toDisplayString(e.unref(S)),7),e.createElementVNode("div",{class:e.normalizeClass([t.signalBarsContainerClass]),style:e.normalizeStyle(t.signalBarsContainerStyle)},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(d),(c,l)=>(e.openBlock(),e.createElementBlock("div",{key:l,class:e.normalizeClass([t.signalBarClass]),style:e.normalizeStyle({...t.signalBarStyle,width:"2px",height:(l+1)/e.unref(d).length*100+"%",backgroundColor:c?r.value:"var(--ground-100)"})},null,6))),128))],6),e.createElementVNode("div",{class:e.normalizeClass([t.statusTextContainerClass]),style:e.normalizeStyle(t.statusTextContainerStyle)},[e.createElementVNode("span",{class:e.normalizeClass([t.latencyTextClass]),style:e.normalizeStyle({color:r.value,...t.latencyTextStyle})},e.toDisplayString(e.unref(p))+"ms",7)],6),e.unref(h)?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass([t.alertClass]),style:e.normalizeStyle({...t.alertStyle,position:"fixed",zIndex:"50",...m(e.unref(i))})},[e.createElementVNode("span",{class:e.normalizeClass([t.alertMessageClass]),style:e.normalizeStyle(t.alertMessageStyle)},e.toDisplayString(e.unref(C)),7),e.createElementVNode("button",{class:e.normalizeClass([t.closeButtonClass]),style:e.normalizeStyle(t.closeButtonStyle),onClick:n[0]||(n[0]=(...c)=>e.unref(s)&&e.unref(s)(...c))},n[1]||(n[1]=[e.createElementVNode("span",{class:"close-icon"},null,-1)]),6)],6)):e.createCommentVNode("",!0)],6))}}),[["__scopeId","data-v-9684ad4c"]]);f.NetworkStatusTemplate=x,f.useNetworkStatus=T,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});