@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,55 @@
1
+ //#region src/usePreferredLanguage.d.ts
2
+
3
+ interface PreferredLanguageReturn {
4
+ /**
5
+ * Language effectively used by the application.
6
+ */
7
+ language: string;
8
+ /**
9
+ * Updates the user-selected language.
10
+ */
11
+ setUserLanguage: (lang: string) => void;
12
+ /**
13
+ * System / browser language.
14
+ */
15
+ systemLanguage: string;
16
+ /**
17
+ * User-selected language, if any.
18
+ */
19
+ userLanguage: string | null;
20
+ }
21
+ /**
22
+ * `usePreferredLanguage` is a custom React hook that resolves the effective language for the application.
23
+ * This hook is SSR-safe and unopinionated.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * function LanguageSelector() {
28
+ * const {
29
+ * language,
30
+ * userLanguage,
31
+ * systemLanguage,
32
+ * setUserLanguage,
33
+ * } = useResolvedLanguage();
34
+ *
35
+ * return (
36
+ * <div>
37
+ * <p>Resolved: {language}</p>
38
+ * <p>System: {systemLanguage}</p>
39
+ * <p>User: {userLanguage ?? 'system default'}</p>
40
+ *
41
+ * <button onClick={() => setUserLanguage('en')}>
42
+ * English
43
+ * </button>
44
+ *
45
+ * <button onClick={() => setUserLanguage('es-PE')}>
46
+ * Español
47
+ * </button>
48
+ * </div>
49
+ * );
50
+ * }
51
+ * ```
52
+ */
53
+ declare function usePreferredLanguage(): PreferredLanguageReturn;
54
+ //#endregion
55
+ export { usePreferredLanguage };
@@ -0,0 +1,127 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/usePreferredLanguage.ts
4
+ function createSystemLanguageStore() {
5
+ const listeners = /* @__PURE__ */ new Set();
6
+ let listening = false;
7
+ function emit() {
8
+ listeners.forEach((listener) => listener());
9
+ }
10
+ function subscribe(listener) {
11
+ listeners.add(listener);
12
+ if (!listening && typeof window !== "undefined") {
13
+ window.addEventListener("languagechange", emit);
14
+ listening = true;
15
+ }
16
+ return () => {
17
+ listeners.delete(listener);
18
+ if (listeners.size === 0 && listening) {
19
+ window.removeEventListener("languagechange", emit);
20
+ listening = false;
21
+ }
22
+ };
23
+ }
24
+ function getSnapshot() {
25
+ if (typeof window === "undefined") return "en";
26
+ return window.navigator.language;
27
+ }
28
+ function getServerSnapshot() {
29
+ return "en";
30
+ }
31
+ return {
32
+ getServerSnapshot,
33
+ getSnapshot,
34
+ subscribe
35
+ };
36
+ }
37
+ const systemLanguageStore = createSystemLanguageStore();
38
+ function createUserLanguageStore() {
39
+ const listeners = /* @__PURE__ */ new Set();
40
+ const storageKey = "preferred-language";
41
+ let listening = false;
42
+ function emit() {
43
+ listeners.forEach((listener) => listener());
44
+ }
45
+ function subscribe(listener) {
46
+ listeners.add(listener);
47
+ if (!listening && typeof window !== "undefined") {
48
+ const onStorage = (event) => {
49
+ if (event.key === storageKey) emit();
50
+ };
51
+ window.addEventListener("storage", onStorage);
52
+ listening = true;
53
+ return () => {
54
+ listeners.delete(listener);
55
+ if (listeners.size === 0) {
56
+ window.removeEventListener("storage", onStorage);
57
+ listening = false;
58
+ }
59
+ };
60
+ }
61
+ return () => listeners.delete(listener);
62
+ }
63
+ function getSnapshot() {
64
+ if (typeof window === "undefined") return "en";
65
+ return localStorage.getItem(storageKey) ?? "en";
66
+ }
67
+ function getServerSnapshot() {
68
+ return "en";
69
+ }
70
+ function setLanguage(lang) {
71
+ if (typeof window === "undefined") return;
72
+ localStorage.setItem(storageKey, lang);
73
+ emit();
74
+ }
75
+ return {
76
+ getServerSnapshot,
77
+ getSnapshot,
78
+ setLanguage,
79
+ subscribe
80
+ };
81
+ }
82
+ const userLanguageStore = createUserLanguageStore();
83
+ /**
84
+ * `usePreferredLanguage` is a custom React hook that resolves the effective language for the application.
85
+ * This hook is SSR-safe and unopinionated.
86
+ *
87
+ * @example
88
+ * ```tsx
89
+ * function LanguageSelector() {
90
+ * const {
91
+ * language,
92
+ * userLanguage,
93
+ * systemLanguage,
94
+ * setUserLanguage,
95
+ * } = useResolvedLanguage();
96
+ *
97
+ * return (
98
+ * <div>
99
+ * <p>Resolved: {language}</p>
100
+ * <p>System: {systemLanguage}</p>
101
+ * <p>User: {userLanguage ?? 'system default'}</p>
102
+ *
103
+ * <button onClick={() => setUserLanguage('en')}>
104
+ * English
105
+ * </button>
106
+ *
107
+ * <button onClick={() => setUserLanguage('es-PE')}>
108
+ * Español
109
+ * </button>
110
+ * </div>
111
+ * );
112
+ * }
113
+ * ```
114
+ */
115
+ function usePreferredLanguage() {
116
+ const systemLanguage = React.useSyncExternalStore(systemLanguageStore.subscribe, systemLanguageStore.getSnapshot, systemLanguageStore.getServerSnapshot);
117
+ const userLanguage = React.useSyncExternalStore(userLanguageStore.subscribe, userLanguageStore.getSnapshot, userLanguageStore.getServerSnapshot);
118
+ return {
119
+ language: userLanguage || systemLanguage || "en",
120
+ setUserLanguage: userLanguageStore.setLanguage,
121
+ systemLanguage,
122
+ userLanguage: userLanguage ?? null
123
+ };
124
+ }
125
+
126
+ //#endregion
127
+ export { usePreferredLanguage };
@@ -0,0 +1,67 @@
1
+ //#region src/usePreferredTheme.d.ts
2
+ type Theme = string;
3
+ interface PreferredThemeReturn {
4
+ /**
5
+ * Sets a user-selected theme.
6
+ */
7
+ setUserTheme: (theme: Theme | null) => void;
8
+ /**
9
+ * System / OS preferred theme.
10
+ */
11
+ systemTheme: Theme;
12
+ /**
13
+ * Theme effectively used by the application.
14
+ */
15
+ theme: Theme;
16
+ /**
17
+ * Toggles between two themes.
18
+ * Defaults to 'light' and 'dark'.
19
+ */
20
+ toggleTheme: (options?: {
21
+ dark?: Theme;
22
+ light?: Theme;
23
+ }) => void;
24
+ /**
25
+ * User-selected theme, if any.
26
+ */
27
+ userTheme: Theme | null;
28
+ }
29
+ /**
30
+ * `usePreferredTheme` resolves the effective theme for the application.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * function ThemeSwitcher() {
35
+ * const {
36
+ * theme,
37
+ * systemTheme,
38
+ * userTheme,
39
+ * toggleTheme,
40
+ * setUserTheme
41
+ * } = usePreferredTheme();
42
+ *
43
+ * return (
44
+ * <div>
45
+ * <p>Resolved: {theme}</p>
46
+ * <p>System: {systemTheme}</p>
47
+ * <p>User: {userTheme ?? 'system default'}</p>
48
+ *
49
+ * <button onClick={() => toggleTheme()}>
50
+ * Toggle
51
+ * </button>
52
+ *
53
+ * <button onClick={() => setUserTheme('dark')}>
54
+ * Force Dark
55
+ * </button>
56
+ *
57
+ * <button onClick={() => setUserTheme(null)}>
58
+ * Reset to System
59
+ * </button>
60
+ * </div>
61
+ * );
62
+ * }
63
+ * ```
64
+ */
65
+ declare function usePreferredTheme(): PreferredThemeReturn;
66
+ //#endregion
67
+ export { usePreferredTheme };
@@ -0,0 +1,133 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/usePreferredTheme.ts
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ function emit() {
6
+ listeners.forEach((listener) => listener());
7
+ }
8
+ let media = null;
9
+ let mediaListenerAttached = false;
10
+ const systemThemeStore = {
11
+ getServerSnapshot() {
12
+ return "light";
13
+ },
14
+ getSnapshot() {
15
+ if (typeof window === "undefined") return "light";
16
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
17
+ },
18
+ suscribe(listener) {
19
+ listeners.add(listener);
20
+ if (typeof window !== "undefined") {
21
+ if (!media) media = window.matchMedia("(prefers-color-scheme: dark)");
22
+ if (!mediaListenerAttached) {
23
+ media.addEventListener("change", emit);
24
+ mediaListenerAttached = true;
25
+ }
26
+ return () => {
27
+ listeners.delete(listener);
28
+ if (listeners.size === 0 && media && mediaListenerAttached) {
29
+ media.removeEventListener("change", emit);
30
+ mediaListenerAttached = false;
31
+ }
32
+ };
33
+ }
34
+ return () => listeners.delete(listener);
35
+ }
36
+ };
37
+ const storageKey = "preferred-theme";
38
+ const userThemeStore = {
39
+ getSeverSnapshot() {
40
+ return null;
41
+ },
42
+ getSnapshot() {
43
+ if (typeof window === "undefined") return null;
44
+ return localStorage.getItem(storageKey) ?? null;
45
+ },
46
+ setTheme(theme) {
47
+ if (typeof window === "undefined") return;
48
+ if (theme === null) localStorage.removeItem(storageKey);
49
+ else localStorage.setItem(storageKey, theme);
50
+ emit();
51
+ },
52
+ suscribe(listener) {
53
+ listeners.add(listener);
54
+ if (typeof window !== "undefined") {
55
+ const onStorage = (event) => {
56
+ if (event.key === storageKey) emit();
57
+ };
58
+ window.addEventListener("storage", onStorage);
59
+ return () => {
60
+ listeners.delete(listener);
61
+ window.removeEventListener("storage", onStorage);
62
+ };
63
+ }
64
+ return () => listeners.delete(listener);
65
+ }
66
+ };
67
+ function updateDOMTheme(theme) {
68
+ if (typeof window === "undefined") return;
69
+ const root = document.documentElement;
70
+ if (theme === "dark") root.classList.add("dark");
71
+ else root.classList.remove("dark");
72
+ root.style.colorScheme = theme;
73
+ }
74
+ /**
75
+ * `usePreferredTheme` resolves the effective theme for the application.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * function ThemeSwitcher() {
80
+ * const {
81
+ * theme,
82
+ * systemTheme,
83
+ * userTheme,
84
+ * toggleTheme,
85
+ * setUserTheme
86
+ * } = usePreferredTheme();
87
+ *
88
+ * return (
89
+ * <div>
90
+ * <p>Resolved: {theme}</p>
91
+ * <p>System: {systemTheme}</p>
92
+ * <p>User: {userTheme ?? 'system default'}</p>
93
+ *
94
+ * <button onClick={() => toggleTheme()}>
95
+ * Toggle
96
+ * </button>
97
+ *
98
+ * <button onClick={() => setUserTheme('dark')}>
99
+ * Force Dark
100
+ * </button>
101
+ *
102
+ * <button onClick={() => setUserTheme(null)}>
103
+ * Reset to System
104
+ * </button>
105
+ * </div>
106
+ * );
107
+ * }
108
+ * ```
109
+ */
110
+ function usePreferredTheme() {
111
+ const systemTheme = React.useSyncExternalStore(systemThemeStore.suscribe, systemThemeStore.getSnapshot, systemThemeStore.getServerSnapshot);
112
+ const userTheme = React.useSyncExternalStore(userThemeStore.suscribe, userThemeStore.getSnapshot, userThemeStore.getSeverSnapshot);
113
+ const resolved = userTheme ?? systemTheme ?? "light";
114
+ React.useEffect(() => {
115
+ updateDOMTheme(resolved);
116
+ }, [resolved]);
117
+ const toggleTheme = React.useCallback((options) => {
118
+ const light = options?.light ?? "light";
119
+ const dark = options?.dark ?? "dark";
120
+ const next = resolved === "dark" ? light : dark;
121
+ userThemeStore.setTheme(next);
122
+ }, [resolved]);
123
+ return {
124
+ setUserTheme: userThemeStore.setTheme,
125
+ systemTheme,
126
+ theme: resolved,
127
+ toggleTheme,
128
+ userTheme: userTheme ?? null
129
+ };
130
+ }
131
+
132
+ //#endregion
133
+ export { usePreferredTheme };
@@ -0,0 +1,12 @@
1
+ //#region src/usePreviousDistinct.d.ts
2
+ /**
3
+ * `usePreviousDistinct` is a React hook that returns the previous value of a state variable, but only if it is different from the current value.
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * const prevUserId = usePreviousDistinct(userId);
8
+ * ```
9
+ */
10
+ declare function usePreviousDistinct<T>(value: T): T | undefined;
11
+ //#endregion
12
+ export { usePreviousDistinct };
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/usePreviousDistinct.ts
4
+ /**
5
+ * `usePreviousDistinct` is a React hook that returns the previous value of a state variable, but only if it is different from the current value.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const prevUserId = usePreviousDistinct(userId);
10
+ * ```
11
+ */
12
+ function usePreviousDistinct(value) {
13
+ const prevRef = React.useRef(void 0);
14
+ const currentRef = React.useRef(void 0);
15
+ if (!Object.is(value, currentRef.current)) {
16
+ prevRef.current = currentRef.current;
17
+ currentRef.current = value;
18
+ }
19
+ return prevRef.current;
20
+ }
21
+
22
+ //#endregion
23
+ export { usePreviousDistinct };
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useResettableState.d.ts
4
+
5
+ /**
6
+ * `useResettableState` is a React state hook with an explicit reset mechanism.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const [count, setCount, reset] = useResettableState(0);
11
+ * ```
12
+ */
13
+ declare function useResettableState<T>(initialState: T | (() => T)): readonly [T, React.Dispatch<React.SetStateAction<T>>, () => void];
14
+ //#endregion
15
+ export { useResettableState };
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useResettableState.ts
4
+ /**
5
+ * `useResettableState` is a React state hook with an explicit reset mechanism.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const [count, setCount, reset] = useResettableState(0);
10
+ * ```
11
+ */
12
+ function useResettableState(initialState) {
13
+ const initialRef = React.useRef(initialState instanceof Function ? initialState() : initialState);
14
+ const [state, setState] = React.useState(initialState);
15
+ return [
16
+ state,
17
+ setState,
18
+ React.useCallback(() => {
19
+ setState(typeof initialRef.current === "function" ? initialRef.current() : initialRef.current);
20
+ }, [])
21
+ ];
22
+ }
23
+
24
+ //#endregion
25
+ export { useResettableState };
@@ -0,0 +1,48 @@
1
+ //#region src/useScreenOrientation.d.ts
2
+ declare global {
3
+ interface ScreenOrientation {
4
+ lock(orientation: ScreenOrientationLock): Promise<void>;
5
+ unlock(): void;
6
+ }
7
+ type ScreenOrientationLock = 'any' | 'natural' | 'portrait' | 'landscape' | 'portrait-primary' | 'portrait-secondary' | 'landscape-primary' | 'landscape-secondary';
8
+ }
9
+ type OrientationType = 'portrait-primary' | 'portrait-secondary' | 'landscape-primary' | 'landscape-secondary';
10
+ interface UseScreenOrientationReturn {
11
+ /**
12
+ * Current orientation angle in degrees.
13
+ */
14
+ angle: number | null;
15
+ /**
16
+ * Whether the Screen Orientation API is supported.
17
+ */
18
+ isSupported: boolean;
19
+ /**
20
+ * Locks the screen orientation.
21
+ */
22
+ lock: (orientation: ScreenOrientationLock) => Promise<void>;
23
+ /**
24
+ * Current orientation type (e.g. portrait-primary).
25
+ */
26
+ type: OrientationType | null;
27
+ /**
28
+ * Unlocks the screen orientation.
29
+ */
30
+ unlock: () => void;
31
+ }
32
+ /**
33
+ * `useScreenOrientation` provides unopinionated access to the Screen Orientation API.
34
+ * It exposes current orientation state and helpers to lock/unlock orientation without imposing UI decisiones.
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * const orientation = useScreenOrientation();
39
+ *
40
+ * if (orientation.type === 'landscape-primary') {
41
+ * // adapt layout
42
+ * }
43
+ * ```
44
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Screen_Orientation_API
45
+ */
46
+ declare function useScreenOrientation(): UseScreenOrientationReturn;
47
+ //#endregion
48
+ export { useScreenOrientation };
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useScreenOrientation.ts
4
+ /**
5
+ * `useScreenOrientation` provides unopinionated access to the Screen Orientation API.
6
+ * It exposes current orientation state and helpers to lock/unlock orientation without imposing UI decisiones.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const orientation = useScreenOrientation();
11
+ *
12
+ * if (orientation.type === 'landscape-primary') {
13
+ * // adapt layout
14
+ * }
15
+ * ```
16
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Screen_Orientation_API
17
+ */
18
+ function useScreenOrientation() {
19
+ const isSupported = typeof screen !== "undefined" && screen.orientation !== void 0;
20
+ const [type, setType] = React.useState(isSupported ? screen.orientation.type : null);
21
+ const [angle, setAngle] = React.useState(isSupported ? screen.orientation.angle : null);
22
+ const lock = React.useCallback(async (orientation) => {
23
+ if (!isSupported) return;
24
+ await screen.orientation.lock(orientation);
25
+ }, [isSupported]);
26
+ const unlock = React.useCallback(() => {
27
+ if (!isSupported) return;
28
+ screen.orientation.unlock();
29
+ }, [isSupported]);
30
+ React.useEffect(() => {
31
+ if (!isSupported) return;
32
+ const handleChange = () => {
33
+ setType(screen.orientation.type);
34
+ setAngle(screen.orientation.angle);
35
+ };
36
+ screen.orientation.addEventListener("change", handleChange);
37
+ return () => {
38
+ screen.orientation.removeEventListener("change", handleChange);
39
+ };
40
+ }, [isSupported]);
41
+ return {
42
+ angle,
43
+ isSupported,
44
+ lock,
45
+ type,
46
+ unlock
47
+ };
48
+ }
49
+
50
+ //#endregion
51
+ export { useScreenOrientation };
@@ -0,0 +1,16 @@
1
+ //#region src/useScreenSize.d.ts
2
+ interface ScreenSizeReturn {
3
+ height: number;
4
+ width: number;
5
+ }
6
+ /**
7
+ * `useScreenSize` returns the current screen size.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const { width, height } = useScreenSize();
12
+ * ```
13
+ */
14
+ declare function useScreenSize(): ScreenSizeReturn;
15
+ //#endregion
16
+ export { useScreenSize };
@@ -0,0 +1,34 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useScreenSize.ts
4
+ /**
5
+ * `useScreenSize` returns the current screen size.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const { width, height } = useScreenSize();
10
+ * ```
11
+ */
12
+ function useScreenSize() {
13
+ const [size, setSize] = React.useState({
14
+ height: 0,
15
+ width: 0
16
+ });
17
+ React.useEffect(() => {
18
+ const handleResize = () => {
19
+ setSize({
20
+ height: window.innerHeight,
21
+ width: window.innerWidth
22
+ });
23
+ };
24
+ handleResize();
25
+ window.addEventListener("resize", handleResize);
26
+ return () => {
27
+ window.removeEventListener("resize", handleResize);
28
+ };
29
+ }, []);
30
+ return size;
31
+ }
32
+
33
+ //#endregion
34
+ export { useScreenSize };
@@ -0,0 +1,37 @@
1
+ //#region src/useScreenWakeLock.d.ts
2
+ interface UseScreenWakeLockReturn {
3
+ /**
4
+ * Whether the wake lock is currently active.
5
+ */
6
+ isActive: boolean;
7
+ /**
8
+ * Whether the Wake Lock API is supported.
9
+ */
10
+ isSupported: boolean;
11
+ /**
12
+ * Releases the wake lock.
13
+ */
14
+ release: () => Promise<void>;
15
+ /**
16
+ * Requests a screen wake lock.
17
+ */
18
+ request: () => Promise<void>;
19
+ }
20
+ /**
21
+ * `useScreenWakeLock` provides unopinionated access to the Screen Wake Lock Web API.
22
+ * It allows consumers to request and release a screen wake lock without imposing lifecycle or UI behavior.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const wakeLock = useScreenWakeLock();
27
+ *
28
+ * useEffect(() => {
29
+ * wakeLock.request();
30
+ * return () => wakeLock.release();
31
+ * }, []);
32
+ * ```
33
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API
34
+ */
35
+ declare function useScreenWakeLock(): UseScreenWakeLockReturn;
36
+ //#endregion
37
+ export { useScreenWakeLock };
@@ -0,0 +1,48 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/useScreenWakeLock.ts
4
+ /**
5
+ * `useScreenWakeLock` provides unopinionated access to the Screen Wake Lock Web API.
6
+ * It allows consumers to request and release a screen wake lock without imposing lifecycle or UI behavior.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const wakeLock = useScreenWakeLock();
11
+ *
12
+ * useEffect(() => {
13
+ * wakeLock.request();
14
+ * return () => wakeLock.release();
15
+ * }, []);
16
+ * ```
17
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API
18
+ */
19
+ function useScreenWakeLock() {
20
+ const isSupported = typeof navigator !== "undefined" && "wakeLock" in navigator;
21
+ const lockRef = React.useRef(null);
22
+ const [isActive, setIsActive] = React.useState(false);
23
+ const request = React.useCallback(async () => {
24
+ if (!isSupported || lockRef.current) return;
25
+ try {
26
+ lockRef.current = await navigator.wakeLock.request("screen");
27
+ setIsActive(true);
28
+ lockRef.current.addEventListener("release", () => {
29
+ lockRef.current = null;
30
+ setIsActive(false);
31
+ });
32
+ } catch {}
33
+ }, [isSupported]);
34
+ return {
35
+ isActive,
36
+ isSupported,
37
+ release: React.useCallback(async () => {
38
+ if (!lockRef.current) return;
39
+ await lockRef.current.release();
40
+ lockRef.current = null;
41
+ setIsActive(false);
42
+ }, []),
43
+ request
44
+ };
45
+ }
46
+
47
+ //#endregion
48
+ export { useScreenWakeLock };