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.
Files changed (103) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +36 -26
  3. package/dist/hooks/useAsyncEffect/useAsyncEffect.cjs +1 -0
  4. package/dist/hooks/useAsyncEffect/useAsyncEffect.mjs +1 -0
  5. package/dist/hooks/useCallbackOncePerRender/useCallbackOncePerRender.cjs +1 -0
  6. package/dist/hooks/useCallbackOncePerRender/useCallbackOncePerRender.mjs +1 -0
  7. package/dist/hooks/useConditionalEffect/useConditionalEffect.cjs +1 -0
  8. package/dist/hooks/useConditionalEffect/useConditionalEffect.mjs +1 -0
  9. package/dist/hooks/useInputState/useInputState.cjs +9 -3
  10. package/dist/hooks/useInputState/useInputState.d.cts +11 -4
  11. package/dist/hooks/useInputState/useInputState.d.mts +11 -4
  12. package/dist/hooks/useInputState/useInputState.mjs +9 -3
  13. package/dist/hooks/useLoading/useLoading.cjs +3 -5
  14. package/dist/hooks/useLoading/useLoading.d.cts +2 -5
  15. package/dist/hooks/useLoading/useLoading.d.mts +2 -5
  16. package/dist/hooks/useLoading/useLoading.mjs +3 -5
  17. package/dist/hooks/usePreservedReference/usePreservedReference.cjs +1 -0
  18. package/dist/hooks/usePreservedReference/usePreservedReference.mjs +1 -0
  19. package/dist/hooks/usePrevious/usePrevious.cjs +1 -0
  20. package/dist/hooks/usePrevious/usePrevious.mjs +1 -0
  21. package/dist/hooks/useRefEffect/useRefEffect.cjs +1 -0
  22. package/dist/hooks/useRefEffect/useRefEffect.mjs +1 -0
  23. package/dist/hooks/useStorageState/useStorageState.cjs +1 -0
  24. package/dist/hooks/useStorageState/useStorageState.mjs +1 -0
  25. package/dist/hooks/useThrottledCallback/useThrottledCallback.cjs +9 -1
  26. package/dist/hooks/useThrottledCallback/useThrottledCallback.mjs +9 -1
  27. package/dist/index.cjs +34 -0
  28. package/dist/index.d.cts +19 -1
  29. package/dist/index.d.mts +19 -1
  30. package/dist/index.mjs +18 -1
  31. package/dist/mobile/hooks/useAvoidKeyboard/index.d.cts +3 -0
  32. package/dist/mobile/hooks/useAvoidKeyboard/index.d.mts +3 -0
  33. package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.cjs +75 -0
  34. package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.d.cts +89 -0
  35. package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.d.mts +89 -0
  36. package/dist/mobile/hooks/useAvoidKeyboard/useAvoidKeyboard.mjs +75 -0
  37. package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.cjs +47 -0
  38. package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.d.cts +37 -0
  39. package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.d.mts +37 -0
  40. package/dist/mobile/hooks/useBodyScrollLock/useBodyScrollLock.mjs +47 -0
  41. package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.cjs +41 -0
  42. package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.cts +41 -0
  43. package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.d.mts +41 -0
  44. package/dist/mobile/hooks/useKeyboardHeight/useKeyboardHeight.mjs +41 -0
  45. package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.cjs +88 -0
  46. package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.d.cts +77 -0
  47. package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.d.mts +77 -0
  48. package/dist/mobile/hooks/useNetworkStatus/useNetworkStatus.mjs +88 -0
  49. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.cjs +73 -0
  50. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.cts +62 -0
  51. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.mts +62 -0
  52. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.mjs +73 -0
  53. package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.cjs +74 -0
  54. package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.cts +55 -0
  55. package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.mts +55 -0
  56. package/dist/mobile/hooks/useSafeAreaInset/useSafeAreaInset.mjs +74 -0
  57. package/dist/mobile/hooks/useScrollDirection/useScrollDirection.cjs +79 -0
  58. package/dist/mobile/hooks/useScrollDirection/useScrollDirection.d.cts +40 -0
  59. package/dist/mobile/hooks/useScrollDirection/useScrollDirection.d.mts +40 -0
  60. package/dist/mobile/hooks/useScrollDirection/useScrollDirection.mjs +79 -0
  61. package/dist/mobile/hooks/useVisualViewport/useVisualViewport.cjs +77 -0
  62. package/dist/mobile/hooks/useVisualViewport/useVisualViewport.d.cts +89 -0
  63. package/dist/mobile/hooks/useVisualViewport/useVisualViewport.d.mts +89 -0
  64. package/dist/mobile/hooks/useVisualViewport/useVisualViewport.mjs +77 -0
  65. package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.cjs +55 -0
  66. package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.cts +22 -0
  67. package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.d.mts +22 -0
  68. package/dist/mobile/utils/disableBodyScrollLock/disableBodyScrollLock.mjs +55 -0
  69. package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.cjs +49 -0
  70. package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.cts +23 -0
  71. package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.d.mts +23 -0
  72. package/dist/mobile/utils/enableBodyScrollLock/enableBodyScrollLock.mjs +49 -0
  73. package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.cjs +35 -0
  74. package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.d.cts +28 -0
  75. package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.d.mts +28 -0
  76. package/dist/mobile/utils/getKeyboardHeight/getKeyboardHeight.mjs +35 -0
  77. package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.cjs +58 -0
  78. package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.d.cts +44 -0
  79. package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.d.mts +44 -0
  80. package/dist/mobile/utils/getSafeAreaInset/getSafeAreaInset.mjs +58 -0
  81. package/dist/mobile/utils/isAndroid/isAndroid.cjs +32 -0
  82. package/dist/mobile/utils/isAndroid/isAndroid.d.cts +27 -0
  83. package/dist/mobile/utils/isAndroid/isAndroid.d.mts +27 -0
  84. package/dist/mobile/utils/isAndroid/isAndroid.mjs +32 -0
  85. package/dist/mobile/utils/isIOS/isIOS.cjs +37 -0
  86. package/dist/mobile/utils/isIOS/isIOS.d.cts +30 -0
  87. package/dist/mobile/utils/isIOS/isIOS.d.mts +30 -0
  88. package/dist/mobile/utils/isIOS/isIOS.mjs +37 -0
  89. package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.cjs +28 -0
  90. package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.d.cts +25 -0
  91. package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.d.mts +25 -0
  92. package/dist/mobile/utils/isKeyboardVisible/isKeyboardVisible.mjs +28 -0
  93. package/dist/mobile/utils/isServer/isServer.cjs +24 -0
  94. package/dist/mobile/utils/isServer/isServer.d.cts +22 -0
  95. package/dist/mobile/utils/isServer/isServer.d.mts +22 -0
  96. package/dist/mobile/utils/isServer/isServer.mjs +24 -0
  97. package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.cjs +71 -0
  98. package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.d.cts +64 -0
  99. package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.d.mts +64 -0
  100. package/dist/mobile/utils/subscribeKeyboardHeight/subscribeKeyboardHeight.mjs +71 -0
  101. package/dist/utils/buildContext/buildContext.cjs +1 -0
  102. package/dist/utils/buildContext/buildContext.mjs +1 -0
  103. package/package.json +22 -8
