@vibehooks/react 0.0.1

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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/dist/index.d.ts +54 -0
  4. package/dist/index.js +55 -0
  5. package/dist/useAsyncState.d.ts +52 -0
  6. package/dist/useAsyncState.js +173 -0
  7. package/dist/useAudio.d.ts +26 -0
  8. package/dist/useAudio.js +64 -0
  9. package/dist/useAutoScroll.d.ts +47 -0
  10. package/dist/useAutoScroll.js +122 -0
  11. package/dist/useBarcode.d.ts +77 -0
  12. package/dist/useBarcode.js +140 -0
  13. package/dist/useBatteryStatus.d.ts +53 -0
  14. package/dist/useBatteryStatus.js +67 -0
  15. package/dist/useBodyScrollFreeze.d.ts +36 -0
  16. package/dist/useBodyScrollFreeze.js +74 -0
  17. package/dist/useCameraCapture.d.ts +76 -0
  18. package/dist/useCameraCapture.js +116 -0
  19. package/dist/useCookies.d.ts +42 -0
  20. package/dist/useCookies.js +61 -0
  21. package/dist/useCopyToClipboard.d.ts +22 -0
  22. package/dist/useCopyToClipboard.js +31 -0
  23. package/dist/useCountDown.d.ts +80 -0
  24. package/dist/useCountDown.js +106 -0
  25. package/dist/useDebouncedState.d.ts +47 -0
  26. package/dist/useDebouncedState.js +47 -0
  27. package/dist/useExternalNotifications.d.ts +36 -0
  28. package/dist/useExternalNotifications.js +100 -0
  29. package/dist/useFile.d.ts +74 -0
  30. package/dist/useFile.js +74 -0
  31. package/dist/useFullScreen.d.ts +20 -0
  32. package/dist/useFullScreen.js +43 -0
  33. package/dist/useGeolocation.d.ts +47 -0
  34. package/dist/useGeolocation.js +68 -0
  35. package/dist/useHoverIntent.d.ts +45 -0
  36. package/dist/useHoverIntent.js +81 -0
  37. package/dist/useIdle.d.ts +47 -0
  38. package/dist/useIdle.js +59 -0
  39. package/dist/useIndexedDB.d.ts +60 -0
  40. package/dist/useIndexedDB.js +75 -0
  41. package/dist/useIntersectionObserver.d.ts +45 -0
  42. package/dist/useIntersectionObserver.js +70 -0
  43. package/dist/useIntervalSafe.d.ts +72 -0
  44. package/dist/useIntervalSafe.js +85 -0
  45. package/dist/useIsClient.d.ts +12 -0
  46. package/dist/useIsClient.js +21 -0
  47. package/dist/useIsDesktop.d.ts +12 -0
  48. package/dist/useIsDesktop.js +23 -0
  49. package/dist/useIsFirstRender.d.ts +12 -0
  50. package/dist/useIsFirstRender.js +21 -0
  51. package/dist/useList.d.ts +19 -0
  52. package/dist/useList.js +44 -0
  53. package/dist/useLocalNotifications.d.ts +23 -0
  54. package/dist/useLocalNotifications.js +50 -0
  55. package/dist/useLocalStorage.d.ts +45 -0
  56. package/dist/useLocalStorage.js +71 -0
  57. package/dist/useNetworkInformation.d.ts +138 -0
  58. package/dist/useNetworkInformation.js +76 -0
  59. package/dist/useOnline.d.ts +17 -0
  60. package/dist/useOnline.js +29 -0
  61. package/dist/usePageVisibility.d.ts +32 -0
  62. package/dist/usePageVisibility.js +65 -0
  63. package/dist/usePermissions.d.ts +28 -0
  64. package/dist/usePermissions.js +70 -0
  65. package/dist/usePictureInPicture.d.ts +47 -0
  66. package/dist/usePictureInPicture.js +60 -0
  67. package/dist/usePopover.d.ts +54 -0
  68. package/dist/usePopover.js +67 -0
  69. package/dist/usePreferredLanguage.d.ts +55 -0
  70. package/dist/usePreferredLanguage.js +127 -0
  71. package/dist/usePreferredTheme.d.ts +67 -0
  72. package/dist/usePreferredTheme.js +133 -0
  73. package/dist/usePreviousDistinct.d.ts +12 -0
  74. package/dist/usePreviousDistinct.js +23 -0
  75. package/dist/useResettableState.d.ts +15 -0
  76. package/dist/useResettableState.js +25 -0
  77. package/dist/useScreenOrientation.d.ts +48 -0
  78. package/dist/useScreenOrientation.js +51 -0
  79. package/dist/useScreenSize.d.ts +16 -0
  80. package/dist/useScreenSize.js +34 -0
  81. package/dist/useScreenWakeLock.d.ts +37 -0
  82. package/dist/useScreenWakeLock.js +48 -0
  83. package/dist/useServerSentEvent.d.ts +57 -0
  84. package/dist/useServerSentEvent.js +78 -0
  85. package/dist/useShoppingCart.d.ts +54 -0
  86. package/dist/useShoppingCart.js +122 -0
  87. package/dist/useSmartVideo.d.ts +35 -0
  88. package/dist/useSmartVideo.js +76 -0
  89. package/dist/useSpeech.d.ts +74 -0
  90. package/dist/useSpeech.js +156 -0
  91. package/dist/useSummarizer.d.ts +92 -0
  92. package/dist/useSummarizer.js +83 -0
  93. package/dist/useTaskQueue.d.ts +25 -0
  94. package/dist/useTaskQueue.js +51 -0
  95. package/dist/useThrottledCallback.d.ts +32 -0
  96. package/dist/useThrottledCallback.js +42 -0
  97. package/dist/useTimeout.d.ts +58 -0
  98. package/dist/useTimeout.js +70 -0
  99. package/dist/useToggle.d.ts +30 -0
  100. package/dist/useToggle.js +23 -0
  101. package/dist/useTraceUpdates.d.ts +22 -0
  102. package/dist/useTraceUpdates.js +38 -0
  103. package/dist/useTranslator.d.ts +110 -0
  104. package/dist/useTranslator.js +119 -0
  105. package/dist/useUserActivation.d.ts +40 -0
  106. package/dist/useUserActivation.js +63 -0
  107. package/dist/useVibration.d.ts +55 -0
  108. package/dist/useVibration.js +50 -0
  109. package/dist/useWebsocket.d.ts +80 -0
  110. package/dist/useWebsocket.js +125 -0
  111. package/package.json +70 -0
