diff --git a/package.json b/package.json index 2dbe25d..d1a8374 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "sass-embedded": "1.85.1", "uuid": "11.1.0", "vue": "3.5.13", - "wrdu-keyboard": "github:0PandaDEV/keyboard" + "@waradu/keyboard": "4.2.0" }, "overrides": { "chokidar": "^3.6.0" diff --git a/pages/index.vue b/pages/index.vue index 774b0a0..ddce6ca 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,41 +1,68 @@ diff --git a/plugins/keyboard.ts b/plugins/keyboard.ts index 17e8d63..dfc7d44 100644 --- a/plugins/keyboard.ts +++ b/plugins/keyboard.ts @@ -1,281 +1,27 @@ -import { Key, keyboard } from "wrdu-keyboard"; import { platform } from "@tauri-apps/plugin-os"; - -type KeyboardHandler = (event: KeyboardEvent) => void; - -const activeContexts = new Set(); -const handlersByContext: Record< - string, - Array<{ - keys: Key[]; - callback: KeyboardHandler; - prevent: boolean; - priority?: number; - }> -> = {}; - -const PRIORITY = { - HIGH: 100, - MEDIUM: 50, - LOW: 0, -}; - -let currentOS = "windows"; - -const useKeyboard = { - PRIORITY, - - registerContext: (contextName: string) => { - if (!handlersByContext[contextName]) { - handlersByContext[contextName] = []; - } - }, - - enableContext: (contextName: string) => { - if (!handlersByContext[contextName]) { - useKeyboard.registerContext(contextName); - } - activeContexts.add(contextName); - - initKeyboardHandlers(); - }, - - disableContext: (contextName: string) => { - activeContexts.delete(contextName); - - initKeyboardHandlers(); - }, - - on: ( - contextName: string, - keys: Key[], - callback: KeyboardHandler, - options: { prevent?: boolean; priority?: number } = {} - ) => { - if (!handlersByContext[contextName]) { - useKeyboard.registerContext(contextName); - } - - const existingHandlerIndex = handlersByContext[contextName].findIndex( - (handler) => - handler.keys.length === keys.length && - handler.keys.every((key, i) => key === keys[i]) && - handler.callback.toString() === callback.toString() - ); - - if (existingHandlerIndex !== -1) { - handlersByContext[contextName][existingHandlerIndex] = { - keys, - callback, - prevent: options.prevent ?? true, - priority: options.priority ?? PRIORITY.LOW, - }; - } else { - handlersByContext[contextName].push({ - keys, - callback, - prevent: options.prevent ?? true, - priority: options.priority ?? PRIORITY.LOW, - }); - } - - if (activeContexts.has(contextName)) { - initKeyboardHandlers(); - } - }, - - clearAll: () => { - keyboard.clear(); - }, - - setupAppShortcuts: (options: { - onNavigateUp?: () => void; - onNavigateDown?: () => void; - onSelect?: () => void; - onEscape?: () => void; - onToggleActions?: () => void; - contextName?: string; - priority?: number; - }) => { - const { - onNavigateUp, - onNavigateDown, - onSelect, - onEscape, - onToggleActions, - contextName = "app", - priority = PRIORITY.LOW, - } = options; - - if (!handlersByContext[contextName]) { - useKeyboard.registerContext(contextName); - } - - if (onNavigateUp) { - useKeyboard.on(contextName, [Key.UpArrow], () => onNavigateUp(), { - priority, - }); - } - - if (onNavigateDown) { - useKeyboard.on(contextName, [Key.DownArrow], () => onNavigateDown(), { - priority, - }); - } - - if (onSelect) { - useKeyboard.on(contextName, [Key.Enter], () => onSelect(), { priority }); - } - - if (onEscape) { - useKeyboard.on(contextName, [Key.Escape], () => onEscape(), { priority }); - } - - if (onToggleActions) { - const togglePriority = Math.max(priority, PRIORITY.HIGH); - - if (currentOS === "macos") { - useKeyboard.on( - contextName, - [Key.LeftMeta, Key.K], - () => onToggleActions(), - { priority: togglePriority } - ); - useKeyboard.on( - contextName, - [Key.RightMeta, Key.K], - () => onToggleActions(), - { priority: togglePriority } - ); - } else { - useKeyboard.on( - contextName, - [Key.LeftControl, Key.K], - () => onToggleActions(), - { priority: togglePriority } - ); - useKeyboard.on( - contextName, - [Key.RightControl, Key.K], - () => onToggleActions(), - { priority: togglePriority } - ); - } - } - }, - - setupKeybindCapture: (options: { - onCapture: (key: string) => void; - onComplete: () => void; - }) => { - const { onCapture, onComplete } = options; - - keyboard.prevent.down([Key.All], (event: KeyboardEvent) => { - if (event.code === "Escape") { - onComplete(); - return; - } - onCapture(event.code); - }); - }, -}; - -const initKeyboardHandlers = () => { - keyboard.clear(); - - let allHandlers: Array<{ - keys: Key[]; - callback: KeyboardHandler; - prevent: boolean; - priority: number; - contextName: string; - }> = []; - - for (const contextName of activeContexts) { - const handlers = handlersByContext[contextName] || []; - allHandlers = [ - ...allHandlers, - ...handlers.map((handler) => ({ - ...handler, - priority: handler.priority ?? PRIORITY.LOW, - contextName, - })), - ]; - } - - allHandlers.sort((a, b) => b.priority - a.priority); - - const handlersByKeyCombination: Record< - string, - Array<(typeof allHandlers)[0]> - > = {}; - - allHandlers.forEach((handler) => { - const keyCombo = handler.keys.sort().join("+"); - if (!handlersByKeyCombination[keyCombo]) { - handlersByKeyCombination[keyCombo] = []; - } - handlersByKeyCombination[keyCombo].push(handler); - }); - - Object.entries(handlersByKeyCombination).forEach(([_keyCombo, handlers]) => { - handlers.sort((a, b) => b.priority - a.priority); - const handler = handlers[0]; - - const wrappedCallback: KeyboardHandler = (event) => { - const isMetaCombo = - handler.keys.length > 1 && - (handler.keys.includes(Key.LeftMeta) || - handler.keys.includes(Key.RightMeta) || - handler.keys.includes(Key.LeftControl) || - handler.keys.includes(Key.RightControl)); - - const isNavigationKey = - event.key === "ArrowUp" || - event.key === "ArrowDown" || - event.key === "Enter" || - event.key === "Escape"; - - const isInInput = - event.target instanceof HTMLInputElement || - event.target instanceof HTMLTextAreaElement; - - if ( - (isMetaCombo || isNavigationKey || !isInInput) && - activeContexts.has(handler.contextName) - ) { - handler.callback(event); - } - }; - - if (handler.prevent) { - keyboard.prevent.down(handler.keys, wrappedCallback); - } else { - keyboard.down(handler.keys, wrappedCallback); - } - }); -}; +import { useKeyboard, Key } from "@waradu/keyboard"; export default defineNuxtPlugin(async (nuxtApp) => { + const keyboardInstance = useKeyboard(); + let currentOS = "windows"; try { - const osName = platform(); + const osName = await Promise.resolve(platform()); currentOS = osName.toLowerCase().includes("mac") ? "macos" : "windows"; } catch (error) { console.error("Error detecting platform:", error); } - initKeyboardHandlers(); - - nuxtApp.hook("page:finish", () => { - initKeyboardHandlers(); + // Defer initialization until the app is mounted + nuxtApp.hook('app:mounted', () => { + keyboardInstance.init(); }); - return { - provide: { - keyboard: { - ...useKeyboard, - Key, - }, - }, - }; + nuxtApp.provide('keyboard', { + listen: keyboardInstance.listen.bind(keyboardInstance), + init: keyboardInstance.init.bind(keyboardInstance), + Key, + currentOS, + // Provide a clear method if users need to manually clear all listeners from the instance + clearAll: keyboardInstance.clear ? keyboardInstance.clear.bind(keyboardInstance) : () => { console.warn('@waradu/keyboard instance does not have a clear method'); } + }); }); diff --git a/types/keyboard.d.ts b/types/keyboard.d.ts new file mode 100644 index 0000000..62d26e4 --- /dev/null +++ b/types/keyboard.d.ts @@ -0,0 +1,27 @@ +import type { Key as WaraduKey, useKeyboard } from '@waradu/keyboard'; + +declare module '#app' { + interface NuxtApp { + $keyboard: { + listen: ReturnType['listen']; + init: ReturnType['init']; + Key: typeof WaraduKey; + currentOS: string; + clearAll: () => void; + }; + } +} + +declare module 'vue' { + interface ComponentCustomProperties { + $keyboard: { + listen: ReturnType['listen']; + init: ReturnType['init']; + Key: typeof WaraduKey; + currentOS: string; + clearAll: () => void; + }; + } +} + +export {}; \ No newline at end of file