@peter.naydenov/shortcuts 3.5.2 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +939 -0
- package/CODE_OF_CONDUCT.md +84 -0
- package/CONTRIBUTING.md +476 -0
- package/Changelog.md +32 -2
- package/How.to.create.plugins.md +929 -0
- package/Migration.guide.md +48 -0
- package/README.md +396 -24
- package/dist/main.d.ts +54 -2
- package/dist/methods/_normalizeWithPlugins.d.ts +63 -1
- package/dist/methods/_readShortcutWithPlugins.d.ts +8 -1
- package/dist/methods/_setupPlugin.d.ts +9 -0
- package/dist/methods/_systemAction.d.ts +8 -1
- package/dist/methods/changeContext.d.ts +8 -1
- package/dist/methods/index.d.ts +2 -0
- package/dist/methods/listShortcuts.d.ts +1 -16
- package/dist/methods/load.d.ts +8 -1
- package/dist/methods/unload.d.ts +8 -1
- package/dist/plugins/click/_findTarget.d.ts +9 -1
- package/dist/plugins/click/_listenDOM.d.ts +76 -3
- package/dist/plugins/click/_normalizeShortcutName.d.ts +7 -1
- package/dist/plugins/click/_registerShortcutEvents.d.ts +26 -0
- package/dist/plugins/click/index.d.ts +6 -31
- package/dist/plugins/form/_defaults.d.ts +13 -1
- package/dist/plugins/form/_listenDOM.d.ts +66 -3
- package/dist/plugins/form/_registerShortcutEvents.d.ts +95 -1
- package/dist/plugins/form/index.d.ts +2 -29
- package/dist/plugins/hover/_findTarget.d.ts +10 -0
- package/dist/plugins/hover/_listenDOM.d.ts +68 -0
- package/dist/plugins/hover/_normalizeShortcutName.d.ts +2 -0
- package/dist/plugins/hover/_registerShortcutEvents.d.ts +28 -0
- package/dist/plugins/hover/index.d.ts +14 -0
- package/dist/plugins/key/_listenDOM.d.ts +61 -3
- package/dist/plugins/key/_registerShortcutEvents.d.ts +26 -0
- package/dist/plugins/key/_specialChars.d.ts +6 -31
- package/dist/plugins/key/index.d.ts +2 -29
- package/dist/plugins/scroll/_listenDOM.d.ts +58 -0
- package/dist/plugins/scroll/_normalizeShortcutName.d.ts +2 -0
- package/dist/plugins/scroll/_registerShortcutEvents.d.ts +28 -0
- package/dist/plugins/scroll/index.d.ts +16 -0
- package/dist/shortcuts.cjs +1 -1
- package/dist/shortcuts.esm.mjs +1 -1
- package/dist/shortcuts.umd.js +1 -1
- package/dist/src/main.d.ts +172 -0
- package/dist/src/methods/_normalizeWithPlugins.d.ts +64 -0
- package/dist/src/methods/_readShortcutWithPlugins.d.ts +9 -0
- package/dist/src/methods/_setupPlugin.d.ts +9 -0
- package/dist/src/methods/_systemAction.d.ts +9 -0
- package/dist/src/methods/changeContext.d.ts +9 -0
- package/dist/src/methods/index.d.ts +19 -0
- package/dist/src/methods/listShortcuts.d.ts +2 -0
- package/dist/src/methods/load.d.ts +9 -0
- package/dist/src/methods/unload.d.ts +9 -0
- package/dist/src/plugins/click/_findTarget.d.ts +10 -0
- package/dist/src/plugins/click/_listenDOM.d.ts +78 -0
- package/dist/src/plugins/click/_normalizeShortcutName.d.ts +8 -0
- package/dist/src/plugins/click/_readClickEvent.d.ts +2 -0
- package/dist/src/plugins/click/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/click/index.d.ts +16 -0
- package/dist/src/plugins/form/_defaults.d.ts +17 -0
- package/dist/src/plugins/form/_listenDOM.d.ts +68 -0
- package/dist/src/plugins/form/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/form/_registerShortcutEvents.d.ts +96 -0
- package/dist/src/plugins/form/index.d.ts +9 -0
- package/dist/src/plugins/hover/_findTarget.d.ts +10 -0
- package/dist/src/plugins/hover/_listenDOM.d.ts +68 -0
- package/dist/src/plugins/hover/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/hover/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/hover/index.d.ts +14 -0
- package/dist/src/plugins/key/_listenDOM.d.ts +63 -0
- package/dist/src/plugins/key/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/key/_readKeyEvent.d.ts +2 -0
- package/dist/src/plugins/key/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/key/_specialChars.d.ts +7 -0
- package/dist/src/plugins/key/index.d.ts +14 -0
- package/dist/src/plugins/scroll/_listenDOM.d.ts +58 -0
- package/dist/src/plugins/scroll/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/scroll/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/scroll/index.d.ts +16 -0
- package/eslint.config.js +80 -0
- package/html/assets/index-COTh6lXR.css +1 -0
- package/html/assets/index-DOkKC3NI.js +53 -0
- package/html/bg.png +0 -0
- package/html/favicon.ico +0 -0
- package/html/favicon.svg +5 -0
- package/html/html.meta.json.gz +0 -0
- package/html/index.html +32 -0
- package/package.json +24 -19
- package/shortcuts.png +0 -0
- package/src/main.js +52 -22
- package/src/methods/_normalizeWithPlugins.js +26 -2
- package/src/methods/_readShortcutWithPlugins.js +9 -2
- package/src/methods/_setupPlugin.js +93 -0
- package/src/methods/_systemAction.js +12 -4
- package/src/methods/changeContext.js +11 -3
- package/src/methods/index.js +2 -0
- package/src/methods/listShortcuts.js +5 -12
- package/src/methods/load.js +11 -4
- package/src/methods/unload.js +8 -1
- package/src/plugins/click/_findTarget.js +11 -5
- package/src/plugins/click/_listenDOM.js +58 -20
- package/src/plugins/click/_normalizeShortcutName.js +11 -4
- package/src/plugins/click/_readClickEvent.js +1 -1
- package/src/plugins/click/_registerShortcutEvents.js +33 -5
- package/src/plugins/click/index.js +33 -60
- package/src/plugins/form/_defaults.js +13 -3
- package/src/plugins/form/_listenDOM.js +46 -9
- package/src/plugins/form/_normalizeShortcutName.js +2 -2
- package/src/plugins/form/_registerShortcutEvents.js +93 -17
- package/src/plugins/form/index.js +25 -56
- package/src/plugins/hover/_findTarget.js +26 -0
- package/src/plugins/hover/_listenDOM.js +154 -0
- package/src/plugins/hover/_normalizeShortcutName.js +21 -0
- package/src/plugins/hover/_registerShortcutEvents.js +51 -0
- package/src/plugins/hover/index.js +71 -0
- package/src/plugins/key/_listenDOM.js +67 -33
- package/src/plugins/key/_normalizeShortcutName.js +4 -3
- package/src/plugins/key/_readKeyEvent.js +1 -1
- package/src/plugins/key/_registerShortcutEvents.js +34 -5
- package/src/plugins/key/_specialChars.js +5 -0
- package/src/plugins/key/index.js +34 -59
- package/src/plugins/scroll/_listenDOM.js +141 -0
- package/src/plugins/scroll/_normalizeShortcutName.js +21 -0
- package/src/plugins/scroll/_registerShortcutEvents.js +50 -0
- package/src/plugins/scroll/index.js +61 -0
- package/test/01-general.test.js +92 -23
- package/test/02-key.test.js +241 -40
- package/test/03-click.test.js +291 -47
- package/test/04-form.test.js +241 -47
- package/test/05-hover.test.js +463 -0
- package/test/06-scroll.test.js +374 -0
- package/test-helpers/Block.jsx +3 -2
- package/test-helpers/style.css +6 -1
- package/tsconfig.json +2 -1
- package/vitest.config.js +13 -11
- package/How..to.make.plugins.md +0 -41
package/Migration.guide.md
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
# Migration Guides
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## From version 3.x.x to version 4.0.0 (Upcoming)
|
|
5
|
+
|
|
6
|
+
### Plugin Target Attributes Changes
|
|
7
|
+
|
|
8
|
+
**Breaking Changes:**
|
|
9
|
+
- Plugin `click` parameter `clickTarget` now accepts an **array of attribute names** instead of a single string
|
|
10
|
+
- Plugin `hover` parameter `hoverTarget` now accepts an **array of attribute names** instead of a single string
|
|
11
|
+
|
|
12
|
+
**Migration Required:**
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
// Version 3.x.x (old)
|
|
16
|
+
short.enablePlugin(pluginClick, { clickTarget: 'data-button' })
|
|
17
|
+
short.enablePlugin(pluginHover, { hoverTarget: 'data-menu' })
|
|
18
|
+
|
|
19
|
+
// Version 4.0.0 (new)
|
|
20
|
+
short.enablePlugin(pluginClick, { clickTarget: ['data-button'] })
|
|
21
|
+
short.enablePlugin(pluginHover, { hoverTarget: ['data-menu'] })
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Default Values Updated:**
|
|
25
|
+
- `clickTarget` default: `['data-click', 'href']` (was `'data-click'`)
|
|
26
|
+
- `hoverTarget` default: `['data-hover']` (was `'data-hover'`)
|
|
27
|
+
|
|
28
|
+
**Benefits:**
|
|
29
|
+
- More flexible target detection
|
|
30
|
+
- Support for multiple attribute patterns
|
|
31
|
+
- Better compatibility with existing HTML patterns
|
|
32
|
+
|
|
33
|
+
### Per-Context Setup Examples Updated
|
|
34
|
+
|
|
35
|
+
All setup examples in the documentation have been updated to use arrays:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
// Version 4.0.0 per-context setup
|
|
39
|
+
const shortcutDefinition = {
|
|
40
|
+
myContext: {
|
|
41
|
+
'click:setup': () => ({
|
|
42
|
+
clickTarget: ['data-action', 'data-button', 'href'] // Array format
|
|
43
|
+
}),
|
|
44
|
+
'hover:setup': () => ({
|
|
45
|
+
hoverTarget: ['data-interactive', 'data-hover'] // Array format
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
|
|
4
52
|
## From version 2.x.x to version 3.x.x
|
|
5
53
|
|
|
6
54
|
Reason for significant refactoring of the code was my desire to make the library extensible with a plugins. Plugins role is to convert DOM events to shortcut strings, then the core part will trigger the action functions related to the shortcut. Now we have a core, plugin interface and plugins. All listener for `keyboard` and `mouse clicks` are moved to plugins. Mouse events are tracked by `click` plugin and keyboard events are tracked by `key` plugin.
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<img src="shortcuts.png" width="100%" alt="Shortcuts" align="center" />
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
# Shortcuts (@peter.naydenov/shortcuts)
|
|
2
6
|
|
|
3
7
|

|
|
@@ -13,13 +17,42 @@ Currently existing plugins:
|
|
|
13
17
|
- `key` - Converts keyboard events to shortcuts;
|
|
14
18
|
- `click` - Converts mouse events to shortcuts;
|
|
15
19
|
- `form` - Form element changes to shortcuts;
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
- `hover` - Mouse hover events to shortcuts;
|
|
21
|
+
- `scroll` - Scroll events to shortcuts;
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
## Shortcut Description Rules
|
|
22
|
-
The shortcuts definition includes a context name and a set of rules(object). The rules are a set of key-value pairs. The key
|
|
26
|
+
The shortcuts definition includes a context name and a set of rules(object). The rules are a set of key-value pairs. The key contains a plugin name and a shortcut name and the value is a function or array of functions, to be executed when the shortcut is triggered (action function).
|
|
27
|
+
|
|
28
|
+
### Per-Context Plugin Setup (Preferred Method)
|
|
29
|
+
Every plugin supports a `setup` event (e.g., `key:setup`, `click:setup`, `hover:setup`, `scroll:setup`) that allows you to configure plugin settings specifically for that context. This is the **preferred method** for customizing plugins as it provides:
|
|
30
|
+
|
|
31
|
+
- **Context-specific configuration** - Different settings for different contexts
|
|
32
|
+
- **Cleaner code** - No global plugin options needed
|
|
33
|
+
- **Better maintainability** - Settings are defined alongside the shortcuts they affect
|
|
34
|
+
|
|
35
|
+
The setup function receives:
|
|
36
|
+
- `dependencies` - External dependencies set via `setDependencies()`
|
|
37
|
+
- `defaults` - Default plugin options as a starting point
|
|
38
|
+
|
|
39
|
+
Example pattern:
|
|
40
|
+
```js
|
|
41
|
+
const shortcutDefinition = {
|
|
42
|
+
context1: {
|
|
43
|
+
'plugin:setup': ({ dependencies, defaults }) => {
|
|
44
|
+
return {
|
|
45
|
+
// Override specific options for this context
|
|
46
|
+
option1: 'customValue1',
|
|
47
|
+
option2: 123
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
'plugin:event': () => { /* your action */ }
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See individual plugin sections for specific setup examples.
|
|
23
56
|
|
|
24
57
|
```js
|
|
25
58
|
// { context: { shortcutName: actionFunction } }
|
|
@@ -50,9 +83,9 @@ Load a shortcut definition by calling `load` method.
|
|
|
50
83
|
|
|
51
84
|
```js
|
|
52
85
|
// for es6 module projects:
|
|
53
|
-
import { shortcuts, pluginKey, pluginClick, pluginForm } from '@peter.naydenov/shortcuts'
|
|
86
|
+
import { shortcuts, pluginKey, pluginClick, pluginForm, pluginHover, pluginScroll } from '@peter.naydenov/shortcuts'
|
|
54
87
|
// for commonjs projects:
|
|
55
|
-
const { shortcuts, pluginKey, pluginClick, pluginForm } = require('@peter.naydenov/shortcuts')
|
|
88
|
+
const { shortcuts, pluginKey, pluginClick, pluginForm, pluginHover, pluginScroll } = require('@peter.naydenov/shortcuts')
|
|
56
89
|
|
|
57
90
|
|
|
58
91
|
|
|
@@ -76,7 +109,228 @@ To deactivate a context without starting other context, call `changeContext` met
|
|
|
76
109
|
|
|
77
110
|
```js
|
|
78
111
|
short.changeContext ()
|
|
79
|
-
```
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Plugin 'hover' Shortcut Descriptions
|
|
116
|
+
`Hover` plugin is used to detect when mouse enters or leaves specific HTML elements. The plugin supports two main events: hover on and hover off.
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
hover:on // Triggered when mouse enters a target element
|
|
120
|
+
hover:off // Triggered when mouse leaves a target element
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Define Hover Targets
|
|
124
|
+
Target HTML elements for `hover` plugin are defined by `data-hover` attribute. The value of the attribute is the name of the target. Example:
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<div data-hover="menu">Menu content</div>
|
|
128
|
+
<!-- target name is 'menu' -->
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Attribute is customizable by setting `hoverTarget` hover plugin option. By default, it checks for `['data-hover']`. You can provide an array of attribute names. Read more in section `Options`.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
### Hover Action Functions
|
|
136
|
+
Hover plugin action functions receive the following arguments:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
function myHoverHandler ({
|
|
140
|
+
context // (string) Name of the current context;
|
|
141
|
+
, note // (string) Name of the note or null if note isn't set;
|
|
142
|
+
, dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
|
|
143
|
+
, target // (DOM element). Target element of the hover event;
|
|
144
|
+
, targetProps // (object). Coordinates of the target element (top, left, right, bottom, width, height) or null if target element is not available;
|
|
145
|
+
, x // (number). X coordinate of the target element;
|
|
146
|
+
, y // (number). Y coordinate of the target element;
|
|
147
|
+
, event // (object). Original hover event object;
|
|
148
|
+
}) {
|
|
149
|
+
// Body of the handler. Do something...
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Hover Detection Timing
|
|
154
|
+
Hover events are detected with a delay to avoid triggering when mouse quickly moves over elements. The default delay is 320ms but you can change it by setting `wait` hover plugin option.
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
short.enablePlugin ( pluginHover, { wait: 500 }) // set the delay to 500ms
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Per-Context Setup (Preferred Method)
|
|
161
|
+
Instead of global plugin options, you can use `hover:setup` event to configure plugin settings per context. This is the preferred method for customization.
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
const shortcutDefinition = {
|
|
165
|
+
navigation: {
|
|
166
|
+
'hover:setup': ({ dependencies, defaults }) => {
|
|
167
|
+
// Customize hover settings for this context only
|
|
168
|
+
return {
|
|
169
|
+
wait: 200, // Faster hover detection for navigation
|
|
170
|
+
hoverTarget: ['data-nav-item', 'data-menu'] // Array of attribute names
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
'hover:on': ({ target }) => {
|
|
174
|
+
target.classList.add('active');
|
|
175
|
+
},
|
|
176
|
+
'hover:off': ({ target }) => {
|
|
177
|
+
target.classList.remove('active');
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
slowTooltips: {
|
|
181
|
+
'hover:setup': ({ dependencies, defaults }) => {
|
|
182
|
+
// Slower hover detection for tooltips
|
|
183
|
+
return {
|
|
184
|
+
wait: 800, // Slower hover detection
|
|
185
|
+
hoverTarget: ['data-tooltip', 'data-help'] // Different attributes for tooltips
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
'hover:on': ({ target }) => {
|
|
189
|
+
// Show tooltip with delay
|
|
190
|
+
setTimeout(() => target.classList.add('visible'), 100);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
short.enablePlugin(pluginHover);
|
|
196
|
+
short.load(shortcutDefinition);
|
|
197
|
+
short.changeContext('navigation'); // Uses navigation settings
|
|
198
|
+
// short.changeContext('slowTooltips'); // Uses tooltip settings
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The `hover:setup` function receives:
|
|
202
|
+
- `dependencies` - External dependencies set via `setDependencies()`
|
|
203
|
+
- `defaults` - Default plugin options as a starting point or just for reference
|
|
204
|
+
|
|
205
|
+
Example usage:
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
const shortcutDefinition = {
|
|
209
|
+
navigation: {
|
|
210
|
+
'hover:on': ({ target }) => {
|
|
211
|
+
// Mouse entered the target
|
|
212
|
+
target.classList.add('active');
|
|
213
|
+
},
|
|
214
|
+
'hover:off': ({ target }) => {
|
|
215
|
+
// Mouse left the target
|
|
216
|
+
target.classList.remove('active');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
short.enablePlugin(pluginHover);
|
|
222
|
+
short.load(shortcutDefinition);
|
|
223
|
+
short.changeContext('navigation');
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Plugin 'scroll' Shortcut Descriptions
|
|
227
|
+
`Scroll` plugin is used to detect scroll events on the page. The plugin supports four main scroll directions:
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
scroll:up // Triggered when scrolling up
|
|
231
|
+
scroll:down // Triggered when scrolling down
|
|
232
|
+
scroll:left // Triggered when scrolling left
|
|
233
|
+
scroll:right // Triggered when scrolling right
|
|
234
|
+
scroll:end // Triggered when scrolling stops (after endScrollWait timeout)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Scroll Detection Settings
|
|
238
|
+
Scroll events are detected with specific timing and distance thresholds to avoid excessive triggering. The default settings are:
|
|
239
|
+
|
|
240
|
+
- `scrollWait`: 50ms - Delay between scroll events
|
|
241
|
+
- `endScrollWait`: 400ms - Delay when scroll was stopped
|
|
242
|
+
- `minSpace`: 40px - Minimum distance between scroll events
|
|
243
|
+
|
|
244
|
+
These can be customized by setting scroll plugin options:
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
short.enablePlugin ( pluginScroll, {
|
|
248
|
+
scrollWait: 100, // set delay to 100ms
|
|
249
|
+
endScrollWait: 600, // set end scroll delay to 600ms
|
|
250
|
+
minSpace: 60 // set minimum distance to 60px
|
|
251
|
+
})
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Per-Context Setup (Preferred Method)
|
|
255
|
+
Instead of global plugin options, you can use `scroll:setup` event to configure plugin settings per context. This is preferred method for customization.
|
|
256
|
+
|
|
257
|
+
```js
|
|
258
|
+
const shortcutDefinition = {
|
|
259
|
+
sensitiveScrolling: {
|
|
260
|
+
'scroll:setup': ({ dependencies, defaults }) => {
|
|
261
|
+
// High sensitivity for gaming or precise interactions
|
|
262
|
+
return {
|
|
263
|
+
scrollWait: 20, // Very responsive
|
|
264
|
+
endScrollWait: 200, // Quick end detection
|
|
265
|
+
minSpace: 20 // Small movements trigger
|
|
266
|
+
};
|
|
267
|
+
},
|
|
268
|
+
'scroll:up': () => console.log('Sensitive scroll up'),
|
|
269
|
+
'scroll:down': () => console.log('Sensitive scroll down'),
|
|
270
|
+
'scroll:end': () => console.log('Sensitive scroll ended')
|
|
271
|
+
},
|
|
272
|
+
lazyScrolling: {
|
|
273
|
+
'scroll:setup': ({ dependencies, defaults }) => {
|
|
274
|
+
// Low sensitivity for reading or casual browsing
|
|
275
|
+
return {
|
|
276
|
+
scrollWait: 150, // Less responsive
|
|
277
|
+
endScrollWait: 800, // Slow end detection
|
|
278
|
+
minSpace: 80 // Larger movements needed
|
|
279
|
+
};
|
|
280
|
+
},
|
|
281
|
+
'scroll:up': () => console.log('Lazy scroll up'),
|
|
282
|
+
'scroll:down': () => console.log('Lazy scroll down'),
|
|
283
|
+
'scroll:end': () => console.log('Lazy scroll ended')
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
short.enablePlugin(pluginScroll);
|
|
288
|
+
short.load(shortcutDefinition);
|
|
289
|
+
short.changeContext('sensitiveScrolling'); // Uses sensitive settings
|
|
290
|
+
// short.changeContext('lazyScrolling'); // Uses lazy settings
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The `scroll:setup` function receives:
|
|
294
|
+
- `dependencies` - External dependencies set via `setDependencies()`
|
|
295
|
+
- `defaults` - Default plugin options as a starting point
|
|
296
|
+
|
|
297
|
+
### Scroll Action Functions
|
|
298
|
+
Scroll plugin action functions receive the following arguments:
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
function myScrollHandler ({
|
|
302
|
+
context // (string) Name of the current context;
|
|
303
|
+
, note // (string) Name of the note or null if note isn't set;
|
|
304
|
+
, dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
|
|
305
|
+
, event // (object). Original scroll event object;
|
|
306
|
+
}) {
|
|
307
|
+
// Body of the handler. Do something...
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Example usage:
|
|
312
|
+
|
|
313
|
+
```js
|
|
314
|
+
const shortcutDefinition = {
|
|
315
|
+
scrollView: {
|
|
316
|
+
'scroll:up': () => {
|
|
317
|
+
console.log('User scrolled up');
|
|
318
|
+
},
|
|
319
|
+
'scroll:down': () => {
|
|
320
|
+
console.log('User scrolled down');
|
|
321
|
+
},
|
|
322
|
+
'scroll:end': () => {
|
|
323
|
+
console.log('User stopped scrolling');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
short.enablePlugin(pluginScroll);
|
|
329
|
+
short.load(shortcutDefinition);
|
|
330
|
+
short.changeContext('scrollView');
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
```
|
|
80
334
|
|
|
81
335
|
Shortcuts context has `note` that works like sub-contexts. Every shortcut function receives a context and note as arguments, so you can have fine control over the context.
|
|
82
336
|
|
|
@@ -151,6 +405,50 @@ Multiple clicks are detected automatically by time interval between clicks. The
|
|
|
151
405
|
short.enablePlugin ( pluginClick, { mouseWait: 500 }) // set the interval to 500ms
|
|
152
406
|
```
|
|
153
407
|
|
|
408
|
+
### Per-Context Setup (Preferred Method)
|
|
409
|
+
Instead of global plugin options, you can use `click:setup` event to configure plugin settings per context. This is preferred method for customization.
|
|
410
|
+
|
|
411
|
+
```js
|
|
412
|
+
const shortcutDefinition = {
|
|
413
|
+
fastClicking: {
|
|
414
|
+
'click:setup': ({ dependencies, defaults }) => {
|
|
415
|
+
// Fast clicking for gaming or rapid interactions
|
|
416
|
+
return {
|
|
417
|
+
mouseWait: 150, // Very fast click detection
|
|
418
|
+
clickTarget: ['data-game-btn', 'data-action'] // Array of attributes for game buttons
|
|
419
|
+
};
|
|
420
|
+
},
|
|
421
|
+
'click:left-1': ({ target }) => {
|
|
422
|
+
console.log('Fast single click');
|
|
423
|
+
},
|
|
424
|
+
'click:left-2': ({ target }) => {
|
|
425
|
+
console.log('Fast double click');
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
slowClicking: {
|
|
429
|
+
'click:setup': ({ dependencies, defaults }) => {
|
|
430
|
+
// Slower clicking for form submissions or important actions
|
|
431
|
+
return {
|
|
432
|
+
mouseWait: 600, // Slower click detection
|
|
433
|
+
clickTarget: ['data-form-action', 'data-submit'] // Array of attributes for form actions
|
|
434
|
+
};
|
|
435
|
+
},
|
|
436
|
+
'click:left-1': ({ target }) => {
|
|
437
|
+
console.log('Deliberate single click');
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
short.enablePlugin(pluginClick);
|
|
443
|
+
short.load(shortcutDefinition);
|
|
444
|
+
short.changeContext('fastClicking'); // Uses fast settings
|
|
445
|
+
// short.changeContext('slowClicking'); // Uses slow settings
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
The `click:setup` function receives:
|
|
449
|
+
- `dependencies` - External dependencies set via `setDependencies()`
|
|
450
|
+
- `defaults` - Default plugin options as a starting point
|
|
451
|
+
|
|
154
452
|
Read more in section `Options`.
|
|
155
453
|
|
|
156
454
|
|
|
@@ -162,7 +460,7 @@ Target HTML elements for `shortcuts` are defined by `data-click` attribute. The
|
|
|
162
460
|
<!-- target name is 'id' -->
|
|
163
461
|
```
|
|
164
462
|
|
|
165
|
-
Attribute is customizable by setting `clickTarget` click plugin option. Read more in section `Options`.
|
|
463
|
+
Attribute is customizable by setting `clickTarget` click plugin option. By default, it checks for `['data-click', 'href']`. You can provide an array of attribute names. Read more in section `Options`.
|
|
166
464
|
|
|
167
465
|
If current shortcuts context contain definition for 2 or more clicks, this may slow down the execution of single shortcuts because `shortcuts` will wait for the time interval to detect multiple clicks. To avoid this for specific targets, you can set `data-quick-click` attribute to the target element. Example:
|
|
168
466
|
|
|
@@ -225,6 +523,45 @@ Order of describing keyboard event and modifier keys is not important, but seque
|
|
|
225
523
|
|
|
226
524
|
Keyboard sequence is detected automatically by time interval between key presses. The default interval is 480ms but you can change it by setting `keyWait` key plugin option. Read more in section `Options`.
|
|
227
525
|
|
|
526
|
+
### Per-Context Setup (Preferred Method)
|
|
527
|
+
Instead of global plugin options, you can use `key:setup` event to configure plugin settings per context. This is preferred method for customization.
|
|
528
|
+
|
|
529
|
+
```js
|
|
530
|
+
const shortcutDefinition = {
|
|
531
|
+
fastTyping: {
|
|
532
|
+
'key:setup': ({ dependencies, defaults }) => {
|
|
533
|
+
// Fast key detection for gaming or rapid input
|
|
534
|
+
return {
|
|
535
|
+
keyWait: 200, // Very fast sequence detection
|
|
536
|
+
streamKeys: (key) => console.log('Key pressed:', key) // Enable key streaming
|
|
537
|
+
};
|
|
538
|
+
},
|
|
539
|
+
'key:a,b,c': () => console.log('Fast sequence triggered'),
|
|
540
|
+
'key:ctrl+s': () => console.log('Fast save')
|
|
541
|
+
},
|
|
542
|
+
slowTyping: {
|
|
543
|
+
'key:setup': ({ dependencies, defaults }) => {
|
|
544
|
+
// Slower key detection for accessibility or careful input
|
|
545
|
+
return {
|
|
546
|
+
keyWait: 800, // Slower sequence detection
|
|
547
|
+
streamKeys: false // Disable key streaming
|
|
548
|
+
};
|
|
549
|
+
},
|
|
550
|
+
'key:a,b,c': () => console.log('Slow sequence triggered'),
|
|
551
|
+
'key:ctrl+s': () => console.log('Careful save')
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
short.enablePlugin(pluginKey);
|
|
556
|
+
short.load(shortcutDefinition);
|
|
557
|
+
short.changeContext('fastTyping'); // Uses fast settings
|
|
558
|
+
// short.changeContext('slowTyping'); // Uses slow settings
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
The `key:setup` function receives:
|
|
562
|
+
- `dependencies` - External dependencies set via `setDependencies()`
|
|
563
|
+
- `defaults` - Default plugin options as a starting point
|
|
564
|
+
|
|
228
565
|
There is a way to disable automatic sequence detection and mark the begining and the end of the sequense by using a keyboard action functions. Read more in section `Keyboard Action Functions`.
|
|
229
566
|
|
|
230
567
|
Special characters that are available for your shortcut descriptions:
|
|
@@ -274,8 +611,8 @@ Definition Example:
|
|
|
274
611
|
```js
|
|
275
612
|
const shortcutScope = {
|
|
276
613
|
...
|
|
277
|
-
, 'form : watch' : () => 'input, button' // Will select all inputs and buttons elements on the page.
|
|
278
|
-
, 'form : define' : ( target ) => { // Target is a DOM element selected by 'form: watch'
|
|
614
|
+
, 'form : watch' : ({dependencies}) => 'input, button' // Will select all inputs and buttons elements on the page.
|
|
615
|
+
, 'form : define' : ({ target, dependencies }) => { // Target is a DOM element selected by 'form: watch'
|
|
279
616
|
if ( target.tagName === 'INPUT' ) { // Will define inputs as 'input' type
|
|
280
617
|
return 'input' // (String) Custom according your preference
|
|
281
618
|
}
|
|
@@ -283,14 +620,15 @@ const shortcutScope = {
|
|
|
283
620
|
return 'button'
|
|
284
621
|
}
|
|
285
622
|
}
|
|
286
|
-
, 'form : action' : () => [
|
|
623
|
+
, 'form : action' : ({ dependencies}) => [
|
|
287
624
|
{
|
|
288
625
|
fn: ({target}) => { console.log ( target)}
|
|
289
626
|
, type : 'input' // According to 'form: define'
|
|
290
627
|
, timing : 'in' // on focus in
|
|
291
628
|
},
|
|
292
629
|
{
|
|
293
|
-
|
|
630
|
+
// Dependencies is available in action functions
|
|
631
|
+
fn: ({target, dependencies }) => { console.log ( 'extra')}
|
|
294
632
|
, type : 'input'
|
|
295
633
|
, timing : 'in' // on focus in
|
|
296
634
|
},
|
|
@@ -314,11 +652,11 @@ Plugin `form` has a default versions for `form:watch` and `form:define` function
|
|
|
314
652
|
```js
|
|
315
653
|
const _defaults = {
|
|
316
654
|
watch : () => 'input, select, textarea, button, a'
|
|
317
|
-
, define: (
|
|
318
|
-
if (
|
|
655
|
+
, define: ({target}) => {
|
|
656
|
+
if ( target.type === 'checkbox' || target.type === 'radio' ) {
|
|
319
657
|
return 'checkbox'
|
|
320
658
|
}
|
|
321
|
-
if (
|
|
659
|
+
if ( target.type == 'button' || target.type=='submit' ) {
|
|
322
660
|
return 'button'
|
|
323
661
|
}
|
|
324
662
|
return 'input'
|
|
@@ -328,6 +666,11 @@ const _defaults = {
|
|
|
328
666
|
|
|
329
667
|
If you want to pause of resume event from `form` plugin, call `short.pause(eventName)` and `short.resume(eventName)` where eventName is a `${type}/${timing}`. Take type and timing from action definitions.
|
|
330
668
|
|
|
669
|
+
### Per-Context Setup (Coming Soon)
|
|
670
|
+
The `form:setup` event is planned for future versions to allow per-context configuration of form plugin settings. Currently, form plugin uses default settings or global plugin options.
|
|
671
|
+
|
|
672
|
+
**Note**: In version 4.0.0, the `form:action` event now has access to `dependencies` at the top level, allowing you to minimize dependency declarations. Other named arguments are not available at the top level of `form:action`.
|
|
673
|
+
|
|
331
674
|
|
|
332
675
|
|
|
333
676
|
## Action Functions
|
|
@@ -441,7 +784,20 @@ const short = shortcut ({onShortcut: (shortcut) => console.log(shortcut) }) // L
|
|
|
441
784
|
### Plugin 'click' options
|
|
442
785
|
```js
|
|
443
786
|
mouseWait : 'Timeout for entering multiple mouse events. Default value - 320.'
|
|
444
|
-
, clickTarget : '
|
|
787
|
+
, clickTarget : 'Array of attribute names to recognize click items in HTML. Default value - ["data-click", "href"]' // checks for data-click='someName' or href attributes
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### Plugin 'hover' options
|
|
791
|
+
```js
|
|
792
|
+
wait : 'Time to wait for hover sequence in ms. Default value - 320.'
|
|
793
|
+
, hoverTarget : 'Array of attribute names to recognize hover items in HTML. Default value - ["data-hover"]' // checks for data-hover='someName' attribute
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### Plugin 'scroll' options
|
|
797
|
+
```js
|
|
798
|
+
scrollWait : 'Delay between scroll events in ms. Default value - 50.'
|
|
799
|
+
, endScrollWait : 'Delay when scroll was stopped in ms. Default value - 400.'
|
|
800
|
+
, minSpace : 'Minimum distance between scroll events in px. Default value - 40.'
|
|
445
801
|
```
|
|
446
802
|
|
|
447
803
|
Plugin options are provided as a second argument during the plugin enabling. It's look like this:
|
|
@@ -454,7 +810,18 @@ Plugin options are provided as a second argument during the plugin enabling. It'
|
|
|
454
810
|
|
|
455
811
|
short.enablePlugin ( pluginClick, {
|
|
456
812
|
mouseWait: 200 // set the interval between multiple clicks to 200ms
|
|
457
|
-
, clickTarget: 'puk'
|
|
813
|
+
, clickTarget: ['data-puk', 'data-button'] // array of attribute names to check
|
|
814
|
+
})
|
|
815
|
+
|
|
816
|
+
short.enablePlugin ( pluginHover, {
|
|
817
|
+
wait: 500 // set the hover delay to 500ms
|
|
818
|
+
, hoverTarget: ['data-hover-me', 'data-interactive'] // array of attribute names to check
|
|
819
|
+
})
|
|
820
|
+
|
|
821
|
+
short.enablePlugin ( pluginScroll, {
|
|
822
|
+
scrollWait: 100 // set the delay between scroll events to 100ms
|
|
823
|
+
, endScrollWait: 600 // set the end scroll delay to 600ms
|
|
824
|
+
, minSpace: 60 // set minimum distance to 60px
|
|
458
825
|
})
|
|
459
826
|
|
|
460
827
|
```
|
|
@@ -490,18 +857,22 @@ Plugin options are provided as a second argument during the plugin enabling. It'
|
|
|
490
857
|
The library includes TypeScript definitions. Install the package and TypeScript will automatically detect the types.
|
|
491
858
|
|
|
492
859
|
```typescript
|
|
493
|
-
import { shortcuts, pluginKey, pluginClick, pluginForm } from '@peter.naydenov/shortcuts';
|
|
860
|
+
import { shortcuts, pluginKey, pluginClick, pluginForm, pluginHover, pluginScroll } from '@peter.naydenov/shortcuts';
|
|
494
861
|
|
|
495
862
|
const short: ShortcutsAPI = shortcuts();
|
|
496
|
-
|
|
497
|
-
short.enablePlugin(
|
|
498
|
-
|
|
863
|
+
const shortcutPlugins = [ pluginKey, pluginClick, pluginForm, pluginHover, pluginScroll ];
|
|
864
|
+
shortcutPlugins.forEach( plugin => short.enablePlugin(plugin) );
|
|
865
|
+
|
|
866
|
+
|
|
499
867
|
|
|
500
868
|
// Type-safe shortcut definitions
|
|
501
869
|
const shortcutDefinition = {
|
|
502
870
|
myContext: {
|
|
503
871
|
'key:ctrl+s': () => console.log('Saved'),
|
|
504
|
-
'click:left-1': (args: { target: HTMLElement }) => console.log('Clicked', args.target)
|
|
872
|
+
'click:left-1': (args: { target: HTMLElement }) => console.log('Clicked', args.target),
|
|
873
|
+
'hover:on': (args: { target: HTMLElement }) => console.log('Hovered', args.target),
|
|
874
|
+
'scroll:down': () => console.log('Scrolled down'),
|
|
875
|
+
'scroll:end': () => console.log('Scrolling ended')
|
|
505
876
|
}
|
|
506
877
|
};
|
|
507
878
|
|
|
@@ -513,10 +884,11 @@ The `ShortcutsAPI` interface provides full type safety for all methods and their
|
|
|
513
884
|
|
|
514
885
|
## Links
|
|
515
886
|
|
|
516
|
-
- [
|
|
517
|
-
- [Migration guide](https://github.com/PeterNaydenov/shortcuts/blob/main/Migration.guide.md)
|
|
887
|
+
- [API reference](https://github.com/PeterNaydenov/shortcuts/blob/main/API.md)
|
|
518
888
|
- [How to make a plugin](https://github.com/PeterNaydenov/shortcuts/blob/main/How.to.make.plugins.md)
|
|
519
|
-
|
|
889
|
+
- [ Build a SPA apps with shortcuts (@peter.naydenov/cuts)](https://github.com/PeterNaydenov/cuts )
|
|
890
|
+
- [History of changes - changelog](https://github.com/PeterNaydenov/shortcuts/blob/main/Changelog.md)
|
|
891
|
+
- [Migration guide](https://github.com/PeterNaydenov/shortcuts/blob/main/Migration.guide.md)
|
|
520
892
|
|
|
521
893
|
|
|
522
894
|
## Credits
|
package/dist/main.d.ts
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
export type dependencies = {
|
|
2
|
+
/**
|
|
3
|
+
* - Event emitter instance
|
|
4
|
+
*/
|
|
5
|
+
ev: any;
|
|
6
|
+
/**
|
|
7
|
+
* - Internal API object
|
|
8
|
+
*/
|
|
9
|
+
inAPI: any;
|
|
10
|
+
/**
|
|
11
|
+
* - Public API object
|
|
12
|
+
*/
|
|
13
|
+
API: any;
|
|
14
|
+
/**
|
|
15
|
+
* - Extra dependencies object
|
|
16
|
+
*/
|
|
17
|
+
extra: any;
|
|
18
|
+
};
|
|
19
|
+
export type state = {
|
|
20
|
+
/**
|
|
21
|
+
* - Current context data container with name and note properties
|
|
22
|
+
*/
|
|
23
|
+
currentContext: any;
|
|
24
|
+
/**
|
|
25
|
+
* - Shortcuts object: { contextName : { shortcut : callback[] } }
|
|
26
|
+
*/
|
|
27
|
+
shortcuts: any;
|
|
28
|
+
/**
|
|
29
|
+
* - Array of active plugins
|
|
30
|
+
*/
|
|
31
|
+
plugins: any[];
|
|
32
|
+
/**
|
|
33
|
+
* - Keyboard shortcut log function
|
|
34
|
+
*/
|
|
35
|
+
exposeShortcut: Function | null;
|
|
36
|
+
/**
|
|
37
|
+
* - Name for error events
|
|
38
|
+
*/
|
|
39
|
+
ERROR_EVENT_NAME: string;
|
|
40
|
+
};
|
|
1
41
|
export type PluginAPI = {
|
|
2
42
|
/**
|
|
3
43
|
* - Get plugin prefix
|
|
@@ -24,6 +64,16 @@ export type PluginAPI = {
|
|
|
24
64
|
*/
|
|
25
65
|
destroy: () => void;
|
|
26
66
|
};
|
|
67
|
+
export type contextShortcuts = {
|
|
68
|
+
/**
|
|
69
|
+
* - Context name
|
|
70
|
+
*/
|
|
71
|
+
context: string;
|
|
72
|
+
/**
|
|
73
|
+
* - List of shortcuts in a context
|
|
74
|
+
*/
|
|
75
|
+
shortcuts: string[];
|
|
76
|
+
};
|
|
27
77
|
export type ShortcutsAPI = {
|
|
28
78
|
/**
|
|
29
79
|
* - Enable a plugin
|
|
@@ -92,7 +142,7 @@ export type ShortcutsAPI = {
|
|
|
92
142
|
/**
|
|
93
143
|
* - List shortcuts
|
|
94
144
|
*/
|
|
95
|
-
listShortcuts: (arg0: string | null) => string[] |
|
|
145
|
+
listShortcuts: (arg0: string | null) => string[] | contextShortcuts[] | null;
|
|
96
146
|
/**
|
|
97
147
|
* - Load shortcuts into contexts
|
|
98
148
|
*/
|
|
@@ -117,4 +167,6 @@ declare function main(options?: {
|
|
|
117
167
|
import pluginKey from './plugins/key/index.js';
|
|
118
168
|
import pluginClick from './plugins/click/index.js';
|
|
119
169
|
import pluginForm from './plugins/form/index.js';
|
|
120
|
-
|
|
170
|
+
import pluginHover from './plugins/hover/index.js';
|
|
171
|
+
import pluginScroll from './plugins/scroll/index.js';
|
|
172
|
+
export { main as shortcuts, pluginKey, pluginClick, pluginForm, pluginHover, pluginScroll };
|