react-visibility-hooks 1.0.4 → 1.0.6
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/README.md +207 -0
- package/package.json +7 -5
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# react-visibility-hooks
|
|
2
|
+
|
|
3
|
+
> Tiny, SSR-safe React hooks for page visibility, idle detection and smart polling
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-visibility-hooks)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
A collection of lightweight React hooks that help you build performance-conscious applications by detecting page visibility, user idle state, and managing smart polling strategies.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 🪶 **Lightweight** - Zero dependencies (except peer dependencies)
|
|
13
|
+
- 🔒 **SSR-safe** - Works seamlessly with Next.js, Remix, and other SSR frameworks
|
|
14
|
+
- 📦 **Tree-shakeable** - Import only what you need
|
|
15
|
+
- 🎯 **TypeScript** - Fully typed with TypeScript
|
|
16
|
+
- ⚡ **Performance-focused** - Pause expensive operations when users aren't looking
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install react-visibility-hooks
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For `useSmartPolling`, you'll also need to install `@tanstack/react-query`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @tanstack/react-query
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Hooks
|
|
31
|
+
|
|
32
|
+
### `useDocVisible`
|
|
33
|
+
|
|
34
|
+
Detect when the browser tab is visible or hidden using the [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API).
|
|
35
|
+
|
|
36
|
+
**Use cases:**
|
|
37
|
+
- Pause animations when tab is hidden
|
|
38
|
+
- Stop fetching data when user isn't viewing the page
|
|
39
|
+
- Save battery and resources
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { useDocVisible } from 'react-visibility-hooks';
|
|
43
|
+
|
|
44
|
+
function MyComponent() {
|
|
45
|
+
const isVisible = useDocVisible();
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
Tab is currently: {isVisible ? 'visible' : 'hidden'}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### `useIdleVisibility`
|
|
56
|
+
|
|
57
|
+
Detect when the user is idle (no mouse movement or keyboard activity) combined with page visibility state.
|
|
58
|
+
|
|
59
|
+
**Use cases:**
|
|
60
|
+
- Show "Are you still there?" prompts
|
|
61
|
+
- Auto-pause media after inactivity
|
|
62
|
+
- Reduce background activity when user is away
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { useIdleVisibility } from 'react-visibility-hooks';
|
|
66
|
+
|
|
67
|
+
function MyComponent() {
|
|
68
|
+
const { visible, idle } = useIdleVisibility(60000); // 60 seconds timeout
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<p>Page visible: {visible ? 'yes' : 'no'}</p>
|
|
73
|
+
<p>User idle: {idle ? 'yes' : 'no'}</p>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
- `timeout` (optional): Milliseconds of inactivity before user is considered idle (default: 60000)
|
|
81
|
+
|
|
82
|
+
### `useAutoPauseVideo`
|
|
83
|
+
|
|
84
|
+
Automatically pause and resume videos based on page visibility.
|
|
85
|
+
|
|
86
|
+
**Use cases:**
|
|
87
|
+
- Auto-pause videos when user switches tabs
|
|
88
|
+
- Better UX for video-heavy applications
|
|
89
|
+
- Save bandwidth and resources
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { useRef } from 'react';
|
|
93
|
+
import { useAutoPauseVideo } from 'react-visibility-hooks';
|
|
94
|
+
|
|
95
|
+
function VideoPlayer() {
|
|
96
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
97
|
+
useAutoPauseVideo(videoRef);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<video ref={videoRef} src="video.mp4" controls />
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `useSmartPolling`
|
|
106
|
+
|
|
107
|
+
Smart polling that only refetches data when the page is visible. Built on top of [@tanstack/react-query](https://tanstack.com/query).
|
|
108
|
+
|
|
109
|
+
**Use cases:**
|
|
110
|
+
- Real-time dashboards
|
|
111
|
+
- Live notifications
|
|
112
|
+
- Auto-refresh data feeds
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { useSmartPolling } from 'react-visibility-hooks';
|
|
116
|
+
|
|
117
|
+
function Dashboard() {
|
|
118
|
+
const { data, isLoading } = useSmartPolling(async () => {
|
|
119
|
+
const response = await fetch('/api/stats');
|
|
120
|
+
return response.json();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (isLoading) return <div>Loading...</div>;
|
|
124
|
+
|
|
125
|
+
return <div>{JSON.stringify(data)}</div>;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Note:** This hook requires `@tanstack/react-query` to be installed. Polling is automatically paused when the tab is hidden and resumes when visible (default interval: 5 seconds).
|
|
130
|
+
|
|
131
|
+
## SSR Support
|
|
132
|
+
|
|
133
|
+
All hooks are SSR-safe and will work correctly with:
|
|
134
|
+
- Next.js (App Router & Pages Router)
|
|
135
|
+
- Remix
|
|
136
|
+
- Gatsby
|
|
137
|
+
- Any other React SSR framework
|
|
138
|
+
|
|
139
|
+
The hooks check for `document` availability and gracefully handle server-side rendering.
|
|
140
|
+
|
|
141
|
+
## TypeScript
|
|
142
|
+
|
|
143
|
+
This package is written in TypeScript and includes type definitions out of the box. All hooks are fully typed for the best developer experience.
|
|
144
|
+
|
|
145
|
+
## Browser Support
|
|
146
|
+
|
|
147
|
+
Works in all modern browsers that support:
|
|
148
|
+
- [Page Visibility API](https://caniuse.com/pagevisibility)
|
|
149
|
+
- React 18+
|
|
150
|
+
|
|
151
|
+
## Examples
|
|
152
|
+
|
|
153
|
+
### Pause expensive calculations when tab is hidden
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { useDocVisible } from 'react-visibility-hooks';
|
|
157
|
+
import { useEffect } from 'react';
|
|
158
|
+
|
|
159
|
+
function ExpensiveComponent() {
|
|
160
|
+
const isVisible = useDocVisible();
|
|
161
|
+
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (!isVisible) return; // Skip when hidden
|
|
164
|
+
|
|
165
|
+
const interval = setInterval(() => {
|
|
166
|
+
// Expensive operation
|
|
167
|
+
performCalculation();
|
|
168
|
+
}, 1000);
|
|
169
|
+
|
|
170
|
+
return () => clearInterval(interval);
|
|
171
|
+
}, [isVisible]);
|
|
172
|
+
|
|
173
|
+
return <div>...</div>;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Show idle warning
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { useIdleVisibility } from 'react-visibility-hooks';
|
|
181
|
+
|
|
182
|
+
function IdleWarning() {
|
|
183
|
+
const { idle } = useIdleVisibility(300000); // 5 minutes
|
|
184
|
+
|
|
185
|
+
if (!idle) return null;
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className="warning">
|
|
189
|
+
Are you still there? Your session will expire soon.
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Contributing
|
|
196
|
+
|
|
197
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT © [Aniket Raj](https://github.com/exewhyz)
|
|
202
|
+
|
|
203
|
+
## Links
|
|
204
|
+
|
|
205
|
+
- [GitHub Repository](https://github.com/exewhyz/react-visibility-hooks)
|
|
206
|
+
- [Issue Tracker](https://github.com/exewhyz/react-visibility-hooks/issues)
|
|
207
|
+
- [NPM Package](https://www.npmjs.com/package/react-visibility-hooks)
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-visibility-hooks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Tiny, SSR-safe React hooks for page visibility, idle detection and smart polling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
|
-
"module": "./dist/index.
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
12
13
|
"require": "./dist/index.cjs"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
"url": "https://github.com/exewhyz/react-visibility-hooks/issues"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"react": ">=
|
|
48
|
-
"
|
|
48
|
+
"@tanstack/react-query": ">=4",
|
|
49
|
+
"react": ">=18"
|
|
49
50
|
},
|
|
50
51
|
"peerDependenciesMeta": {
|
|
51
52
|
"@tanstack/react-query": {
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"@types/jest": "^30.0.0",
|
|
58
59
|
"@types/react": "^19.2.13",
|
|
59
60
|
"jest": "^30.2.0",
|
|
61
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
60
62
|
"jsdom": "^28.0.0",
|
|
61
63
|
"ts-jest": "^29.4.6",
|
|
62
64
|
"tsup": "^8.5.1",
|