### JavaScript Hotkey Installation Example Source: https://github.com/github/hotkey/blob/main/_autodocs/ARCHITECTURE.md Shows how to programmatically install hotkeys by iterating over elements with 'data-hotkey' attributes and calling the 'install' function. ```javascript import {install} from '@github/hotkey' for (const el of document.querySelectorAll('[data-hotkey]')) { install(el) // OR install(el, 'custom-hotkey') } ``` -------------------------------- ### Install Hotkey Library Source: https://github.com/github/hotkey/blob/main/pages/demo.html Import and install the hotkey library for all elements with a 'data-hotkey' attribute. This is the primary setup for using hotkeys on the page. ```javascript import {install} from './hotkey/index.js' for (const el of document.querySelectorAll('\\[data-hotkey\\]')) { install(el) } ``` -------------------------------- ### Install and Test Project Source: https://github.com/github/hotkey/blob/main/README.md Standard npm commands for installing dependencies and running tests for the project. ```bash npm install ``` ```bash npm test ``` -------------------------------- ### install() Source: https://github.com/github/hotkey/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt Installs the hotkey listener globally. This function sets up the necessary event listeners to capture keyboard events and trigger hotkey actions. ```APIDOC ## install() ### Description Installs the hotkey listener globally, enabling the capture of keyboard events for hotkey functionality. ### Method `install()` ### Parameters This function does not accept any parameters. ### Return Type `void` ### Throws This function does not explicitly throw errors, but underlying event listener setup might fail in rare cases. ### Examples ```javascript import { install } from '@github/hotkey'; install(); // Hotkeys are now active globally. ``` ### Source File `api-reference/install.md` (218 lines) ``` -------------------------------- ### JavaScript Installation for Scoped Hotkeys Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Installs hotkey elements. The order of installation and focus state affects which hotkey is triggered first. ```javascript install(document.getElementById('global-save')) install(document.getElementById('editor-save')) // User presses Mod+s while focused on textarea: // → global-save button's click() is triggered first (if it's higher in DOM tree) // → User must blur textarea for editor-save to take precedence ``` -------------------------------- ### Install Hotkey Programmatically Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Demonstrates how to use the `install` function to programmatically register hotkeys on HTML elements, either by reading the `data-hotkey` attribute or by providing a custom hotkey string. ```typescript // Use data-hotkey attribute const button = document.querySelector('[data-hotkey="j"]') install(button) // Override with custom hotkey const button2 = document.querySelector('#my-button') install(button2, 'Mod+k') // Use with aliased hotkeys const button3 = document.querySelector('#search') install(button3, 's,/') ``` -------------------------------- ### Install Hotkeys with Custom Attribute Source: https://github.com/github/hotkey/blob/main/README.md Installs hotkeys by passing the hotkey string directly to the `install` function, using a custom data attribute like `data-shortcut`. ```javascript for (const el of document.querySelectorAll('[data-shortcut]')) { install(el, el.dataset.shortcut) } ``` -------------------------------- ### Install Hotkeys from HTML Attributes Source: https://github.com/github/hotkey/blob/main/README.md Installs all hotkeys defined by the `data-hotkey` attribute on the page. This is the default behavior for elements. ```javascript import {install} from '@github/hotkey' // Install all the hotkeys on the page for (const el of document.querySelectorAll('[data-hotkey]')) { install(el) } ``` -------------------------------- ### Install Hotkey Programmatically Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/install.md Install a hotkey listener by programmatically specifying the hotkey string. This is useful when the hotkey is not defined in HTML. ```typescript const button = document.getElementById('my-button') install(button, 'Control+s') ``` -------------------------------- ### RadixTrie get() Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Shows how to retrieve a child node using the 'get' method after a path has been inserted. ```typescript const trie = new RadixTrie() // After inserting ['a', 'b'] const node = trie.get('a') ``` -------------------------------- ### Single Key Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md A simple example of a data-hotkey attribute with a single key. ```html ``` -------------------------------- ### Key Sequence Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Shows how to define a key sequence using space-separated keys in the data-hotkey attribute. ```html Code ``` -------------------------------- ### NormalizedSequenceString Examples Source: https://github.com/github/hotkey/blob/main/_autodocs/types.md Demonstrates different NormalizedSequenceString formats, including single keys, two-key sequences, and sequences with modifiers. Examples include common GitHub navigation shortcuts. ```typescript const sequences: NormalizedSequenceString[] = [ 's', // Single key 'g i', // Two-key sequence 'Control+k', // Single key with modifier 'Mod+m Control+j', // Multiple hotkeys with modifiers 'g c', // Common GitHub sequence (navigate to code) 'g i', // Common GitHub sequence (navigate to issues) 'Control+Shift+x a' // Three hotkeys ] ``` -------------------------------- ### RadixTrie Constructor Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Demonstrates creating a new RadixTrie instance and setting its parent. ```typescript const root = new RadixTrie() const child = new RadixTrie(root) // child's parent is root ``` -------------------------------- ### Scoped and Global Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md This example shows a button scoped to a textarea and another global button, both responding to the same hotkey. The scoped button only fires when the textarea is focused. ```html ``` -------------------------------- ### Batch Installation of Hotkeys Source: https://github.com/github/hotkey/blob/main/_autodocs/README.md Installs hotkeys declared via the 'data-hotkey' attribute on multiple elements. Ensure elements have the 'data-hotkey' attribute. ```typescript for (const element of document.querySelectorAll('[data-hotkey]')) { install(element) } ``` -------------------------------- ### install() Source: https://github.com/github/hotkey/blob/main/_autodocs/MODULE_INDEX.md Register a hotkey on an HTML element. This function is part of the main entry point and allows users to associate a hotkey with a specific HTML element. ```APIDOC ## install() ### Description Register a hotkey on an HTML element. ### Signature `(element: HTMLElement, hotkey?: string) => void` ### Parameters #### Path Parameters - **element** (HTMLElement) - Required - The HTML element to register the hotkey on. - **hotkey** (string) - Optional - The hotkey string to register. ``` -------------------------------- ### Basic Syntax: Single Keys Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Examples of defining single keys as hotkeys, including named keys like 'Enter'. ```plaintext j // The 'j' key k // The 'k' key ? // Shift+/ (you type the shift-produced symbol) Enter // Named keys from KeyboardEvent.key ``` -------------------------------- ### Hotkey Input Examples Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Shows various input hotkey strings and their corresponding behavior, including single keys, sequences, and modifier combinations. ```text s | Press 's' | s,/ | Press 's' OR '/' | g c | Press 'g', then 'c' | g c,g i | Press 'g c' OR 'g i' | Control+s | Hold Control, press 's' | Mod+s | Platform modifier + 's' | Control+Shift+a | Hold Control and Shift, press 'a' | Control+Shift+? | Hold Control and Shift, press '/' (which produces '?') | Control+,,x | Hold Control and press ',' OR press 'x' ``` -------------------------------- ### Leaf Constructor Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/Leaf.md Demonstrates the instantiation of a Leaf node and verifies its parent reference. ```typescript const parentNode = new RadixTrie() const leaf = new Leaf(parentNode) console.log(leaf.parent === parentNode) // true ``` -------------------------------- ### Override data-hotkey with install() Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Demonstrates how to programmatically override a data-hotkey attribute by providing a hotkey string as the second argument to the install() function. ```typescript const button = document.getElementById('my-button') // Ignores data-hotkey attribute, uses 's' instead install(button, 's') ``` -------------------------------- ### Usage of expandHotkeyToEdges in Library Install Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/utilities.md Shows how `expandHotkeyToEdges` is used within the library's `install` function to process hotkey strings from elements or attributes, preparing them for insertion into a trie. ```typescript function install(element: HTMLElement, hotkey?: string): void { const hotkeys = expandHotkeyToEdges(hotkey || element.getAttribute('data-hotkey') || '') // hotkeys is an array of sequences, e.g., [['g', 'i'], ['g', 'c']] const leaves = hotkeys.map(h => (hotkeyRadixTrie.insert(h) as Leaf).add(element) ) } ``` -------------------------------- ### Install Hotkey with HTML Attribute Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/install.md Use this snippet to install a hotkey listener using the data-hotkey attribute on an element. Ensure the element has the attribute defined. ```typescript const button = document.querySelector('[data-hotkey]') install(button) ``` ```html ``` -------------------------------- ### Multiple Aliases Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Demonstrates using comma-separated values in data-hotkey to define multiple aliases for a single action. ```html Search ``` -------------------------------- ### install() Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/install.md Registers a hotkey listener on an HTML element. When the hotkey is pressed, the element receives a `hotkey-fire` event and then either calls `focus()` (for form fields) or `click()` (for other elements). ```APIDOC ## install(element: HTMLElement, hotkey?: string): void ### Description Registers a hotkey listener on an HTML element. When the hotkey is pressed, the element receives a `hotkey-fire` event and then either calls `focus()` (for form fields) or `click()` (for other elements). ### Parameters #### Path Parameters - **element** (HTMLElement) - Required - The DOM element to attach the hotkey to - **hotkey** (string) - Optional - Optional hotkey string to override the `data-hotkey` attribute. If omitted, reads from element's `data-hotkey` attribute ### Return Value Returns `undefined`. The function registers event handlers globally on first call and attaches metadata to the element. ### Behavior - On the first call to `install`, registers a `keydown` event listener on the `document` - Parses the hotkey string into individual hotkey sequences using `expandHotkeyToEdges` - Inserts each hotkey edge sequence into the global `RadixTrie` and stores leaf node references in a `WeakMap` keyed by the element - Form fields (input, textarea, select) and elements with `contenteditable` trigger `focus()` when hotkey fires - All other elements trigger `click()` - All elements emit a cancellable `hotkey-fire` custom event before the action (focus/click) is executed - If the event is prevented, the action is skipped ### Events Fired The element will dispatch a custom `hotkey-fire` event with the following properties: - `detail.path`: Array of normalized hotkey strings that were pressed (e.g., `['Control+s']` or `['g', 'i']` for sequences) - `cancelable: true` — calling `preventDefault()` on this event prevents the default action (focus/click) ### Examples #### Basic HTML attribute usage ```typescript const button = document.querySelector('[data-hotkey]') install(button) ``` ```html ``` #### Programmatic hotkey specification ```typescript const button = document.getElementById('my-button') install(button, 'Control+s') ``` #### Custom behavior with hotkey-fire event ```typescript const button = document.getElementById('custom-button') install(button, 'Mod+e') button.addEventListener('hotkey-fire', (event) => { event.preventDefault() // prevent the default click() console.log('Custom behavior triggered by:', event.detail.path) }) ``` #### Multiple hotkey aliases ```typescript const searchButton = document.getElementById('search') install(searchButton, 's,/') // triggers on 's' or '/' ``` #### Key sequences ```typescript const newIssueButton = document.getElementById('new-issue') install(newIssueButton, 'g i') // triggers on 'g' followed by 'i' ``` #### Scoped hotkeys (form field specific) ```html ``` When the hotkey is scoped to a form field, it only activates when that specific form field is focused. ### Form Field Behavior The function automatically detects form fields using `isFormField` and calls `focus()` instead of `click()`. Form fields include: - `` elements (except type `submit`, `reset`, `checkbox`, `radio`, `file`) - ` ``` -------------------------------- ### Scope Interaction Example Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Demonstrates global and scoped hotkeys. The scoped hotkey only works when the specified element is focused. ```html ``` -------------------------------- ### RadixTrie insert() Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Demonstrates inserting various key sequences into a RadixTrie, illustrating how intermediate nodes are created or reused and how terminal leaves are formed. ```typescript const trie = new RadixTrie() // Insert a two-key sequence const leaf1 = trie.insert(['g', 'i']) // path: g → i (Leaf) // Insert a single key const leaf2 = trie.insert(['s']) // path: s (Leaf) // Insert another sequence starting with 'g' const leaf3 = trie.insert(['g', 'c']) // path: g → c (Leaf) // The 'g' node was already a RadixTrie, so this just adds a new child // Now trie structure: // root // ├─ 'g' (RadixTrie) // │ ├─ 'i' (Leaf) // │ └─ 'c' (Leaf) // └─ 's' (Leaf) ``` -------------------------------- ### SequenceTrackerOptions Interface Example Source: https://github.com/github/hotkey/blob/main/_autodocs/types.md Shows how to configure a SequenceTracker with an optional onReset callback. This callback is invoked when the sequence times out due to inactivity. ```typescript const tracker = new SequenceTracker({ onReset() { console.log('Sequence timed out') // Reset UI state, show help, etc. } }) ``` -------------------------------- ### RadixTrie Structure Example Source: https://github.com/github/hotkey/blob/main/_autodocs/ARCHITECTURE.md Illustrates the hierarchical structure of the RadixTrie used for storing hotkey mappings, showing intermediate RadixTrie nodes and terminal Leaf nodes. ```text Root ├─ 's' (Leaf) → [button#search] ├─ 'g' (RadixTrie) │ ├─ 'i' (Leaf) → [a#navigate-issues] │ └─ 'c' (Leaf) → [a#navigate-code] └─ 'j' (Leaf) → [a#next-page] ``` -------------------------------- ### Remapping Hotkeys at Runtime Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Remap a hotkey by uninstalling the old one and installing the new one for the specified element. ```javascript function remapHotkey(element, newHotkey) { uninstall(element) install(element, newHotkey) } const saveButton = document.getElementById('save') remapHotkey(saveButton, 'Mod+e') // Changed from Mod+s to Mod+e ``` -------------------------------- ### Initialize Hotkey Mapper and Event Listeners Source: https://github.com/github/hotkey/blob/main/pages/hotkey_mapper.html Sets up the SequenceTracker, gets references to DOM elements, and attaches event listeners for keydown, keyup, and reset actions to capture and display hotkey sequences. ```javascript import {eventToHotkeyString} from './hotkey/index.js' import {SEQUENCE_DELIMITER, SequenceTracker} from './hotkey/sequence.js' const userAgentElement = document.getElementById('user-agent') userAgentElement.textContent = navigator.userAgent const hotkeyCodeElement = document.getElementById('hotkey-code') const sequenceStatusElement = document.getElementById('sequence-status') const resetButtonElement = document.getElementById('reset-button') const sequenceTracker = new SequenceTracker({ onReset() { sequenceStatusElement.hidden = true } }) const modifierKeyNames = ['Alt', 'Control', 'Meta', 'Shift'] // we only want to add lone modifier keys to the sequence if they are lifted without pressing another key // otherwise, the chord Control+f would become "Control Control+f". But we do want to be able to display sequences // like "Control f", which is pressing and releasing control, then f. let lastKeyDownModifierEvent = null const registerEvent = event => { sequenceTracker.registerKeypress(event) sequenceStatusElement.hidden = false event.target.value = sequenceTracker.path.join(SEQUENCE_DELIMITER) } hotkeyCodeElement.addEventListener('keydown', event => { lastKeyDownModifierEvent = null // always leave Tab alone so focus can leave the input if (event.key === 'Tab') return event.preventDefault() event.stopPropagation() if (modifierKeyNames.includes(event.key)) { lastKeyDownModifierEvent = event return } registerEvent(event) }) hotkeyCodeElement.addEventListener('keyup', () => { // we still have to use the keydown event, not the keyup event, because the keyup event won't have the modifier // properties (ie, `ctrlKey` will be false). if (lastKeyDownModifierEvent) registerEvent(lastKeyDownModifierEvent) }) resetButtonElement.addEventListener('click', () => { sequenceTracker.reset() hotkeyCodeElement.value = '' }) ``` -------------------------------- ### Leaf Add Method Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/Leaf.md Shows how to add elements to a leaf and use method chaining. Verifies the number and identity of children. ```typescript const leaf = new Leaf(parentNode) const button = document.getElementById('my-button') // Method chaining leaf.add(button).add(anotherButton) // Verify the children console.log(leaf.children.length) // 2 console.log(leaf.children[0] === button) // true ``` -------------------------------- ### Modifiers Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Illustrates using modifier keys like Control, Alt, and Meta with a specific key in the data-hotkey attribute. ```html Help ``` -------------------------------- ### uninstall() Source: https://github.com/github/hotkey/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt Uninstalls the global hotkey listener. This function removes all event listeners set up by `install()`, effectively disabling hotkey functionality. ```APIDOC ## uninstall() ### Description Uninstalls the global hotkey listener, disabling all previously registered hotkey actions. ### Method `uninstall()` ### Parameters This function does not accept any parameters. ### Return Type `void` ### Throws This function does not explicitly throw errors. ### Examples ```javascript import { uninstall } from '@github/hotkey'; uninstall(); // Hotkeys are no longer active. ``` ### Source File `api-reference/uninstall.md` (205 lines) ``` -------------------------------- ### Hotkey String Normalization Example Source: https://github.com/github/hotkey/blob/main/_autodocs/ARCHITECTURE.md Illustrates the input and expected output of hotkey string normalization, which ensures consistent comparison across different user inputs and platforms by localizing 'Mod' and sorting modifiers. ```plaintext Input: User-provided or HTML-defined hotkey string 'Shift+Mod+s' (in any order, might have Mod) 'Control+Shift+Alt+x' (modifiers in any order) Output: Normalized hotkey string 'Meta+Shift+s' (on macOS) 'Control+Shift+s' (on Windows) 'Control+Alt+Shift+x' (consistent order) ``` -------------------------------- ### Install Hotkey with Multiple Aliases Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/install.md Assign multiple hotkey aliases to a single element. The listener will trigger if any of the specified hotkeys are pressed. ```typescript const searchButton = document.getElementById('search') install(searchButton, 's,/') // triggers on 's' or '/' ``` -------------------------------- ### SequenceTracker State Example Source: https://github.com/github/hotkey/blob/main/_autodocs/ARCHITECTURE.md Shows the internal state of the SequenceTracker, including the current path of pressed keys and the space-separated sequence string. ```typescript tracker.path // ['g', 'i'] after pressing g then i tracker.sequence // 'g i' (space-separated) ``` -------------------------------- ### Runtime Keydown Event Handling Example Source: https://github.com/github/hotkey/blob/main/_autodocs/ARCHITECTURE.md Illustrates the process of handling a 'keydown' event, including converting the event to a hotkey string, trie lookup, and sequence tracking. ```typescript document.addEventListener('keydown', keyDownHandler) ``` -------------------------------- ### NormalizedHotkeyString Examples Source: https://github.com/github/hotkey/blob/main/_autodocs/types.md Illustrates various valid NormalizedHotkeyString formats, including single keys, keys with modifiers, and special keys like arrow keys and space. ```typescript const hotkeys: NormalizedHotkeyString[] = [ 's', 'Control+s', 'Alt+Delete', 'Control+Alt+Shift+x', 'Meta+Shift+A', 'ArrowUp', 'Space', 'Plus' ] ``` -------------------------------- ### CustomEvent Dispatch Example Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Illustrates the default behavior of a CustomEvent dispatch in the hotkey library. Note that the event does not bubble. ```typescript // Default behavior of CustomEvent element.dispatchEvent(event) // Note: does NOT bubble (bubbles: false) ``` -------------------------------- ### HTML Examples of Hotkey Definitions Source: https://github.com/github/hotkey/blob/main/README.md Demonstrates various ways to define hotkeys in HTML using the `data-hotkey` attribute, including single characters, aliases, sequences, and modifiers. ```html Next Search Code Help Search ``` -------------------------------- ### Install and Uninstall Hotkeys Source: https://github.com/github/hotkey/blob/main/_autodocs/README.md Register or deregister hotkeys on an HTML element. Hotkeys can be read from the `data-hotkey` attribute or provided programmatically. ```typescript import { install, uninstall } from '@github/hotkey' // Install hotkey on an element const button = document.getElementById('my-button') install(button) // Reads from data-hotkey attribute // Or provide hotkey programmatically install(button, 's') // Shortcut for 's' key // Uninstall when done uninstall(button) ``` -------------------------------- ### Usage in Hotkey Library: Install Function Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/Leaf.md Shows how the hotkey library uses Leaf nodes to associate HTMLElements with hotkey sequences. This function inserts an element into the trie. ```typescript // src/index.ts const elementsLeaves = new WeakMap>>() function install(element: HTMLElement, hotkey?: string): void { const hotkeys = expandHotkeyToEdges(hotkey || element.getAttribute('data-hotkey') || '') // hotkeys is an array of edge arrays, e.g., [['g', 'i'], ['g', 'c']] const leaves = hotkeys.map(h => (hotkeyRadixTrie.insert(h) as Leaf).add(element) ) // Store reference to all leaves for this element elementsLeaves.set(element, leaves) } ``` -------------------------------- ### Programmatically Override data-hotkey Attribute Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Use the `install()` function with a specific hotkey string to override any hotkey defined in the `data-hotkey` attribute for a given element. This provides programmatic control over hotkey registration. ```javascript const button = document.querySelector('[data-hotkey]') install(button, 'custom-hotkey') // Uses 'custom-hotkey', ignores data-hotkey ``` -------------------------------- ### Conditional Behavior Based on Hotkey Path Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Implement different actions based on the specific hotkey sequence that was activated. This example shows how to prevent the default action and navigate to different sections based on a two-key sequence. ```javascript element.addEventListener('hotkey-fire', (event) => { const [first, second] = event.detail.path if (event.detail.path.length === 2 && first === 'g' && second === 'c') { event.preventDefault() navigateToCode() } else if (event.detail.path.length === 2 && first === 'g' && second === 'i') { event.preventDefault() navigateToIssues() } // Otherwise, let the default action (click) proceed }) install(element, 'g c,g i') ``` -------------------------------- ### Cleanup on element removal Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/uninstall.md This example shows how to simultaneously remove an element from the DOM and deregister its associated hotkey using uninstall(). This ensures both the element and its hotkey are cleaned up. ```typescript const button = document.getElementById('my-button') install(button, 'Control+s') // Remove both the element from the DOM and deregister its hotkey button.remove() uninstall(button) ``` -------------------------------- ### Register Hotkeys in JavaScript Source: https://github.com/github/hotkey/blob/main/_autodocs/QUICK_START.md Register hotkeys programmatically using the 'install' function. You can register all elements with 'data-hotkey' or specific elements with custom hotkeys. Use 'uninstall' to deregister. ```typescript // Register all hotkeys on page for (const el of document.querySelectorAll('[data-hotkey]')) { install(el) } // Or register specific element with custom hotkey const button = document.getElementById('my-button') install(button, 'Shift+?') // Override data-hotkey // Deregister when done uninstall(button) ``` -------------------------------- ### Leaf Delete Method Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/Leaf.md Demonstrates removing an element from a leaf, verifying the deletion status and the resulting children count. Also shows attempting to delete a non-existent element. ```typescript const leaf = new Leaf(parentNode) const button = document.getElementById('my-button') leaf.add(button) console.log(leaf.children.length) // 1 const deleted = leaf.delete(button) console.log(deleted) // true console.log(leaf.children.length) // 0 // Try to delete a non-existent element const notDeleted = leaf.delete(someOtherElement) console.log(notDeleted) // false ``` -------------------------------- ### Custom Action with Hotkey Source: https://github.com/github/hotkey/blob/main/_autodocs/README.md Installs a hotkey on a specific element and listens for the 'hotkey-fire' event to execute custom logic. The event's default behavior should be prevented if custom action is handled. ```typescript const button = document.getElementById('action') install(button, 'Mod+e') button.addEventListener('hotkey-fire', (event) => { event.preventDefault() // Your custom action }) ``` -------------------------------- ### SEQUENCE_DELIMITER Constant Example Source: https://github.com/github/hotkey/blob/main/_autodocs/types.md Demonstrates the usage of the SEQUENCE_DELIMITER constant, which represents the space character used to separate hotkeys in sequences. It's useful for parsing and displaying sequences. ```typescript import { SEQUENCE_DELIMITER } from '@github/hotkey' const sequence = 'g i' const parts = sequence.split(SEQUENCE_DELIMITER) // parts = ['g', 'i'] ``` -------------------------------- ### Basic Syntax: Multiple Aliases Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Demonstrates defining multiple hotkey aliases separated by commas. Any alias will trigger the action. ```plaintext a,b // Press 'a' OR 'b' s,/ // Press 's' OR '/' g c,g i // Press 'g c' OR 'g i' ``` -------------------------------- ### Track Hotkey Usage with Analytics Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md This snippet listens for 'hotkey-fire' events to track hotkey activations and send analytics data. It uses the capture phase, but notes that 'hotkey-fire' does not bubble, requiring listeners to be attached during installation. ```javascript // Track all hotkey usage document.addEventListener('hotkey-fire', (event) => { if (event.target.dataset.hotkeyAnalytics !== 'false') { const sequence = event.detail.path.join(' ') const elementId = event.target.id analytics.track('hotkey_activated', { sequence, elementId, timestamp: Date.now() }) } }, true) // Use capture phase to catch all events ``` ```javascript const originalInstall = window.install window.install = function(element, hotkey) { originalInstall(element, hotkey) element.addEventListener('hotkey-fire', (event) => { const sequence = event.detail.path.join(' ') analytics.track('hotkey_activated', { sequence, element: element.id || element.className, timestamp: Date.now() }) }) } ``` -------------------------------- ### get() Method Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Retrieves a child node from the RadixTrie using an edge string. ```APIDOC ## get(edge: string): RadixTrie | Leaf ### Description Retrieves a child node by its corresponding edge string. ### Parameters #### Path Parameters * **edge** (string) - Required - The edge identifier to look up. ### Return Value Returns the child `RadixTrie` or `Leaf` if found, `undefined` otherwise. ### Example ```typescript const trie = new RadixTrie() // After inserting ['a', 'b'] const node = trie.get('a') ``` ``` -------------------------------- ### Get child from RadixTrie Source: https://github.com/github/hotkey/blob/main/_autodocs/MODULE_INDEX.md Retrieves a child node from the RadixTrie using an edge string. ```typescript trie.get(edge: string) => RadixTrie | Leaf ``` -------------------------------- ### Basic Hotkey Combinations Source: https://github.com/github/hotkey/blob/main/_autodocs/QUICK_START.md Demonstrates various single key, modifier, and sequence hotkey combinations. ```text j Single key s,/ Multiple aliases Control+s Modifier + key Control+Alt+h Multiple modifiers Shift+? Shift for symbol g c Two-key sequence . v Period and V sequence Mod+k Platform-aware Mod+Alt+Shift+x All modifiers Control+,,y Comma as hotkey (Ctrl+comma or Y) ``` -------------------------------- ### Basic Syntax: Key Sequences Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Shows how to define a sequence of keys that must be pressed in order. A timeout applies between key presses. ```plaintext g c // Press 'g', then 'c' g i // Press 'g', then 'i' . c // Press '.', then 'c' ``` -------------------------------- ### Uninstall Hotkeys Source: https://github.com/github/hotkey/blob/main/README.md Removes previously installed hotkeys from elements on the page. This is useful for cleanup or dynamic removal of shortcuts. ```javascript import {uninstall} from '@github/hotkey' for (const el of document.querySelectorAll('[data-hotkey]')) { uninstall(el) } ``` -------------------------------- ### Cascading Deletion Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/Leaf.md Illustrates how an empty leaf triggers its own deletion from the parent trie, potentially cascading up the tree. ```typescript const root = new RadixTrie() const gNode = root.insert(['g']) as RadixTrie const iLeaf = gNode.insert(['i']) as Leaf const button = document.getElementById('my-button') iLeaf.add(button) // Structure: // root → 'g' (RadixTrie) → 'i' (Leaf) → [button] // Delete the button from the leaf iLeaf.delete(button) // Now: // - iLeaf.children is empty, so it's deleted from gNode // - gNode.children is now empty, so gNode is deleted from root // Structure becomes: // root (empty) ``` -------------------------------- ### RadixTrie get() Method Signature Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Retrieves a child node from the current node using its associated edge string. ```typescript get(edge: string): RadixTrie | Leaf ``` -------------------------------- ### Implement Hotkey Help Dialog Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md This code collects all defined hotkeys and their labels, then displays them in a help dialog when a specific help hotkey is triggered. ```javascript const helpButton = document.getElementById('help-button') // Collect all hotkey info const hotkeys = [] for (const element of document.querySelectorAll('[data-hotkey]')) { const hotkey = element.getAttribute('data-hotkey') const label = element.getAttribute('aria-label') || element.textContent hotkeys.push({ hotkey, label, element }) } // Display in help dialog helpButton.addEventListener('hotkey-fire', (event) => { event.preventDefault() showHelpDialog(hotkeys) }) install(helpButton, '?') // Common convention: ? for help ``` -------------------------------- ### SequenceTracker Constructor with Options Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Shows how to instantiate the SequenceTracker with custom options, specifically the `onReset` callback for handling sequence timeouts. ```typescript const tracker = new SequenceTracker({ onReset() { console.log('Sequence timed out') } }) ``` -------------------------------- ### RadixTrie Class Signature Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Defines the generic RadixTrie class with its constructor, parent, children, and core methods: get, insert, and delete. ```typescript class RadixTrie { constructor(trie?: RadixTrie) parent: RadixTrie | null children: {[key: string]: RadixTrie | Leaf} get(edge: string): RadixTrie | Leaf insert(edges: string[]): RadixTrie | Leaf delete(node: RadixTrie | Leaf): boolean } ``` -------------------------------- ### Deregister a single element Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/uninstall.md Use this snippet to deregister a specific HTML element's hotkey. Ensure the element has been previously registered with install(). ```typescript const button = document.getElementById('my-button') install(button, 's') // later... uninstall(button) ``` -------------------------------- ### RadixTrie delete() Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Illustrates deleting nodes from the trie, including cascading deletion of parent nodes when they become empty after a child is removed. ```typescript const trie = new RadixTrie() const leaf1 = trie.insert(['g', 'i']) const leaf2 = trie.insert(['g', 'c']) const leaf3 = trie.insert(['s']) // Delete the 'g' → 'i' branch const gNode = trie.get('g') gNode.delete(leaf1) // Structure after deleting 'i': // root // ├─ 'g' (RadixTrie) // │ └─ 'c' (Leaf) // └─ 's' (Leaf) // Delete the remaining 'g' → 'c' branch gNode.delete(leaf2) // Structure after deleting 'c': // root // └─ 's' (Leaf) // ('g' node was empty and recursively deleted) ``` -------------------------------- ### SequenceTracker CHORD_TIMEOUT Property Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/SequenceTracker.md Access the static CHORD_TIMEOUT property to get the default timeout in milliseconds for sequence resets. The default value is 1500ms. ```typescript static readonly CHORD_TIMEOUT: number = 1500 ``` -------------------------------- ### Special Key Names in Hotkey Syntax Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Illustrates how to use special key names for keys like Space and Plus that have conflicting symbols in the hotkey syntax. ```html ``` -------------------------------- ### Leaf.add() Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Appends a value to a Leaf's children array and returns the leaf for chaining operations. This is useful for associating elements with registered hotkeys. ```typescript const leaf = trie.insert(['s']) as Leaf const button = document.getElementById('button') leaf.add(button) ``` -------------------------------- ### Full Hotkey Grammar Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Provides the formal grammar for constructing hotkey strings, defining sequences, hotkeys, modifiers, and keys. ```text HOTKEY_STRING := HOTKEY_SEQUENCE ( ',' HOTKEY_SEQUENCE )* HOTKEY_SEQUENCE := HOTKEY ( ' ' HOTKEY )* HOTKEY := ( MODIFIER '+' )* KEY MODIFIER := 'Control' | 'Alt' | 'Meta' | 'Shift' | 'Mod' KEY := ``` -------------------------------- ### Get Current Sequence String Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/SequenceTracker.md Obtain the current sequence of key presses as a single, space-separated string. This is a convenient string representation of the recorded hotkeys. ```typescript const tracker = new SequenceTracker() tracker.registerKeypress(createKeyboardEvent('g')) tracker.registerKeypress(createKeyboardEvent('i')) console.log(tracker.sequence) // 'g i' ``` -------------------------------- ### SequenceTracker Instance Methods Source: https://github.com/github/hotkey/blob/main/_autodocs/MODULE_INDEX.md Methods for interacting with the SequenceTracker to record and manage keypress sequences. ```APIDOC ## SequenceTracker Instance Methods ### `registerKeypress()` #### Description Record a keypress in the sequence. #### Signature `(event: KeyboardEvent) => void` ### `reset()` #### Description Clear the sequence and stop the timer. #### Signature `() => void` ``` -------------------------------- ### Form Field Integration Logic Source: https://github.com/github/hotkey/blob/main/_autodocs/QUICK_START.md When using 'data-hotkey-scope', ensure the hotkey is installed on the target element. The hotkey will only trigger when the scoped element (e.g., textarea) has focus. ```typescript install(document.getElementById('save')) // Hotkey only works when textarea is focused // When focused on textarea + press Mod+s // → save button fires // When focused elsewhere + press Mod+s // → hotkey ignored ``` -------------------------------- ### Dynamically Change Hotkeys Source: https://github.com/github/hotkey/blob/main/_autodocs/QUICK_START.md Update hotkeys on an element by first uninstalling the old one and then installing the new one. This allows for dynamic changes to hotkey bindings. ```typescript function updateHotkey(element, newHotkey) { uninstall(element) install(element, newHotkey) } const button = document.getElementById('action') updateHotkey(button, 'Mod+k') // Change hotkey ``` -------------------------------- ### Keyboard Event Targets for Hotkeys Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Hotkeys respond to the currently focused element, not the element that defines the hotkey. This example shows a hotkey firing when the focus is on a textarea. ```html ``` ```javascript install(document.getElementById('save')) // User clicks in textarea and presses Mod+s: // → The keydown event targets the textarea // → The hotkey for save button fires (but only if not scoped, or scoped correctly) ``` -------------------------------- ### Platform-Agnostic Modifier Hotkey Example Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Uses the 'Mod' keyword in data-hotkey to represent the platform's primary modifier key (Meta on macOS, Control on Windows/Linux). ```html Settings ``` -------------------------------- ### Basic Syntax: Modifiers Source: https://github.com/github/hotkey/blob/main/_autodocs/configuration.md Illustrates defining hotkeys with modifier keys (Control, Alt, Meta, Shift) prepended to the main key, separated by '+'. ```plaintext Control+s // Control key + 's' Alt+Delete // Alt key + Delete key Control+Alt+h // Control + Alt + 'h' Shift+? // Shift + '/' (produces '?') Control+Alt+Meta+Shift+x // All modifiers + 'x' ``` -------------------------------- ### Handle hotkey-fire CustomEvent Source: https://github.com/github/hotkey/blob/main/_autodocs/MODULE_INDEX.md Example of adding an event listener to an element to handle the 'hotkey-fire' custom event. It logs the hotkey path and prevents the default action. ```typescript element.addEventListener('hotkey-fire', (event: CustomEvent) => { console.log('Hotkey sequence:', event.detail.path) event.preventDefault() // prevent default focus/click }) ``` -------------------------------- ### Leaf.delete() Example Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/RadixTrie.md Removes a value from a Leaf's children array. If the leaf becomes empty after deletion, it triggers a cascade to remove the leaf from its parent trie. ```typescript const leaf = trie.insert(['s']) as Leaf const button = document.getElementById('button') leaf.add(button) leaf.delete(button) // If this was the only value, leaf is deleted from parent ``` -------------------------------- ### Handle Multiple Elements with the Same Hotkey Source: https://github.com/github/hotkey/blob/main/_autodocs/EVENTS_AND_INTEGRATION.md Demonstrates the behavior when multiple elements share the same hotkey. It highlights that only the last registered element will fire its action due to internal logic that breaks after the first match. ```html ``` ```javascript install(document.getElementById('btn1')) install(document.getElementById('btn2')) // When user presses 's': // 1. Both hotkey-fire events are dispatched // 2. Both click() are called (in reverse order of registration) ``` ```typescript for (let i = newTriePosition.children.length - 1; i >= 0; i -= 1) { elementToFire = newTriePosition.children[i] const scope = elementToFire.getAttribute('data-hotkey-scope') if ((!formField && !scope) || (formField && target.id === scope)) { shouldFire = true break // ← Stops at first matching element } } if (elementToFire && shouldFire) { fireDeterminedAction(elementToFire, sequenceTracker.path) event.preventDefault() } ``` -------------------------------- ### Platform-aware normalization using default platform Source: https://github.com/github/hotkey/blob/main/_autodocs/api-reference/normalizeSequence.md Shows how normalizeSequence uses the default navigator.platform to normalize sequences, assuming a Windows environment. ```typescript // Assume we're on Windows normalizeSequence('Mod+k Mod+j') // Result: 'Control+k Control+j' ```