feat: implement Figlet, Pastel, and Unit tools with a unified layout

- Add Figlet text converter with font selection and history
- Add Pastel color palette generator and manipulation suite
- Add comprehensive Units converter with category-based logic
- Introduce AppShell with Sidebar and Header for navigation
- Modernize theme system with CSS variables and new animations
- Update project configuration and dependencies
This commit is contained in:
2026-02-22 21:35:53 +01:00
parent ff6bb873eb
commit 2000623c67
540 changed files with 338653 additions and 809 deletions

View File

@@ -0,0 +1,106 @@
import { useEffect } from 'react';
export interface KeyboardShortcut {
key: string;
ctrl?: boolean;
shift?: boolean;
alt?: boolean;
meta?: boolean;
handler: (event: KeyboardEvent) => void;
description?: string;
}
/**
* Hook to register keyboard shortcuts
*
* @example
* ```tsx
* useKeyboard([
* {
* key: 'c',
* meta: true, // Cmd on Mac, Ctrl on Windows
* handler: () => copyToClipboard(),
* description: 'Copy color',
* },
* {
* key: 'k',
* meta: true,
* handler: () => openCommandPalette(),
* description: 'Open command palette',
* },
* ]);
* ```
*/
export function useKeyboard(shortcuts: KeyboardShortcut[]) {
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
for (const shortcut of shortcuts) {
const keyMatches = event.key.toLowerCase() === shortcut.key.toLowerCase();
// Check if required modifiers match (only check if explicitly required)
const ctrlMatches = shortcut.ctrl === true ? event.ctrlKey : true;
const shiftMatches = shortcut.shift === true ? event.shiftKey : true;
const altMatches = shortcut.alt === true ? event.altKey : true;
// Handle meta/cmd key with cross-platform support
let metaMatches = true;
if (shortcut.meta === true) {
// On Mac: require Cmd key
// On Windows/Linux: accept Ctrl key as Cmd equivalent
const isMac = navigator.platform.includes('Mac');
metaMatches = isMac ? event.metaKey : event.ctrlKey;
}
// Ensure unwanted modifiers are not pressed (unless explicitly required)
const noExtraCtrl = shortcut.ctrl === true || shortcut.meta === true || !event.ctrlKey;
const noExtraShift = shortcut.shift === true || !event.shiftKey;
const noExtraAlt = shortcut.alt === true || !event.altKey;
const noExtraMeta = shortcut.meta === true || !event.metaKey;
if (
keyMatches &&
ctrlMatches &&
shiftMatches &&
altMatches &&
metaMatches &&
noExtraCtrl &&
noExtraShift &&
noExtraAlt &&
noExtraMeta
) {
event.preventDefault();
shortcut.handler(event);
break;
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [shortcuts]);
}
/**
* Hook to register a single keyboard shortcut (convenience wrapper)
*/
export function useKeyboardShortcut(
key: string,
handler: (event: KeyboardEvent) => void,
modifiers?: {
ctrl?: boolean;
shift?: boolean;
alt?: boolean;
meta?: boolean;
}
) {
useKeyboard([
{
key,
...modifiers,
handler,
},
]);
}