UNPKG

react-keyhub

Version:

A lightweight, scalable keyboard shortcut manager for React applications with TypeScript support

3 lines (2 loc) 34.1 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o,n,r,s=t(e);exports.ShortcutScope=void 0,(o=exports.ShortcutScope||(exports.ShortcutScope={})).GLOBAL="global",o.LOCAL="local",exports.ShortcutStatus=void 0,(n=exports.ShortcutStatus||(exports.ShortcutStatus={})).ENABLED="enabled",n.DISABLED="disabled",exports.ShortcutType=void 0,(r=exports.ShortcutType||(exports.ShortcutType={})).REGULAR="regular",r.SEQUENCE="sequence";const c=e=>{if(!e)return"";if(e.includes(" "))return e.split(" ").map((e=>c(e))).join(" ");const t=e.toLowerCase().split("+"),o=t.filter((e=>["ctrl","control","alt","option","shift","meta","cmd","command","win","windows"].includes(e))).map((e=>"control"===e?"ctrl":"option"===e?"alt":["cmd","command","win","windows"].includes(e)?"meta":e)),n=t.filter((e=>!["ctrl","control","alt","option","shift","meta","cmd","command","win","windows"].includes(e))).map((e=>"space"===e?"space":"escape"===e?"esc":"arrowup"===e?"up":"arrowdown"===e?"down":"arrowleft"===e?"left":"arrowright"===e?"right":e));return[...Array.from(new Set(o)).sort(),...n].filter(Boolean).join("+")},u=e=>{const t=[];e.ctrlKey&&t.push("ctrl"),e.altKey&&t.push("alt"),e.shiftKey&&t.push("shift"),e.metaKey&&t.push("meta");const o=e.key.toLowerCase();let n=o;return" "===o&&(n="space"),"escape"===o&&(n="esc"),"arrowup"===o&&(n="up"),"arrowdown"===o&&(n="down"),"arrowleft"===o&&(n="left"),"arrowright"===o&&(n="right"),["control","ctrl","alt","shift","meta","command","cmd"].includes(o)?t.sort().join("+"):[...t.sort(),n].join("+")},h=(e,t)=>{let o=null;return function(...n){null!==o&&clearTimeout(o),o=setTimeout((()=>{o=null,e(...n)}),t)}},a=()=>Math.random().toString(36).substring(2,9),i={preventDefault:!0,stopPropagation:!0,target:"undefined"!=typeof document?document:void 0,debounceTime:0,sequenceTimeout:1e3,ignoreInputFields:!0,ignoreModifierOnlyEvents:!0};class l{constructor(e,t={}){this.activeContext=null,this.sequenceBuffer=[],this.sequenceTimer=null,this.paused=!1,this._shortcutIdToKeyCombo=null,this.shortcuts=e,this.subscriptions=new Map,this.shortcutIdToSubscriptions=new Map,this.options=Object.assign(Object.assign({},i),t),this.isListening=!1;const o=e=>{if(this.paused)return;const t=e;if(this.options.ignoreInputFields&&(t.target instanceof HTMLInputElement||t.target instanceof HTMLTextAreaElement||t.target instanceof HTMLElement&&t.target.isContentEditable))return;const o=u(t);this.options.ignoreModifierOnlyEvents&&["ctrl","alt","shift","meta","ctrl+alt","ctrl+shift","ctrl+meta","alt+shift","alt+meta","shift+meta"].includes(o)||(this.handleSequence(o,t),this.emit(o,t))};this.handleKeyDown=this.options.debounceTime>0?h(o,this.options.debounceTime):o,this.startListening()}startListening(){!this.isListening&&this.options.target&&(this.options.target.addEventListener("keydown",this.handleKeyDown),this.isListening=!0)}stopListening(){this.isListening&&this.options.target&&(this.options.target.removeEventListener("keydown",this.handleKeyDown),this.isListening=!1)}pause(){this.paused=!0}resume(){this.paused=!1}setContext(e){this.activeContext=e}getContext(){return this.activeContext}handleSequence(e,t){this.sequenceBuffer.push(e),this.sequenceTimer&&clearTimeout(this.sequenceTimer),this.sequenceTimer=setTimeout((()=>{this.sequenceBuffer=[]}),this.options.sequenceTimeout);const o=this.sequenceBuffer.join(" "),n=Object.entries(this.shortcuts).filter((([e,t])=>"sequence"===t.type&&t.sequence===o));n.length>0&&(n.forEach((([e,o])=>{if("disabled"===o.status)return;if(o.context&&this.activeContext!==o.context)return;this.options.preventDefault&&t.preventDefault(),this.options.stopPropagation&&t.stopPropagation();const n=this.shortcutIdToSubscriptions.get(e)||[];if(n.length>0){const e=n[0];try{e.callback(t)}catch(e){}}else if(o.action)try{o.action(t)}catch(e){}})),this.sequenceBuffer=[],this.sequenceTimer&&(clearTimeout(this.sequenceTimer),this.sequenceTimer=null))}on(e,t){const o=this.shortcuts[e];if(!o)return"test"===process.env.NODE_ENV&&console.warn(`Shortcut "${e}" is not defined`),"";const n="sequence"===o.type?e:o.keyCombo,r=c(n),s=a(),u={id:s,callback:t,priority:o.priority,shortcutId:e};this.subscriptions.has(r)||this.subscriptions.set(r,[]);const h=this.subscriptions.get(r);h.push(u),h.sort(((e,t)=>t.priority-e.priority)),this.shortcutIdToSubscriptions.has(e)||this.shortcutIdToSubscriptions.set(e,[]);const i=this.shortcutIdToSubscriptions.get(e);return i.push(u),i.sort(((e,t)=>t.priority-e.priority)),this._shortcutIdToKeyCombo=this._shortcutIdToKeyCombo||new Map,this._shortcutIdToKeyCombo.set(e,r),s}logSubscriptions(){}off(e){for(const[t,o]of this.subscriptions.entries()){const n=o.findIndex((t=>t.id===e));if(-1!==n){const e=[...o.slice(0,n),...o.slice(n+1)];this.subscriptions.set(t,e)}}for(const[t,o]of this.shortcutIdToSubscriptions.entries()){const n=o.findIndex((t=>t.id===e));if(-1!==n){const e=[...o.slice(0,n),...o.slice(n+1)];this.shortcutIdToSubscriptions.set(t,e);break}}}emit(e,t){const o=c(e),n=[...this.subscriptions.get(o)||[]];if(n.length>0){const e=n[0];this.options.preventDefault&&t.preventDefault(),this.options.stopPropagation&&t.stopPropagation();try{e.callback(t)}catch(e){}return}const r=Object.entries(this.shortcuts).filter((([e,t])=>{if("sequence"===t.type)return!1;return c(t.keyCombo)===o}));if(0!==r.length)for(const[e,o]of r){if("disabled"===o.status)continue;if(o.context&&this.activeContext!==o.context)continue;const n=this.shortcutIdToSubscriptions.get(e)||[];if(n.length>0){const e=n[0];this.options.preventDefault&&t.preventDefault(),this.options.stopPropagation&&t.stopPropagation();try{return void e.callback(t)}catch(e){}}if(o.action){this.options.preventDefault&&t.preventDefault(),this.options.stopPropagation&&t.stopPropagation();try{return void o.action(t)}catch(e){}}}}updateShortcut(e,t){if(!this.shortcuts[e])return void("test"===process.env.NODE_ENV&&console.warn(`Shortcut "${e}" is not defined`));const o=this.shortcuts[e];o.type,this.shortcuts[e]=Object.assign(Object.assign({},o),t)}registerShortcut(e,t){this.shortcuts[e]=t}unregisterShortcut(e){this.shortcuts[e]&&delete this.shortcuts[e]}enableShortcut(e){this.updateShortcut(e,{status:exports.ShortcutStatus.ENABLED})}disableShortcut(e){this.updateShortcut(e,{status:exports.ShortcutStatus.DISABLED})}getShortcuts(){return Object.assign({},this.shortcuts)}getShortcutsByGroup(e){return Object.entries(this.shortcuts).filter((([t,o])=>o.group===e)).reduce(((e,[t,o])=>(e[t]=o,e)),{})}getShortcutGroups(){const e=new Set;return Object.values(this.shortcuts).forEach((t=>{t.group&&e.add(t.group)})),Array.from(e)}destroy(){this.stopListening(),this.subscriptions.clear(),this.sequenceTimer&&(clearTimeout(this.sequenceTimer),this.sequenceTimer=null)}}const p={save:{keyCombo:"ctrl+s",name:"Save",description:"Save the current document",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"File",type:exports.ShortcutType.REGULAR},saveAs:{keyCombo:"ctrl+shift+s",name:"Save As",description:"Save the current document with a new name",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"File",type:exports.ShortcutType.REGULAR},print:{keyCombo:"ctrl+p",name:"Print",description:"Print the current document",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"File",type:exports.ShortcutType.REGULAR},newWindow:{keyCombo:"ctrl+shift+n",name:"New Window",description:"Open a new window or tab",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"File",type:exports.ShortcutType.REGULAR},find:{keyCombo:"ctrl+f",name:"Find",description:"Find text in the current document",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},replace:{keyCombo:"ctrl+h",name:"Replace",description:"Replace text in the current document",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},undo:{keyCombo:"ctrl+z",name:"Undo",description:"Undo the last action",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},redo:{keyCombo:"ctrl+y",name:"Redo",description:"Redo the last undone action",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},cut:{keyCombo:"ctrl+x",name:"Cut",description:"Cut the selected content to the clipboard",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},copy:{keyCombo:"ctrl+c",name:"Copy",description:"Copy the selected content to the clipboard",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},paste:{keyCombo:"ctrl+v",name:"Paste",description:"Paste content from the clipboard",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},selectAll:{keyCombo:"ctrl+a",name:"Select All",description:"Select all content in the current document",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Edit",type:exports.ShortcutType.REGULAR},goToLine:{keyCombo:"ctrl+g",name:"Go to Line",description:"Navigate to a specific line",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Navigation",type:exports.ShortcutType.REGULAR},goToFile:{keyCombo:"ctrl+p",name:"Go to File",description:"Navigate to a specific file",scope:exports.ShortcutScope.GLOBAL,priority:90,status:exports.ShortcutStatus.ENABLED,group:"Navigation",context:"editor",type:exports.ShortcutType.REGULAR},help:{keyCombo:"f1",name:"Help",description:"Show help information",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Help",type:exports.ShortcutType.REGULAR},showShortcuts:{keyCombo:"ctrl+/",name:"Show Shortcuts",description:"Show all available keyboard shortcuts",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Help",type:exports.ShortcutType.REGULAR},gitCommands:{sequence:"g c",name:"Git Commands",description:"Show git commands menu",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Git",type:exports.ShortcutType.SEQUENCE},gitStatus:{sequence:"g s",name:"Git Status",description:"Show git status",scope:exports.ShortcutScope.GLOBAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Git",type:exports.ShortcutType.SEQUENCE},vimUp:{keyCombo:"k",name:"Move Up",description:"Move cursor up",scope:exports.ShortcutScope.LOCAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Vim Navigation",context:"vim",type:exports.ShortcutType.REGULAR},vimDown:{keyCombo:"j",name:"Move Down",description:"Move cursor down",scope:exports.ShortcutScope.LOCAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Vim Navigation",context:"vim",type:exports.ShortcutType.REGULAR},vimLeft:{keyCombo:"h",name:"Move Left",description:"Move cursor left",scope:exports.ShortcutScope.LOCAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Vim Navigation",context:"vim",type:exports.ShortcutType.REGULAR},vimRight:{keyCombo:"l",name:"Move Right",description:"Move cursor right",scope:exports.ShortcutScope.LOCAL,priority:100,status:exports.ShortcutStatus.ENABLED,group:"Vim Navigation",context:"vim",type:exports.ShortcutType.REGULAR}},d=e.createContext(null),b=()=>{const t=e.useContext(d);if(!t)throw new Error("useKeyHub must be used within a KeyHubProvider");return t.eventBus},y=()=>{const t=e.useContext(d);if(!t)throw new Error("useKeyHubShortcuts must be used within a KeyHubProvider");return t.shortcuts},m=()=>b().getShortcuts(),k=()=>b().getShortcutGroups();function f(t,o){const n=b(),r=y(),s=e.useRef(!1),h=e.useRef(o);e.useEffect((()=>{h.current=o}),[o]);const a=e.useCallback((e=>{var o;const s=e;if(!n||n.paused)return;const a=r[t];if(!a)return;if("disabled"===a.status)return;const i=null===(o=n.getContext)||void 0===o?void 0:o.call(n);if(a.context&&i!==a.context)return;const l=u(s),p=c(l);let d=!1;if("regular"===a.type){d=c(a.keyCombo)===p}else if("sequence"===a.type)return;if(!d)return;const b=n.options;(null==b?void 0:b.preventDefault)&&s.preventDefault(),(null==b?void 0:b.stopPropagation)&&s.stopPropagation();try{h.current(s)}catch(e){}}),[n,t,r]);return e.useEffect((()=>{const e=null==n?void 0:n.options,o=null==e?void 0:e.target;if(n&&o)try{return s.current=t in r,s.current?(o.addEventListener("keydown",a),()=>{o.removeEventListener("keydown",a)}):void("test"===process.env.NODE_ENV&&console.warn(`Shortcut "${String(t)}" is not registered. Available shortcuts: ${Object.keys(r).join(", ")}`))}catch(e){return void(s.current=!1)}else s.current=!1}),[n,t,r,a]),s.current}const x=e=>e.split("+").map((e=>{const t=e.charAt(0).toUpperCase()+e.slice(1);switch(e.toLowerCase()){case"ctrl":return"Ctrl";case"alt":return"Alt";case"shift":return"Shift";case"meta":return navigator.platform.includes("Mac")?"⌘":"Win";case"esc":return"Esc";case"space":return"Space";default:return t}})).join(" + "),g=({children:e})=>s.default.createElement("kbd",{className:"keyhub-shortcut-sheet-key"},e),S=({shortcut:e})=>{if("sequence"===e.type){const t=e.sequence.split(" ");return s.default.createElement("div",{className:"keyhub-shortcut-sheet-key-combo"},t.map(((e,t)=>s.default.createElement(s.default.Fragment,{key:t},t>0&&s.default.createElement("span",{className:"keyhub-shortcut-sheet-key-then"},"then"),s.default.createElement(g,null,x(e))))))}const t=e.keyCombo.split("+");return s.default.createElement("div",{className:"keyhub-shortcut-sheet-key-combo"},t.map(((e,t)=>s.default.createElement(s.default.Fragment,{key:t},t>0&&s.default.createElement("span",{className:"keyhub-shortcut-sheet-key-plus"},"+"),s.default.createElement(g,null,x(e))))))};exports.EventBus=l,exports.KeyHubProvider=({shortcuts:t=p,options:o={},children:n})=>{const[r]=e.useState((()=>new l(t,o))),c={eventBus:r,shortcuts:t};return e.useEffect((()=>()=>{r.destroy()}),[r]),s.default.createElement(d.Provider,{value:c},n)},exports.ShortcutSheet=({isOpen:t,onClose:o,filter:n={},className:r="",theme:c="light",layout:u="modal"})=>{const h=m(),a=k(),[i,l]=e.useState(n.search||""),[p,d]=e.useState(n.scope||"all"),[b,y]=e.useState(n.group||"all"),[f,x]=e.useState(n.context||"all"),[g,E]=e.useState(a[0]||"all"),[v,w]=e.useState("light");e.useEffect((()=>{if("auto"===c){const e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches;w(e?"dark":"light");const t=window.matchMedia("(prefers-color-scheme: dark)"),o=e=>{w(e.matches?"dark":"light")};return t.addEventListener("change",o),()=>t.removeEventListener("change",o)}}),[c]);const L="auto"===c?v:c,C=e.useMemo((()=>{const e=new Set;return Object.values(h).forEach((t=>{t.context&&e.add(t.context)})),Array.from(e)}),[h]),A=e.useMemo((()=>Object.entries(h).filter((([e,t])=>{if("all"!==p&&t.scope!==p)return!1;if("all"!==b&&t.group!==b)return!1;if("all"!==f&&t.context!==f)return!1;if("all"!==g&&t.group!==g)return!1;const o=i.toLowerCase();return""===i||t.name.toLowerCase().includes(o)||t.description.toLowerCase().includes(o)||"regular"===t.type&&t.keyCombo.toLowerCase().includes(o)||"sequence"===t.type&&t.sequence.toLowerCase().includes(o)}))),[h,i,p,b,f,g]),N=e.useMemo((()=>{const e={};return A.forEach((t=>{const o=t[1].group||"Ungrouped";e[o]||(e[o]=[]),e[o].push(t)})),e}),[A]);return t?s.default.createElement("div",{className:`keyhub-shortcut-sheet keyhub-theme-${L} keyhub-layout-${u} ${r}`},s.default.createElement("div",{className:"keyhub-shortcut-sheet-overlay",onClick:o}),s.default.createElement("div",{className:"keyhub-shortcut-sheet-content"},s.default.createElement("div",{className:"keyhub-shortcut-sheet-header"},s.default.createElement("h2",null,"Keyboard Shortcuts"),s.default.createElement("button",{className:"keyhub-shortcut-sheet-close",onClick:o,"aria-label":"Close"},"×")),s.default.createElement("div",{className:"keyhub-shortcut-sheet-filters"},s.default.createElement("div",{className:"keyhub-shortcut-sheet-search-container"},s.default.createElement("input",{type:"text",placeholder:"Search shortcuts...",value:i,onChange:e=>l(e.target.value),className:"keyhub-shortcut-sheet-search"}),i&&s.default.createElement("button",{className:"keyhub-shortcut-sheet-search-clear",onClick:()=>l(""),"aria-label":"Clear search"},"×")),s.default.createElement("div",{className:"keyhub-shortcut-sheet-filter-controls"},s.default.createElement("select",{value:p,onChange:e=>d(e.target.value),className:"keyhub-shortcut-sheet-scope","aria-label":"Filter by scope"},s.default.createElement("option",{value:"all"},"All Scopes"),s.default.createElement("option",{value:"global"},"Global"),s.default.createElement("option",{value:"local"},"Local")),C.length>0&&s.default.createElement("select",{value:f,onChange:e=>x(e.target.value),className:"keyhub-shortcut-sheet-context","aria-label":"Filter by context"},s.default.createElement("option",{value:"all"},"All Contexts"),C.map((e=>s.default.createElement("option",{key:e,value:e},e)))))),a.length>0&&s.default.createElement("div",{className:"keyhub-shortcut-sheet-tabs"},s.default.createElement("button",{className:"keyhub-shortcut-sheet-tab "+("all"===g?"active":""),onClick:()=>E("all")},"All"),a.map((e=>s.default.createElement("button",{key:e,className:"keyhub-shortcut-sheet-tab "+(g===e?"active":""),onClick:()=>E(e)},e)))),s.default.createElement("div",{className:"keyhub-shortcut-sheet-list"},0===Object.keys(N).length?s.default.createElement("div",{className:"keyhub-shortcut-sheet-empty"},"No shortcuts found."):s.default.createElement("div",{className:"keyhub-shortcut-sheet-groups"},Object.entries(N).map((([e,t])=>s.default.createElement("div",{key:e,className:"keyhub-shortcut-sheet-group"},s.default.createElement("h3",{className:"keyhub-shortcut-sheet-group-title"},e),s.default.createElement("div",{className:"keyhub-shortcut-sheet-cards"},t.map((([e,t])=>s.default.createElement("div",{key:e,className:`keyhub-shortcut-sheet-card keyhub-shortcut-${t.status}`},s.default.createElement("div",{className:"keyhub-shortcut-sheet-card-header"},s.default.createElement("h4",{className:"keyhub-shortcut-sheet-card-title"},t.name),t.context&&s.default.createElement("span",{className:"keyhub-shortcut-sheet-card-context"},t.context)),s.default.createElement("div",{className:"keyhub-shortcut-sheet-card-description"},t.description),s.default.createElement("div",{className:"keyhub-shortcut-sheet-card-footer"},s.default.createElement(S,{shortcut:t}),s.default.createElement("span",{className:"keyhub-shortcut-sheet-card-scope"},t.scope))))))))))))):null},exports.ShortcutSheetStyles="\n.keyhub-shortcut-sheet {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 9999;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n}\n\n.keyhub-shortcut-sheet-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n transition: opacity 0.2s ease;\n}\n\n.keyhub-shortcut-sheet-content {\n position: relative;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 90%;\n max-width: 1000px;\n max-height: 100vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: keyhub-sheet-appear 0.2s ease;\n transition: transform 0.2s ease;\n}\n\n@keyframes keyhub-sheet-appear {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Light theme */\n.keyhub-theme-light .keyhub-shortcut-sheet-content {\n background-color: white;\n color: #333;\n}\n\n/* Dark theme */\n.keyhub-theme-dark .keyhub-shortcut-sheet-content {\n background-color: #1e1e1e;\n color: #eee;\n}\n\n/* Modal layout */\n.keyhub-layout-modal .keyhub-shortcut-sheet-content {\n width: 90%;\n max-width: 1000px;\n}\n\n/* Sidebar layout */\n.keyhub-layout-sidebar .keyhub-shortcut-sheet-content {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 450px;\n max-width: 90%;\n border-radius: 0;\n border-top-left-radius: 12px;\n border-bottom-left-radius: 12px;\n animation: keyhub-sheet-slide-in 0.3s ease;\n}\n\n@keyframes keyhub-sheet-slide-in {\n from {\n transform: translateX(100%);\n }\n to {\n transform: translateX(0);\n }\n}\n\n.keyhub-shortcut-sheet-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-header {\n border-color: #eee;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-header {\n border-color: #333;\n}\n\n.keyhub-shortcut-sheet-header h2 {\n margin: 0;\n font-size: 22px;\n font-weight: 600;\n}\n\n.keyhub-shortcut-sheet-close {\n background: none;\n border: none;\n font-size: 22px;\n cursor: pointer;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: all 0.2s;\n padding:0px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-close {\n color: #666;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-close:hover {\n background-color: #f0f0f0;\n color: #333;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-close {\n color: #aaa;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-close:hover {\n background-color: #333;\n color: #fff;\n}\n\n.keyhub-shortcut-sheet-filters {\n display: flex;\n flex-direction: column;\n padding: 16px 24px;\n gap: 12px;\n border-bottom: 1px solid;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-filters {\n border-color: #eee;\n background-color: #fafafa;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-filters {\n border-color: #333;\n background-color: #252525;\n}\n\n.keyhub-shortcut-sheet-search-container {\n position: relative;\n flex: 1;\n}\n\n.keyhub-shortcut-sheet-search {\n width: 100%;\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 15px;\n border: 1px solid;\n transition: all 0.2s;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-search {\n border-color: #ddd;\n background-color: white;\n color: #333;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-search:focus {\n border-color: #0066cc;\n box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2);\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-search {\n border-color: #444;\n background-color: #2a2a2a;\n color: #eee;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-search:focus {\n border-color: #4da3ff;\n box-shadow: 0 0 0 2px rgba(77, 163, 255, 0.2);\n}\n\n.keyhub-shortcut-sheet-search-clear {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n font-size: 18px;\n cursor: pointer;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: all 0.2s;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-search-clear {\n color: #999;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-search-clear:hover {\n background-color: #f0f0f0;\n color: #666;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-search-clear {\n color: #777;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-search-clear:hover {\n background-color: #444;\n color: #aaa;\n}\n\n.keyhub-shortcut-sheet-filter-controls {\n display: flex;\n gap: 12px;\n}\n\n.keyhub-shortcut-sheet-scope,\n.keyhub-shortcut-sheet-context {\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 14px;\n border: 1px solid;\n transition: all 0.2s;\n cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n padding-right: 32px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-scope,\n.keyhub-theme-light .keyhub-shortcut-sheet-context {\n border-color: #ddd;\n background-color: white;\n color: #333;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-scope:focus,\n.keyhub-theme-light .keyhub-shortcut-sheet-context:focus {\n border-color: #0066cc;\n box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2);\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-scope,\n.keyhub-theme-dark .keyhub-shortcut-sheet-context {\n border-color: #444;\n background-color: #2a2a2a;\n color: #eee;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-scope:focus,\n.keyhub-theme-dark .keyhub-shortcut-sheet-context:focus {\n border-color: #4da3ff;\n box-shadow: 0 0 0 2px rgba(77, 163, 255, 0.2);\n}\n\n.keyhub-shortcut-sheet-tabs {\n display: flex;\n overflow-x: auto;\n padding: 0 24px;\n border-bottom: 1px solid;\n scrollbar-width: thin;\n background-color: transparent;\n min-height: 45px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-tabs {\n border-color: #eee;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-tabs {\n border-color: #333;\n}\n\n.keyhub-shortcut-sheet-tab {\n padding: 14px 18px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: all 0.2s;\n border-radius:0px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-tab {\n color: #666;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-tab:hover:not(.active) {\n color: #333;\n background-color: #f5f5f5;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-tab {\n color: #aaa;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-tab:hover:not(.active) {\n color: #eee;\n background-color: #333;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-tab.active {\n color: #0066cc;\n border-color: #0066cc;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-tab.active {\n color: #4da3ff;\n border-color: #4da3ff;\n}\n\n.keyhub-shortcut-sheet-list {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px;\n}\n\n.keyhub-shortcut-sheet-empty {\n padding: 40px 24px;\n text-align: center;\n color: #999;\n font-size: 16px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n}\n\n.keyhub-shortcut-sheet-empty:before {\n content: \"🔍\";\n font-size: 32px;\n opacity: 0.7;\n}\n\n.keyhub-shortcut-sheet-groups {\n display: flex;\n flex-direction: column;\n gap: 28px;\n}\n\n.keyhub-shortcut-sheet-group-title {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n padding-bottom: 8px;\n border-bottom: 1px solid;\n display: flex;\n align-items: center;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-group-title {\n color: #444;\n border-color: #eee;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-group-title {\n color: #ddd;\n border-color: #333;\n}\n\n.keyhub-shortcut-sheet-cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n}\n\n.keyhub-shortcut-sheet-card {\n border-radius: 10px;\n padding: 18px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n border: 1px solid;\n transition: all 0.2s;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-card {\n border-color: #eee;\n background-color: #f9f9f9;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-card:hover {\n border-color: #ddd;\n background-color: #f5f5f5;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);\n transform: translateY(-2px);\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-card {\n border-color: #333;\n background-color: #252525;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-card:hover {\n border-color: #444;\n background-color: #2a2a2a;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transform: translateY(-2px);\n}\n\n.keyhub-shortcut-sheet-card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n}\n\n.keyhub-shortcut-sheet-card-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 1.3;\n}\n\n.keyhub-shortcut-sheet-card-context {\n font-size: 12px;\n padding: 3px 8px;\n border-radius: 12px;\n white-space: nowrap;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-card-context {\n background-color: #e0e0e0;\n color: #555;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-card-context {\n background-color: #444;\n color: #ccc;\n}\n\n.keyhub-shortcut-sheet-card-description {\n font-size: 14px;\n line-height: 1.5;\n flex-grow: 1;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-card-description {\n color: #666;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-card-description {\n color: #aaa;\n}\n\n.keyhub-shortcut-sheet-card-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 8px;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.keyhub-shortcut-sheet-card-scope {\n font-size: 12px;\n padding: 3px 8px;\n border-radius: 12px;\n text-transform: capitalize;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-card-scope {\n background-color: #e0e0e0;\n color: #555;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-card-scope {\n background-color: #444;\n color: #ccc;\n}\n\n.keyhub-shortcut-sheet-key-combo {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.keyhub-shortcut-sheet-key {\n font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;\n padding: 4px 8px;\n border-radius: 6px;\n font-size: 13px;\n min-width: 24px;\n text-align: center;\n border: 1px solid;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-key {\n background-color: white;\n border-color: #ddd;\n color: #333;\n box-shadow: 0 2px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-key {\n background-color: #333;\n border-color: #444;\n color: #eee;\n box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2), 0 1px 0 rgba(0, 0, 0, 0.2);\n}\n\n.keyhub-shortcut-sheet-key-plus,\n.keyhub-shortcut-sheet-key-then {\n font-size: 13px;\n font-weight: 500;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-key-plus,\n.keyhub-theme-light .keyhub-shortcut-sheet-key-then {\n color: #999;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-key-plus,\n.keyhub-theme-dark .keyhub-shortcut-sheet-key-then {\n color: #777;\n}\n\n.keyhub-shortcut-disabled {\n opacity: 0.6;\n}\n\n/* Scrollbar styling */\n.keyhub-shortcut-sheet-list::-webkit-scrollbar,\n.keyhub-shortcut-sheet-tabs::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-list::-webkit-scrollbar-track,\n.keyhub-theme-light .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-track {\n background: #f1f1f1;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-list::-webkit-scrollbar-thumb,\n.keyhub-theme-light .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 4px;\n}\n\n.keyhub-theme-light .keyhub-shortcut-sheet-list::-webkit-scrollbar-thumb:hover,\n.keyhub-theme-light .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-list::-webkit-scrollbar-track,\n.keyhub-theme-dark .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-track {\n background: #2a2a2a;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-list::-webkit-scrollbar-thumb,\n.keyhub-theme-dark .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-thumb {\n background: #444;\n border-radius: 4px;\n}\n\n.keyhub-theme-dark .keyhub-shortcut-sheet-list::-webkit-scrollbar-thumb:hover,\n.keyhub-theme-dark .keyhub-shortcut-sheet-tabs::-webkit-scrollbar-thumb:hover {\n background: #555;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .keyhub-shortcut-sheet-cards {\n grid-template-columns: 1fr;\n }\n \n .keyhub-shortcut-sheet-filter-controls {\n flex-direction: column;\n }\n \n .keyhub-layout-sidebar .keyhub-shortcut-sheet-content {\n width: 100%;\n max-width: 100%;\n border-radius: 0;\n }\n \n .keyhub-shortcut-sheet-header {\n padding: 16px 20px;\n }\n \n .keyhub-shortcut-sheet-list {\n padding: 16px 20px;\n }\n \n .keyhub-shortcut-sheet-card {\n padding: 16px;\n }\n}\n\n@media (max-width: 480px) {\n .keyhub-shortcut-sheet-header h2 {\n font-size: 18px;\n }\n \n .keyhub-shortcut-sheet-card-footer {\n flex-direction: column;\n align-items: flex-start;\n }\n}\n",exports.debounce=h,exports.defaultShortcuts=p,exports.eventToKeyCombo=u,exports.generateId=a,exports.getRegisteredShortcuts=function(){try{return y()}catch(e){return"test"===process.env.NODE_ENV&&console.warn("Unable to get registered shortcuts:",e),{}}},exports.normalizeKeyCombo=c,exports.useKey=f,exports.useKeyHub=b,exports.useKeyboardShortcut=f,exports.useShortcut=f,exports.useShortcutContext=t=>{const o=b();e.useEffect((()=>{o.setContext(t)}),[o,t])},exports.useShortcutGroups=k,exports.useShortcutPause=t=>{const o=b();e.useEffect((()=>{t?o.pause():o.resume()}),[o,t])},exports.useShortcutRegister=(t,o)=>{const n=b();e.useEffect((()=>(n.registerShortcut(t,o),()=>{n.unregisterShortcut(t)})),[n,t,o])},exports.useShortcutSheet=m,exports.useShortcutStatus=(t,o)=>{const n=b();e.useEffect((()=>{o?n.enableShortcut(t):n.disableShortcut(t)}),[n,t,o])},exports.useShortcutUpdate=(t,o)=>{const n=b();e.useEffect((()=>{n.updateShortcut(t,o)}),[n,t,o])},exports.useShortcutsByGroup=e=>b().getShortcutsByGroup(e); //# sourceMappingURL=index.js.map