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,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../../utils/isServer/isServer.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
//#region src/mobile/hooks/useVisualViewport/useVisualViewport.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useVisualViewport` is a React hook that tracks Visual Viewport changes.
|
|
8
|
+
* It returns the actual visible area in mobile WebView, which changes when
|
|
9
|
+
* the keyboard appears or the user zooms/scrolls.
|
|
10
|
+
*
|
|
11
|
+
* **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API.
|
|
12
|
+
* Always check for null before accessing viewport properties.
|
|
13
|
+
*
|
|
14
|
+
* **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead
|
|
15
|
+
* for a simpler API.
|
|
16
|
+
*
|
|
17
|
+
* @returns {{ viewport: VisualViewportState | null }} An object containing the Visual Viewport state.
|
|
18
|
+
* - viewport `VisualViewportState | null` - Visual Viewport state object, or `null` if not supported (SSR or browsers without the Visual Viewport API);
|
|
19
|
+
* - viewport.width `number` - Viewport width in pixels;
|
|
20
|
+
* - viewport.height `number` - Viewport height in pixels;
|
|
21
|
+
* - viewport.offsetLeft `number` - Viewport left offset in pixels from the layout viewport. Typically 0 unless horizontal scrolling or panning occurs;
|
|
22
|
+
* - viewport.offsetTop `number` - Viewport top offset in pixels from the layout viewport. Becomes negative on iOS when the keyboard appears, so use `-offsetTop` for the keyboard height. Typically remains 0 on Android;
|
|
23
|
+
* - viewport.scale `number` - Pinch-zoom scaling factor. 1.0 means no zoom, greater than 1.0 means zoomed in;
|
|
24
|
+
*
|
|
25
|
+
* @see {@link useKeyboardHeight} - Simpler hook for keyboard height only
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* function CustomLayout() {
|
|
29
|
+
* const { viewport } = useVisualViewport();
|
|
30
|
+
*
|
|
31
|
+
* // Always check for null first
|
|
32
|
+
* if (!viewport) {
|
|
33
|
+
* return <div>Visual Viewport not supported</div>;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* const { width, height, offsetTop, scale } = viewport;
|
|
37
|
+
*
|
|
38
|
+
* // Hide floating UI when user zooms in
|
|
39
|
+
* const showFloatingUI = scale <= 1.3;
|
|
40
|
+
*
|
|
41
|
+
* return (
|
|
42
|
+
* <div style={{ height }}>
|
|
43
|
+
* {showFloatingUI && <FloatingButton />}
|
|
44
|
+
* Viewport-aware content
|
|
45
|
+
* </div>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
*/
|
|
49
|
+
function useVisualViewport() {
|
|
50
|
+
const visualViewport = require_isServer.isServer() ? null : window.visualViewport;
|
|
51
|
+
const [viewport, setViewport] = (0, react.useState)(() => visualViewport != null ? getVisualViewportState(visualViewport) : null);
|
|
52
|
+
const updateViewportState = (0, react.useCallback)(() => {
|
|
53
|
+
(0, react.startTransition)(() => {
|
|
54
|
+
setViewport(window.visualViewport != null ? getVisualViewportState(window.visualViewport) : null);
|
|
55
|
+
});
|
|
56
|
+
}, []);
|
|
57
|
+
(0, react.useEffect)(function handleVisualViewportChange() {
|
|
58
|
+
window.visualViewport?.addEventListener("resize", updateViewportState);
|
|
59
|
+
window.visualViewport?.addEventListener("scroll", updateViewportState);
|
|
60
|
+
return function cleanup() {
|
|
61
|
+
window.visualViewport?.removeEventListener("resize", updateViewportState);
|
|
62
|
+
window.visualViewport?.removeEventListener("scroll", updateViewportState);
|
|
63
|
+
};
|
|
64
|
+
}, [updateViewportState]);
|
|
65
|
+
return { viewport };
|
|
66
|
+
}
|
|
67
|
+
function getVisualViewportState(visualViewport) {
|
|
68
|
+
return {
|
|
69
|
+
width: visualViewport.width,
|
|
70
|
+
height: visualViewport.height,
|
|
71
|
+
offsetLeft: visualViewport.offsetLeft,
|
|
72
|
+
offsetTop: visualViewport.offsetTop,
|
|
73
|
+
scale: visualViewport.scale
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
exports.useVisualViewport = useVisualViewport;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useVisualViewport/useVisualViewport.d.ts
|
|
3
|
+
type VisualViewportState = {
|
|
4
|
+
/** Viewport width (px) */
|
|
5
|
+
width: number;
|
|
6
|
+
/** Viewport height (px) */
|
|
7
|
+
height: number;
|
|
8
|
+
/**
|
|
9
|
+
* Viewport left offset (px) from the layout viewport
|
|
10
|
+
*
|
|
11
|
+
* Typically 0 unless horizontal scrolling or panning occurs
|
|
12
|
+
*/
|
|
13
|
+
offsetLeft: number;
|
|
14
|
+
/**
|
|
15
|
+
* Viewport top offset (px) from the layout viewport
|
|
16
|
+
*
|
|
17
|
+
* On iOS: Becomes negative when keyboard appears (e.g., -300px means 300px keyboard height)
|
|
18
|
+
* On Android: Typically remains 0
|
|
19
|
+
*
|
|
20
|
+
* Use `-offsetTop` to get accurate keyboard height on iOS
|
|
21
|
+
*/
|
|
22
|
+
offsetTop: number;
|
|
23
|
+
/**
|
|
24
|
+
* Pinch-zoom scaling factor
|
|
25
|
+
*
|
|
26
|
+
* - 1.0 = no zoom (default)
|
|
27
|
+
* - > 1.0 = zoomed in
|
|
28
|
+
* - < 1.0 = zoomed out (rare, depends on viewport settings)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const { viewport } = useVisualViewport();
|
|
33
|
+
* if (viewport && viewport.scale > 1.3) {
|
|
34
|
+
* // Hide floating UI when user zooms in
|
|
35
|
+
* setShowFloatingButton(false);
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
scale: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @description
|
|
43
|
+
* `useVisualViewport` is a React hook that tracks Visual Viewport changes.
|
|
44
|
+
* It returns the actual visible area in mobile WebView, which changes when
|
|
45
|
+
* the keyboard appears or the user zooms/scrolls.
|
|
46
|
+
*
|
|
47
|
+
* **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API.
|
|
48
|
+
* Always check for null before accessing viewport properties.
|
|
49
|
+
*
|
|
50
|
+
* **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead
|
|
51
|
+
* for a simpler API.
|
|
52
|
+
*
|
|
53
|
+
* @returns {{ viewport: VisualViewportState | null }} An object containing the Visual Viewport state.
|
|
54
|
+
* - viewport `VisualViewportState | null` - Visual Viewport state object, or `null` if not supported (SSR or browsers without the Visual Viewport API);
|
|
55
|
+
* - viewport.width `number` - Viewport width in pixels;
|
|
56
|
+
* - viewport.height `number` - Viewport height in pixels;
|
|
57
|
+
* - viewport.offsetLeft `number` - Viewport left offset in pixels from the layout viewport. Typically 0 unless horizontal scrolling or panning occurs;
|
|
58
|
+
* - viewport.offsetTop `number` - Viewport top offset in pixels from the layout viewport. Becomes negative on iOS when the keyboard appears, so use `-offsetTop` for the keyboard height. Typically remains 0 on Android;
|
|
59
|
+
* - viewport.scale `number` - Pinch-zoom scaling factor. 1.0 means no zoom, greater than 1.0 means zoomed in;
|
|
60
|
+
*
|
|
61
|
+
* @see {@link useKeyboardHeight} - Simpler hook for keyboard height only
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* function CustomLayout() {
|
|
65
|
+
* const { viewport } = useVisualViewport();
|
|
66
|
+
*
|
|
67
|
+
* // Always check for null first
|
|
68
|
+
* if (!viewport) {
|
|
69
|
+
* return <div>Visual Viewport not supported</div>;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* const { width, height, offsetTop, scale } = viewport;
|
|
73
|
+
*
|
|
74
|
+
* // Hide floating UI when user zooms in
|
|
75
|
+
* const showFloatingUI = scale <= 1.3;
|
|
76
|
+
*
|
|
77
|
+
* return (
|
|
78
|
+
* <div style={{ height }}>
|
|
79
|
+
* {showFloatingUI && <FloatingButton />}
|
|
80
|
+
* Viewport-aware content
|
|
81
|
+
* </div>
|
|
82
|
+
* );
|
|
83
|
+
* }
|
|
84
|
+
*/
|
|
85
|
+
declare function useVisualViewport(): {
|
|
86
|
+
viewport: VisualViewportState | null;
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
89
|
+
export { useVisualViewport };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/hooks/useVisualViewport/useVisualViewport.d.ts
|
|
3
|
+
type VisualViewportState = {
|
|
4
|
+
/** Viewport width (px) */
|
|
5
|
+
width: number;
|
|
6
|
+
/** Viewport height (px) */
|
|
7
|
+
height: number;
|
|
8
|
+
/**
|
|
9
|
+
* Viewport left offset (px) from the layout viewport
|
|
10
|
+
*
|
|
11
|
+
* Typically 0 unless horizontal scrolling or panning occurs
|
|
12
|
+
*/
|
|
13
|
+
offsetLeft: number;
|
|
14
|
+
/**
|
|
15
|
+
* Viewport top offset (px) from the layout viewport
|
|
16
|
+
*
|
|
17
|
+
* On iOS: Becomes negative when keyboard appears (e.g., -300px means 300px keyboard height)
|
|
18
|
+
* On Android: Typically remains 0
|
|
19
|
+
*
|
|
20
|
+
* Use `-offsetTop` to get accurate keyboard height on iOS
|
|
21
|
+
*/
|
|
22
|
+
offsetTop: number;
|
|
23
|
+
/**
|
|
24
|
+
* Pinch-zoom scaling factor
|
|
25
|
+
*
|
|
26
|
+
* - 1.0 = no zoom (default)
|
|
27
|
+
* - > 1.0 = zoomed in
|
|
28
|
+
* - < 1.0 = zoomed out (rare, depends on viewport settings)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const { viewport } = useVisualViewport();
|
|
33
|
+
* if (viewport && viewport.scale > 1.3) {
|
|
34
|
+
* // Hide floating UI when user zooms in
|
|
35
|
+
* setShowFloatingButton(false);
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
scale: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @description
|
|
43
|
+
* `useVisualViewport` is a React hook that tracks Visual Viewport changes.
|
|
44
|
+
* It returns the actual visible area in mobile WebView, which changes when
|
|
45
|
+
* the keyboard appears or the user zooms/scrolls.
|
|
46
|
+
*
|
|
47
|
+
* **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API.
|
|
48
|
+
* Always check for null before accessing viewport properties.
|
|
49
|
+
*
|
|
50
|
+
* **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead
|
|
51
|
+
* for a simpler API.
|
|
52
|
+
*
|
|
53
|
+
* @returns {{ viewport: VisualViewportState | null }} An object containing the Visual Viewport state.
|
|
54
|
+
* - viewport `VisualViewportState | null` - Visual Viewport state object, or `null` if not supported (SSR or browsers without the Visual Viewport API);
|
|
55
|
+
* - viewport.width `number` - Viewport width in pixels;
|
|
56
|
+
* - viewport.height `number` - Viewport height in pixels;
|
|
57
|
+
* - viewport.offsetLeft `number` - Viewport left offset in pixels from the layout viewport. Typically 0 unless horizontal scrolling or panning occurs;
|
|
58
|
+
* - viewport.offsetTop `number` - Viewport top offset in pixels from the layout viewport. Becomes negative on iOS when the keyboard appears, so use `-offsetTop` for the keyboard height. Typically remains 0 on Android;
|
|
59
|
+
* - viewport.scale `number` - Pinch-zoom scaling factor. 1.0 means no zoom, greater than 1.0 means zoomed in;
|
|
60
|
+
*
|
|
61
|
+
* @see {@link useKeyboardHeight} - Simpler hook for keyboard height only
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* function CustomLayout() {
|
|
65
|
+
* const { viewport } = useVisualViewport();
|
|
66
|
+
*
|
|
67
|
+
* // Always check for null first
|
|
68
|
+
* if (!viewport) {
|
|
69
|
+
* return <div>Visual Viewport not supported</div>;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* const { width, height, offsetTop, scale } = viewport;
|
|
73
|
+
*
|
|
74
|
+
* // Hide floating UI when user zooms in
|
|
75
|
+
* const showFloatingUI = scale <= 1.3;
|
|
76
|
+
*
|
|
77
|
+
* return (
|
|
78
|
+
* <div style={{ height }}>
|
|
79
|
+
* {showFloatingUI && <FloatingButton />}
|
|
80
|
+
* Viewport-aware content
|
|
81
|
+
* </div>
|
|
82
|
+
* );
|
|
83
|
+
* }
|
|
84
|
+
*/
|
|
85
|
+
declare function useVisualViewport(): {
|
|
86
|
+
viewport: VisualViewportState | null;
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
89
|
+
export { useVisualViewport };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isServer } from "../../utils/isServer/isServer.mjs";
|
|
3
|
+
import { startTransition, useCallback, useEffect, useState } from "react";
|
|
4
|
+
//#region src/mobile/hooks/useVisualViewport/useVisualViewport.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useVisualViewport` is a React hook that tracks Visual Viewport changes.
|
|
8
|
+
* It returns the actual visible area in mobile WebView, which changes when
|
|
9
|
+
* the keyboard appears or the user zooms/scrolls.
|
|
10
|
+
*
|
|
11
|
+
* **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API.
|
|
12
|
+
* Always check for null before accessing viewport properties.
|
|
13
|
+
*
|
|
14
|
+
* **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead
|
|
15
|
+
* for a simpler API.
|
|
16
|
+
*
|
|
17
|
+
* @returns {{ viewport: VisualViewportState | null }} An object containing the Visual Viewport state.
|
|
18
|
+
* - viewport `VisualViewportState | null` - Visual Viewport state object, or `null` if not supported (SSR or browsers without the Visual Viewport API);
|
|
19
|
+
* - viewport.width `number` - Viewport width in pixels;
|
|
20
|
+
* - viewport.height `number` - Viewport height in pixels;
|
|
21
|
+
* - viewport.offsetLeft `number` - Viewport left offset in pixels from the layout viewport. Typically 0 unless horizontal scrolling or panning occurs;
|
|
22
|
+
* - viewport.offsetTop `number` - Viewport top offset in pixels from the layout viewport. Becomes negative on iOS when the keyboard appears, so use `-offsetTop` for the keyboard height. Typically remains 0 on Android;
|
|
23
|
+
* - viewport.scale `number` - Pinch-zoom scaling factor. 1.0 means no zoom, greater than 1.0 means zoomed in;
|
|
24
|
+
*
|
|
25
|
+
* @see {@link useKeyboardHeight} - Simpler hook for keyboard height only
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* function CustomLayout() {
|
|
29
|
+
* const { viewport } = useVisualViewport();
|
|
30
|
+
*
|
|
31
|
+
* // Always check for null first
|
|
32
|
+
* if (!viewport) {
|
|
33
|
+
* return <div>Visual Viewport not supported</div>;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* const { width, height, offsetTop, scale } = viewport;
|
|
37
|
+
*
|
|
38
|
+
* // Hide floating UI when user zooms in
|
|
39
|
+
* const showFloatingUI = scale <= 1.3;
|
|
40
|
+
*
|
|
41
|
+
* return (
|
|
42
|
+
* <div style={{ height }}>
|
|
43
|
+
* {showFloatingUI && <FloatingButton />}
|
|
44
|
+
* Viewport-aware content
|
|
45
|
+
* </div>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
*/
|
|
49
|
+
function useVisualViewport() {
|
|
50
|
+
const visualViewport = isServer() ? null : window.visualViewport;
|
|
51
|
+
const [viewport, setViewport] = useState(() => visualViewport != null ? getVisualViewportState(visualViewport) : null);
|
|
52
|
+
const updateViewportState = useCallback(() => {
|
|
53
|
+
startTransition(() => {
|
|
54
|
+
setViewport(window.visualViewport != null ? getVisualViewportState(window.visualViewport) : null);
|
|
55
|
+
});
|
|
56
|
+
}, []);
|
|
57
|
+
useEffect(function handleVisualViewportChange() {
|
|
58
|
+
window.visualViewport?.addEventListener("resize", updateViewportState);
|
|
59
|
+
window.visualViewport?.addEventListener("scroll", updateViewportState);
|
|
60
|
+
return function cleanup() {
|
|
61
|
+
window.visualViewport?.removeEventListener("resize", updateViewportState);
|
|
62
|
+
window.visualViewport?.removeEventListener("scroll", updateViewportState);
|
|
63
|
+
};
|
|
64
|
+
}, [updateViewportState]);
|
|
65
|
+
return { viewport };
|
|
66
|
+
}
|
|
67
|
+
function getVisualViewportState(visualViewport) {
|
|
68
|
+
return {
|
|
69
|
+
width: visualViewport.width,
|
|
70
|
+
height: visualViewport.height,
|
|
71
|
+
offsetLeft: visualViewport.offsetLeft,
|
|
72
|
+
offsetTop: visualViewport.offsetTop,
|
|
73
|
+
scale: visualViewport.scale
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { useVisualViewport };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../isServer/isServer.cjs");
|
|
3
|
+
//#region src/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data attribute key for storing scroll position
|
|
6
|
+
*/
|
|
7
|
+
const SCROLL_POSITION_ATTR = "data-simplikit-scroll-y";
|
|
8
|
+
/**
|
|
9
|
+
* @description
|
|
10
|
+
* `disableBodyScrollLock` is a utility function that unlocks the body scroll.
|
|
11
|
+
* It restores the scroll locked by `enableBodyScrollLock` and returns to the saved scroll position.
|
|
12
|
+
*
|
|
13
|
+
* Safe to call in SSR environment (no-op on server).
|
|
14
|
+
* Safe to call even if not locked (no-op).
|
|
15
|
+
*
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // When modal opens
|
|
20
|
+
* enableBodyScrollLock();
|
|
21
|
+
*
|
|
22
|
+
* // When modal closes
|
|
23
|
+
* disableBodyScrollLock();
|
|
24
|
+
*/
|
|
25
|
+
function disableBodyScrollLock() {
|
|
26
|
+
if (require_isServer.isServer()) return;
|
|
27
|
+
const savedScrollY = document.body.getAttribute(SCROLL_POSITION_ATTR);
|
|
28
|
+
if (savedScrollY == null) return;
|
|
29
|
+
removeScrollLockStyles();
|
|
30
|
+
restoreScrollPosition(savedScrollY);
|
|
31
|
+
clearSavedScrollPosition();
|
|
32
|
+
}
|
|
33
|
+
function removeScrollLockStyles() {
|
|
34
|
+
const { body } = document;
|
|
35
|
+
body.style.removeProperty("overflow");
|
|
36
|
+
body.style.removeProperty("position");
|
|
37
|
+
body.style.removeProperty("top");
|
|
38
|
+
body.style.removeProperty("left");
|
|
39
|
+
body.style.removeProperty("right");
|
|
40
|
+
body.style.removeProperty("bottom");
|
|
41
|
+
}
|
|
42
|
+
function restoreScrollPosition(savedScrollY) {
|
|
43
|
+
const scrollY = Number(savedScrollY);
|
|
44
|
+
if (Number.isNaN(scrollY)) {
|
|
45
|
+
console.warn("[react-simplikit] Invalid scroll position, defaulting to 0");
|
|
46
|
+
window.scrollTo(0, 0);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
window.scrollTo(0, scrollY);
|
|
50
|
+
}
|
|
51
|
+
function clearSavedScrollPosition() {
|
|
52
|
+
document.body.removeAttribute(SCROLL_POSITION_ATTR);
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
exports.disableBodyScrollLock = disableBodyScrollLock;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* `disableBodyScrollLock` is a utility function that unlocks the body scroll.
|
|
6
|
+
* It restores the scroll locked by `enableBodyScrollLock` and returns to the saved scroll position.
|
|
7
|
+
*
|
|
8
|
+
* Safe to call in SSR environment (no-op on server).
|
|
9
|
+
* Safe to call even if not locked (no-op).
|
|
10
|
+
*
|
|
11
|
+
* @returns {void}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // When modal opens
|
|
15
|
+
* enableBodyScrollLock();
|
|
16
|
+
*
|
|
17
|
+
* // When modal closes
|
|
18
|
+
* disableBodyScrollLock();
|
|
19
|
+
*/
|
|
20
|
+
declare function disableBodyScrollLock(): void;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { disableBodyScrollLock };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* `disableBodyScrollLock` is a utility function that unlocks the body scroll.
|
|
6
|
+
* It restores the scroll locked by `enableBodyScrollLock` and returns to the saved scroll position.
|
|
7
|
+
*
|
|
8
|
+
* Safe to call in SSR environment (no-op on server).
|
|
9
|
+
* Safe to call even if not locked (no-op).
|
|
10
|
+
*
|
|
11
|
+
* @returns {void}
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // When modal opens
|
|
15
|
+
* enableBodyScrollLock();
|
|
16
|
+
*
|
|
17
|
+
* // When modal closes
|
|
18
|
+
* disableBodyScrollLock();
|
|
19
|
+
*/
|
|
20
|
+
declare function disableBodyScrollLock(): void;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { disableBodyScrollLock };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isServer } from "../isServer/isServer.mjs";
|
|
3
|
+
//#region src/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data attribute key for storing scroll position
|
|
6
|
+
*/
|
|
7
|
+
const SCROLL_POSITION_ATTR = "data-simplikit-scroll-y";
|
|
8
|
+
/**
|
|
9
|
+
* @description
|
|
10
|
+
* `disableBodyScrollLock` is a utility function that unlocks the body scroll.
|
|
11
|
+
* It restores the scroll locked by `enableBodyScrollLock` and returns to the saved scroll position.
|
|
12
|
+
*
|
|
13
|
+
* Safe to call in SSR environment (no-op on server).
|
|
14
|
+
* Safe to call even if not locked (no-op).
|
|
15
|
+
*
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // When modal opens
|
|
20
|
+
* enableBodyScrollLock();
|
|
21
|
+
*
|
|
22
|
+
* // When modal closes
|
|
23
|
+
* disableBodyScrollLock();
|
|
24
|
+
*/
|
|
25
|
+
function disableBodyScrollLock() {
|
|
26
|
+
if (isServer()) return;
|
|
27
|
+
const savedScrollY = document.body.getAttribute(SCROLL_POSITION_ATTR);
|
|
28
|
+
if (savedScrollY == null) return;
|
|
29
|
+
removeScrollLockStyles();
|
|
30
|
+
restoreScrollPosition(savedScrollY);
|
|
31
|
+
clearSavedScrollPosition();
|
|
32
|
+
}
|
|
33
|
+
function removeScrollLockStyles() {
|
|
34
|
+
const { body } = document;
|
|
35
|
+
body.style.removeProperty("overflow");
|
|
36
|
+
body.style.removeProperty("position");
|
|
37
|
+
body.style.removeProperty("top");
|
|
38
|
+
body.style.removeProperty("left");
|
|
39
|
+
body.style.removeProperty("right");
|
|
40
|
+
body.style.removeProperty("bottom");
|
|
41
|
+
}
|
|
42
|
+
function restoreScrollPosition(savedScrollY) {
|
|
43
|
+
const scrollY = Number(savedScrollY);
|
|
44
|
+
if (Number.isNaN(scrollY)) {
|
|
45
|
+
console.warn("[react-simplikit] Invalid scroll position, defaulting to 0");
|
|
46
|
+
window.scrollTo(0, 0);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
window.scrollTo(0, scrollY);
|
|
50
|
+
}
|
|
51
|
+
function clearSavedScrollPosition() {
|
|
52
|
+
document.body.removeAttribute(SCROLL_POSITION_ATTR);
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { disableBodyScrollLock };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../isServer/isServer.cjs");
|
|
3
|
+
//#region src/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data attribute key for storing scroll position
|
|
6
|
+
*/
|
|
7
|
+
const SCROLL_POSITION_ATTR = "data-simplikit-scroll-y";
|
|
8
|
+
/**
|
|
9
|
+
* @description
|
|
10
|
+
* `enableBodyScrollLock` is a utility function that locks the body scroll.
|
|
11
|
+
* It prevents the body from scrolling by applying fixed positioning.
|
|
12
|
+
* This is useful when opening modals, drawers, or other overlay components.
|
|
13
|
+
*
|
|
14
|
+
* Safe to call in SSR environment (no-op on server).
|
|
15
|
+
* Calling multiple times has no effect until unlocked.
|
|
16
|
+
*
|
|
17
|
+
* @returns {void}
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // When modal opens
|
|
21
|
+
* enableBodyScrollLock();
|
|
22
|
+
*
|
|
23
|
+
* // When modal closes
|
|
24
|
+
* disableBodyScrollLock();
|
|
25
|
+
*/
|
|
26
|
+
function enableBodyScrollLock() {
|
|
27
|
+
if (require_isServer.isServer()) return;
|
|
28
|
+
if (isBodyScrollLocked()) return;
|
|
29
|
+
const scrollY = window.scrollY;
|
|
30
|
+
saveScrollPosition(scrollY);
|
|
31
|
+
applyScrollLockStyles(scrollY);
|
|
32
|
+
}
|
|
33
|
+
function isBodyScrollLocked() {
|
|
34
|
+
return document.body.getAttribute(SCROLL_POSITION_ATTR) != null;
|
|
35
|
+
}
|
|
36
|
+
function saveScrollPosition(scrollY) {
|
|
37
|
+
document.body.setAttribute(SCROLL_POSITION_ATTR, scrollY.toString());
|
|
38
|
+
}
|
|
39
|
+
function applyScrollLockStyles(scrollY) {
|
|
40
|
+
const { body } = document;
|
|
41
|
+
body.style.overflow = "hidden";
|
|
42
|
+
body.style.position = "fixed";
|
|
43
|
+
body.style.top = `-${scrollY}px`;
|
|
44
|
+
body.style.left = "0px";
|
|
45
|
+
body.style.right = "0px";
|
|
46
|
+
body.style.bottom = "0px";
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
exports.enableBodyScrollLock = enableBodyScrollLock;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* `enableBodyScrollLock` is a utility function that locks the body scroll.
|
|
6
|
+
* It prevents the body from scrolling by applying fixed positioning.
|
|
7
|
+
* This is useful when opening modals, drawers, or other overlay components.
|
|
8
|
+
*
|
|
9
|
+
* Safe to call in SSR environment (no-op on server).
|
|
10
|
+
* Calling multiple times has no effect until unlocked.
|
|
11
|
+
*
|
|
12
|
+
* @returns {void}
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // When modal opens
|
|
16
|
+
* enableBodyScrollLock();
|
|
17
|
+
*
|
|
18
|
+
* // When modal closes
|
|
19
|
+
* disableBodyScrollLock();
|
|
20
|
+
*/
|
|
21
|
+
declare function enableBodyScrollLock(): void;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { enableBodyScrollLock };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* `enableBodyScrollLock` is a utility function that locks the body scroll.
|
|
6
|
+
* It prevents the body from scrolling by applying fixed positioning.
|
|
7
|
+
* This is useful when opening modals, drawers, or other overlay components.
|
|
8
|
+
*
|
|
9
|
+
* Safe to call in SSR environment (no-op on server).
|
|
10
|
+
* Calling multiple times has no effect until unlocked.
|
|
11
|
+
*
|
|
12
|
+
* @returns {void}
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // When modal opens
|
|
16
|
+
* enableBodyScrollLock();
|
|
17
|
+
*
|
|
18
|
+
* // When modal closes
|
|
19
|
+
* disableBodyScrollLock();
|
|
20
|
+
*/
|
|
21
|
+
declare function enableBodyScrollLock(): void;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { enableBodyScrollLock };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isServer } from "../isServer/isServer.mjs";
|
|
3
|
+
//#region src/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data attribute key for storing scroll position
|
|
6
|
+
*/
|
|
7
|
+
const SCROLL_POSITION_ATTR = "data-simplikit-scroll-y";
|
|
8
|
+
/**
|
|
9
|
+
* @description
|
|
10
|
+
* `enableBodyScrollLock` is a utility function that locks the body scroll.
|
|
11
|
+
* It prevents the body from scrolling by applying fixed positioning.
|
|
12
|
+
* This is useful when opening modals, drawers, or other overlay components.
|
|
13
|
+
*
|
|
14
|
+
* Safe to call in SSR environment (no-op on server).
|
|
15
|
+
* Calling multiple times has no effect until unlocked.
|
|
16
|
+
*
|
|
17
|
+
* @returns {void}
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // When modal opens
|
|
21
|
+
* enableBodyScrollLock();
|
|
22
|
+
*
|
|
23
|
+
* // When modal closes
|
|
24
|
+
* disableBodyScrollLock();
|
|
25
|
+
*/
|
|
26
|
+
function enableBodyScrollLock() {
|
|
27
|
+
if (isServer()) return;
|
|
28
|
+
if (isBodyScrollLocked()) return;
|
|
29
|
+
const scrollY = window.scrollY;
|
|
30
|
+
saveScrollPosition(scrollY);
|
|
31
|
+
applyScrollLockStyles(scrollY);
|
|
32
|
+
}
|
|
33
|
+
function isBodyScrollLocked() {
|
|
34
|
+
return document.body.getAttribute(SCROLL_POSITION_ATTR) != null;
|
|
35
|
+
}
|
|
36
|
+
function saveScrollPosition(scrollY) {
|
|
37
|
+
document.body.setAttribute(SCROLL_POSITION_ATTR, scrollY.toString());
|
|
38
|
+
}
|
|
39
|
+
function applyScrollLockStyles(scrollY) {
|
|
40
|
+
const { body } = document;
|
|
41
|
+
body.style.overflow = "hidden";
|
|
42
|
+
body.style.position = "fixed";
|
|
43
|
+
body.style.top = `-${scrollY}px`;
|
|
44
|
+
body.style.left = "0px";
|
|
45
|
+
body.style.right = "0px";
|
|
46
|
+
body.style.bottom = "0px";
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { enableBodyScrollLock };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_isServer = require("../isServer/isServer.cjs");
|
|
3
|
+
//#region src/mobile/utils/getKeyboardHeight/getKeyboardHeight.ts
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* `getKeyboardHeight` is a utility function that returns the current on-screen keyboard height in pixels.
|
|
7
|
+
*
|
|
8
|
+
* This function uses the Visual Viewport API to calculate the keyboard height.
|
|
9
|
+
* It assumes a modern environment where Visual Viewport is supported
|
|
10
|
+
* (Safari / WKWebView 14+, Chrome / Android WebView 80+).
|
|
11
|
+
*
|
|
12
|
+
* The keyboard height is computed as:
|
|
13
|
+
* `window.innerHeight - visualViewport.height - visualViewport.offsetTop`
|
|
14
|
+
*
|
|
15
|
+
* The subtraction of `offsetTop` is required to correctly handle iOS behavior
|
|
16
|
+
* where the visual viewport may shift vertically when the keyboard appears.
|
|
17
|
+
*
|
|
18
|
+
* @returns {number} The keyboard height in pixels. Returns 0 if the keyboard is not visible.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const height = getKeyboardHeight();
|
|
22
|
+
*
|
|
23
|
+
* if (height > 0) {
|
|
24
|
+
* footer.style.paddingBottom = `${height}px`;
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
function getKeyboardHeight() {
|
|
28
|
+
if (require_isServer.isServer()) return 0;
|
|
29
|
+
const visualViewport = window.visualViewport;
|
|
30
|
+
if (visualViewport == null) return 0;
|
|
31
|
+
const height = window.innerHeight - visualViewport.height - visualViewport.offsetTop;
|
|
32
|
+
return Math.max(0, height);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
exports.getKeyboardHeight = getKeyboardHeight;
|