@@ -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 };
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { isServer } from "../../utils/isServer/isServer.mjs";
3
+ import { useEffect, useState } from "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] = useState(() => getPageVisibility());
50
+ 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 (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
+ export { usePageVisibility };
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ const require_isServer = require("../../utils/isServer/isServer.cjs");
3
+ const require_getSafeAreaInset = require("../../utils/getSafeAreaInset/getSafeAreaInset.cjs");
4
+ let react = require("react");
5
+ //#region src/mobile/hooks/useSafeAreaInset/useSafeAreaInset.ts
6
+ /**
7
+ * @description
8
+ * `useSafeAreaInset` is a React hook that tracks safe area inset changes.
9
+ * It returns the safe area insets that automatically update when the screen
10
+ * orientation changes (e.g., portrait to landscape).
11
+ *
12
+ * Safe area insets account for device-specific UI elements:
13
+ * - **top**: Notch, Dynamic Island, or status bar
14
+ * - **bottom**: Home indicator on Face ID devices
15
+ * - **left/right**: Rounded corners in landscape mode
16
+ *
17
+ * @returns {SafeAreaInset} An object containing safe area insets for all four sides.
18
+ * - top `number` - Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar;
19
+ * - bottom `number` - Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices;
20
+ * - left `number` - Left safe area inset in pixels. Accounts for rounded corners in landscape mode;
21
+ * - right `number` - Right safe area inset in pixels. Accounts for rounded corners in landscape mode;
22
+ *
23
+ * @example
24
+ * function MyComponent() {
25
+ * const safeArea = useSafeAreaInset();
26
+ *
27
+ * return (
28
+ * <div style={{
29
+ * paddingTop: safeArea.top,
30
+ * paddingBottom: safeArea.bottom,
31
+ * paddingLeft: safeArea.left,
32
+ * paddingRight: safeArea.right,
33
+ * }}>
34
+ * Content that respects safe areas
35
+ * </div>
36
+ * );
37
+ * }
38
+ *
39
+ * @example
40
+ * // Automatically updates when screen rotates
41
+ * function RotationAwareHeader() {
42
+ * const { top, left, right } = useSafeAreaInset();
43
+ *
44
+ * return (
45
+ * <header style={{
46
+ * paddingTop: top,
47
+ * paddingLeft: left,
48
+ * paddingRight: right,
49
+ * }}>
50
+ * Header content
51
+ * </header>
52
+ * );
53
+ * }
54
+ */
55
+ function useSafeAreaInset() {
56
+ const [inset, setInset] = (0, react.useState)(() => require_getSafeAreaInset.getSafeAreaInset());
57
+ const updateInset = (0, react.useCallback)(() => {
58
+ (0, react.startTransition)(() => {
59
+ setInset(require_getSafeAreaInset.getSafeAreaInset());
60
+ });
61
+ }, []);
62
+ (0, react.useEffect)(function handleOrientationChange() {
63
+ if (require_isServer.isServer()) return;
64
+ window.addEventListener("resize", updateInset);
65
+ window.addEventListener("orientationchange", updateInset);
66
+ return function cleanup() {
67
+ window.removeEventListener("resize", updateInset);
68
+ window.removeEventListener("orientationchange", updateInset);
69
+ };
70
+ }, [updateInset]);
71
+ return inset;
72
+ }
73
+ //#endregion
74
+ exports.useSafeAreaInset = useSafeAreaInset;
@@ -0,0 +1,55 @@
1
+
2
+ import { SafeAreaInset } from "../../utils/getSafeAreaInset/getSafeAreaInset.cjs";
3
+ //#region src/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.ts
4
+ /**
5
+ * @description
6
+ * `useSafeAreaInset` is a React hook that tracks safe area inset changes.
7
+ * It returns the safe area insets that automatically update when the screen
8
+ * orientation changes (e.g., portrait to landscape).
9
+ *
10
+ * Safe area insets account for device-specific UI elements:
11
+ * - **top**: Notch, Dynamic Island, or status bar
12
+ * - **bottom**: Home indicator on Face ID devices
13
+ * - **left/right**: Rounded corners in landscape mode
14
+ *
15
+ * @returns {SafeAreaInset} An object containing safe area insets for all four sides.
16
+ * - top `number` - Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar;
17
+ * - bottom `number` - Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices;
18
+ * - left `number` - Left safe area inset in pixels. Accounts for rounded corners in landscape mode;
19
+ * - right `number` - Right safe area inset in pixels. Accounts for rounded corners in landscape mode;
20
+ *
21
+ * @example
22
+ * function MyComponent() {
23
+ * const safeArea = useSafeAreaInset();
24
+ *
25
+ * return (
26
+ * <div style={{
27
+ * paddingTop: safeArea.top,
28
+ * paddingBottom: safeArea.bottom,
29
+ * paddingLeft: safeArea.left,
30
+ * paddingRight: safeArea.right,
31
+ * }}>
32
+ * Content that respects safe areas
33
+ * </div>
34
+ * );
35
+ * }
36
+ *
37
+ * @example
38
+ * // Automatically updates when screen rotates
39
+ * function RotationAwareHeader() {
40
+ * const { top, left, right } = useSafeAreaInset();
41
+ *
42
+ * return (
43
+ * <header style={{
44
+ * paddingTop: top,
45
+ * paddingLeft: left,
46
+ * paddingRight: right,
47
+ * }}>
48
+ * Header content
49
+ * </header>
50
+ * );
51
+ * }
52
+ */
53
+ declare function useSafeAreaInset(): SafeAreaInset;
54
+ //#endregion
55
+ export { useSafeAreaInset };
@@ -0,0 +1,55 @@
1
+
2
+ import { SafeAreaInset } from "../../utils/getSafeAreaInset/getSafeAreaInset.mjs";
3
+ //#region src/mobile/hooks/useSafeAreaInset/useSafeAreaInset.d.ts
4
+ /**
5
+ * @description
6
+ * `useSafeAreaInset` is a React hook that tracks safe area inset changes.
7
+ * It returns the safe area insets that automatically update when the screen
8
+ * orientation changes (e.g., portrait to landscape).
9
+ *
10
+ * Safe area insets account for device-specific UI elements:
11
+ * - **top**: Notch, Dynamic Island, or status bar
12
+ * - **bottom**: Home indicator on Face ID devices
13
+ * - **left/right**: Rounded corners in landscape mode
14
+ *
15
+ * @returns {SafeAreaInset} An object containing safe area insets for all four sides.
16
+ * - top `number` - Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar;
17
+ * - bottom `number` - Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices;
18
+ * - left `number` - Left safe area inset in pixels. Accounts for rounded corners in landscape mode;
19
+ * - right `number` - Right safe area inset in pixels. Accounts for rounded corners in landscape mode;
20
+ *
21
+ * @example
22
+ * function MyComponent() {
23
+ * const safeArea = useSafeAreaInset();
24
+ *
25
+ * return (
26
+ * <div style={{
27
+ * paddingTop: safeArea.top,
28
+ * paddingBottom: safeArea.bottom,
29
+ * paddingLeft: safeArea.left,
30
+ * paddingRight: safeArea.right,
31
+ * }}>
32
+ * Content that respects safe areas
33
+ * </div>
34
+ * );
35
+ * }
36
+ *
37
+ * @example
38
+ * // Automatically updates when screen rotates
39
+ * function RotationAwareHeader() {
40
+ * const { top, left, right } = useSafeAreaInset();
41
+ *
42
+ * return (
43
+ * <header style={{
44
+ * paddingTop: top,
45
+ * paddingLeft: left,
46
+ * paddingRight: right,
47
+ * }}>
48
+ * Header content
49
+ * </header>
50
+ * );
51
+ * }
52
+ */
53
+ declare function useSafeAreaInset(): SafeAreaInset;
54
+ //#endregion
55
+ export { useSafeAreaInset };
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { isServer } from "../../utils/isServer/isServer.mjs";
3
+ import { getSafeAreaInset } from "../../utils/getSafeAreaInset/getSafeAreaInset.mjs";
4
+ import { startTransition, useCallback, useEffect, useState } from "react";
5
+ //#region src/mobile/hooks/useSafeAreaInset/useSafeAreaInset.ts
6
+ /**
7
+ * @description
8
+ * `useSafeAreaInset` is a React hook that tracks safe area inset changes.
9
+ * It returns the safe area insets that automatically update when the screen
10
+ * orientation changes (e.g., portrait to landscape).
11
+ *
12
+ * Safe area insets account for device-specific UI elements:
13
+ * - **top**: Notch, Dynamic Island, or status bar
14
+ * - **bottom**: Home indicator on Face ID devices
15
+ * - **left/right**: Rounded corners in landscape mode
16
+ *
17
+ * @returns {SafeAreaInset} An object containing safe area insets for all four sides.
18
+ * - top `number` - Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar;
19
+ * - bottom `number` - Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices;
20
+ * - left `number` - Left safe area inset in pixels. Accounts for rounded corners in landscape mode;
21
+ * - right `number` - Right safe area inset in pixels. Accounts for rounded corners in landscape mode;
22
+ *
23
+ * @example
24
+ * function MyComponent() {
25
+ * const safeArea = useSafeAreaInset();
26
+ *
27
+ * return (
28
+ * <div style={{
29
+ * paddingTop: safeArea.top,
30
+ * paddingBottom: safeArea.bottom,
31
+ * paddingLeft: safeArea.left,
32
+ * paddingRight: safeArea.right,
33
+ * }}>
34
+ * Content that respects safe areas
35
+ * </div>
36
+ * );
37
+ * }
38
+ *
39
+ * @example
40
+ * // Automatically updates when screen rotates
41
+ * function RotationAwareHeader() {
42
+ * const { top, left, right } = useSafeAreaInset();
43
+ *
44
+ * return (
45
+ * <header style={{
46
+ * paddingTop: top,
47
+ * paddingLeft: left,
48
+ * paddingRight: right,
49
+ * }}>
50
+ * Header content
51
+ * </header>
52
+ * );
53
+ * }
54
+ */
55
+ function useSafeAreaInset() {
56
+ const [inset, setInset] = useState(() => getSafeAreaInset());
57
+ const updateInset = useCallback(() => {
58
+ startTransition(() => {
59
+ setInset(getSafeAreaInset());
60
+ });
61
+ }, []);
62
+ useEffect(function handleOrientationChange() {
63
+ if (isServer()) return;
64
+ window.addEventListener("resize", updateInset);
65
+ window.addEventListener("orientationchange", updateInset);
66
+ return function cleanup() {
67
+ window.removeEventListener("resize", updateInset);
68
+ window.removeEventListener("orientationchange", updateInset);
69
+ };
70
+ }, [updateInset]);
71
+ return inset;
72
+ }
73
+ //#endregion
74
+ export { useSafeAreaInset };
@@ -0,0 +1,79 @@
1
+ "use client";
2
+ const require_isServer = require("../../utils/isServer/isServer.cjs");
3
+ let react = require("react");
4
+ //#region src/mobile/hooks/useScrollDirection/useScrollDirection.ts
5
+ /**
6
+ * @description
7
+ * `useScrollDirection` is a React hook that detects scroll direction.
8
+ * It returns scroll direction (up/down) and current scroll position.
9
+ * Throttled by default (50ms) for performance.
10
+ *
11
+ * @param {UseScrollDirectionOptions} [options] - Configuration options.
12
+ * @param {number} [options.throttleMs=50] - Throttle interval in milliseconds.
13
+ * @returns {ScrollDirectionState} Scroll direction state: `direction` (`'up' | 'down' | null`) and `position` (px).
14
+ *
15
+ * @example
16
+ * function Header() {
17
+ * const { direction, position } = useScrollDirection();
18
+ *
19
+ * // Hide header on scroll down
20
+ * const isHidden = direction === 'down' && position > 100;
21
+ *
22
+ * return (
23
+ * <header className={isHidden ? 'hidden' : 'visible'}>
24
+ * My Header
25
+ * </header>
26
+ * );
27
+ * }
28
+ */
29
+ function useScrollDirection(options = {}) {
30
+ const { throttleMs = 50 } = options;
31
+ const [scrollInfo, setScrollInfo] = (0, react.useState)({
32
+ direction: null,
33
+ position: require_isServer.isServer() ? 0 : window.scrollY
34
+ });
35
+ const lastScrollYRef = (0, react.useRef)(require_isServer.isServer() ? 0 : window.scrollY);
36
+ const throttleTimerRef = (0, react.useRef)(null);
37
+ const updateScrollDirection = (0, react.useCallback)(({ currentScrollY, lastScrollY }) => {
38
+ if (currentScrollY > lastScrollY) {
39
+ setScrollInfo({
40
+ direction: "down",
41
+ position: currentScrollY
42
+ });
43
+ return;
44
+ }
45
+ if (currentScrollY < lastScrollY) {
46
+ setScrollInfo({
47
+ direction: "up",
48
+ position: currentScrollY
49
+ });
50
+ return;
51
+ }
52
+ }, []);
53
+ const startThrottle = (0, react.useCallback)(() => {
54
+ throttleTimerRef.current = setTimeout(function clearThrottle() {
55
+ throttleTimerRef.current = null;
56
+ }, throttleMs);
57
+ }, [throttleMs]);
58
+ (0, react.useEffect)(function handleScrollDirectionChange() {
59
+ function handleScroll() {
60
+ if (throttleTimerRef.current != null) return;
61
+ const currentScrollY = window.scrollY;
62
+ const lastScrollY = lastScrollYRef.current;
63
+ lastScrollYRef.current = currentScrollY;
64
+ startThrottle();
65
+ updateScrollDirection({
66
+ currentScrollY,
67
+ lastScrollY
68
+ });
69
+ }
70
+ window.addEventListener("scroll", handleScroll, { passive: true });
71
+ return function cleanup() {
72
+ window.removeEventListener("scroll", handleScroll);
73
+ if (throttleTimerRef.current != null) clearTimeout(throttleTimerRef.current);
74
+ };
75
+ }, [startThrottle, updateScrollDirection]);
76
+ return scrollInfo;
77
+ }
78
+ //#endregion
79
+ exports.useScrollDirection = useScrollDirection;
@@ -0,0 +1,40 @@
1
+
2
+ //#region src/mobile/hooks/useScrollDirection/useScrollDirection.d.ts
3
+ type ScrollDirection = 'up' | 'down' | null;
4
+ type ScrollDirectionState = {
5
+ /** Current scroll direction */
6
+ direction: ScrollDirection;
7
+ /** Current scroll Y position (px) */
8
+ position: number;
9
+ };
10
+ type UseScrollDirectionOptions = {
11
+ /** Throttle interval (ms) - default: 50ms */
12
+ throttleMs?: number;
13
+ };
14
+ /**
15
+ * @description
16
+ * `useScrollDirection` is a React hook that detects scroll direction.
17
+ * It returns scroll direction (up/down) and current scroll position.
18
+ * Throttled by default (50ms) for performance.
19
+ *
20
+ * @param {UseScrollDirectionOptions} [options] - Configuration options.
21
+ * @param {number} [options.throttleMs=50] - Throttle interval in milliseconds.
22
+ * @returns {ScrollDirectionState} Scroll direction state: `direction` (`'up' | 'down' | null`) and `position` (px).
23
+ *
24
+ * @example
25
+ * function Header() {
26
+ * const { direction, position } = useScrollDirection();
27
+ *
28
+ * // Hide header on scroll down
29
+ * const isHidden = direction === 'down' && position > 100;
30
+ *
31
+ * return (
32
+ * <header className={isHidden ? 'hidden' : 'visible'}>
33
+ * My Header
34
+ * </header>
35
+ * );
36
+ * }
37
+ */
38
+ declare function useScrollDirection(options?: UseScrollDirectionOptions): ScrollDirectionState;
39
+ //#endregion
40
+ export { useScrollDirection };
@@ -0,0 +1,40 @@
1
+
2
+ //#region src/mobile/hooks/useScrollDirection/useScrollDirection.d.ts
3
+ type ScrollDirection = 'up' | 'down' | null;
4
+ type ScrollDirectionState = {
5
+ /** Current scroll direction */
6
+ direction: ScrollDirection;
7
+ /** Current scroll Y position (px) */
8
+ position: number;
9
+ };
10
+ type UseScrollDirectionOptions = {
11
+ /** Throttle interval (ms) - default: 50ms */
12
+ throttleMs?: number;
13
+ };
14
+ /**
15
+ * @description
16
+ * `useScrollDirection` is a React hook that detects scroll direction.
17
+ * It returns scroll direction (up/down) and current scroll position.
18
+ * Throttled by default (50ms) for performance.
19
+ *
20
+ * @param {UseScrollDirectionOptions} [options] - Configuration options.
21
+ * @param {number} [options.throttleMs=50] - Throttle interval in milliseconds.
22
+ * @returns {ScrollDirectionState} Scroll direction state: `direction` (`'up' | 'down' | null`) and `position` (px).
23
+ *
24
+ * @example
25
+ * function Header() {
26
+ * const { direction, position } = useScrollDirection();
27
+ *
28
+ * // Hide header on scroll down
29
+ * const isHidden = direction === 'down' && position > 100;
30
+ *
31
+ * return (
32
+ * <header className={isHidden ? 'hidden' : 'visible'}>
33
+ * My Header
34
+ * </header>
35
+ * );
36
+ * }
37
+ */
38
+ declare function useScrollDirection(options?: UseScrollDirectionOptions): ScrollDirectionState;
39
+ //#endregion
40
+ export { useScrollDirection };
@@ -0,0 +1,79 @@
1
+ "use client";
2
+ import { isServer } from "../../utils/isServer/isServer.mjs";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ //#region src/mobile/hooks/useScrollDirection/useScrollDirection.ts
5
+ /**
6
+ * @description
7
+ * `useScrollDirection` is a React hook that detects scroll direction.
8
+ * It returns scroll direction (up/down) and current scroll position.
9
+ * Throttled by default (50ms) for performance.
10
+ *
11
+ * @param {UseScrollDirectionOptions} [options] - Configuration options.
12
+ * @param {number} [options.throttleMs=50] - Throttle interval in milliseconds.
13
+ * @returns {ScrollDirectionState} Scroll direction state: `direction` (`'up' | 'down' | null`) and `position` (px).
14
+ *
15
+ * @example
16
+ * function Header() {
17
+ * const { direction, position } = useScrollDirection();
18
+ *
19
+ * // Hide header on scroll down
20
+ * const isHidden = direction === 'down' && position > 100;
21
+ *
22
+ * return (
23
+ * <header className={isHidden ? 'hidden' : 'visible'}>
24
+ * My Header
25
+ * </header>
26
+ * );
27
+ * }
28
+ */
29
+ function useScrollDirection(options = {}) {
30
+ const { throttleMs = 50 } = options;
31
+ const [scrollInfo, setScrollInfo] = useState({
32
+ direction: null,
33
+ position: isServer() ? 0 : window.scrollY
34
+ });
35
+ const lastScrollYRef = useRef(isServer() ? 0 : window.scrollY);
36
+ const throttleTimerRef = useRef(null);
37
+ const updateScrollDirection = useCallback(({ currentScrollY, lastScrollY }) => {
38
+ if (currentScrollY > lastScrollY) {
39
+ setScrollInfo({
40
+ direction: "down",
41
+ position: currentScrollY
42
+ });
43
+ return;
44
+ }
45
+ if (currentScrollY < lastScrollY) {
46
+ setScrollInfo({
47
+ direction: "up",
48
+ position: currentScrollY
49
+ });
50
+ return;
51
+ }
52
+ }, []);
53
+ const startThrottle = useCallback(() => {
54
+ throttleTimerRef.current = setTimeout(function clearThrottle() {
55
+ throttleTimerRef.current = null;
56
+ }, throttleMs);
57
+ }, [throttleMs]);
58
+ useEffect(function handleScrollDirectionChange() {
59
+ function handleScroll() {
60
+ if (throttleTimerRef.current != null) return;
61
+ const currentScrollY = window.scrollY;
62
+ const lastScrollY = lastScrollYRef.current;
63
+ lastScrollYRef.current = currentScrollY;
64
+ startThrottle();
65
+ updateScrollDirection({
66
+ currentScrollY,
67
+ lastScrollY
68
+ });
69
+ }
70
+ window.addEventListener("scroll", handleScroll, { passive: true });
71
+ return function cleanup() {
72
+ window.removeEventListener("scroll", handleScroll);
73
+ if (throttleTimerRef.current != null) clearTimeout(throttleTimerRef.current);
74
+ };
75
+ }, [startThrottle, updateScrollDirection]);
76
+ return scrollInfo;
77
+ }
78
+ //#endregion
79
+ export { useScrollDirection };