react-simplikit 0.0.52 → 0.1.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/CHANGELOG.md +106 -0
- package/README.md +36 -26
- package/dist/hooks/useAsyncEffect/useAsyncEffect.cjs +1 -0
- package/dist/hooks/useAsyncEffect/useAsyncEffect.mjs +1 -0
- package/dist/hooks/useCallbackOncePerRender/useCallbackOncePerRender.cjs +1 -0
- package/dist/hooks/useCallbackOncePerRender/useCallbackOncePerRender.mjs +1 -0
- package/dist/hooks/useConditionalEffect/useConditionalEffect.cjs +1 -0
- package/dist/hooks/useConditionalEffect/useConditionalEffect.mjs +1 -0
- package/dist/hooks/useInputState/useInputState.cjs +9 -3
- package/dist/hooks/useInputState/useInputState.d.cts +11 -4
- package/dist/hooks/useInputState/useInputState.d.mts +11 -4
- package/dist/hooks/useInputState/useInputState.mjs +9 -3
- package/dist/hooks/useLoading/useLoading.cjs +3 -5
- package/dist/hooks/useLoading/useLoading.d.cts +2 -5
- package/dist/hooks/useLoading/useLoading.d.mts +2 -5
- package/dist/hooks/useLoading/useLoading.mjs +3 -5
- package/dist/hooks/usePreservedReference/usePreservedReference.cjs +1 -0
- package/dist/hooks/usePreservedReference/usePreservedReference.mjs +1 -0
- package/dist/hooks/usePrevious/usePrevious.cjs +1 -0
- package/dist/hooks/usePrevious/usePrevious.mjs +1 -0
- package/dist/hooks/useRefEffect/useRefEffect.cjs +1 -0
- package/dist/hooks/useRefEffect/useRefEffect.mjs +1 -0
- package/dist/hooks/useStorageState/useStorageState.cjs +1 -0
- package/dist/hooks/useStorageState/useStorageState.mjs +1 -0
- package/dist/hooks/useThrottledCallback/useThrottledCallback.cjs +9 -1
- package/dist/hooks/useThrottledCallback/useThrottledCallback.mjs +9 -1
- package/dist/index.cjs +34 -0
- package/dist/index.d.cts +19 -1
- package/dist/index.d.mts +19 -1
- package/dist/index.mjs +18 -1
- package/dist/mobile/hooks/useAvoidKeyboard/index.d.cts +3 -0
- package/dist/mobile/hooks/useAvoidKeyboard/index.d.mts +3 -0
- package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.cjs +75 -0
- package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.d.cts +89 -0
- package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.d.mts +89 -0
- package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.mjs +75 -0
- package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.cjs +47 -0
- package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.d.cts +37 -0
- package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.d.mts +37 -0
- package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.mjs +47 -0
- package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.cjs +41 -0
- package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.cts +41 -0
- package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.mts +41 -0
- package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.mjs +41 -0
- package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.cjs +88 -0
- package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.d.cts +77 -0
- package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.d.mts +77 -0
- package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.mjs +88 -0
- package/dist/mobile/hooks/usePageVisibility/usePageVisibility.cjs +73 -0
- package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.cts +62 -0
- package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.mts +62 -0
- package/dist/mobile/hooks/usePageVisibility/usePageVisibility.mjs +73 -0
- package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.cjs +74 -0
- package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.cts +55 -0
- package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.mts +55 -0
- package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.mjs +74 -0
- package/dist/mobile/hooks/useScrollDirection/useScrollDirection.cjs +79 -0
- package/dist/mobile/hooks/useScrollDirection/useScrollDirection.d.cts +40 -0
- package/dist/mobile/hooks/useScrollDirection/useScrollDirection.d.mts +40 -0
- package/dist/mobile/hooks/useScrollDirection/useScrollDirection.mjs +79 -0
- package/dist/mobile/hooks/useVisualViewport/useVisualViewport.cjs +77 -0
- package/dist/mobile/hooks/useVisualViewport/useVisualViewport.d.cts +89 -0
- package/dist/mobile/hooks/useVisualViewport/useVisualViewport.d.mts +89 -0
- package/dist/mobile/hooks/useVisualViewport/useVisualViewport.mjs +77 -0
- package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.cjs +55 -0
- package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.cts +22 -0
- package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.mts +22 -0
- package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.mjs +55 -0
- package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.cjs +49 -0
- package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.cts +23 -0
- package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.mts +23 -0
- package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.mjs +49 -0
- package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.cjs +35 -0
- package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.d.cts +28 -0
- package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.d.mts +28 -0
- package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.mjs +35 -0
- package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.cjs +58 -0
- package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.d.cts +44 -0
- package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.d.mts +44 -0
- package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.mjs +58 -0
- package/dist/mobile/utils/isAndroid/isAndroid.cjs +32 -0
- package/dist/mobile/utils/isAndroid/isAndroid.d.cts +27 -0
- package/dist/mobile/utils/isAndroid/isAndroid.d.mts +27 -0
- package/dist/mobile/utils/isAndroid/isAndroid.mjs +32 -0
- package/dist/mobile/utils/isIOS/isIOS.cjs +37 -0
- package/dist/mobile/utils/isIOS/isIOS.d.cts +30 -0
- package/dist/mobile/utils/isIOS/isIOS.d.mts +30 -0
- package/dist/mobile/utils/isIOS/isIOS.mjs +37 -0
- package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.cjs +28 -0
- package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.d.cts +25 -0
- package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.d.mts +25 -0
- package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.mjs +28 -0
- package/dist/mobile/utils/isServer/isServer.cjs +24 -0
- package/dist/mobile/utils/isServer/isServer.d.cts +22 -0
- package/dist/mobile/utils/isServer/isServer.d.mts +22 -0
- package/dist/mobile/utils/isServer/isServer.mjs +24 -0
- package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.cjs +71 -0
- package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.d.cts +64 -0
- package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.d.mts +64 -0
- package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.mjs +71 -0
- package/dist/utils/buildContext/buildContext.cjs +1 -0
- package/dist/utils/buildContext/buildContext.mjs +1 -0
- package/package.json +22 -8
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { disableBodyScrollLock } from "../../utils/disableBodyScrollLock/disableBodyScrollLock.mjs";
|
|
3
|
+
import { enableBodyScrollLock } from "../../utils/enableBodyScrollLock/enableBodyScrollLock.mjs";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
//#region src/mobile/hooks/useBodyScrollLock/useBodyScrollLock.ts
|
|
6
|
+
/**
|
|
7
|
+
* @description
|
|
8
|
+
* `useBodyScrollLock` is a React hook that locks body scroll while the component is mounted.
|
|
9
|
+
* It automatically locks on mount and unlocks on unmount.
|
|
10
|
+
*
|
|
11
|
+
* **Note:** For multiple overlapping modals, use a single lock at the parent level.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* function Modal() {
|
|
15
|
+
* useBodyScrollLock();
|
|
16
|
+
* return <div className="modal">Modal content</div>;
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Multiple modals - single lock pattern
|
|
21
|
+
* function BodyScrollLock() {
|
|
22
|
+
* useBodyScrollLock();
|
|
23
|
+
* return null;
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* function App() {
|
|
27
|
+
* const hasModal = showModal1 || showModal2;
|
|
28
|
+
*
|
|
29
|
+
* return (
|
|
30
|
+
* <>
|
|
31
|
+
* {hasModal && <BodyScrollLock />}
|
|
32
|
+
* {showModal1 && <Modal1 />}
|
|
33
|
+
* {showModal2 && <Modal2 />}
|
|
34
|
+
* </>
|
|
35
|
+
* );
|
|
36
|
+
* }
|
|
37
|
+
*/
|
|
38
|
+
function useBodyScrollLock() {
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
enableBodyScrollLock();
|
|
41
|
+
return () => {
|
|
42
|
+
disableBodyScrollLock();
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { useBodyScrollLock };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_subscribeKeyboardHeight = require("../../utils/subscribeKeyboardHeight/subscribeKeyboardHeight.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
//#region src/mobile/hooks/useKeyboardHeight/useKeyboardHeight.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useKeyboardHeight` is a React hook that tracks the on-screen keyboard height.
|
|
8
|
+
* It returns the current keyboard height in pixels, which updates automatically
|
|
9
|
+
* when the keyboard appears, disappears, or changes size.
|
|
10
|
+
*
|
|
11
|
+
* @param {UseKeyboardHeightOptions} [options] - Configuration options.
|
|
12
|
+
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
|
|
13
|
+
*
|
|
14
|
+
* @returns {UseKeyboardHeightResult} An object containing the current keyboard height.
|
|
15
|
+
* - keyboardHeight `number` - The current keyboard height in pixels. 0 when the keyboard is hidden;
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* function ChatInput() {
|
|
19
|
+
* const { keyboardHeight } = useKeyboardHeight();
|
|
20
|
+
*
|
|
21
|
+
* return (
|
|
22
|
+
* <div style={{ paddingBottom: `${keyboardHeight}px` }}>
|
|
23
|
+
* <input type="text" placeholder="Type a message..." />
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
function useKeyboardHeight(options = {}) {
|
|
29
|
+
const { immediate = true } = options;
|
|
30
|
+
const [keyboardHeight, setKeyboardHeight] = (0, react.useState)(0);
|
|
31
|
+
(0, react.useEffect)(function subscribeToKeyboardHeight() {
|
|
32
|
+
const { unsubscribe } = require_subscribeKeyboardHeight.subscribeKeyboardHeight({
|
|
33
|
+
callback: setKeyboardHeight,
|
|
34
|
+
immediate
|
|
35
|
+
});
|
|
36
|
+
return unsubscribe;
|
|
37
|
+
}, [immediate]);
|
|
38
|
+
return { keyboardHeight };
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
exports.useKeyboardHeight = useKeyboardHeight;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.ts
|
|
3
|
+
type UseKeyboardHeightOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* If true, the hook will get the initial keyboard height on mount.
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
immediate?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type UseKeyboardHeightResult = {
|
|
11
|
+
/**
|
|
12
|
+
* The current keyboard height in pixels.
|
|
13
|
+
*/
|
|
14
|
+
keyboardHeight: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* `useKeyboardHeight` is a React hook that tracks the on-screen keyboard height.
|
|
19
|
+
* It returns the current keyboard height in pixels, which updates automatically
|
|
20
|
+
* when the keyboard appears, disappears, or changes size.
|
|
21
|
+
*
|
|
22
|
+
* @param {UseKeyboardHeightOptions} [options] - Configuration options.
|
|
23
|
+
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
|
|
24
|
+
*
|
|
25
|
+
* @returns {UseKeyboardHeightResult} An object containing the current keyboard height.
|
|
26
|
+
* - keyboardHeight `number` - The current keyboard height in pixels. 0 when the keyboard is hidden;
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* function ChatInput() {
|
|
30
|
+
* const { keyboardHeight } = useKeyboardHeight();
|
|
31
|
+
*
|
|
32
|
+
* return (
|
|
33
|
+
* <div style={{ paddingBottom: `${keyboardHeight}px` }}>
|
|
34
|
+
* <input type="text" placeholder="Type a message..." />
|
|
35
|
+
* </div>
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
declare function useKeyboardHeight(options?: UseKeyboardHeightOptions): UseKeyboardHeightResult;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { useKeyboardHeight };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.ts
|
|
3
|
+
type UseKeyboardHeightOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* If true, the hook will get the initial keyboard height on mount.
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
immediate?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type UseKeyboardHeightResult = {
|
|
11
|
+
/**
|
|
12
|
+
* The current keyboard height in pixels.
|
|
13
|
+
*/
|
|
14
|
+
keyboardHeight: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* `useKeyboardHeight` is a React hook that tracks the on-screen keyboard height.
|
|
19
|
+
* It returns the current keyboard height in pixels, which updates automatically
|
|
20
|
+
* when the keyboard appears, disappears, or changes size.
|
|
21
|
+
*
|
|
22
|
+
* @param {UseKeyboardHeightOptions} [options] - Configuration options.
|
|
23
|
+
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
|
|
24
|
+
*
|
|
25
|
+
* @returns {UseKeyboardHeightResult} An object containing the current keyboard height.
|
|
26
|
+
* - keyboardHeight `number` - The current keyboard height in pixels. 0 when the keyboard is hidden;
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* function ChatInput() {
|
|
30
|
+
* const { keyboardHeight } = useKeyboardHeight();
|
|
31
|
+
*
|
|
32
|
+
* return (
|
|
33
|
+
* <div style={{ paddingBottom: `${keyboardHeight}px` }}>
|
|
34
|
+
* <input type="text" placeholder="Type a message..." />
|
|
35
|
+
* </div>
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
declare function useKeyboardHeight(options?: UseKeyboardHeightOptions): UseKeyboardHeightResult;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { useKeyboardHeight };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { subscribeKeyboardHeight } from "../../utils/subscribeKeyboardHeight/subscribeKeyboardHeight.mjs";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
//#region src/mobile/hooks/useKeyboardHeight/useKeyboardHeight.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useKeyboardHeight` is a React hook that tracks the on-screen keyboard height.
|
|
8
|
+
* It returns the current keyboard height in pixels, which updates automatically
|
|
9
|
+
* when the keyboard appears, disappears, or changes size.
|
|
10
|
+
*
|
|
11
|
+
* @param {UseKeyboardHeightOptions} [options] - Configuration options.
|
|
12
|
+
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
|
|
13
|
+
*
|
|
14
|
+
* @returns {UseKeyboardHeightResult} An object containing the current keyboard height.
|
|
15
|
+
* - keyboardHeight `number` - The current keyboard height in pixels. 0 when the keyboard is hidden;
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* function ChatInput() {
|
|
19
|
+
* const { keyboardHeight } = useKeyboardHeight();
|
|
20
|
+
*
|
|
21
|
+
* return (
|
|
22
|
+
* <div style={{ paddingBottom: `${keyboardHeight}px` }}>
|
|
23
|
+
* <input type="text" placeholder="Type a message..." />
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
function useKeyboardHeight(options = {}) {
|
|
29
|
+
const { immediate = true } = options;
|
|
30
|
+
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
31
|
+
useEffect(function subscribeToKeyboardHeight() {
|
|
32
|
+
const { unsubscribe } = subscribeKeyboardHeight({
|
|
33
|
+
callback: setKeyboardHeight,
|
|
34
|
+
immediate
|
|
35
|
+
});
|
|
36
|
+
return unsubscribe;
|
|
37
|
+
}, [immediate]);
|
|
38
|
+
return { keyboardHeight };
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { useKeyboardHeight };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../../utils/isServer/isServer.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
//#region src/mobile/hooks/useNetworkStatus/useNetworkStatus.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useNetworkStatus` is a React hook that provides access to the Network Information API.
|
|
8
|
+
* It provides raw network connection data. Returns undefined for all properties
|
|
9
|
+
* if the API is not supported (e.g., Safari, Firefox).
|
|
10
|
+
*
|
|
11
|
+
* **Browser Support**:
|
|
12
|
+
* - Chrome/Edge (Android): Full support
|
|
13
|
+
* - Chrome/Edge (Desktop): Partial support (effectiveType, downlink, rtt, saveData)
|
|
14
|
+
* - Firefox: Not supported
|
|
15
|
+
* - Safari: Not supported
|
|
16
|
+
*
|
|
17
|
+
* @returns {NetworkStatus} Network status information
|
|
18
|
+
* - `effectiveType` - Connection quality: 'slow-2g' | '2g' | '3g' | '4g'
|
|
19
|
+
* - `type` - Physical connection: 'wifi' | 'cellular' | 'ethernet' | etc.
|
|
20
|
+
* - `downlink` - Downlink speed in Mbps
|
|
21
|
+
* - `rtt` - Round-trip time in milliseconds
|
|
22
|
+
* - `saveData` - User's data saver preference
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* function AdaptiveImage() {
|
|
26
|
+
* const { effectiveType, saveData } = useNetworkStatus();
|
|
27
|
+
*
|
|
28
|
+
* // Determine quality based on your app's needs
|
|
29
|
+
* const useHighQuality = effectiveType === '4g' && !saveData;
|
|
30
|
+
*
|
|
31
|
+
* return (
|
|
32
|
+
* <img
|
|
33
|
+
* src={useHighQuality ? 'high-res.jpg' : 'low-res.jpg'}
|
|
34
|
+
* alt="Content"
|
|
35
|
+
* />
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* function VideoPlayer() {
|
|
41
|
+
* const { type, downlink } = useNetworkStatus();
|
|
42
|
+
*
|
|
43
|
+
* // Custom logic: only autoplay on wifi with good bandwidth
|
|
44
|
+
* const shouldAutoplay = type === 'wifi' && (downlink ?? 0) > 5;
|
|
45
|
+
*
|
|
46
|
+
* return <video src="video.mp4" autoPlay={shouldAutoplay} />;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* @see https://wicg.github.io/netinfo/
|
|
50
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
|
|
51
|
+
*/
|
|
52
|
+
function useNetworkStatus() {
|
|
53
|
+
const [networkStatus, setNetworkStatus] = (0, react.useState)(getNetworkStatus);
|
|
54
|
+
(0, react.useEffect)(function subscribeToNetworkChanges() {
|
|
55
|
+
if (require_isServer.isServer()) return;
|
|
56
|
+
const connection = getNavigatorConnection();
|
|
57
|
+
if (connection == null) return;
|
|
58
|
+
function updateNetworkStatus() {
|
|
59
|
+
setNetworkStatus(getNetworkStatus());
|
|
60
|
+
}
|
|
61
|
+
connection.addEventListener("change", updateNetworkStatus);
|
|
62
|
+
return function cleanup() {
|
|
63
|
+
connection.removeEventListener("change", updateNetworkStatus);
|
|
64
|
+
};
|
|
65
|
+
}, []);
|
|
66
|
+
return networkStatus;
|
|
67
|
+
}
|
|
68
|
+
function getNavigatorConnection() {
|
|
69
|
+
if (require_isServer.isServer() || !("connection" in navigator)) return null;
|
|
70
|
+
try {
|
|
71
|
+
return navigator.connection ?? null;
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function getNetworkStatus() {
|
|
77
|
+
const connection = getNavigatorConnection();
|
|
78
|
+
if (connection == null) return {};
|
|
79
|
+
return {
|
|
80
|
+
effectiveType: connection.effectiveType,
|
|
81
|
+
type: connection.type,
|
|
82
|
+
downlink: connection.downlink,
|
|
83
|
+
rtt: connection.rtt,
|
|
84
|
+
saveData: connection.saveData
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
exports.useNetworkStatus = useNetworkStatus;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useNetworkStatus/useNetworkStatus.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Effective connection type based on Network Information API
|
|
5
|
+
* @see https://wicg.github.io/netinfo/#effective-connection-types
|
|
6
|
+
*/
|
|
7
|
+
type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
|
|
8
|
+
/**
|
|
9
|
+
* Physical connection type
|
|
10
|
+
* @see https://wicg.github.io/netinfo/#dom-connectiontype
|
|
11
|
+
*/
|
|
12
|
+
type ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';
|
|
13
|
+
/**
|
|
14
|
+
* Network status information from Network Information API
|
|
15
|
+
*/
|
|
16
|
+
type NetworkStatus = {
|
|
17
|
+
/** Effective connection type (4g, 3g, 2g, slow-2g) - undefined if API not supported */
|
|
18
|
+
effectiveType?: EffectiveConnectionType;
|
|
19
|
+
/** Physical connection type (wifi, cellular, etc.) - undefined if API not supported */
|
|
20
|
+
type?: ConnectionType;
|
|
21
|
+
/** Downlink speed in Mbps - undefined if API not supported */
|
|
22
|
+
downlink?: number;
|
|
23
|
+
/** Round-trip time in milliseconds - undefined if API not supported */
|
|
24
|
+
rtt?: number;
|
|
25
|
+
/** User's data saver preference - undefined if API not supported */
|
|
26
|
+
saveData?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @description
|
|
30
|
+
* `useNetworkStatus` is a React hook that provides access to the Network Information API.
|
|
31
|
+
* It provides raw network connection data. Returns undefined for all properties
|
|
32
|
+
* if the API is not supported (e.g., Safari, Firefox).
|
|
33
|
+
*
|
|
34
|
+
* **Browser Support**:
|
|
35
|
+
* - Chrome/Edge (Android): Full support
|
|
36
|
+
* - Chrome/Edge (Desktop): Partial support (effectiveType, downlink, rtt, saveData)
|
|
37
|
+
* - Firefox: Not supported
|
|
38
|
+
* - Safari: Not supported
|
|
39
|
+
*
|
|
40
|
+
* @returns {NetworkStatus} Network status information
|
|
41
|
+
* - `effectiveType` - Connection quality: 'slow-2g' | '2g' | '3g' | '4g'
|
|
42
|
+
* - `type` - Physical connection: 'wifi' | 'cellular' | 'ethernet' | etc.
|
|
43
|
+
* - `downlink` - Downlink speed in Mbps
|
|
44
|
+
* - `rtt` - Round-trip time in milliseconds
|
|
45
|
+
* - `saveData` - User's data saver preference
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* function AdaptiveImage() {
|
|
49
|
+
* const { effectiveType, saveData } = useNetworkStatus();
|
|
50
|
+
*
|
|
51
|
+
* // Determine quality based on your app's needs
|
|
52
|
+
* const useHighQuality = effectiveType === '4g' && !saveData;
|
|
53
|
+
*
|
|
54
|
+
* return (
|
|
55
|
+
* <img
|
|
56
|
+
* src={useHighQuality ? 'high-res.jpg' : 'low-res.jpg'}
|
|
57
|
+
* alt="Content"
|
|
58
|
+
* />
|
|
59
|
+
* );
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* function VideoPlayer() {
|
|
64
|
+
* const { type, downlink } = useNetworkStatus();
|
|
65
|
+
*
|
|
66
|
+
* // Custom logic: only autoplay on wifi with good bandwidth
|
|
67
|
+
* const shouldAutoplay = type === 'wifi' && (downlink ?? 0) > 5;
|
|
68
|
+
*
|
|
69
|
+
* return <video src="video.mp4" autoPlay={shouldAutoplay} />;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* @see https://wicg.github.io/netinfo/
|
|
73
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
|
|
74
|
+
*/
|
|
75
|
+
declare function useNetworkStatus(): NetworkStatus;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { ConnectionType, EffectiveConnectionType, NetworkStatus, useNetworkStatus };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useNetworkStatus/useNetworkStatus.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Effective connection type based on Network Information API
|
|
5
|
+
* @see https://wicg.github.io/netinfo/#effective-connection-types
|
|
6
|
+
*/
|
|
7
|
+
type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
|
|
8
|
+
/**
|
|
9
|
+
* Physical connection type
|
|
10
|
+
* @see https://wicg.github.io/netinfo/#dom-connectiontype
|
|
11
|
+
*/
|
|
12
|
+
type ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';
|
|
13
|
+
/**
|
|
14
|
+
* Network status information from Network Information API
|
|
15
|
+
*/
|
|
16
|
+
type NetworkStatus = {
|
|
17
|
+
/** Effective connection type (4g, 3g, 2g, slow-2g) - undefined if API not supported */
|
|
18
|
+
effectiveType?: EffectiveConnectionType;
|
|
19
|
+
/** Physical connection type (wifi, cellular, etc.) - undefined if API not supported */
|
|
20
|
+
type?: ConnectionType;
|
|
21
|
+
/** Downlink speed in Mbps - undefined if API not supported */
|
|
22
|
+
downlink?: number;
|
|
23
|
+
/** Round-trip time in milliseconds - undefined if API not supported */
|
|
24
|
+
rtt?: number;
|
|
25
|
+
/** User's data saver preference - undefined if API not supported */
|
|
26
|
+
saveData?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @description
|
|
30
|
+
* `useNetworkStatus` is a React hook that provides access to the Network Information API.
|
|
31
|
+
* It provides raw network connection data. Returns undefined for all properties
|
|
32
|
+
* if the API is not supported (e.g., Safari, Firefox).
|
|
33
|
+
*
|
|
34
|
+
* **Browser Support**:
|
|
35
|
+
* - Chrome/Edge (Android): Full support
|
|
36
|
+
* - Chrome/Edge (Desktop): Partial support (effectiveType, downlink, rtt, saveData)
|
|
37
|
+
* - Firefox: Not supported
|
|
38
|
+
* - Safari: Not supported
|
|
39
|
+
*
|
|
40
|
+
* @returns {NetworkStatus} Network status information
|
|
41
|
+
* - `effectiveType` - Connection quality: 'slow-2g' | '2g' | '3g' | '4g'
|
|
42
|
+
* - `type` - Physical connection: 'wifi' | 'cellular' | 'ethernet' | etc.
|
|
43
|
+
* - `downlink` - Downlink speed in Mbps
|
|
44
|
+
* - `rtt` - Round-trip time in milliseconds
|
|
45
|
+
* - `saveData` - User's data saver preference
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* function AdaptiveImage() {
|
|
49
|
+
* const { effectiveType, saveData } = useNetworkStatus();
|
|
50
|
+
*
|
|
51
|
+
* // Determine quality based on your app's needs
|
|
52
|
+
* const useHighQuality = effectiveType === '4g' && !saveData;
|
|
53
|
+
*
|
|
54
|
+
* return (
|
|
55
|
+
* <img
|
|
56
|
+
* src={useHighQuality ? 'high-res.jpg' : 'low-res.jpg'}
|
|
57
|
+
* alt="Content"
|
|
58
|
+
* />
|
|
59
|
+
* );
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* function VideoPlayer() {
|
|
64
|
+
* const { type, downlink } = useNetworkStatus();
|
|
65
|
+
*
|
|
66
|
+
* // Custom logic: only autoplay on wifi with good bandwidth
|
|
67
|
+
* const shouldAutoplay = type === 'wifi' && (downlink ?? 0) > 5;
|
|
68
|
+
*
|
|
69
|
+
* return <video src="video.mp4" autoPlay={shouldAutoplay} />;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* @see https://wicg.github.io/netinfo/
|
|
73
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
|
|
74
|
+
*/
|
|
75
|
+
declare function useNetworkStatus(): NetworkStatus;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { ConnectionType, EffectiveConnectionType, NetworkStatus, useNetworkStatus };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isServer } from "../../utils/isServer/isServer.mjs";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
//#region src/mobile/hooks/useNetworkStatus/useNetworkStatus.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useNetworkStatus` is a React hook that provides access to the Network Information API.
|
|
8
|
+
* It provides raw network connection data. Returns undefined for all properties
|
|
9
|
+
* if the API is not supported (e.g., Safari, Firefox).
|
|
10
|
+
*
|
|
11
|
+
* **Browser Support**:
|
|
12
|
+
* - Chrome/Edge (Android): Full support
|
|
13
|
+
* - Chrome/Edge (Desktop): Partial support (effectiveType, downlink, rtt, saveData)
|
|
14
|
+
* - Firefox: Not supported
|
|
15
|
+
* - Safari: Not supported
|
|
16
|
+
*
|
|
17
|
+
* @returns {NetworkStatus} Network status information
|
|
18
|
+
* - `effectiveType` - Connection quality: 'slow-2g' | '2g' | '3g' | '4g'
|
|
19
|
+
* - `type` - Physical connection: 'wifi' | 'cellular' | 'ethernet' | etc.
|
|
20
|
+
* - `downlink` - Downlink speed in Mbps
|
|
21
|
+
* - `rtt` - Round-trip time in milliseconds
|
|
22
|
+
* - `saveData` - User's data saver preference
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* function AdaptiveImage() {
|
|
26
|
+
* const { effectiveType, saveData } = useNetworkStatus();
|
|
27
|
+
*
|
|
28
|
+
* // Determine quality based on your app's needs
|
|
29
|
+
* const useHighQuality = effectiveType === '4g' && !saveData;
|
|
30
|
+
*
|
|
31
|
+
* return (
|
|
32
|
+
* <img
|
|
33
|
+
* src={useHighQuality ? 'high-res.jpg' : 'low-res.jpg'}
|
|
34
|
+
* alt="Content"
|
|
35
|
+
* />
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* function VideoPlayer() {
|
|
41
|
+
* const { type, downlink } = useNetworkStatus();
|
|
42
|
+
*
|
|
43
|
+
* // Custom logic: only autoplay on wifi with good bandwidth
|
|
44
|
+
* const shouldAutoplay = type === 'wifi' && (downlink ?? 0) > 5;
|
|
45
|
+
*
|
|
46
|
+
* return <video src="video.mp4" autoPlay={shouldAutoplay} />;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* @see https://wicg.github.io/netinfo/
|
|
50
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
|
|
51
|
+
*/
|
|
52
|
+
function useNetworkStatus() {
|
|
53
|
+
const [networkStatus, setNetworkStatus] = useState(getNetworkStatus);
|
|
54
|
+
useEffect(function subscribeToNetworkChanges() {
|
|
55
|
+
if (isServer()) return;
|
|
56
|
+
const connection = getNavigatorConnection();
|
|
57
|
+
if (connection == null) return;
|
|
58
|
+
function updateNetworkStatus() {
|
|
59
|
+
setNetworkStatus(getNetworkStatus());
|
|
60
|
+
}
|
|
61
|
+
connection.addEventListener("change", updateNetworkStatus);
|
|
62
|
+
return function cleanup() {
|
|
63
|
+
connection.removeEventListener("change", updateNetworkStatus);
|
|
64
|
+
};
|
|
65
|
+
}, []);
|
|
66
|
+
return networkStatus;
|
|
67
|
+
}
|
|
68
|
+
function getNavigatorConnection() {
|
|
69
|
+
if (isServer() || !("connection" in navigator)) return null;
|
|
70
|
+
try {
|
|
71
|
+
return navigator.connection ?? null;
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function getNetworkStatus() {
|
|
77
|
+
const connection = getNavigatorConnection();
|
|
78
|
+
if (connection == null) return {};
|
|
79
|
+
return {
|
|
80
|
+
effectiveType: connection.effectiveType,
|
|
81
|
+
type: connection.type,
|
|
82
|
+
downlink: connection.downlink,
|
|
83
|
+
rtt: connection.rtt,
|
|
84
|
+
saveData: connection.saveData
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { useNetworkStatus };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../../utils/isServer/isServer.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
//#region src/mobile/hooks/usePageVisibility/usePageVisibility.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `usePageVisibility` is a React hook that detects page visibility changes.
|
|
8
|
+
* It monitors when the user switches tabs or minimizes the browser using the Page Visibility API.
|
|
9
|
+
* Useful for pausing/resuming animations, videos, or background tasks.
|
|
10
|
+
*
|
|
11
|
+
* **SSR Behavior**: Returns `{ isVisible: true, visibilityState: 'visible' }` during server-side rendering.
|
|
12
|
+
*
|
|
13
|
+
* @returns {PageVisibility} Page visibility information
|
|
14
|
+
* - `isVisible` - True if page is currently visible to the user
|
|
15
|
+
* - `visibilityState` - Current visibility state: 'visible' | 'hidden'
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* function VideoPlayer() {
|
|
19
|
+
* const { isVisible } = usePageVisibility();
|
|
20
|
+
* const videoRef = useRef<HTMLVideoElement>(null);
|
|
21
|
+
*
|
|
22
|
+
* useEffect(() => {
|
|
23
|
+
* if (!videoRef.current) return;
|
|
24
|
+
*
|
|
25
|
+
* // Pause video when tab is hidden
|
|
26
|
+
* if (!isVisible) {
|
|
27
|
+
* videoRef.current.pause();
|
|
28
|
+
* }
|
|
29
|
+
* }, [isVisible]);
|
|
30
|
+
*
|
|
31
|
+
* return <video ref={videoRef} src="video.mp4" />;
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* function Analytics() {
|
|
36
|
+
* const { isVisible, visibilityState } = usePageVisibility();
|
|
37
|
+
*
|
|
38
|
+
* useEffect(() => {
|
|
39
|
+
* if (visibilityState === 'hidden') {
|
|
40
|
+
* // Track when user leaves the page
|
|
41
|
+
* analytics.track('page_hidden');
|
|
42
|
+
* }
|
|
43
|
+
* }, [visibilityState]);
|
|
44
|
+
*
|
|
45
|
+
* return null;
|
|
46
|
+
* }
|
|
47
|
+
*/
|
|
48
|
+
function usePageVisibility() {
|
|
49
|
+
const [pageVisibility, setPageVisibility] = (0, react.useState)(() => getPageVisibility());
|
|
50
|
+
(0, react.useEffect)(function handleVisibilityChange() {
|
|
51
|
+
function updateVisibility() {
|
|
52
|
+
setPageVisibility(() => getPageVisibility());
|
|
53
|
+
}
|
|
54
|
+
document.addEventListener("visibilitychange", updateVisibility);
|
|
55
|
+
return function cleanup() {
|
|
56
|
+
document.removeEventListener("visibilitychange", updateVisibility);
|
|
57
|
+
};
|
|
58
|
+
}, []);
|
|
59
|
+
return pageVisibility;
|
|
60
|
+
}
|
|
61
|
+
function getPageVisibility() {
|
|
62
|
+
if (require_isServer.isServer()) return {
|
|
63
|
+
isVisible: true,
|
|
64
|
+
visibilityState: "visible"
|
|
65
|
+
};
|
|
66
|
+
const visibilityState = document.visibilityState;
|
|
67
|
+
return {
|
|
68
|
+
isVisible: visibilityState === "visible",
|
|
69
|
+
visibilityState
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
exports.usePageVisibility = usePageVisibility;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/usePageVisibility/usePageVisibility.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Page visibility state derived from browser's DocumentVisibilityState.
|
|
5
|
+
* Excludes 'prerender' as it is deprecated and not used in modern browsers.
|
|
6
|
+
*/
|
|
7
|
+
type VisibilityState = Exclude<DocumentVisibilityState, 'prerender'>;
|
|
8
|
+
/**
|
|
9
|
+
* Page visibility information
|
|
10
|
+
*/
|
|
11
|
+
type PageVisibility = {
|
|
12
|
+
/** True if page is currently visible */
|
|
13
|
+
isVisible: boolean;
|
|
14
|
+
/** Current visibility state: 'visible' | 'hidden' */
|
|
15
|
+
visibilityState: VisibilityState;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* @description
|
|
19
|
+
* `usePageVisibility` is a React hook that detects page visibility changes.
|
|
20
|
+
* It monitors when the user switches tabs or minimizes the browser using the Page Visibility API.
|
|
21
|
+
* Useful for pausing/resuming animations, videos, or background tasks.
|
|
22
|
+
*
|
|
23
|
+
* **SSR Behavior**: Returns `{ isVisible: true, visibilityState: 'visible' }` during server-side rendering.
|
|
24
|
+
*
|
|
25
|
+
* @returns {PageVisibility} Page visibility information
|
|
26
|
+
* - `isVisible` - True if page is currently visible to the user
|
|
27
|
+
* - `visibilityState` - Current visibility state: 'visible' | 'hidden'
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* function VideoPlayer() {
|
|
31
|
+
* const { isVisible } = usePageVisibility();
|
|
32
|
+
* const videoRef = useRef<HTMLVideoElement>(null);
|
|
33
|
+
*
|
|
34
|
+
* useEffect(() => {
|
|
35
|
+
* if (!videoRef.current) return;
|
|
36
|
+
*
|
|
37
|
+
* // Pause video when tab is hidden
|
|
38
|
+
* if (!isVisible) {
|
|
39
|
+
* videoRef.current.pause();
|
|
40
|
+
* }
|
|
41
|
+
* }, [isVisible]);
|
|
42
|
+
*
|
|
43
|
+
* return <video ref={videoRef} src="video.mp4" />;
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* function Analytics() {
|
|
48
|
+
* const { isVisible, visibilityState } = usePageVisibility();
|
|
49
|
+
*
|
|
50
|
+
* useEffect(() => {
|
|
51
|
+
* if (visibilityState === 'hidden') {
|
|
52
|
+
* // Track when user leaves the page
|
|
53
|
+
* analytics.track('page_hidden');
|
|
54
|
+
* }
|
|
55
|
+
* }, [visibilityState]);
|
|
56
|
+
*
|
|
57
|
+
* return null;
|
|
58
|
+
* }
|
|
59
|
+
*/
|
|
60
|
+
declare function usePageVisibility(): PageVisibility;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { PageVisibility, VisibilityState, usePageVisibility };
|