/** * Integration Examples * Complete examples showing all 4 keyboard/event hooks working together * * These examples demonstrate real-world usage patterns and best practices. */ import { useEffect, useRef, useState } from 'react' import { useKeyboardShortcuts } from './useKeyboardShortcuts' import { useClickOutside } from './useClickOutside' import { useHotkeys } from './useHotkeys' import { useEventListener } from './useEventListener' /** * Example 1: Command Palette with Keyboard Shortcuts * * Features: * - Open with Ctrl+K * - Navigate with arrow keys * - Select with Enter * - Close with Escape */ export function CommandPaletteExample() { const [isOpen, setIsOpen] = useState(false) const [selectedIndex, setSelectedIndex] = useState(0) const { registerShortcut, unregister } = useKeyboardShortcuts() useEffect(() => { // Open palette const openId = registerShortcut({ key: 'k', ctrl: true, onPress: () => setIsOpen(true), preventDefault: true, }) // Navigation const upId = registerShortcut({ key: 'ArrowUp', onPress: () => setSelectedIndex((prev) => Math.max(0, prev - 1)), }) const downId = registerShortcut({ key: 'ArrowDown', onPress: () => setSelectedIndex((prev) => prev + 1), }) // Selection const selectId = registerShortcut({ key: 'Enter', onPress: () => handleSelect(), }) // Close const closeId = registerShortcut({ key: 'Escape', onPress: () => setIsOpen(false), }) return () => { unregister(openId) unregister(upId) unregister(downId) unregister(selectId) unregister(closeId) } }, [registerShortcut]) const handleSelect = () => { console.log('Selected index:', selectedIndex) setIsOpen(false) } return (

Command Palette (Ctrl+K)

{isOpen && (
Item {selectedIndex}
)}
) } /** * Example 2: Advanced Modal with Click Outside Detection * * Features: * - Click outside closes modal * - Trigger button excluded from close * - Backdrop animation delay * - Touch and mouse support */ export function AdvancedModalExample() { const triggerButtonRef = useRef(null) const modal = useClickOutside({ excludeRefs: [triggerButtonRef], onClickOutside: () => { console.log('Modal closed by outside click') }, includeTouch: true, delayMs: 0, // Immediate close }) return (
{modal.isOpen && (

Modal Content

)}
) } /** * Example 3: IDE-like Editor with Multiple Hotkeys * * Features: * - Save: Ctrl+S / Cmd+S * - Find: Ctrl+F / Cmd+F * - Replace: Ctrl+H / Cmd+H * - Close: Escape * - Format: Ctrl+Shift+I / Cmd+Shift+I */ export function IDEEditorExample() { const hotkeys = useHotkeys() useEffect(() => { // Save file hotkeys.register('ctrl+s', () => { console.log('Saving file...') }, { preventDefault: true, }) // Find dialog hotkeys.register('ctrl+f', () => { console.log('Opening find...') }, { preventDefault: true, }) // Find & Replace hotkeys.register('ctrl+h', () => { console.log('Opening find & replace...') }, { preventDefault: true, }) // Format code hotkeys.register('ctrl+shift+i', () => { console.log('Formatting code...') }, { preventDefault: true, }) // Close hotkeys.register('Escape', () => { console.log('Closing dialogs...') }) // Cleanup all hotkeys on unmount return () => hotkeys.unregisterAll() }, [hotkeys]) return (

IDE Editor

Try: Ctrl+S, Ctrl+F, Ctrl+H, Ctrl+Shift+I

) } /** * Example 4: Window Resize Listener with Performance * * Features: * - Track window size * - Passive listener for performance * - Debounced updates * - Responsive breakpoints */ export function ResponsiveLayoutExample() { const [windowSize, setWindowSize] = useState({ width: typeof window !== 'undefined' ? window.innerWidth : 0, height: typeof window !== 'undefined' ? window.innerHeight : 0, }) const debounceRef = useRef>() const { add } = useEventListener() useEffect(() => { // Add passive resize listener return add(window, 'resize', (e: UIEvent) => { // Debounce the update if (debounceRef.current) { clearTimeout(debounceRef.current) } debounceRef.current = setTimeout(() => { const target = e.target as Window setWindowSize({ width: target.innerWidth, height: target.innerHeight, }) }, 100) }, { passive: true, }) }, [add]) const isMobile = windowSize.width < 640 const isTablet = windowSize.width >= 640 && windowSize.width < 1024 const isDesktop = windowSize.width >= 1024 return (

Responsive Layout

Size: {windowSize.width}x{windowSize.height}

{isMobile &&

Mobile view

} {isTablet &&

Tablet view

} {isDesktop &&

Desktop view

}
) } /** * Example 5: Complete Dashboard with All Hooks * * Features: * - Command palette (Ctrl+K) * - Dropdown menus (click outside) * - Global hotkeys (save, search) * - Event listeners (resize, scroll) */ export function CompleteDashboardExample() { const [commandPaletteOpen, setCommandPaletteOpen] = useState(false) const [userMenuOpen, setUserMenuOpen] = useState(false) const [scrollPosition, setScrollPosition] = useState(0) const userMenuRef = useClickOutside({ onClickOutside: () => setUserMenuOpen(false), }) const { registerShortcut, unregister } = useKeyboardShortcuts() const hotkeys = useHotkeys() const { add } = useEventListener() useEffect(() => { // Command palette shortcut const cmdId = registerShortcut({ key: 'k', ctrl: true, onPress: () => setCommandPaletteOpen(true), preventDefault: true, }) // Close command palette with Escape const escapeId = registerShortcut({ key: 'Escape', onPress: () => setCommandPaletteOpen(false), }) return () => { unregister(cmdId) unregister(escapeId) } }, [registerShortcut, unregister]) useEffect(() => { // Global hotkeys for dashboard hotkeys.register('ctrl+s', () => { console.log('Saving dashboard...') }, { preventDefault: true }) hotkeys.register('ctrl+f', () => { console.log('Opening search...') }, { preventDefault: true }) return () => hotkeys.unregisterAll() }, [hotkeys]) useEffect(() => { // Track scroll position return add(window, 'scroll', (e: Event) => { setScrollPosition(window.scrollY) }, { passive: true, }) }, [add]) return (

Dashboard

{userMenuRef.isOpen && (
Profile
Settings
Logout
)}

Scroll position: {scrollPosition}

Try Ctrl+K for command palette, Ctrl+S to save

{commandPaletteOpen && (
)}
) } /** * Example 6: Custom Hook Composition * * Shows how to create a higher-level hook that combines * all 4 keyboard/event hooks for common patterns. */ export function useDialogWithShortcuts() { const [isOpen, setIsOpen] = useState(false) const { ref, isOpen: clickOutsideOpen, setIsOpen: setClickOutsideOpen } = useClickOutside({ onClickOutside: () => setIsOpen(false), }) const { registerShortcut, unregister } = useKeyboardShortcuts() useEffect(() => { if (!isOpen) return // Close with Escape const id = registerShortcut({ key: 'Escape', onPress: () => setIsOpen(false), }) return () => unregister(id) }, [isOpen, registerShortcut, unregister]) return { ref, isOpen, setIsOpen, } } // Usage of custom hook export function DialogWithShortcutsExample() { const dialog = useDialogWithShortcuts() return (
{dialog.isOpen && (

Dialog (Click outside or press Escape to close)

)}
) } /** * Example 7: Form with Save Hotkey * * Features: * - Auto-save on Ctrl+S * - Debounced keyboard input * - Click outside closes suggestions */ export function FormWithHotkeysExample() { const [formData, setFormData] = useState({ name: '', email: '' }) const [showSuggestions, setShowSuggestions] = useState(false) const suggestionsRef = useClickOutside({ onClickOutside: () => setShowSuggestions(false), }) const { registerShortcut, unregister } = useKeyboardShortcuts() const { add } = useEventListener() useEffect(() => { // Save with Ctrl+S const saveId = registerShortcut({ key: 's', ctrl: true, onPress: () => { console.log('Saving form:', formData) }, preventDefault: true, }) return () => unregister(saveId) }, [formData, registerShortcut, unregister]) useEffect(() => { // Listen for input changes to show suggestions const inputElement = document.getElementById('email-input') as HTMLInputElement if (!inputElement) return return add(inputElement, 'focus', () => { setShowSuggestions(true) }) }, [add]) return (
setFormData({ ...formData, name: e.target.value })} />
setFormData({ ...formData, email: e.target.value })} /> {showSuggestions && (
suggestion@example.com
user@example.com
)}
) }