@auraqule/react-network-status 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # react-network-status
2
+
3
+ > A React hook to monitor network connectivity, online/offline state, and connection type. SSR-safe, zero dependencies beyond React.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/react-network-status)](https://www.npmjs.com/package/react-network-status)
6
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/react-network-status)](https://bundlephobia.com/package/react-network-status)
7
+ [![license](https://img.shields.io/npm/l/react-network-status)](./LICENSE)
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install react-network-status
13
+ # or
14
+ pnpm add react-network-status
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```tsx
20
+ import { useNetworkStatus } from "react-network-status";
21
+
22
+ function App() {
23
+ const {
24
+ isOnline,
25
+ isOffline,
26
+ connectionType,
27
+ effectiveType,
28
+ downlink,
29
+ rtt,
30
+ saveData,
31
+ refresh,
32
+ } = useNetworkStatus();
33
+
34
+ return (
35
+ <div>
36
+ <p>Status: {isOnline ? "Online 🟢" : "Offline 🔴"}</p>
37
+ <p>Connection: {connectionType}</p>
38
+ <p>Effective type: {effectiveType}</p>
39
+ {downlink && <p>Downlink: {downlink} Mbps</p>}
40
+ {rtt && <p>RTT: {rtt} ms</p>}
41
+ {saveData && <p>Data saver: enabled</p>}
42
+ <button onClick={refresh}>Refresh</button>
43
+ </div>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `useNetworkStatus()`
51
+
52
+ No options — just call it.
53
+
54
+ ### Returns
55
+
56
+ | Value | Type | Description |
57
+ |---|---|---|
58
+ | `isOnline` | `boolean` | Whether the browser has network access |
59
+ | `isOffline` | `boolean` | Inverse of `isOnline` |
60
+ | `connectionType` | `ConnectionType` | wifi, ethernet, cellular, 2g, 3g, 4g, 5g, unknown |
61
+ | `effectiveType` | `EffectiveConnectionType` | slow-2g, 2g, 3g, 4g, unknown |
62
+ | `downlink` | `number \| undefined` | Estimated bandwidth in Mbps |
63
+ | `rtt` | `number \| undefined` | Estimated round-trip time in ms |
64
+ | `saveData` | `boolean \| undefined` | Whether data saver is enabled |
65
+ | `refresh` | `() => void` | Manually re-read network status |
66
+
67
+ > `connectionType`, `effectiveType`, `downlink`, `rtt`, and `saveData` rely on the [Network Information API](https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API), which is not supported in all browsers. They will return `undefined` or `"unknown"` when unavailable.
68
+
69
+ ## Use Cases
70
+
71
+ - Show offline banners or toasts
72
+ - Disable uploads/fetches when offline
73
+ - Adapt image quality based on connection speed
74
+ - Warn users on slow connections before heavy operations
75
+ - Respect data saver preferences
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,39 @@
1
+ type ConnectionType = "wifi" | "ethernet" | "cellular" | "2g" | "3g" | "4g" | "5g" | "slow-2g" | "unknown" | "none";
2
+ type EffectiveConnectionType = "slow-2g" | "2g" | "3g" | "4g" | "unknown";
3
+ interface NetworkStatus {
4
+ /** Whether the browser has network access */
5
+ isOnline: boolean;
6
+ /** Whether the browser is offline */
7
+ isOffline: boolean;
8
+ /** The type of connection (wifi, cellular, etc.) — may be undefined if unsupported */
9
+ connectionType: ConnectionType;
10
+ /** Effective connection type based on observed latency — may be undefined if unsupported */
11
+ effectiveType: EffectiveConnectionType;
12
+ /** Estimated downlink bandwidth in Mbps — undefined if unsupported */
13
+ downlink: number | undefined;
14
+ /** Estimated round-trip time in ms — undefined if unsupported */
15
+ rtt: number | undefined;
16
+ /** Whether the user has enabled data saver mode — undefined if unsupported */
17
+ saveData: boolean | undefined;
18
+ /** Manually re-check network status */
19
+ refresh: () => void;
20
+ }
21
+ interface NetworkInformation extends EventTarget {
22
+ type?: string;
23
+ effectiveType?: string;
24
+ downlink?: number;
25
+ rtt?: number;
26
+ saveData?: boolean;
27
+ addEventListener(type: "change", listener: () => void): void;
28
+ removeEventListener(type: "change", listener: () => void): void;
29
+ }
30
+ declare global {
31
+ interface Navigator {
32
+ connection?: NetworkInformation;
33
+ mozConnection?: NetworkInformation;
34
+ webkitConnection?: NetworkInformation;
35
+ }
36
+ }
37
+ declare function useNetworkStatus(): NetworkStatus;
38
+
39
+ export { type ConnectionType, type EffectiveConnectionType, type NetworkStatus, useNetworkStatus };
@@ -0,0 +1,39 @@
1
+ type ConnectionType = "wifi" | "ethernet" | "cellular" | "2g" | "3g" | "4g" | "5g" | "slow-2g" | "unknown" | "none";
2
+ type EffectiveConnectionType = "slow-2g" | "2g" | "3g" | "4g" | "unknown";
3
+ interface NetworkStatus {
4
+ /** Whether the browser has network access */
5
+ isOnline: boolean;
6
+ /** Whether the browser is offline */
7
+ isOffline: boolean;
8
+ /** The type of connection (wifi, cellular, etc.) — may be undefined if unsupported */
9
+ connectionType: ConnectionType;
10
+ /** Effective connection type based on observed latency — may be undefined if unsupported */
11
+ effectiveType: EffectiveConnectionType;
12
+ /** Estimated downlink bandwidth in Mbps — undefined if unsupported */
13
+ downlink: number | undefined;
14
+ /** Estimated round-trip time in ms — undefined if unsupported */
15
+ rtt: number | undefined;
16
+ /** Whether the user has enabled data saver mode — undefined if unsupported */
17
+ saveData: boolean | undefined;
18
+ /** Manually re-check network status */
19
+ refresh: () => void;
20
+ }
21
+ interface NetworkInformation extends EventTarget {
22
+ type?: string;
23
+ effectiveType?: string;
24
+ downlink?: number;
25
+ rtt?: number;
26
+ saveData?: boolean;
27
+ addEventListener(type: "change", listener: () => void): void;
28
+ removeEventListener(type: "change", listener: () => void): void;
29
+ }
30
+ declare global {
31
+ interface Navigator {
32
+ connection?: NetworkInformation;
33
+ mozConnection?: NetworkInformation;
34
+ webkitConnection?: NetworkInformation;
35
+ }
36
+ }
37
+ declare function useNetworkStatus(): NetworkStatus;
38
+
39
+ export { type ConnectionType, type EffectiveConnectionType, type NetworkStatus, useNetworkStatus };
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/useNetworkStatus.ts
6
+ function getConnection() {
7
+ var _a, _b;
8
+ if (typeof navigator === "undefined") return void 0;
9
+ return (_b = (_a = navigator.connection) != null ? _a : navigator.mozConnection) != null ? _b : navigator.webkitConnection;
10
+ }
11
+ function getConnectionType(connection) {
12
+ var _a;
13
+ if (!(connection == null ? void 0 : connection.type)) return "unknown";
14
+ return (_a = connection.type) != null ? _a : "unknown";
15
+ }
16
+ function getEffectiveType(connection) {
17
+ var _a;
18
+ if (!(connection == null ? void 0 : connection.effectiveType)) return "unknown";
19
+ return (_a = connection.effectiveType) != null ? _a : "unknown";
20
+ }
21
+ function getSnapshot() {
22
+ const isOnline = typeof navigator !== "undefined" ? navigator.onLine : true;
23
+ const connection = getConnection();
24
+ return {
25
+ isOnline,
26
+ isOffline: !isOnline,
27
+ connectionType: getConnectionType(connection),
28
+ effectiveType: getEffectiveType(connection),
29
+ downlink: connection == null ? void 0 : connection.downlink,
30
+ rtt: connection == null ? void 0 : connection.rtt,
31
+ saveData: connection == null ? void 0 : connection.saveData
32
+ };
33
+ }
34
+ function useNetworkStatus() {
35
+ const [status, setStatus] = react.useState(getSnapshot);
36
+ const update = react.useCallback(() => {
37
+ setStatus(getSnapshot());
38
+ }, []);
39
+ react.useEffect(() => {
40
+ window.addEventListener("online", update);
41
+ window.addEventListener("offline", update);
42
+ const connection = getConnection();
43
+ connection == null ? void 0 : connection.addEventListener("change", update);
44
+ return () => {
45
+ window.removeEventListener("online", update);
46
+ window.removeEventListener("offline", update);
47
+ connection == null ? void 0 : connection.removeEventListener("change", update);
48
+ };
49
+ }, [update]);
50
+ return { ...status, refresh: update };
51
+ }
52
+
53
+ exports.useNetworkStatus = useNetworkStatus;
54
+ //# sourceMappingURL=index.js.map
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useNetworkStatus.ts"],"names":["useState","useCallback","useEffect"],"mappings":";;;;;AAsDA,SAAS,aAAA,GAAgD;AAtDzD,EAAA,IAAA,EAAA,EAAA,EAAA;AAuDE,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,EAAa,OAAO,MAAA;AAC7C,EAAA,OAAA,CACE,qBAAU,UAAA,KAAV,IAAA,GAAA,EAAA,GACA,SAAA,CAAU,aAAA,KADV,YAEA,SAAA,CAAU,gBAAA;AAEd;AAEA,SAAS,kBAAkB,UAAA,EAAiD;AA/D5E,EAAA,IAAA,EAAA;AAgEE,EAAA,IAAI,EAAC,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,IAAA,CAAA,EAAM,OAAO,SAAA;AAC9B,EAAA,OAAA,CAAQ,EAAA,GAAA,UAAA,CAAW,SAAX,IAAA,GAAA,EAAA,GAAsC,SAAA;AAChD;AAEA,SAAS,iBAAiB,UAAA,EAA0D;AApEpF,EAAA,IAAA,EAAA;AAqEE,EAAA,IAAI,EAAC,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,aAAA,CAAA,EAAe,OAAO,SAAA;AACvC,EAAA,OAAA,CAAQ,EAAA,GAAA,UAAA,CAAW,kBAAX,IAAA,GAAA,EAAA,GAAwD,SAAA;AAClE;AAEA,SAAS,WAAA,GAA8C;AACrD,EAAA,MAAM,QAAA,GAAW,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,MAAA,GAAS,IAAA;AACvE,EAAA,MAAM,aAAa,aAAA,EAAc;AAEjC,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,WAAW,CAAC,QAAA;AAAA,IACZ,cAAA,EAAgB,kBAAkB,UAAU,CAAA;AAAA,IAC5C,aAAA,EAAe,iBAAiB,UAAU,CAAA;AAAA,IAC1C,UAAU,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,QAAA;AAAA,IACtB,KAAK,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,GAAA;AAAA,IACjB,UAAU,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY;AAAA,GACxB;AACF;AAEO,SAAS,gBAAA,GAAkC;AAChD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIA,eAAyC,WAAW,CAAA;AAEhF,EAAA,MAAM,MAAA,GAASC,kBAAY,MAAM;AAC/B,IAAA,SAAA,CAAU,aAAa,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACxC,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,MAAM,CAAA;AAEzC,IAAA,MAAM,aAAa,aAAA,EAAc;AACjC,IAAA,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,iBAAiB,QAAA,EAAU,MAAA,CAAA;AAEvC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,MAAM,CAAA;AAC3C,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,MAAM,CAAA;AAC5C,MAAA,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,oBAAoB,QAAA,EAAU,MAAA,CAAA;AAAA,IAC5C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAO;AACtC","file":"index.js","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\n\nexport type ConnectionType =\n | \"wifi\"\n | \"ethernet\"\n | \"cellular\"\n | \"2g\"\n | \"3g\"\n | \"4g\"\n | \"5g\"\n | \"slow-2g\"\n | \"unknown\"\n | \"none\";\n\nexport type EffectiveConnectionType = \"slow-2g\" | \"2g\" | \"3g\" | \"4g\" | \"unknown\";\n\nexport interface NetworkStatus {\n /** Whether the browser has network access */\n isOnline: boolean;\n /** Whether the browser is offline */\n isOffline: boolean;\n /** The type of connection (wifi, cellular, etc.) — may be undefined if unsupported */\n connectionType: ConnectionType;\n /** Effective connection type based on observed latency — may be undefined if unsupported */\n effectiveType: EffectiveConnectionType;\n /** Estimated downlink bandwidth in Mbps — undefined if unsupported */\n downlink: number | undefined;\n /** Estimated round-trip time in ms — undefined if unsupported */\n rtt: number | undefined;\n /** Whether the user has enabled data saver mode — undefined if unsupported */\n saveData: boolean | undefined;\n /** Manually re-check network status */\n refresh: () => void;\n}\n\n// Network Information API types (not yet in all TS lib versions)\ninterface NetworkInformation extends EventTarget {\n type?: string;\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n saveData?: boolean;\n addEventListener(type: \"change\", listener: () => void): void;\n removeEventListener(type: \"change\", listener: () => void): void;\n}\n\ndeclare global {\n interface Navigator {\n connection?: NetworkInformation;\n mozConnection?: NetworkInformation;\n webkitConnection?: NetworkInformation;\n }\n}\n\nfunction getConnection(): NetworkInformation | undefined {\n if (typeof navigator === \"undefined\") return undefined;\n return (\n navigator.connection ??\n navigator.mozConnection ??\n navigator.webkitConnection\n );\n}\n\nfunction getConnectionType(connection?: NetworkInformation): ConnectionType {\n if (!connection?.type) return \"unknown\";\n return (connection.type as ConnectionType) ?? \"unknown\";\n}\n\nfunction getEffectiveType(connection?: NetworkInformation): EffectiveConnectionType {\n if (!connection?.effectiveType) return \"unknown\";\n return (connection.effectiveType as EffectiveConnectionType) ?? \"unknown\";\n}\n\nfunction getSnapshot(): Omit<NetworkStatus, \"refresh\"> {\n const isOnline = typeof navigator !== \"undefined\" ? navigator.onLine : true;\n const connection = getConnection();\n\n return {\n isOnline,\n isOffline: !isOnline,\n connectionType: getConnectionType(connection),\n effectiveType: getEffectiveType(connection),\n downlink: connection?.downlink,\n rtt: connection?.rtt,\n saveData: connection?.saveData,\n };\n}\n\nexport function useNetworkStatus(): NetworkStatus {\n const [status, setStatus] = useState<Omit<NetworkStatus, \"refresh\">>(getSnapshot);\n\n const update = useCallback(() => {\n setStatus(getSnapshot());\n }, []);\n\n useEffect(() => {\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n\n const connection = getConnection();\n connection?.addEventListener(\"change\", update);\n\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n connection?.removeEventListener(\"change\", update);\n };\n }, [update]);\n\n return { ...status, refresh: update };\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,53 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+
3
+ // src/useNetworkStatus.ts
4
+ function getConnection() {
5
+ var _a, _b;
6
+ if (typeof navigator === "undefined") return void 0;
7
+ return (_b = (_a = navigator.connection) != null ? _a : navigator.mozConnection) != null ? _b : navigator.webkitConnection;
8
+ }
9
+ function getConnectionType(connection) {
10
+ var _a;
11
+ if (!(connection == null ? void 0 : connection.type)) return "unknown";
12
+ return (_a = connection.type) != null ? _a : "unknown";
13
+ }
14
+ function getEffectiveType(connection) {
15
+ var _a;
16
+ if (!(connection == null ? void 0 : connection.effectiveType)) return "unknown";
17
+ return (_a = connection.effectiveType) != null ? _a : "unknown";
18
+ }
19
+ function getSnapshot() {
20
+ const isOnline = typeof navigator !== "undefined" ? navigator.onLine : true;
21
+ const connection = getConnection();
22
+ return {
23
+ isOnline,
24
+ isOffline: !isOnline,
25
+ connectionType: getConnectionType(connection),
26
+ effectiveType: getEffectiveType(connection),
27
+ downlink: connection == null ? void 0 : connection.downlink,
28
+ rtt: connection == null ? void 0 : connection.rtt,
29
+ saveData: connection == null ? void 0 : connection.saveData
30
+ };
31
+ }
32
+ function useNetworkStatus() {
33
+ const [status, setStatus] = useState(getSnapshot);
34
+ const update = useCallback(() => {
35
+ setStatus(getSnapshot());
36
+ }, []);
37
+ useEffect(() => {
38
+ window.addEventListener("online", update);
39
+ window.addEventListener("offline", update);
40
+ const connection = getConnection();
41
+ connection == null ? void 0 : connection.addEventListener("change", update);
42
+ return () => {
43
+ window.removeEventListener("online", update);
44
+ window.removeEventListener("offline", update);
45
+ connection == null ? void 0 : connection.removeEventListener("change", update);
46
+ };
47
+ }, [update]);
48
+ return { ...status, refresh: update };
49
+ }
50
+
51
+ export { useNetworkStatus };
52
+ //# sourceMappingURL=index.mjs.map
53
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useNetworkStatus.ts"],"names":[],"mappings":";;;AAsDA,SAAS,aAAA,GAAgD;AAtDzD,EAAA,IAAA,EAAA,EAAA,EAAA;AAuDE,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,EAAa,OAAO,MAAA;AAC7C,EAAA,OAAA,CACE,qBAAU,UAAA,KAAV,IAAA,GAAA,EAAA,GACA,SAAA,CAAU,aAAA,KADV,YAEA,SAAA,CAAU,gBAAA;AAEd;AAEA,SAAS,kBAAkB,UAAA,EAAiD;AA/D5E,EAAA,IAAA,EAAA;AAgEE,EAAA,IAAI,EAAC,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,IAAA,CAAA,EAAM,OAAO,SAAA;AAC9B,EAAA,OAAA,CAAQ,EAAA,GAAA,UAAA,CAAW,SAAX,IAAA,GAAA,EAAA,GAAsC,SAAA;AAChD;AAEA,SAAS,iBAAiB,UAAA,EAA0D;AApEpF,EAAA,IAAA,EAAA;AAqEE,EAAA,IAAI,EAAC,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,aAAA,CAAA,EAAe,OAAO,SAAA;AACvC,EAAA,OAAA,CAAQ,EAAA,GAAA,UAAA,CAAW,kBAAX,IAAA,GAAA,EAAA,GAAwD,SAAA;AAClE;AAEA,SAAS,WAAA,GAA8C;AACrD,EAAA,MAAM,QAAA,GAAW,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,MAAA,GAAS,IAAA;AACvE,EAAA,MAAM,aAAa,aAAA,EAAc;AAEjC,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,WAAW,CAAC,QAAA;AAAA,IACZ,cAAA,EAAgB,kBAAkB,UAAU,CAAA;AAAA,IAC5C,aAAA,EAAe,iBAAiB,UAAU,CAAA;AAAA,IAC1C,UAAU,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,QAAA;AAAA,IACtB,KAAK,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,GAAA;AAAA,IACjB,UAAU,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY;AAAA,GACxB;AACF;AAEO,SAAS,gBAAA,GAAkC;AAChD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAyC,WAAW,CAAA;AAEhF,EAAA,MAAM,MAAA,GAAS,YAAY,MAAM;AAC/B,IAAA,SAAA,CAAU,aAAa,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACxC,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,MAAM,CAAA;AAEzC,IAAA,MAAM,aAAa,aAAA,EAAc;AACjC,IAAA,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,iBAAiB,QAAA,EAAU,MAAA,CAAA;AAEvC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,MAAM,CAAA;AAC3C,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,MAAM,CAAA;AAC5C,MAAA,UAAA,IAAA,IAAA,GAAA,MAAA,GAAA,UAAA,CAAY,oBAAoB,QAAA,EAAU,MAAA,CAAA;AAAA,IAC5C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAO;AACtC","file":"index.mjs","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\n\nexport type ConnectionType =\n | \"wifi\"\n | \"ethernet\"\n | \"cellular\"\n | \"2g\"\n | \"3g\"\n | \"4g\"\n | \"5g\"\n | \"slow-2g\"\n | \"unknown\"\n | \"none\";\n\nexport type EffectiveConnectionType = \"slow-2g\" | \"2g\" | \"3g\" | \"4g\" | \"unknown\";\n\nexport interface NetworkStatus {\n /** Whether the browser has network access */\n isOnline: boolean;\n /** Whether the browser is offline */\n isOffline: boolean;\n /** The type of connection (wifi, cellular, etc.) — may be undefined if unsupported */\n connectionType: ConnectionType;\n /** Effective connection type based on observed latency — may be undefined if unsupported */\n effectiveType: EffectiveConnectionType;\n /** Estimated downlink bandwidth in Mbps — undefined if unsupported */\n downlink: number | undefined;\n /** Estimated round-trip time in ms — undefined if unsupported */\n rtt: number | undefined;\n /** Whether the user has enabled data saver mode — undefined if unsupported */\n saveData: boolean | undefined;\n /** Manually re-check network status */\n refresh: () => void;\n}\n\n// Network Information API types (not yet in all TS lib versions)\ninterface NetworkInformation extends EventTarget {\n type?: string;\n effectiveType?: string;\n downlink?: number;\n rtt?: number;\n saveData?: boolean;\n addEventListener(type: \"change\", listener: () => void): void;\n removeEventListener(type: \"change\", listener: () => void): void;\n}\n\ndeclare global {\n interface Navigator {\n connection?: NetworkInformation;\n mozConnection?: NetworkInformation;\n webkitConnection?: NetworkInformation;\n }\n}\n\nfunction getConnection(): NetworkInformation | undefined {\n if (typeof navigator === \"undefined\") return undefined;\n return (\n navigator.connection ??\n navigator.mozConnection ??\n navigator.webkitConnection\n );\n}\n\nfunction getConnectionType(connection?: NetworkInformation): ConnectionType {\n if (!connection?.type) return \"unknown\";\n return (connection.type as ConnectionType) ?? \"unknown\";\n}\n\nfunction getEffectiveType(connection?: NetworkInformation): EffectiveConnectionType {\n if (!connection?.effectiveType) return \"unknown\";\n return (connection.effectiveType as EffectiveConnectionType) ?? \"unknown\";\n}\n\nfunction getSnapshot(): Omit<NetworkStatus, \"refresh\"> {\n const isOnline = typeof navigator !== \"undefined\" ? navigator.onLine : true;\n const connection = getConnection();\n\n return {\n isOnline,\n isOffline: !isOnline,\n connectionType: getConnectionType(connection),\n effectiveType: getEffectiveType(connection),\n downlink: connection?.downlink,\n rtt: connection?.rtt,\n saveData: connection?.saveData,\n };\n}\n\nexport function useNetworkStatus(): NetworkStatus {\n const [status, setStatus] = useState<Omit<NetworkStatus, \"refresh\">>(getSnapshot);\n\n const update = useCallback(() => {\n setStatus(getSnapshot());\n }, []);\n\n useEffect(() => {\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n\n const connection = getConnection();\n connection?.addEventListener(\"change\", update);\n\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n connection?.removeEventListener(\"change\", update);\n };\n }, [update]);\n\n return { ...status, refresh: update };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@auraqule/react-network-status",
3
+ "version": "0.2.0",
4
+ "description": "A React hook to monitor network connectivity, online/offline state, and connection type",
5
+ "keywords": [
6
+ "react",
7
+ "hook",
8
+ "network",
9
+ "online",
10
+ "offline",
11
+ "connectivity",
12
+ "connection"
13
+ ],
14
+ "author": "Christian Peters <auraqule@gmail.com>",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/auraqule/react-utils-monorepo.git",
19
+ "directory": "packages/react-idle-detect"
20
+ },
21
+ "main": "./dist/index.js",
22
+ "module": "./dist/index.mjs",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "import": "./dist/index.mjs",
27
+ "require": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "peerDependencies": {
35
+ "react": ">=16.8.0"
36
+ },
37
+ "devDependencies": {
38
+ "@testing-library/react": "^14.0.0",
39
+ "@types/react": "^18.2.0",
40
+ "react": "^18.3.1",
41
+ "react-dom": "18.3.1",
42
+ "tsup": "^8.0.1",
43
+ "typescript": "^5.3.3",
44
+ "vitest": "^1.2.0"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "dev": "tsup --watch",
49
+ "test": "vitest run",
50
+ "lint": "tsc --noEmit"
51
+ }
52
+ }