UNPKG

@afex-dapps/idle-timer

Version:

Idle Timer library for detecting user inactivity and managing session timeouts

391 lines (309 loc) 10.2 kB
# @afex-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 @afex-dapps/idle-timer # or yarn add @afex-dapps/idle-timer # or pnpm add @afex-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)