UseKeypress
guarahooks/use-keypressFreeHook
Tracks keyboard combinations and key presses.
Install it
npx shadcn@latest add https://guarahooks.com/r/use-keypress.jsonSource
1'use client';23import { useCallback, useEffect, useMemo, useRef } from 'react';45interface UseKeyboardOptions {6 combo: string | string[];7 callback: (event: KeyboardEvent) => void;8 preventDefault?: boolean;9 target?: HTMLElement | null;10}1112function normalizeCombo(combo: string): string {13 const parts = combo14 .toLowerCase()15 .split('+')16 .map((p) => p.trim());1718 const modifiers = ['ctrl', 'alt', 'shift', 'meta'];19 const keys: string[] = [];20 const mods: string[] = [];2122 for (const part of parts) {23 if (modifiers.includes(part)) {24 mods.push(part);25 } else {26 keys.push(part);27 }28 }2930 // Sort modifiers for consistent comparison31 mods.sort((a, b) => modifiers.indexOf(a) - modifiers.indexOf(b));32 return [...mods, ...keys].join('+');33}3435function eventMatchesCombo(36 event: KeyboardEvent,37 normalizedCombo: string,38): boolean {39 const modifiers = ['ctrl', 'alt', 'shift', 'meta'];40 const eventMods = [41 event.ctrlKey ? 'ctrl' : null,42 event.altKey ? 'alt' : null,43 event.shiftKey ? 'shift' : null,44 event.metaKey ? 'meta' : null,45 ].filter(Boolean) as string[];4647 const key = event.key.toLowerCase();48 const comboParts = normalizedCombo.split('+');49 const comboMods = comboParts.filter((p) => modifiers.includes(p));50 const comboKey = comboParts.find((p) => !modifiers.includes(p));5152 // All modifiers in combo must be pressed53 if (comboMods.length !== eventMods.length) return false;5455 for (const mod of comboMods) {56 if (!eventMods.includes(mod)) return false;57 }5859 // Key must match60 return key === comboKey;61}6263export function useKeypress({64 combo,65 callback,66 preventDefault = false,67 target,68}: UseKeyboardOptions) {69 const callbackRef = useRef(callback);7071 useEffect(() => {72 callbackRef.current = callback;73 }, [callback]);7475 // Memoize normalized combos for performance76 const normalizedCombos = useMemo(() => {77 const combos = Array.isArray(combo) ? combo : [combo];78 return combos.map(normalizeCombo);79 }, [combo]);8081 // Memoize handler to avoid unnecessary re-attachments82 const handler = useCallback(83 (event: Event) => {84 const keyboardEvent = event as KeyboardEvent;85 for (const normCombo of normalizedCombos) {86 if (eventMatchesCombo(keyboardEvent, normCombo)) {87 if (preventDefault) keyboardEvent.preventDefault();88 callbackRef.current(keyboardEvent);89 break;90 }91 }92 },93 [normalizedCombos, preventDefault],94 );9596// … truncated
Files it writes
More from guarahooks
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| UseAbortControlleruse-abort-controller | guarahooks | Hooks | Free | no deps | |
| UseArrayStateuse-array-state | guarahooks | Hooks | Free | no deps | |
| UseAxiosuse-axios | guarahooks | Hooks | Free | no deps | |
| UseBatteryStatususe-battery-status | guarahooks | Hooks | Free | no deps | |
| UseBetterAuthuse-better-auth | guarahooks | Hooks | Free | no deps | |
| UseClickOutsideuse-click-outside | guarahooks | Hooks | Free | no deps | |
| UseConfirmuse-confirm | guarahooks | Hooks | Free | no deps | |
| UseCookieuse-cookie | guarahooks | Hooks | Free | no deps |
