@afex-dapps/idle-timer
Version:
Idle Timer library for detecting user inactivity and managing session timeouts
391 lines (309 loc) • 10.2 kB
Markdown
# -dapps/idle-timer
A React library for detecting user inactivity and managing session timeouts with customizable UI components.
## Features
- 🕐 Configurable inactivity detection
- ⚠️ Customizable timeout warning prompts
- 🔄 Cross-tab synchronization
- 🎨 Bring your own UI components
- 📱 TypeScript support
- 🪝 React hooks API
- ⏱️ Built-in countdown timer functionality
- 🎯 Modal/prompt management utilities
## Installation
```bash
npm install -dapps/idle-timer
# or
yarn add -dapps/idle-timer
# or
pnpm add -dapps/idle-timer
```
> **Note:** This library requires `react` and `react-dom` as a peer dependency.
## Quick Start
### Basic Usage with useIdleTimeout Hook
```tsx
import { useState } from "react";
import { IdleTimerProvider, useIdleTimeout } from "@afex-dapps/idle-timer";
function MyComponent() {
const [isLoggedIn, setIsLoggedIn] = useState(true);
const { remainingTime, continueUserSession, showIdleTimerPrompt } =
useIdleTimeout({
timeout: 5 * 60 * 1000, // 5 minutes
promptBeforeIdle: 1 * 60 * 1000, // 1 minute warning
onIdle: () => {
setIsLoggedIn(false);
console.log("User logged out due to inactivity");
},
disabled: !isLoggedIn, // Only run when logged in
});
return (
<IdleTimerProvider>
<div>
<h1>{isLoggedIn ? "Welcome!" : "Please log in"}</h1>
{showIdleTimerPrompt && (
<div className="warning-modal">
<p>Session expires in {remainingTime} seconds</p>
<button onClick={continueUserSession}>Continue Session</button>
</div>
)}
</div>
</IdleTimerProvider>
);
}
```
### Advanced Usage with Custom Modal
```tsx
import { useState } from "react";
import {
IdleTimerProvider,
useIdleTimeout,
formatTime,
} from "@afex-dapps/idle-timer";
// Custom prompt component
const SessionTimeoutModal = ({
isOpen,
remainingTime,
onContinue,
onLogout,
}) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white p-6 rounded-lg max-w-md">
<h2 className="text-xl font-bold mb-4">⚠️ Session Timeout Warning</h2>
<p className="mb-4">
Your session will expire in{" "}
<span className="font-mono text-2xl text-red-600">
{formatTime(remainingTime)}
</span>
</p>
<div className="flex gap-3">
<button
onClick={onContinue}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Continue Session
</button>
<button
onClick={onLogout}
className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600"
>
Logout Now
</button>
</div>
</div>
</div>
);
};
function App() {
const [isAuthenticated, setIsAuthenticated] = useState(true);
const handleLogout = () => {
setIsAuthenticated(false);
// Your logout logic here
console.log("Logging out...");
};
const { remainingTime, continueUserSession, showIdleTimerPrompt } =
useIdleTimeout({
timeout: 300000, // 5 minutes
promptBeforeIdle: 60000, // 1 minute
crossTab: true,
leaderElection: true,
onIdle: handleLogout,
disabled: !isAuthenticated,
});
return (
<IdleTimerProvider>
<div>
<h1>{isAuthenticated ? "Dashboard" : "Login Required"}</h1>
<SessionTimeoutModal
isOpen={showIdleTimerPrompt}
remainingTime={remainingTime}
onContinue={continueUserSession}
onLogout={handleLogout}
/>
</div>
</IdleTimerProvider>
);
}
```
### Using Hooks Directly
```tsx
import { useIdleTimeout } from "@afex-dapps/idle-timer";
function MyComponent() {
const { remainingTime, continueUserSession, showIdleTimerPrompt, idleTimer } =
useIdleTimeout({
timeout: 300000, // 5 minutes
promptBeforeIdle: 60000, // 1 minute
onIdle: () => console.log("User is idle"),
onPrompt: () => console.log("Showing prompt"),
});
if (showIdleTimerPrompt) {
return (
<div>
<p>You'll be logged out in {remainingTime} seconds</p>
<button onClick={continueUserSession}>Stay Active</button>
</div>
);
}
return <div>Your content here</div>;
}
```
## API Reference
### useIdleTimeout Hook
The main hook that provides idle timeout functionality.
**Parameters:**
- `config: IIdleTimerProps` - Configuration object from react-idle-timer
**Returns:**
```tsx
{
remainingTime: number; // Time remaining in seconds
continueUserSession: () => void; // Function to reset timer and continue session
showIdleTimerPrompt: boolean; // Whether to show the timeout prompt
idleTimer: IIdleTimer; // The underlying idle timer instance
}
```
### IdleTimerProvider
Provider component from react-idle-timer. Wrap your app with this component.
```tsx
import { IdleTimerProvider } from "@afex-dapps/idle-timer";
<IdleTimerProvider>
<YourApp />
</IdleTimerProvider>;
```
### Configuration Options
All configuration options are passed directly to react-idle-timer. Common options include:
| Property | Type | Default | Description |
| ------------------ | ---------- | ---------------- | --------------------------------- |
| `timeout` | `number` | `300000` (5 min) | Time in ms before user is idle |
| `promptBeforeIdle` | `number` | `60000` (1 min) | Time in ms to show warning |
| `crossTab` | `boolean` | `true` | Sync across browser tabs |
| `leaderElection` | `boolean` | `true` | Use leader election for cross-tab |
| `syncTimers` | `number` | `500` | Sync interval in ms |
| `disabled` | `boolean` | `false` | Disable the timer |
| `onIdle` | `function` | - | Callback when user becomes idle |
| `onPrompt` | `function` | - | Callback when prompt is shown |
| `onAction` | `function` | - | Callback when user is active |
For a complete list of options, see the [react-idle-timer documentation](https://github.com/supremetechnopriest/react-idle-timer).
### Utility Functions
- `formatTime(ms: number): string` - Format time as MM:SS
- `millisecondsToSeconds(ms: number): number` - Convert ms to seconds
- `secondsToMilliseconds(seconds: number): number` - Convert seconds to ms
### Debug Hook
```tsx
import { useIdleTimerDebug } from "@afex-dapps/idle-timer";
function MyComponent() {
const { idleTimer } = useIdleTimeout({
/* config */
});
// Enable debug logging (logs timer state every second)
useIdleTimerDebug(idleTimer, true);
return <div>Your component</div>;
}
```
## Migration from Original Code
If you're migrating from the original `InactivityProvider` code, here's how to adapt it:
```tsx
// Before (original code)
function InacitivityProvider({ children }) {
const { asPath } = useRouter();
const [opened, disclosure] = useDisclosure(false);
const logout = useLogout();
const disabled = asPath === "/" || asPath.startsWith("/auth");
const handleContinueSession = () => {
disclosure.close();
interval.stop();
timer.reset();
};
// ... rest of original code
}
// After (using this library)
function InactivityProvider({ children }) {
const { asPath } = useRouter();
const logout = useLogout();
const disabled = asPath === "/" || asPath.startsWith("/auth");
const { remainingTime, continueUserSession, showIdleTimerPrompt } =
useIdleTimeout({
timeout: 1000 * 60 * 5, // 5 minutes
promptBeforeIdle: 1000 * 60, // 1 minute
onIdle: logout,
disabled,
});
return (
<IdleTimerProvider>
{children}
<YourCustomModal
opened={showIdleTimerPrompt}
remainingTime={remainingTime}
onContinue={continueUserSession}
onLogout={logout}
/>
</IdleTimerProvider>
);
}
```
## Constants
The library exports several useful constants:
```tsx
import {
DEFAULT_INACTIVITY_TIME, // 300000ms (5 minutes)
DEFAULT_PROMPT_TIME, // 60000ms (1 minute)
DEFAULT_DISCLOSURE_TIME, // 59 seconds
} from "@afex-dapps/idle-timer";
```
## TypeScript Support
The library is fully typed. Key types include:
```tsx
import type {
UseIdleTimer, // Return type of useIdleTimeout
IdleTimerHandler, // Event handler type
IdleTimerCountdownCallback, // Countdown callback type
UseIdleTimerCountdown, // Countdown hook return type
} from "@afex-dapps/idle-timer";
```
## Best Practices
1. **Always wrap your app with IdleTimerProvider**:
```tsx
import { IdleTimerProvider } from "@afex-dapps/idle-timer";
function App() {
return (
<IdleTimerProvider>
<YourApp />
</IdleTimerProvider>
);
}
```
2. **Use the disabled prop for auth pages**:
```tsx
const disabled = !isAuthenticated || isOnAuthPage;
useIdleTimeout({ disabled, ...config });
```
3. **Handle the continueUserSession properly**:
```tsx
const handleContinue = () => {
// This automatically:
// - Closes the prompt
// - Stops the countdown
// - Resets the idle timer
continueUserSession();
};
```
4. **Customize timeout values for your use case**:
```tsx
// For development (shorter timeouts)
const config = {
timeout: 30 * 1000, // 30 seconds
promptBeforeIdle: 10 * 1000, // 10 seconds
};
// For production (longer timeouts)
const config = {
timeout: 15 * 60 * 1000, // 15 minutes
promptBeforeIdle: 2 * 60 * 1000, // 2 minutes
};
```
## License
MIT
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Dependencies
This library depends on:
- `react-idle-timer` - The core idle timer functionality
- `react` & `react-dom` - React framework (peer dependencies)