@@ -0,0 +1,119 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useTranslator.ts
4
+ /**
5
+ * `useTranslator` is a React custom hook that provides a simple way to translate text using Translator API in Chrome to translate text with AI models provided in the browser.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const {
10
+ * isSupported,
11
+ * translate,
12
+ * checkLanguageSupport,
13
+ * isLanguagePairSupported,
14
+ * isTranslating,
15
+ * translation,
16
+ * error,
17
+ * } = useTranslator({
18
+ * sourceLanguage: "es",
19
+ * targetLanguage: "en-US",
20
+ * onLanguageSupportCheck: (supported) => {
21
+ * console.log("Language pair supported:", supported);
22
+ * },
23
+ * });
24
+ *
25
+ * React.useEffect(() => {
26
+ * checkLanguageSupport();
27
+ * }, [checkLanguageSupport]);
28
+ *
29
+ * const handleTranslate = async () => {
30
+ * await translate("Hola mundo");
31
+ * };
32
+ * ```
33
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Translator
34
+ */
35
+ function useTranslator(options) {
36
+ const { onLanguageSupportCheck, sourceLanguage, targetLanguage } = options;
37
+ const translatorRef = React.useRef(null);
38
+ const [isSupported, setIsSupported] = React.useState(true);
39
+ const [isLanguagePairSupported, setIsLanguagePairSupported] = React.useState(null);
40
+ const [isTranslating, setIsTranslating] = React.useState(false);
41
+ const [translation, setTranslation] = React.useState(null);
42
+ const [error, setError] = React.useState(null);
43
+ React.useEffect(() => {
44
+ if (typeof window === "undefined" || !window.Translator) {
45
+ setIsSupported(false);
46
+ setError(/* @__PURE__ */ new Error("Translator API is not supported in this browser."));
47
+ return;
48
+ }
49
+ setIsSupported(true);
50
+ }, []);
51
+ const checkLanguageSupport = React.useCallback(async () => {
52
+ if (!window.Translator) {
53
+ const error$1 = /* @__PURE__ */ new Error("Translator API is not supported in this browser.");
54
+ setError(error$1);
55
+ throw error$1;
56
+ }
57
+ try {
58
+ const supported = await window.Translator.availability({
59
+ sourceLanguage,
60
+ targetLanguage
61
+ }) === "available";
62
+ setIsLanguagePairSupported(supported);
63
+ onLanguageSupportCheck?.(supported);
64
+ return supported;
65
+ } catch (err) {
66
+ const error$1 = err instanceof Error ? err : /* @__PURE__ */ new Error("Failed to check language support.");
67
+ setError(error$1);
68
+ throw error$1;
69
+ }
70
+ }, [
71
+ sourceLanguage,
72
+ targetLanguage,
73
+ onLanguageSupportCheck
74
+ ]);
75
+ const ensureTranslator = React.useCallback(async () => {
76
+ if (translatorRef.current) return translatorRef.current;
77
+ if (!window.Translator) throw new Error("Translator API is not supported in this browser.");
78
+ const translator = await window.Translator.create({
79
+ sourceLanguage,
80
+ targetLanguage
81
+ });
82
+ translatorRef.current = translator;
83
+ return translator;
84
+ }, [sourceLanguage, targetLanguage]);
85
+ const translate = React.useCallback(async (text) => {
86
+ setIsTranslating(true);
87
+ setError(null);
88
+ try {
89
+ if (isLanguagePairSupported === false) throw new Error("The selected language pair is not supported.");
90
+ const result = await (await ensureTranslator()).translate(text);
91
+ setTranslation(result);
92
+ return result;
93
+ } catch (err) {
94
+ const error$1 = err instanceof Error ? err : /* @__PURE__ */ new Error("Failed to translate text.");
95
+ setError(error$1);
96
+ throw error$1;
97
+ } finally {
98
+ setIsTranslating(false);
99
+ }
100
+ }, [isLanguagePairSupported, ensureTranslator]);
101
+ React.useEffect(() => {
102
+ return () => {
103
+ translatorRef.current?.destroy();
104
+ translatorRef.current = null;
105
+ };
106
+ }, []);
107
+ return {
108
+ checkLanguageSupport,
109
+ error,
110
+ isLanguagePairSupported,
111
+ isSupported,
112
+ isTranslating,
113
+ translate,
114
+ translation
115
+ };
116
+ }
117
+
118
+ //#endregion
119
+ export { useTranslator };
@@ -0,0 +1,40 @@
1
+ //#region src/useUserActivation.d.ts
2
+ interface UseUserActivationReturn {
3
+ /**
4
+ * Whether the user has ever interacted with the document.
5
+ */
6
+ hasBeenActive: boolean;
7
+ /**
8
+ * Whether there is a current transient user activation.
9
+ */
10
+ isActive: boolean;
11
+ /**
12
+ * Indicates whether the UserActivation API is supported.
13
+ */
14
+ isSupported: boolean;
15
+ /**
16
+ * Forces a re-read of the current activation state.
17
+ */
18
+ refresh: () => void;
19
+ }
20
+ /**
21
+ * `useUserActivation` is a React hook that exposes the browser User Activation State.
22
+ * This hook provides read-only access to `navigator.userActivation` allowing consumers to react to transient and persistent user activation without imposing side effects or control flow.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { isActive, hasBeenActive } = useUserActivation();
27
+ *
28
+ * if (!hasBeenActive) {
29
+ * return <p>Please interact with the page.</p>;
30
+ * }
31
+ *
32
+ * if (isActive) {
33
+ * runSensitiveAction();
34
+ * }
35
+ * ```
36
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/UserActivation
37
+ */
38
+ declare function useUserActivation(): UseUserActivationReturn;
39
+ //#endregion
40
+ export { useUserActivation };
@@ -0,0 +1,63 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useUserActivation.ts
4
+ /**
5
+ * `useUserActivation` is a React hook that exposes the browser User Activation State.
6
+ * This hook provides read-only access to `navigator.userActivation` allowing consumers to react to transient and persistent user activation without imposing side effects or control flow.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const { isActive, hasBeenActive } = useUserActivation();
11
+ *
12
+ * if (!hasBeenActive) {
13
+ * return <p>Please interact with the page.</p>;
14
+ * }
15
+ *
16
+ * if (isActive) {
17
+ * runSensitiveAction();
18
+ * }
19
+ * ```
20
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/UserActivation
21
+ */
22
+ function useUserActivation() {
23
+ const isSupported = typeof navigator !== "undefined" && typeof navigator.userActivation !== "undefined";
24
+ const readState = React.useCallback(() => {
25
+ if (!isSupported) return {
26
+ hasBeenActive: false,
27
+ isActive: false
28
+ };
29
+ return {
30
+ hasBeenActive: navigator.userActivation.hasBeenActive,
31
+ isActive: navigator.userActivation.isActive
32
+ };
33
+ }, [isSupported]);
34
+ const [state, setState] = React.useState(() => readState());
35
+ const refresh = React.useCallback(() => {
36
+ setState(readState());
37
+ }, [readState]);
38
+ React.useEffect(() => {
39
+ if (!isSupported) return;
40
+ const events = [
41
+ "mousedown",
42
+ "keydown",
43
+ "touchstart",
44
+ "pointerdown"
45
+ ];
46
+ const handler = () => {
47
+ refresh();
48
+ };
49
+ events.forEach((event) => window.addEventListener(event, handler, { passive: true }));
50
+ return () => {
51
+ events.forEach((event) => window.removeEventListener(event, handler));
52
+ };
53
+ }, [isSupported, refresh]);
54
+ return {
55
+ hasBeenActive: state.hasBeenActive,
56
+ isActive: state.isActive,
57
+ isSupported,
58
+ refresh
59
+ };
60
+ }
61
+
62
+ //#endregion
63
+ export { useUserActivation };
@@ -0,0 +1,55 @@
1
+ //#region src/useVibration.d.ts
2
+ /**
3
+ * Pattern accepted by the Vibration API.
4
+ * A single duration in milliseconds or a vibration pattern array.
5
+ */
6
+ type VibrationPattern = number | number[];
7
+ interface UseVibrationReturn {
8
+ /**
9
+ * Cancels any ongoing vibration.
10
+ * During SSR or when unsupported, does nothing.
11
+ */
12
+ cancel: () => void;
13
+ /**
14
+ * Indicates whether the Vibration API is supported in the current execution environment.
15
+ */
16
+ isSupported: boolean;
17
+ /**
18
+ * Triggers a vibration with the given pattern.
19
+ * Returns `true` if the vibration request was accepted by the user agent, or `false` otherwise.
20
+ * Durring SSR or when unsupported, returns `false`.
21
+ */
22
+ vibrate: (pattern: VibrationPattern) => boolean;
23
+ }
24
+ /**
25
+ * `useVibration` is a React hook to safely access the Vibration API in an unopinionated and SSR-safe manner.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * function Example() {
30
+ * const { isSupported, vibrate, cancel } = useVibration();
31
+ *
32
+ * if (!isSupported) {
33
+ * return <button disabled>Vibration not supported</button>;
34
+ * }
35
+ *
36
+ * return (
37
+ * <>
38
+ * <button onClick={() => vibrate(200)}>
39
+ * Vibrate once
40
+ * </button>
41
+ * <button onClick={() => vibrate([100, 50, 100])}>
42
+ * Vibrate pattern
43
+ * </button>
44
+ * <button onClick={cancel}>
45
+ * Stop vibration
46
+ * </button>
47
+ * </>
48
+ * );
49
+ * }
50
+ * ```
51
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API
52
+ */
53
+ declare function useVibration(): UseVibrationReturn;
54
+ //#endregion
55
+ export { useVibration };
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useVibration.ts
4
+ /**
5
+ * `useVibration` is a React hook to safely access the Vibration API in an unopinionated and SSR-safe manner.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * function Example() {
10
+ * const { isSupported, vibrate, cancel } = useVibration();
11
+ *
12
+ * if (!isSupported) {
13
+ * return <button disabled>Vibration not supported</button>;
14
+ * }
15
+ *
16
+ * return (
17
+ * <>
18
+ * <button onClick={() => vibrate(200)}>
19
+ * Vibrate once
20
+ * </button>
21
+ * <button onClick={() => vibrate([100, 50, 100])}>
22
+ * Vibrate pattern
23
+ * </button>
24
+ * <button onClick={cancel}>
25
+ * Stop vibration
26
+ * </button>
27
+ * </>
28
+ * );
29
+ * }
30
+ * ```
31
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API
32
+ */
33
+ function useVibration() {
34
+ const isSupported = typeof window !== "undefined" && typeof navigator !== "undefined" && typeof navigator.vibrate === "function";
35
+ const vibrate = React.useCallback((pattern) => {
36
+ if (!isSupported) return false;
37
+ return navigator.vibrate(pattern);
38
+ }, [isSupported]);
39
+ return {
40
+ cancel: React.useCallback(() => {
41
+ if (!isSupported) return;
42
+ navigator.vibrate(0);
43
+ }, [isSupported]),
44
+ isSupported,
45
+ vibrate
46
+ };
47
+ }
48
+
49
+ //#endregion
50
+ export { useVibration };
@@ -0,0 +1,80 @@
1
+ //#region src/useWebsocket.d.ts
2
+ interface UseWebsocketOptions<TMessage = unknown> {
3
+ /**
4
+ * Should the socket auto-connect inmediately (default: true)
5
+ */
6
+ autoConnect?: boolean;
7
+ /**
8
+ * Max number of reconnection attempts (default: Infinity)
9
+ */
10
+ maxRetries?: number;
11
+ /**
12
+ * Called when the socket closes unexpectedly
13
+ */
14
+ onClose?: (event: CloseEvent) => void;
15
+ /**
16
+ * Called when an error occurs
17
+ */
18
+ onError?: (event: Event) => void;
19
+ /**
20
+ * Called when a message is received
21
+ */
22
+ onMessage?: (message: TMessage) => void;
23
+ /**
24
+ * Reconnection interval in milliseconds (default: 3000)
25
+ */
26
+ reconnectionInterval?: number;
27
+ /**
28
+ * Websocket url
29
+ */
30
+ url: string;
31
+ }
32
+ interface UseWebsocketReturn<TMessage = unknown> {
33
+ /**
34
+ * Manually reconnect the Websocket
35
+ */
36
+ connect: () => void;
37
+ /**
38
+ * Manually disconnect the Websocket
39
+ */
40
+ disconnect: () => void;
41
+ /**
42
+ * Show any errors
43
+ */
44
+ error: Error | null;
45
+ /**
46
+ * Connection status
47
+ */
48
+ isConnected: boolean;
49
+ /**
50
+ * Latest received message
51
+ */
52
+ message: TMessage | null;
53
+ /**
54
+ * Messages
55
+ */
56
+ messages: TMessage[];
57
+ /**
58
+ * Send a message via Websocket
59
+ */
60
+ send: (data: string | ArrayBuffer | Blob | ArrayBufferView) => void;
61
+ }
62
+ /**
63
+ * `useWebsocket` is a React hook to manage Websocket connections with auto-reconnect, error handling, and SSR safety.
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * const { socket, message, isConnected, send } = useWebsocket<{ text: string }>({
68
+ * url: 'wss://example.com/socket',
69
+ * onMessage: (msg) => console.log(msg),
70
+ * });
71
+ *
72
+ * React.useEffect(() => {
73
+ * if (isConnected) send(JSON.stringify({ hello: 'world' }));
74
+ * }, [isConnected]);
75
+ * ```
76
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
77
+ */
78
+ declare function useWebsocket<TMessage = unknown>(options: UseWebsocketOptions<TMessage>): UseWebsocketReturn<TMessage>;
79
+ //#endregion
80
+ export { useWebsocket };
@@ -0,0 +1,125 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useWebsocket.ts
4
+ /**
5
+ * `useWebsocket` is a React hook to manage Websocket connections with auto-reconnect, error handling, and SSR safety.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const { socket, message, isConnected, send } = useWebsocket<{ text: string }>({
10
+ * url: 'wss://example.com/socket',
11
+ * onMessage: (msg) => console.log(msg),
12
+ * });
13
+ *
14
+ * React.useEffect(() => {
15
+ * if (isConnected) send(JSON.stringify({ hello: 'world' }));
16
+ * }, [isConnected]);
17
+ * ```
18
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
19
+ */
20
+ function useWebsocket(options) {
21
+ const { autoConnect = true, maxRetries = Infinity, onClose, onError, onMessage, reconnectionInterval = 3e3, url } = options;
22
+ const [message, setMessage] = React.useState(null);
23
+ const [messages, setMessages] = React.useState([]);
24
+ const [isConnected, setIsConnected] = React.useState(false);
25
+ const [error, setError] = React.useState(null);
26
+ const socketRef = React.useRef(null);
27
+ const retriesRef = React.useRef(0);
28
+ const reconnectTimeoutRef = React.useRef(null);
29
+ const manualCloseRef = React.useRef(false);
30
+ const hasOpenedRef = React.useRef(false);
31
+ const onMessageRef = React.useRef(onMessage);
32
+ const onCloseRef = React.useRef(onClose);
33
+ const onErrorRef = React.useRef(onError);
34
+ React.useEffect(() => {
35
+ onMessageRef.current = onMessage;
36
+ onCloseRef.current = onClose;
37
+ onErrorRef.current = onError;
38
+ }, [
39
+ onMessage,
40
+ onClose,
41
+ onError
42
+ ]);
43
+ const connect = React.useCallback(() => {
44
+ if (typeof window === "undefined") return;
45
+ manualCloseRef.current = false;
46
+ hasOpenedRef.current = false;
47
+ const ws = new WebSocket(url);
48
+ socketRef.current = ws;
49
+ ws.onopen = () => {
50
+ hasOpenedRef.current = true;
51
+ setIsConnected(true);
52
+ setError(null);
53
+ retriesRef.current = 0;
54
+ };
55
+ ws.onmessage = (event) => {
56
+ let data;
57
+ try {
58
+ data = JSON.parse(event.data);
59
+ } catch {
60
+ data = event.data;
61
+ }
62
+ setMessage(data);
63
+ setMessages((prev) => [...prev, data]);
64
+ onMessageRef.current?.(data);
65
+ };
66
+ ws.onclose = (event) => {
67
+ setIsConnected(false);
68
+ onCloseRef.current?.(event);
69
+ if (hasOpenedRef.current && !manualCloseRef.current && retriesRef.current < maxRetries) {
70
+ retriesRef.current += 1;
71
+ reconnectTimeoutRef.current = setTimeout(connect, reconnectionInterval);
72
+ }
73
+ };
74
+ ws.onerror = (event) => {
75
+ setError((prev) => prev ?? /* @__PURE__ */ new Error("WebSocket error"));
76
+ onErrorRef.current?.(event);
77
+ };
78
+ }, [
79
+ url,
80
+ reconnectionInterval,
81
+ maxRetries
82
+ ]);
83
+ const disconnect = React.useCallback(() => {
84
+ manualCloseRef.current = true;
85
+ if (socketRef.current) {
86
+ socketRef.current.close();
87
+ socketRef.current = null;
88
+ }
89
+ if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current);
90
+ }, []);
91
+ const reconnect = React.useCallback(() => {
92
+ disconnect();
93
+ connect();
94
+ }, [disconnect, connect]);
95
+ React.useEffect(() => {
96
+ if (!autoConnect) return;
97
+ connect();
98
+ return () => {
99
+ disconnect();
100
+ };
101
+ }, [
102
+ autoConnect,
103
+ connect,
104
+ disconnect
105
+ ]);
106
+ return {
107
+ connect: reconnect,
108
+ disconnect,
109
+ error,
110
+ isConnected,
111
+ message,
112
+ messages,
113
+ send: React.useCallback((data) => {
114
+ const socket = socketRef.current;
115
+ if (!socket || socket.readyState !== WebSocket.OPEN) {
116
+ setError(/* @__PURE__ */ new Error("WebSocket is not connected. Message not sent."));
117
+ return;
118
+ }
119
+ socket.send(data);
120
+ }, [])
121
+ };
122
+ }
123
+
124
+ //#endregion
125
+ export { useWebsocket };
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@vibehooks/react",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "description": "Modern React and Next.js hooks, unopinionated and focused on developer experience.",
6
+ "author": "Sebastian Marat Urdanegui Bisalaya <sebasurdanegui@gmail.com>",
7
+ "license": "MIT",
8
+ "homepage": "https://vibehooks.sebastianurdanegui.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/SebastianUrdaneguiBisalaya/vibehooks.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/SebastianUrdaneguiBisalaya/vibehooks/issues"
15
+ },
16
+ "exports": {
17
+ ".": "./dist/index.js",
18
+ "./package.json": "./package.json"
19
+ },
20
+ "main": "./dist/index.js",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "sideEffects": false,
30
+ "lint-staged": {
31
+ "*.{js,ts,tsx,mdx}": [
32
+ "eslint --fix",
33
+ "prettier --write"
34
+ ]
35
+ },
36
+ "peerDependencies": {
37
+ "react": "^19.2.0",
38
+ "react-dom": "^19.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "@commitlint/cli": "^20.4.1",
42
+ "@commitlint/config-conventional": "^20.4.1",
43
+ "@eslint/js": "^9.39.2",
44
+ "@tsconfig/strictest": "^2.0.8",
45
+ "@types/node": "^25.0.3",
46
+ "@types/react": "^19.2.7",
47
+ "@types/react-dom": "^19.2.3",
48
+ "bumpp": "^10.3.2",
49
+ "eslint": "^9.39.2",
50
+ "eslint-plugin-perfectionist": "^5.4.0",
51
+ "eslint-plugin-react": "^7.37.5",
52
+ "globals": "^17.0.0",
53
+ "husky": "^9.1.7",
54
+ "lint-staged": "^16.2.7",
55
+ "prettier": "3.7.4",
56
+ "tsdown": "^0.18.1",
57
+ "typescript": "^5.9.3",
58
+ "typescript-eslint": "^8.53.1"
59
+ },
60
+ "scripts": {
61
+ "build": "tsdown",
62
+ "dev": "tsdown --watch",
63
+ "typecheck": "tsc --noEmit",
64
+ "release": "bumpp && pnpm publish",
65
+ "prettier-check": "prettier --check .",
66
+ "prettier-fix": "prettier --write .",
67
+ "lint": "eslint .",
68
+ "lint-fix": "eslint . --fix"
69
+ }
70
+ }