@keybindy/react
Version:
Keybindy for React: Simple, scoped keyboard shortcuts that require little setup. designed to smoothly blend in with your React applications, allowing for robust keybinding functionality without the overhead.
164 lines (161 loc) • 5.19 kB
JavaScript
import React from 'react';
import ShortcutManager from '@keybindy/core';
let sharedInstance = null;
const getSharedInstance = (options) => {
if (typeof window === 'undefined') {
return null;
}
if (!sharedInstance) {
sharedInstance = new ShortcutManager(options);
}
return sharedInstance;
};
/**
* React hook to manage keyboard shortcuts using a shared instance of `ShortcutManager`.
* This hook is safe for server-side rendering (SSR) and will only initialize the manager on the client.
*
* @param {Object} config - Configuration object.
* @param {boolean} [config.logs=false] - Whether to enable debug logs in the console.
* @param {(info: Shortcut) => void} [config.onShortcutFired] - Callback for when a shortcut is fired.
*
* @returns {Object} Object containing shortcut management methods and the manager instance (null on server).
*/
const useKeybindy = ({ logs = false, onShortcutFired, } = {}) => {
const [manager, setManager] = React.useState(null);
React.useEffect(() => {
if (!manager) {
const instance = getSharedInstance({ onShortcutFired, silent: !logs });
setManager(instance);
}
}, []);
const log = (...args) => {
if (logs)
console.log('[Keybindy]', ...args);
};
const warn = (...args) => {
if (logs)
console.warn('[Keybindy]', ...args);
};
const register = React.useCallback((keys, handler, options) => {
if (!manager)
return;
if (keys.length === 0) {
warn('No keys provided to register');
return;
}
const id = options?.data?.id;
log('Registered:', id ?? keys);
manager.register(keys, handler, options);
}, [manager]);
const unregister = React.useCallback((keys, scope) => {
if (!manager)
return;
if (keys.length === 0) {
warn('No keys provided to unregister');
return;
}
manager.unregister(keys, scope);
log('Unregistered:', keys);
}, [manager]);
const enable = React.useCallback((keys, scope) => {
if (!manager)
return;
if (keys.length === 0) {
warn('No keys provided to enable');
return;
}
manager.enable(keys, scope);
log('Enabled:', keys);
}, [manager]);
const disable = React.useCallback((keys, scope) => {
if (!manager)
return;
if (keys.length === 0) {
warn('No keys provided to disable');
return;
}
manager.disable(keys, scope);
log('Disabled:', keys);
}, [manager]);
const toggle = React.useCallback((keys, scope) => {
if (!manager)
return;
if (keys.length === 0) {
warn('No keys provided to toggle');
return;
}
manager.toggle(keys, scope);
log('Toggled:', keys);
}, [manager]);
const getCheatSheet = React.useCallback((scope) => {
return manager?.getCheatSheet(scope);
}, [manager]);
const getActiveScope = React.useCallback(() => {
return manager?.getActiveScope();
}, [manager]);
const disableAll = React.useCallback((scope) => {
manager?.disableAll(scope);
log(`Disabled all shortcuts${scope ? ` in scope "${scope}"` : ''}`);
}, [manager]);
const enableAll = React.useCallback((scope) => {
manager?.enableAll(scope);
log(`Enabled all shortcuts${scope ? ` in scope "${scope}"` : ''}`);
}, [manager]);
const setScope = React.useCallback((scope) => {
manager?.setActiveScope(scope);
log('Scope set to:', scope);
}, [manager]);
const resetScope = React.useCallback(() => {
manager?.resetScope();
log('Reset scope');
}, [manager]);
const getScopes = React.useCallback(() => {
return manager?.getScopes();
}, [manager]);
const isScopeActive = React.useCallback((scope) => {
return manager?.isScopeActive(scope);
}, [manager]);
const onTyping = React.useCallback((callback) => {
manager?.onTyping(callback);
}, [manager]);
const popScope = React.useCallback(() => {
manager?.popScope();
log('Popped scope, active scope is:', manager?.getActiveScope());
}, [manager]);
const pushScope = React.useCallback((scope) => {
manager?.pushScope(scope);
log('Pushed scope:', scope);
}, [manager]);
const getScopeInfo = React.useCallback((scope) => {
return manager?.getScopesInfo(scope);
}, [manager]);
const destroy = () => {
manager?.destroy();
};
const clear = () => {
manager?.clear();
};
return {
register,
unregister,
enable,
disable,
toggle,
setScope,
getCheatSheet,
destroy,
getScopeInfo,
getActiveScope,
popScope,
pushScope,
resetScope,
getScopes,
isScopeActive,
onTyping,
enableAll,
clear,
disableAll,
manager,
};
};
export { useKeybindy };