@peter.naydenov/shortcuts 1.1.1 → 2.1.0
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/Changelog.md +19 -0
- package/Migration.guide.md +51 -0
- package/README.md +69 -13
- package/index.html +1 -1
- package/package.json +4 -4
- package/src/main.js +104 -50
- package/src/methods/_findTarget.js +19 -0
- package/src/{listen.js → methods/_listen.js} +63 -40
- package/src/{readKeyEvent.js → methods/_readKeyEvent.js} +6 -6
- package/src/{readMouseEvent.js → methods/_readMouseEvent.js} +4 -4
- package/src/{readShortcut.js → methods/_readShortcut.js} +4 -3
- package/src/methods/_specialChars.js +38 -0
- package/src/{changeContext.js → methods/changeContext.js} +18 -2
- package/src/methods/index.js +29 -0
- package/src/methods/listShortcuts.js +40 -0
- package/src/{load.js → methods/load.js} +13 -4
- package/src/{unload.js → methods/unload.js} +11 -3
- package/test/01-general.cy.js +86 -2
- package/test-components/Block.jsx +1 -0
- package/blueprint-docs.md +0 -73
- package/dist/assets/index-3c4377c6.js +0 -1
- package/dist/index.html +0 -32
- package/dist/vite.svg +0 -1
- package/src/findTarget.js +0 -18
- package/src/specialChars.js +0 -31
package/Changelog.md
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
## Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
### 2.1.0 ( 2023-10-17 )
|
|
5
|
+
- [x] Method `setDependencies` to add more external objects available in all action functions;
|
|
6
|
+
- [x] Method `getDependencies` to look at existing `dependencies` list;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### 2.0.0 ( 2023-10-16 )
|
|
11
|
+
- [x] HTML attribute `data-quick-click` is available to speed up single click response;
|
|
12
|
+
- [x] Documentation on methods `pause` and `resume`;
|
|
13
|
+
- [x] Method `listShortcuts` to get names of all shortcuts defined;
|
|
14
|
+
- [x] Arguments for `onShortcut` and `streamKeys` converted to named arguments;
|
|
15
|
+
- [x] Method `setDependencies` to add objects to the "**dependencies**" object available as named argument in all action functions;
|
|
16
|
+
- [x] Method `getDependencies` to look at existing `dependencies` list;
|
|
17
|
+
- [x] Methods `onShortcut` and `streamKeys` have a new argument `dependencies` to pass dependencies to the callback;
|
|
18
|
+
- [x] Dependencies are aviailable for `emit` method as well as first argument;
|
|
19
|
+
- [x] JSdoc type description for public methods;
|
|
20
|
+
- [x] Tag <a> is always a target, regardless of argument 'data-click'. Tag <a> is always a `data-quick-click` target also;
|
|
21
|
+
|
|
22
|
+
|
|
4
23
|
|
|
5
24
|
### 1.1.1 (2023-09-30)
|
|
6
25
|
- [x] Mouse faster response when maxClicks achived. (maxClicks is automatically calculated according shortcut definitions);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Migration Guides
|
|
2
|
+
|
|
3
|
+
## From version 1.x.x to version 2.x.x
|
|
4
|
+
There are 2 breaking changes: in action functions and in emit method.
|
|
5
|
+
### Action functions
|
|
6
|
+
Version 1.x.x:
|
|
7
|
+
```js
|
|
8
|
+
function ( shortcut, contextName, contextNote ) {
|
|
9
|
+
// ...
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
In version 2.x.x:
|
|
13
|
+
```js
|
|
14
|
+
function ({ shortcut, context, note, dependencies } ) {
|
|
15
|
+
// Change:
|
|
16
|
+
// - all arguments are named(properties of single object);
|
|
17
|
+
// - argument order doesn't matter;
|
|
18
|
+
// - added argument `dependencies` to pass dependencies to all action function;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Emit method
|
|
23
|
+
|
|
24
|
+
Version 1.x.x:
|
|
25
|
+
```js
|
|
26
|
+
let result = null;
|
|
27
|
+
const myAllContext = {
|
|
28
|
+
myAll: {
|
|
29
|
+
'yo' : r => result = r
|
|
30
|
+
}}
|
|
31
|
+
short.load ( myAllContext )
|
|
32
|
+
short.changeContext ( 'myAll' )
|
|
33
|
+
short.emit ( 'yo', 'hello' )
|
|
34
|
+
// result == 'hello'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
In version 2.x.x:
|
|
38
|
+
```js
|
|
39
|
+
let result = null;
|
|
40
|
+
const myAllContext = {
|
|
41
|
+
myAll: {
|
|
42
|
+
'yo' : ( dependencies, r ) => result = r
|
|
43
|
+
// Change:
|
|
44
|
+
// - first argument is always dependencies object;
|
|
45
|
+
// - event-data is available from position 2 of arguments list;
|
|
46
|
+
}}
|
|
47
|
+
short.load ( myAllContext )
|
|
48
|
+
short.changeContext ( 'myAll' )
|
|
49
|
+
short.emit ( 'yo', 'hello' )
|
|
50
|
+
// result == 'hello'
|
|
51
|
+
```
|
package/README.md
CHANGED
|
@@ -11,8 +11,11 @@ Define a context based keyboard-shortcuts and describe a mouse clicks. Switch am
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
## What's new?
|
|
14
|
-
Version 1.1.0 is coming with new method `emit` that make possible to trigger context functions also programmatically. In `shortcuts` you can mix keyboard, mouse and programmatical events that is prity everything that can happen in a web page.
|
|
15
14
|
|
|
15
|
+
- Version 1.1.x and above are coming with method `emit` that make possible to trigger shortcuts programmatically. In `shortcuts` you can mix keyboard, mouse and programmatical events that is prity everything that can happen in a web page;
|
|
16
|
+
- Method `setDependencies` comes after version 2.0.0. You can insert external libraries and modules that you will need to access from action functions. They will come as **dependencies** object. In function `emit` will come as first argument. Other arguments are attached behind the dependencies object;
|
|
17
|
+
- Another html data attribute is added - `data-quick-click`. Example: `<button data-click="id" data-quick-click>Click me</button>`. This attribute is saying to `shortcuts` that target element don't need to wait for more then 1 click and shortcut can be executed immediately after the click. Attribute is available in version 2.0.0 and above;
|
|
18
|
+
- Method `listShortcuts` is added in version 2.0.0. It returns a list of shortcuts for requested context. If context is not set, will return a list of all shortcuts;
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
## Shortcut Description Rules
|
|
@@ -131,6 +134,43 @@ Order of describing mouse event and modifier keys is not important.
|
|
|
131
134
|
Multiple clicks are detected automatically by time interval between clicks. The default interval is 320ms but you can change it by setting `mouseWait` option. Read more in section `Options`.
|
|
132
135
|
|
|
133
136
|
|
|
137
|
+
## Define a mouse targets
|
|
138
|
+
Target HTML elements for `shortcuts` are defined by `data-click` attribute. The value of the attribute is the name of the target. Example:
|
|
139
|
+
|
|
140
|
+
```html
|
|
141
|
+
<button data-click="id">Click me</button>
|
|
142
|
+
<!-- target name is 'id' -->
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Attribute is customizable by setting `clickTarget` option. Read more in section `Options`.
|
|
146
|
+
|
|
147
|
+
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:
|
|
148
|
+
|
|
149
|
+
```html
|
|
150
|
+
<button data-click="id" data-quick-click>Click me</button>
|
|
151
|
+
<!-- target name is 'id' and will not wait for more then 1 click -->
|
|
152
|
+
```
|
|
153
|
+
Using a <a> tag is a special case. It's always recognized as a target, and always with attribute `data-quick-click`. No need to set it manually. Example:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<a href="#">Click me</a>
|
|
157
|
+
<!-- Recognized as a target and will not wait for more then 1 click -->
|
|
158
|
+
<!-- Take care for the action from shortcut `mouse-click-left-1`. -->
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Clicking on <a> tag will not execute anything. All events are blocked by default. In your `mouse-click-left-1` action function you can write a code to execute the default action. Example:
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
{
|
|
165
|
+
contextName : {
|
|
166
|
+
'mouse-click-left-1' : function ( {target, event} ) {
|
|
167
|
+
if ( target.tagName === 'A' ) { // All targets that are <a> tags will execute the default action
|
|
168
|
+
window.location.href = target.href // Go to the link
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
134
174
|
|
|
135
175
|
|
|
136
176
|
|
|
@@ -201,6 +241,7 @@ Description of keyboard action functions is:
|
|
|
201
241
|
function myKeyHandler ({
|
|
202
242
|
context // (string) Name of the current context;
|
|
203
243
|
, note // (string) Name of the note or null if note isn't set;
|
|
244
|
+
, dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
|
|
204
245
|
, wait // (function). Call it to stop a sequence timer and write shortcut sequence without a timer.
|
|
205
246
|
, end // (function). Recover the sequence timer;
|
|
206
247
|
, ignore // (function). Call it to ignore the current shortcut from the sequence;
|
|
@@ -220,6 +261,7 @@ Mouse action functions can be described like:
|
|
|
220
261
|
function myMouseHandler ({
|
|
221
262
|
context // (string) Name of the current context;
|
|
222
263
|
, note // (string) Name of the note or null if note isn't set;
|
|
264
|
+
, dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
|
|
223
265
|
, target // (DOM element). Target element of the mouse event;
|
|
224
266
|
, targetProps // (object). Coordinates of the target element (top, left, right, bottom, width, height) or null if target element is not available;
|
|
225
267
|
, x // (number). X coordinate of the target element;
|
|
@@ -239,18 +281,30 @@ function myMouseHandler ({
|
|
|
239
281
|
Description of the methods of shortcut instance:
|
|
240
282
|
|
|
241
283
|
```js
|
|
242
|
-
load
|
|
243
|
-
, unload
|
|
244
|
-
, changeContext
|
|
245
|
-
, emit
|
|
246
|
-
, pause
|
|
247
|
-
, resume
|
|
248
|
-
, listContexts
|
|
249
|
-
, getContext
|
|
250
|
-
, getNote
|
|
251
|
-
, setNote
|
|
284
|
+
load : 'Load and extend a shortcut definition.'
|
|
285
|
+
, unload : 'Remove a shortcut context with all its shortcuts.'
|
|
286
|
+
, changeContext : 'Switch to existing shortcut context.'
|
|
287
|
+
, emit : 'Trigger a shortcut or custom event programmatically.'
|
|
288
|
+
, pause : 'Stop listening for shortcuts.'
|
|
289
|
+
, resume : 'Resume listening for shortcuts.'
|
|
290
|
+
, listContexts : 'Return list of available contexts.'
|
|
291
|
+
, getContext : 'Return a name of current context or null if there is no context selected'
|
|
292
|
+
, getNote : `Return a name of current note or null if note isn't set`
|
|
293
|
+
, setNote : 'Set a note to current context.'
|
|
294
|
+
, setDependencies : 'Set dependencies that will be available in action functions.'
|
|
295
|
+
, getDependencies : 'Return dependencies object.'
|
|
252
296
|
```
|
|
253
297
|
|
|
298
|
+
### How to 'pause' and 'resume'?
|
|
299
|
+
When you want to stop execution of shortcuts, call `short.pause()`. It's equal to `short.pause('*')`. Will stop all shortcuts in the active context. Stop for single shortcut is by calling `short.pause('shortcutName')`. To resume shortcuts execution call `short.resume()`. It's equal to `short.resume('*')`. Will resume all shortcuts in the active context. Resume for single shortcut is by calling `short.resume('shortcutName')`.
|
|
300
|
+
|
|
301
|
+
```js
|
|
302
|
+
// pause all shortcuts in the active context
|
|
303
|
+
short.pause () // will stop all shortcuts in the active context
|
|
304
|
+
short.resume ( 'shift+a' ) // will resume only 'shift+a' shortcut
|
|
305
|
+
|
|
306
|
+
short.resume ('*') // will resume all shortcuts
|
|
307
|
+
```
|
|
254
308
|
|
|
255
309
|
|
|
256
310
|
|
|
@@ -283,10 +337,11 @@ const short = shortcuts ( shortcuts.getDefaults () ) // same as above
|
|
|
283
337
|
|
|
284
338
|
### onShortcut option
|
|
285
339
|
```js
|
|
286
|
-
function onShortcut ( shortcut, context, note ) {
|
|
340
|
+
function onShortcut ({ shortcut, context, note, dependencies }) {
|
|
287
341
|
// shortcut - (string) Triggered shortcut name
|
|
288
342
|
// context - (string) Name of the current context
|
|
289
343
|
// note - (string) Name of the note or null if note isn't set
|
|
344
|
+
// dependencies - (object) Object with dependencies that you have set by calling `setDependencies` method
|
|
290
345
|
}
|
|
291
346
|
```
|
|
292
347
|
|
|
@@ -294,10 +349,11 @@ const short = shortcuts ( shortcuts.getDefaults () ) // same as above
|
|
|
294
349
|
|
|
295
350
|
### streamKeys option
|
|
296
351
|
```js
|
|
297
|
-
function streamKeys ( key, context, note ) {
|
|
352
|
+
function streamKeys ({ key, context, note, dependencies }) {
|
|
298
353
|
// key - (string) Pressed key name
|
|
299
354
|
// context - (string) Name of the current context
|
|
300
355
|
// note - (string) Name of the note or null if note isn't set
|
|
356
|
+
// dependencies - (object) Object with dependencies that you have set by calling `setDependencies` method
|
|
301
357
|
}
|
|
302
358
|
```
|
|
303
359
|
|
package/index.html
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import sc from '/src/main.js'
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
|
-
onShortcut ( shortcut, context, note ) {
|
|
28
|
+
onShortcut ({ shortcut, context, note }) {
|
|
29
29
|
console.log ( '-- RESULTS --->' )
|
|
30
30
|
console.log ( 'Shortcut', shortcut )
|
|
31
31
|
console.log ( 'Context:', context )
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/shortcuts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Context control of shortcuts based on keyboard and mouse events",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shortcut",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@vitejs/plugin-react": "^4.1.0",
|
|
28
|
-
"ask-for-promise": "^1.
|
|
28
|
+
"ask-for-promise": "^1.4.0",
|
|
29
29
|
"chai": "^4.3.10",
|
|
30
|
-
"cypress": "^13.3.
|
|
30
|
+
"cypress": "^13.3.1",
|
|
31
31
|
"mocha": "^10.2.0",
|
|
32
32
|
"react": "^18.2.0",
|
|
33
33
|
"react-dom": "^18.2.0",
|
|
34
|
-
"vite": "^4.4.
|
|
34
|
+
"vite": "^4.4.11"
|
|
35
35
|
},
|
|
36
36
|
"author": "Peter Naydenov",
|
|
37
37
|
"license": "MIT"
|
package/src/main.js
CHANGED
|
@@ -10,21 +10,13 @@
|
|
|
10
10
|
* - Development was started on June 21st, 2023
|
|
11
11
|
* - First version was published on August 14th, 2023
|
|
12
12
|
* - Method 'emit' was added on September 30st, 2023
|
|
13
|
+
* - Version 2.0.0 was published on October 16th, 2023
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
import notice
|
|
18
|
-
|
|
19
|
-
import listen from './listen.js'
|
|
20
|
-
import readShortcut from './readShortcut.js'
|
|
21
|
-
import readKeyEvent from './readKeyEvent.js'
|
|
22
|
-
import readMouseEvent from './readMouseEvent.js'
|
|
23
|
-
import findTarget from './findTarget.js'
|
|
24
|
-
import specialChars from './specialChars.js'
|
|
25
|
-
import load from './load.js'
|
|
26
|
-
import unload from './unload.js'
|
|
27
|
-
import changeContext from './changeContext.js'
|
|
18
|
+
import notice from '@peter.naydenov/notice' // Docs: https://github.com/PeterNaydenov/notice
|
|
19
|
+
import methods from './methods/index.js'
|
|
28
20
|
|
|
29
21
|
|
|
30
22
|
|
|
@@ -33,53 +25,115 @@ import changeContext from './changeContext.js'
|
|
|
33
25
|
function main ( options = {} ) {
|
|
34
26
|
const
|
|
35
27
|
ev = notice () // Event emitter instance
|
|
36
|
-
,
|
|
37
|
-
,
|
|
38
|
-
,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
28
|
+
, inAPI = {} // API for internal methods
|
|
29
|
+
, API = {} // API for public methods
|
|
30
|
+
, state = {
|
|
31
|
+
currentContext : { name: null, note: null } // Context data container
|
|
32
|
+
, shortcuts : {} // shortcuts = { contextName : { shortcut : callback[] } }
|
|
33
|
+
, listenOptions : {
|
|
34
|
+
mouseWait : options.mouseWait ? options.mouseWait : 320 // 320 ms
|
|
35
|
+
, maxClicks : 1 // The maximum number of clicks in a sequence. Controlled automatically by 'changeContext' function.
|
|
36
|
+
, keyWait : options.keyWait ? options.keyWait : 480 // 480 ms
|
|
37
|
+
, maxSequence : 1 // How many keys can be pressed in a sequence. Controlled automatically by 'changeContext' function.
|
|
38
|
+
, clickTarget : options.clickTarget ? options.clickTarget : 'click' // Data-attribute name for click target ( data-click )
|
|
39
|
+
, listenFor : (options.listenFor && Array.isArray(options.listenFor)) ? options.listenFor : [ 'mouse', 'keyboard' ] // What to listen for: ['mouse'], ['keyboard'], ['mouse', 'keyboard']
|
|
40
|
+
, keyIgnore : null // Timer for ignoring key presses after max sequence or null. Not a public option.
|
|
41
|
+
}
|
|
42
|
+
, exposeShortcut : (options.onShortcut && ( typeof options.onShortcut === 'function')) ? options.onShortcut : false
|
|
43
|
+
, streamKeys : (options.streamKeys && ( typeof options.streamKeys === 'function')) ? options.streamKeys : false
|
|
44
|
+
} // state
|
|
52
45
|
, dependencies = {
|
|
53
|
-
|
|
54
|
-
,
|
|
55
|
-
,
|
|
56
|
-
,
|
|
57
|
-
, ev
|
|
58
|
-
, exposeShortcut
|
|
59
|
-
, streamKeys
|
|
46
|
+
ev
|
|
47
|
+
, inAPI
|
|
48
|
+
, API
|
|
49
|
+
, extra : {}
|
|
60
50
|
}
|
|
61
51
|
;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @function getContext
|
|
55
|
+
* @description Get current context name
|
|
56
|
+
* @returns {string} - Current context name
|
|
57
|
+
*/
|
|
58
|
+
API.getContext = () => state.currentContext.name
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @function getNote
|
|
62
|
+
* @description Get current context note
|
|
63
|
+
* @returns {string} - Current context note
|
|
64
|
+
*/
|
|
65
|
+
API.getNote = () => state.currentContext.note
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @function setNote
|
|
69
|
+
* @description Set current context note
|
|
70
|
+
* @param {string} note - Context note
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
API.setNote = (note=null) => { if (typeof note === 'string' || note == null ) state.currentContext.note = note }
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @function pause
|
|
77
|
+
* @description Pause shortcut(s) in current context
|
|
78
|
+
* @param {string} [name='*' ] - Shortcut name that should be paused. Default is '*' - all shortcuts in current context.
|
|
79
|
+
* @returns {void}
|
|
80
|
+
*/
|
|
81
|
+
API.pause = (name='*') => ev.stop ( inAPI._readShortcut(name) )
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @function resume
|
|
85
|
+
* @description Resume shortcut(s) in current context
|
|
86
|
+
* @param {string} [name='*' ] - Shortcut name that should be resumed. Default is '*' - all shortcuts in current context.
|
|
87
|
+
* @returns {void}
|
|
88
|
+
*/
|
|
89
|
+
API.resume = (name='*') => ev.start ( inAPI._readShortcut(name) )
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @function emit
|
|
93
|
+
* @description Emit event for shortcut in current context
|
|
94
|
+
* @param {string} name - Shortcut name
|
|
95
|
+
* @param {any} [args] - Arguments for callback function
|
|
96
|
+
* @returns {void}
|
|
97
|
+
**/
|
|
98
|
+
API.emit = (name,...args) => ev.emit ( inAPI._readShortcut(name), dependencies.extra, ...args )
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @function listContexts
|
|
102
|
+
* @description List all context names
|
|
103
|
+
* @returns {string[]} - Array of context names
|
|
104
|
+
*/
|
|
105
|
+
API.listContexts = () => Object.keys ( shortcuts )
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @function setDependencies
|
|
109
|
+
* @description Set a dependency package that will be provided to each action function
|
|
110
|
+
* @param {object} deps - Enumerate external dependencies
|
|
111
|
+
* @returns {void}
|
|
112
|
+
*/
|
|
113
|
+
API.setDependencies = (deps) => dependencies.extra = { ...dependencies.extra, ...deps }
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @function getDependencies
|
|
117
|
+
* @description Get a dependency package that will be provided to each action function
|
|
118
|
+
* @returns {object} - Enumerate external dependencies
|
|
119
|
+
**/
|
|
120
|
+
API.getDependencies = () => dependencies.extra
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
Object.entries ( methods ).forEach ( ([ name, method ]) => {
|
|
125
|
+
if ( name.startsWith('_') ) inAPI [ name ] = method ( dependencies, state )
|
|
126
|
+
else API [ name ] = method ( dependencies, state )
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
inAPI._listen ()
|
|
130
|
+
return API
|
|
77
131
|
} // main func.
|
|
78
132
|
|
|
79
133
|
|
|
80
134
|
|
|
81
135
|
main.getDefaults = () => ({
|
|
82
|
-
mouseWait : 320 // 320 ms
|
|
136
|
+
mouseWait : 320 // 320 ms
|
|
83
137
|
, keyWait : 480 // 480 ms
|
|
84
138
|
, clickTarget : 'click' // Data-attribute name for click target ( data-click )
|
|
85
139
|
, listenFor : [ 'mouse', 'keyboard' ]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function _findTarget ( dependencies, state ) {
|
|
4
|
+
const { listenOptions : {clickTarget}} = state;
|
|
5
|
+
return function _findTarget ( target ) {
|
|
6
|
+
const t = target;
|
|
7
|
+
if ( t === document ) return null
|
|
8
|
+
if ( t === document.body ) return null
|
|
9
|
+
|
|
10
|
+
if ( t.dataset[clickTarget] ) return t
|
|
11
|
+
if ( t.nodeName === 'A' ) return t
|
|
12
|
+
return _findTarget ( t.parentNode )
|
|
13
|
+
}} // _findTarget func.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export default _findTarget
|
|
18
|
+
|
|
19
|
+
|
|
@@ -2,22 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
function
|
|
5
|
+
function _listen ( dependencies, state ) {
|
|
6
|
+
// Listen for input signals and generate event titles
|
|
7
|
+
return function _listen () {
|
|
6
8
|
const {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
, {
|
|
9
|
+
ev
|
|
10
|
+
, inAPI : {
|
|
11
|
+
_findTarget
|
|
12
|
+
, _specialChars
|
|
13
|
+
, _readKeyEvent
|
|
14
|
+
, _readMouseEvent
|
|
15
|
+
}
|
|
16
|
+
} = dependencies
|
|
17
|
+
, {
|
|
18
|
+
exposeShortcut
|
|
19
|
+
, currentContext
|
|
20
|
+
, streamKeys
|
|
21
|
+
, listenOptions
|
|
22
|
+
} = state
|
|
23
|
+
, {
|
|
16
24
|
mouseWait
|
|
17
25
|
, keyWait
|
|
18
26
|
, clickTarget
|
|
19
|
-
, listenFor
|
|
20
|
-
} =
|
|
27
|
+
, listenFor
|
|
28
|
+
} = listenOptions
|
|
21
29
|
;
|
|
22
30
|
|
|
23
31
|
let
|
|
@@ -54,10 +62,18 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
54
62
|
ignore = false
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
|
-
|
|
65
|
+
const data = {
|
|
66
|
+
wait: waitKeys
|
|
67
|
+
, end:endKeys
|
|
68
|
+
, ignore:ignoreKeys
|
|
69
|
+
, isWaiting:waitingKeys
|
|
70
|
+
, note: currentContext.note
|
|
71
|
+
, context: currentContext.name
|
|
72
|
+
, dependencies : dependencies.extra
|
|
73
|
+
};
|
|
58
74
|
if ( sequence ) {
|
|
59
|
-
ev.emit ( res.join(','),
|
|
60
|
-
if ( exposeShortcut ) exposeShortcut ( res.join(','), currentContext.name, currentContext.note
|
|
75
|
+
ev.emit ( res.join(','), data )
|
|
76
|
+
if ( exposeShortcut ) exposeShortcut ({ shortcut:res.join(','), context: currentContext.name, note:currentContext.note, dependencies:dependencies.extra })
|
|
61
77
|
// Reset:
|
|
62
78
|
r = []
|
|
63
79
|
keyTimer = null
|
|
@@ -68,7 +84,7 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
68
84
|
|
|
69
85
|
function mouseSequenceEnd () { // Execute when mouse sequence ends
|
|
70
86
|
const
|
|
71
|
-
mouseEvent =
|
|
87
|
+
mouseEvent = _readMouseEvent ( mouseDomEvent, count )
|
|
72
88
|
, data = {
|
|
73
89
|
target : mouseTarget
|
|
74
90
|
, targetProps : mouseTarget ? mouseTarget.getBoundingClientRect() : null
|
|
@@ -77,10 +93,11 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
77
93
|
, context : currentContext.name
|
|
78
94
|
, note : currentContext.note
|
|
79
95
|
, event : mouseDomEvent
|
|
96
|
+
, dependencies : dependencies.extra
|
|
80
97
|
}
|
|
81
98
|
;
|
|
82
99
|
ev.emit ( mouseEvent.join('+'), data )
|
|
83
|
-
if ( exposeShortcut ) exposeShortcut ( mouseEvent.join('+'), currentContext.name, currentContext.note )
|
|
100
|
+
if ( exposeShortcut ) exposeShortcut ({ shortcut: mouseEvent.join('+'), context:currentContext.name, note:currentContext.note, dependencies:dependencies.extra })
|
|
84
101
|
// Reset:
|
|
85
102
|
mouseTimer = null
|
|
86
103
|
mouseIgnore = null
|
|
@@ -93,6 +110,7 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
93
110
|
|
|
94
111
|
function listenMouse () {
|
|
95
112
|
window.addEventListener ( 'contextmenu', event => { // Listen for right mouse clicks
|
|
113
|
+
let targetMax = listenOptions.maxClicks; // Maximum number of clicks per target
|
|
96
114
|
event.preventDefault ()
|
|
97
115
|
clearTimeout ( mouseTimer )
|
|
98
116
|
if ( mouseIgnore ) {
|
|
@@ -100,18 +118,21 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
100
118
|
mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
101
119
|
return
|
|
102
120
|
}
|
|
103
|
-
mouseTarget =
|
|
121
|
+
mouseTarget = _findTarget ( event.target )
|
|
122
|
+
if ( mouseTarget && mouseTarget.dataset.hasOwnProperty('quickClick')) targetMax = 1
|
|
123
|
+
if ( mouseTarget && mouseTarget.tagName === 'A' ) targetMax = 1
|
|
104
124
|
mouseDomEvent = event
|
|
105
125
|
count++
|
|
106
|
-
if ( count
|
|
126
|
+
if ( count >= targetMax ) {
|
|
107
127
|
mouseSequenceEnd ()
|
|
108
|
-
mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
128
|
+
if ( targetMax > 1 ) mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
109
129
|
return
|
|
110
130
|
}
|
|
111
131
|
mouseTimer = setTimeout ( mouseSequenceEnd, mouseWait )
|
|
112
132
|
})
|
|
113
133
|
|
|
114
134
|
document.addEventListener ( 'click', event => { // Listen for left and middle mouse clicks
|
|
135
|
+
let targetMax = listenOptions.maxClicks; // Maximum number of clicks per target
|
|
115
136
|
event.preventDefault ()
|
|
116
137
|
clearTimeout ( mouseTimer )
|
|
117
138
|
if ( mouseIgnore ) {
|
|
@@ -119,12 +140,14 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
119
140
|
mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
120
141
|
return
|
|
121
142
|
}
|
|
122
|
-
mouseTarget =
|
|
143
|
+
mouseTarget = _findTarget ( event.target )
|
|
144
|
+
if ( mouseTarget && mouseTarget.dataset.hasOwnProperty('quickClick')) targetMax = 1
|
|
145
|
+
if ( mouseTarget && mouseTarget.tagName === 'A' ) targetMax = 1
|
|
123
146
|
mouseDomEvent = event
|
|
124
147
|
count++
|
|
125
|
-
if ( count >=
|
|
148
|
+
if ( count >= targetMax ) {
|
|
126
149
|
mouseSequenceEnd ()
|
|
127
|
-
mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
150
|
+
if ( targetMax > 1 ) mouseIgnore = setTimeout ( () => mouseIgnore=null, mouseWait )
|
|
128
151
|
return
|
|
129
152
|
}
|
|
130
153
|
mouseTimer = setTimeout ( mouseSequenceEnd, mouseWait )
|
|
@@ -136,17 +159,17 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
136
159
|
function listenKeyboard () {
|
|
137
160
|
document.addEventListener ( 'keydown', event => { // Listen for special keyboard keys
|
|
138
161
|
clearTimeout ( keyTimer )
|
|
139
|
-
if (
|
|
162
|
+
if ( _specialChars.hasOwnProperty(event.code) ) r.push ( _readKeyEvent ( event, _specialChars ))
|
|
140
163
|
else return
|
|
141
|
-
if ( streamKeys ) streamKeys ( event.key, currentContext.name, currentContext.note )
|
|
142
|
-
if (
|
|
143
|
-
clearTimeout (
|
|
144
|
-
|
|
164
|
+
if ( streamKeys ) streamKeys ({ key:event.key, context:currentContext.name, note:currentContext.note, dependencies:dependencies.extra })
|
|
165
|
+
if ( listenOptions.keyIgnore ) {
|
|
166
|
+
clearTimeout ( listenOptions.keyIgnore )
|
|
167
|
+
listenOptions.keyIgnore = setTimeout ( () => listenOptions.keyIgnore=null, keyWait )
|
|
145
168
|
return
|
|
146
169
|
}
|
|
147
|
-
if ( sequence && r.length ===
|
|
170
|
+
if ( sequence && r.length === listenOptions.maxSequence ) {
|
|
148
171
|
keySequenceEnd ()
|
|
149
|
-
|
|
172
|
+
listenOptions.keyIgnore = setTimeout ( () => listenOptions.keyIgnore=null, keyWait )
|
|
150
173
|
return
|
|
151
174
|
}
|
|
152
175
|
if ( sequence ) keyTimer = setTimeout ( keySequenceEnd, keyWait )
|
|
@@ -154,18 +177,18 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
154
177
|
})
|
|
155
178
|
|
|
156
179
|
document.addEventListener ( 'keypress', event => { // Listen for regular keyboard keys
|
|
157
|
-
if (
|
|
180
|
+
if ( _specialChars.hasOwnProperty(event.code) ) return
|
|
158
181
|
clearTimeout ( keyTimer )
|
|
159
|
-
if ( streamKeys ) streamKeys ( event.key, currentContext.name, currentContext.note )
|
|
160
|
-
if (
|
|
161
|
-
clearTimeout (
|
|
162
|
-
|
|
182
|
+
if ( streamKeys ) streamKeys ({ key:event.key, context:currentContext.name, note:currentContext.note, dependencies:dependencies.extra })
|
|
183
|
+
if ( listenOptions.keyIgnore ) {
|
|
184
|
+
clearTimeout ( listenOptions.keyIgnore )
|
|
185
|
+
listenOptions.keyIgnore = setTimeout ( () => listenOptions.keyIgnore=null, keyWait )
|
|
163
186
|
return
|
|
164
187
|
}
|
|
165
|
-
r.push (
|
|
166
|
-
if ( sequence && r.length ===
|
|
188
|
+
r.push ( _readKeyEvent ( event, _specialChars ))
|
|
189
|
+
if ( sequence && r.length === listenOptions.maxSequence ) {
|
|
167
190
|
keySequenceEnd ()
|
|
168
|
-
|
|
191
|
+
listenOptions.keyIgnore = setTimeout ( () => listenOptions.keyIgnore=null, keyWait )
|
|
169
192
|
return
|
|
170
193
|
}
|
|
171
194
|
if ( sequence ) keyTimer = setTimeout ( keySequenceEnd, keyWait )
|
|
@@ -178,10 +201,10 @@ function listen ( dependencies, options, currentContext ) { // Listen for inpu
|
|
|
178
201
|
if ( listenFor.includes('mouse') ) listenMouse ()
|
|
179
202
|
if ( listenFor.includes('keyboard') ) listenKeyboard ()
|
|
180
203
|
|
|
181
|
-
} //
|
|
204
|
+
}} // _listen func.
|
|
182
205
|
|
|
183
206
|
|
|
184
207
|
|
|
185
|
-
export default
|
|
208
|
+
export default _listen
|
|
186
209
|
|
|
187
210
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
function
|
|
3
|
+
function _readKeyEvent () {
|
|
4
|
+
return function _readKeyEvent ( event, _specialChars ) {
|
|
5
5
|
let
|
|
6
6
|
{ shiftKey, altKey, ctrlKey } = event
|
|
7
7
|
, falseKeys = [ 'ControlLeft','ControlRight', 'ShiftLeft', 'ShiftRight', 'AltLeft', 'AltRight', 'Meta' ]
|
|
@@ -15,13 +15,13 @@ function readKeyEvent ( event, specialChars ) {
|
|
|
15
15
|
if ( shiftKey ) res.push ( 'SHIFT' )
|
|
16
16
|
if ( altKey ) res.push ( 'ALT' )
|
|
17
17
|
|
|
18
|
-
if (
|
|
19
|
-
else if (
|
|
18
|
+
if ( _specialChars.hasOwnProperty ( key ) ) res.push ( _specialChars[key].toUpperCase () )
|
|
19
|
+
else if ( !falseKeys.includes(key) ) res.push ( key.toUpperCase () )
|
|
20
20
|
return res.sort ()
|
|
21
|
-
} //
|
|
21
|
+
}} // _readKeyEvent func.
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
export default
|
|
25
|
+
export default _readKeyEvent
|
|
26
26
|
|
|
27
27
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
function
|
|
3
|
+
function _readMouseEvent () {
|
|
4
|
+
return function _readMouseEvent ( event, count ) {
|
|
5
5
|
let
|
|
6
6
|
{ shiftKey, altKey, ctrlKey, key, button } = event
|
|
7
7
|
, mouseNames = [ 'LEFT', 'MIDDLE', 'RIGHT' ]
|
|
@@ -15,10 +15,10 @@ function readMouseEvent ( event, count ) {
|
|
|
15
15
|
if ( altKey ) res.push ( 'ALT' )
|
|
16
16
|
|
|
17
17
|
return res.sort ()
|
|
18
|
-
} //
|
|
18
|
+
}} // _readMouseEvent func.
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
export default
|
|
22
|
+
export default _readMouseEvent
|
|
23
23
|
|
|
24
24
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
// [ crtl+s, shift+alt+o]
|
|
3
|
-
function
|
|
3
|
+
function _readShortcut () {
|
|
4
|
+
return function _readShortcut ( txt ) {
|
|
4
5
|
const r = txt
|
|
5
6
|
.split ( ',' )
|
|
6
7
|
.map ( (x) => x.trim() )
|
|
7
8
|
.map ( (x) => x.split ( '+' ).map(x => x.toUpperCase()).sort().join('+') )
|
|
8
9
|
.join ( ',' );
|
|
9
10
|
return r
|
|
10
|
-
} //
|
|
11
|
+
}} // _readShortcut func.
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
export default
|
|
15
|
+
export default _readShortcut
|
|
15
16
|
|
|
16
17
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function _specialChars () {
|
|
2
|
+
return {
|
|
3
|
+
'ArrowLeft' : 'LEFT'
|
|
4
|
+
, 'ArrowUp' : 'UP'
|
|
5
|
+
, 'ArrowRight' : 'RIGHT'
|
|
6
|
+
, 'ArrowDown' : 'DOWN'
|
|
7
|
+
, 'Enter' : 'ENTER'
|
|
8
|
+
, 'NumpadEnter' : 'ENTER'
|
|
9
|
+
, 'Escape' : 'ESC'
|
|
10
|
+
, 'Backspace' : 'BACKSPACE'
|
|
11
|
+
, 'Space' : 'SPACE'
|
|
12
|
+
, 'Tab' : 'TAB'
|
|
13
|
+
, 'Backquote' : '`'
|
|
14
|
+
, 'BracketLeft' : '['
|
|
15
|
+
, 'BracketRight': ']'
|
|
16
|
+
, 'Equal' : '='
|
|
17
|
+
, 'Slash' : '/'
|
|
18
|
+
, 'Backslash' : '\\'
|
|
19
|
+
, 'IntlBackslash' : '`'
|
|
20
|
+
, 'F1' : 'F1'
|
|
21
|
+
, 'F2' : 'F2'
|
|
22
|
+
, 'F3' : 'F3'
|
|
23
|
+
, 'F4' : 'F4'
|
|
24
|
+
, 'F5' : 'F5'
|
|
25
|
+
, 'F6' : 'F6'
|
|
26
|
+
, 'F7' : 'F7'
|
|
27
|
+
, 'F8' : 'F8'
|
|
28
|
+
, 'F9' : 'F9'
|
|
29
|
+
, 'F10' : 'F10'
|
|
30
|
+
, 'F11' : 'F11'
|
|
31
|
+
, 'F12' : 'F12'
|
|
32
|
+
}}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export default _specialChars
|
|
37
|
+
|
|
38
|
+
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
function changeContext (
|
|
3
|
+
function changeContext ( dependencies, state ) {
|
|
4
|
+
const
|
|
5
|
+
{
|
|
6
|
+
shortcuts
|
|
7
|
+
, listenOptions
|
|
8
|
+
, currentContext
|
|
9
|
+
} = state
|
|
10
|
+
, { ev } = dependencies
|
|
11
|
+
;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @function changeContext
|
|
15
|
+
* @description Change current context with shortcuts belonging to it.
|
|
16
|
+
* @param {string} [contextName=false] - Name of context to change to. Default 'false' will switch off all shortcuts.
|
|
17
|
+
* @returns {void}
|
|
18
|
+
*/
|
|
4
19
|
return function changeContext ( contextName = false ) {
|
|
5
20
|
const current = currentContext.name;
|
|
21
|
+
|
|
6
22
|
listenOptions.maxSequence = 1
|
|
7
23
|
listenOptions.maxClicks = 1
|
|
8
24
|
|
|
@@ -37,7 +53,7 @@ return function changeContext ( contextName = false ) {
|
|
|
37
53
|
}
|
|
38
54
|
list.forEach ( fn => ev.on ( shortcutName, fn ) ) // Enable new context shortcuts
|
|
39
55
|
})
|
|
40
|
-
currentContext.name = contextName
|
|
56
|
+
currentContext.name = contextName
|
|
41
57
|
}} // changeContext func.
|
|
42
58
|
|
|
43
59
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import _findTarget from './_findTarget.js'
|
|
2
|
+
import _listen from './_listen.js'
|
|
3
|
+
import _readKeyEvent from './_readKeyEvent.js'
|
|
4
|
+
import _readMouseEvent from './_readMouseEvent.js'
|
|
5
|
+
import _readShortcut from './_readShortcut.js'
|
|
6
|
+
import _specialChars from './_specialChars.js'
|
|
7
|
+
|
|
8
|
+
import load from './load.js'
|
|
9
|
+
import unload from './unload.js'
|
|
10
|
+
import changeContext from './changeContext.js'
|
|
11
|
+
import listShortcuts from './listShortcuts.js'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
// Internal methods
|
|
17
|
+
_findTarget
|
|
18
|
+
, _listen
|
|
19
|
+
, _readKeyEvent
|
|
20
|
+
, _readMouseEvent
|
|
21
|
+
, _readShortcut
|
|
22
|
+
, _specialChars
|
|
23
|
+
|
|
24
|
+
// Public methods
|
|
25
|
+
, changeContext
|
|
26
|
+
, listShortcuts
|
|
27
|
+
, load
|
|
28
|
+
, unload
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {object} contextShortcuts
|
|
4
|
+
* @property {string} context - Context name
|
|
5
|
+
* @property {string[]} shortcuts - List of shortcuts in a context
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function listShortcuts ( dependencies, state ) {
|
|
11
|
+
const shortcuts = state.shortcuts;
|
|
12
|
+
/**
|
|
13
|
+
* List all shortcuts in all contexts or in a specific context.
|
|
14
|
+
* @param {string}[ contextName=null] - List of shortcuts for provided context name. (optional)
|
|
15
|
+
* @returns {string[]|contextShortcuts[]} - List of shortcuts for a specified context or list of contextShortcuts for all contexts.
|
|
16
|
+
*/
|
|
17
|
+
return function listShortcuts ( contextName=null ) {
|
|
18
|
+
|
|
19
|
+
// Create a list of shortcuts for a specific context:
|
|
20
|
+
if ( contextName != null ) {
|
|
21
|
+
let context = shortcuts[contextName];
|
|
22
|
+
if ( context == null ) return null
|
|
23
|
+
return Object.entries ( context ).map ( ([shortcut, callbacks]) => shortcut )
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create a list of allShortcuts for each context:
|
|
27
|
+
return Object.keys ( shortcuts ).map ( contextName => {
|
|
28
|
+
let result = {};
|
|
29
|
+
result['context'] = contextName
|
|
30
|
+
result['shortcuts'] = Object.entries ( shortcuts[contextName] ).map ( ([shortcut, callbacks]) => shortcut )
|
|
31
|
+
return result
|
|
32
|
+
}) // map
|
|
33
|
+
|
|
34
|
+
}} // listShortcuts func.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export default listShortcuts
|
|
39
|
+
|
|
40
|
+
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
function load ( dependencies, state ) {
|
|
4
|
+
const
|
|
5
|
+
{ shortcuts } = state
|
|
6
|
+
, {
|
|
7
|
+
inAPI : { _readShortcut }
|
|
8
|
+
, API : { changeContext, getContext }
|
|
9
|
+
} = dependencies;
|
|
10
|
+
/**
|
|
11
|
+
* Load a context with shortcuts object
|
|
12
|
+
* @param {Object} obj - Context description object: { contextName : { shortcut : callback[] }
|
|
13
|
+
* @returns {void}
|
|
14
|
+
*/
|
|
6
15
|
return function load ( obj ) {
|
|
7
16
|
const
|
|
8
17
|
currentContextName = getContext ()
|
|
@@ -14,7 +23,7 @@ return function load ( obj ) {
|
|
|
14
23
|
if ( contextName === currentContextName ) hasChanges = true;
|
|
15
24
|
shortcuts [ contextName ] = {}
|
|
16
25
|
description.forEach ( ([ title, callbackList ]) => {
|
|
17
|
-
const name =
|
|
26
|
+
const name = _readShortcut ( title );
|
|
18
27
|
if ( callbackList instanceof Function ) callbackList = [ callbackList ]
|
|
19
28
|
shortcuts [contextName][ name ] = callbackList
|
|
20
29
|
}) // shortcuts.forEach
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
function unload ( dependencies, state ) {
|
|
4
|
+
const
|
|
5
|
+
{ currentContext, shortcuts } = state
|
|
6
|
+
, { ev } = dependencies
|
|
7
|
+
;
|
|
8
|
+
/**
|
|
9
|
+
* @function unload
|
|
10
|
+
* @description Unload a non-active context with shortcuts.
|
|
11
|
+
* @param {string} contextName - Context name to unload
|
|
12
|
+
* @returns {void}
|
|
13
|
+
*/
|
|
6
14
|
return function unload ( contextName ) {
|
|
7
15
|
const current = currentContext.name;
|
|
8
16
|
if ( current === contextName ) {
|
package/test/01-general.cy.js
CHANGED
|
@@ -4,11 +4,13 @@ import '../test-components/style.css'
|
|
|
4
4
|
import shortcuts from '../src/main.js'
|
|
5
5
|
import { expect } from 'chai'
|
|
6
6
|
|
|
7
|
+
import askForPromise from 'ask-for-promise'
|
|
8
|
+
|
|
7
9
|
let
|
|
8
10
|
a = false
|
|
9
11
|
, b = false
|
|
10
12
|
;
|
|
11
|
-
const short = shortcuts ({onShortcut : (
|
|
13
|
+
const short = shortcuts ({onShortcut : ({shortcut, context, note}) => console.log (shortcut, context, note)});
|
|
12
14
|
short.load ({
|
|
13
15
|
general : {
|
|
14
16
|
'shift+a': [ () => a = true ]
|
|
@@ -116,12 +118,94 @@ it ( 'Emit custom event', () => {
|
|
|
116
118
|
const myAllContext = {
|
|
117
119
|
myAll: {
|
|
118
120
|
'mouse-click-leff-1' : () => console.log ( 'nothing' )
|
|
119
|
-
, 'yo' : r => result = r
|
|
121
|
+
, 'yo' : (dependencies,r) => result = r
|
|
120
122
|
}}
|
|
121
123
|
short.load ( myAllContext )
|
|
122
124
|
short.changeContext ( 'myAll' )
|
|
123
125
|
short.emit ( 'yo', 'hello' )
|
|
124
126
|
expect ( result ).to.be.equal ( 'hello' )
|
|
127
|
+
short.changeContext ( 'general' )
|
|
128
|
+
short.unload ( 'myAll' )
|
|
125
129
|
}) // it emit custom event
|
|
126
130
|
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
it ( 'Dependencies on shortcuts', done => {
|
|
134
|
+
const task = askForPromise ();
|
|
135
|
+
expect ( a ).to.be.false
|
|
136
|
+
expect ( b ).to.be.false
|
|
137
|
+
|
|
138
|
+
short.setDependencies ({ task })
|
|
139
|
+
|
|
140
|
+
short.load ({
|
|
141
|
+
'extra' : { // load will overwrite existing 'extra' context definition
|
|
142
|
+
'mouse-click-left-1' : ({dependencies}) => {
|
|
143
|
+
const { task } = dependencies;
|
|
144
|
+
expect ( task ).to.have.property ( 'done' )
|
|
145
|
+
expect ( task ).to.have.property ( 'promise' )
|
|
146
|
+
a = true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}) // load will restart the selected context
|
|
150
|
+
|
|
151
|
+
short.changeContext ( 'extra' )
|
|
152
|
+
cy.get('#rspan').click ()
|
|
153
|
+
cy.wait ( 350 ) // Default wait mouse timeout is 320 ms
|
|
154
|
+
.then ( () => {
|
|
155
|
+
expect ( a ).to.be.true
|
|
156
|
+
done ()
|
|
157
|
+
})
|
|
158
|
+
}) // it dependencies on shortcuts
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
it ( 'List shortcuts', () => {
|
|
163
|
+
let general = short.listShortcuts ('general');
|
|
164
|
+
expect ( general ).to.be.an('array')
|
|
165
|
+
expect ( general ).to.have.lengthOf ( 1 )
|
|
166
|
+
expect ( general[0] ).to.be.equal ( 'A+SHIFT' )
|
|
167
|
+
|
|
168
|
+
let fail = short.listShortcuts ('somethingNotExisting');
|
|
169
|
+
expect ( fail ).to.be.null
|
|
170
|
+
|
|
171
|
+
let all = short.listShortcuts ();
|
|
172
|
+
expect ( all ).to.be.an('array')
|
|
173
|
+
|
|
174
|
+
expect ( all ).to.have.lengthOf ( 2 )
|
|
175
|
+
expect ( all[0] ).to.have.property ( 'context' )
|
|
176
|
+
expect ( all[0] ).to.have.property ( 'shortcuts' )
|
|
177
|
+
expect ( all[0].shortcuts ).to.be.an('array')
|
|
178
|
+
expect ( all[0].shortcuts ).to.have.lengthOf ( 1 )
|
|
179
|
+
expect ( all[0].shortcuts[0] ).to.be.equal ( 'A+SHIFT' )
|
|
180
|
+
expect ( all[0].context ).to.be.equal ( 'general' )
|
|
181
|
+
|
|
182
|
+
}) // it list shortcuts
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
it ( 'Click on anchor', done => {
|
|
187
|
+
// Click on anchor that don't have click-data attribute.
|
|
188
|
+
let result = 'none';
|
|
189
|
+
short.load ({ 'extra' : {
|
|
190
|
+
'mouse-click-left-1' : ({target, context }) => {
|
|
191
|
+
expect ( context ).to.be.equal ( 'extra' )
|
|
192
|
+
expect ( target.nodeName ).to.be.equal ( 'A' )
|
|
193
|
+
result = target.nodeName
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
short.changeContext ( 'extra' )
|
|
198
|
+
cy.get ( '#anchor' ).click ()
|
|
199
|
+
cy.wait ( 3 ) // Consider mouse click has some latency
|
|
200
|
+
// According Cypress documentation:
|
|
201
|
+
// It is unsafe to chain further commands that rely on the subject after .click().
|
|
202
|
+
// source docs: https://docs.cypress.io/api/commands/click
|
|
203
|
+
.then ( () => {
|
|
204
|
+
short.changeContext ( 'general' )
|
|
205
|
+
expect ( result ).to.be.equal ( 'A' )
|
|
206
|
+
done ()
|
|
207
|
+
})
|
|
208
|
+
}) // it click on anchor
|
|
209
|
+
|
|
210
|
+
|
|
127
211
|
}) // describe
|
|
@@ -2,6 +2,7 @@ function Block () {
|
|
|
2
2
|
return <>
|
|
3
3
|
<div className="block" data-click="red"><span id='rspan'>Red</span> </div>
|
|
4
4
|
<button className="big-btn" data-click="mega">Mega button</button>
|
|
5
|
+
<p>Some text with <a href="#" target="_blank">link <span id="anchor">in</span></a> it</p>
|
|
5
6
|
</>
|
|
6
7
|
}
|
|
7
8
|
|
package/blueprint-docs.md
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Shortcuts (@peter.naydenov/shortcuts)
|
|
2
|
-
*UNDER HEAVY DEVELOPMENT - early experimental stage*
|
|
3
|
-
|
|
4
|
-
Build a keyboard shortcuts maps and describe a mouse clicks. Control them on context.
|
|
5
|
-
|
|
6
|
-
Tread it as a "**draft**" during `HEAVY DEVELOPMENT` stage. the API will change frequently and version of the package will not be updated. Will stay at `0.0.1` until the API get usable.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Create shortcuts for your web application based on keyboard and mouse events.
|
|
13
|
-
|
|
14
|
-
Listen for keyboard, mouse and touch events and converts them into event-emmiter events.
|
|
15
|
-
Define a shortcut library with shortcut names and callback functions. The callback functions will be called when the shortcut is pressed. Library `shortcuts` supports a context switching and that allows
|
|
16
|
-
to add, remove and change multiple shortcuts by changing the current context.
|
|
17
|
-
|
|
18
|
-
- Context switching;
|
|
19
|
-
- Listen for keyboard, mouse and touch events;
|
|
20
|
-
- Read a shortcut sequences;
|
|
21
|
-
- Multiple mouse clicks events for left and right mouse buttons;
|
|
22
|
-
- The delay between keypresses and mouse clicks in shortcut sequences are controlled by parameters;
|
|
23
|
-
- Centralized control over mouse click event. All clicks on the page can be described by a single callback function;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Define and conrol shortcuts in your application. Setup a stage, create a shortcut name and associate a list of callback function with it. The callback function will be called when the shortcut is pressed. Changing the stage will stop all shortcuts associated with it old stage and start all shortcuts associated with the new stage.
|
|
27
|
-
|
|
28
|
-
Event sources: keyboard, mouse, touch;
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm i @peter.naydenov/shortcuts
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
From the project file:
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
import shortcuts from '@peter.naydenov/shortcuts'
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Methods
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```js
|
|
47
|
-
'load' : 'Provide context objects, shortcuts related to the context and list of callback functions'
|
|
48
|
-
, 'unload' : 'Remove context objects and shortcuts'
|
|
49
|
-
, 'changeContext' : 'Change the current context. Change active list of shortcuts'
|
|
50
|
-
, 'pause' : 'Disable all shortcuts. No change of context'
|
|
51
|
-
, 'resume' : 'Resume shortcuts after pause'
|
|
52
|
-
, 'getContext' : 'Return the current context name'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## Keyboard Action functions
|
|
57
|
-
Keypress will create an event with name of pressed keys. If `shortcut` has a callback function associated with this name, the callback function will be called.
|
|
58
|
-
|
|
59
|
-
The callback function will receive an object with the following properties:
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
function keyCallback (key) {
|
|
63
|
-
console.log(key)
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
Every shortcut is defined by a callback function. The callback function will be called when the shortcut is pressed. The callback function will receive an object with the following properties:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```js
|
|
70
|
-
function keyCallback (key) {
|
|
71
|
-
console.log(key)
|
|
72
|
-
}
|
|
73
|
-
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))i(o);new MutationObserver(o=>{for(const l of o)if(l.type==="childList")for(const u of l.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&i(u)}).observe(document,{childList:!0,subtree:!0});function t(o){const l={};return o.integrity&&(l.integrity=o.integrity),o.referrerPolicy&&(l.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?l.credentials="include":o.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function i(o){if(o.ep)return;o.ep=!0;const l=t(o);fetch(o.href,l)}})();function M(){function r(){let e={},t={},i=[],o=!1,l="";function u(n,s){e[n]||(e[n]=[]),e[n].push(s)}function c(n,s){t[n]||(t[n]=[]),t[n].push(s)}function y(n,s){if(s){e[n]&&(e[n]=e[n].filter(g=>g!==s)),t[n]&&(t[n]=t[n].filter(g=>g!==s)),e[n]&&e[n].length===0&&delete e[n],t[n]&&t[n].length===0&&delete e[n];return}t[n]&&delete t[n],e[n]&&delete e[n]}function f(){e={},t={},i=[]}function m(n,s){o=!!n,s&&typeof s=="string"&&(l=s)}function d(){const[n,...s]=arguments;if(o&&(console.log(`${l} Event "${n}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),n=="*"&&Object.keys(e).forEach(E=>{i.includes(E)||e[E].forEach(F=>F(...s))}),t[n]){if(i.includes(n))return;t[n].forEach(g=>g(...s)),delete t[n]}if(e[n]){if(i.includes(n))return;e[n].forEach(g=>g(...s))}}function k(n){if(n==="*"){i=[];return}i=i.filter(s=>n!=s)}function p(n){if(n==="*"){const s=Object.keys(e);i=[...Object.keys(t),...s];return}i.push(n)}return{on:u,once:c,off:y,reset:f,emit:d,stop:p,start:k,debug:m}}return new r}function P(r,e,t){const{specialChars:i,readKeyEvent:o,readMouseEvent:l,findTarget:u,ev:c,exposeShortcut:y,streamKeys:f}=r,{mouseWait:m,keyWait:d,clickTarget:k,listenFor:p}=e;let n=[],s=null,g=null,E=null,F=null,h=null,T=!0,L=!1,S=0;const A=()=>T=!1,b=()=>T=!0,O=()=>L=!0,v=()=>T===!1;function I(){let a=n.map(K=>[K.join("+")]);if(!T){let K=a.at(-1);c.emit(K,{wait:A,end:b,ignore:O,isWaiting:v,note:t.note,context:t.name}),L&&(a=a.slice(0,-1),L=!1)}T&&(c.emit(a.join(","),{wait:A,end:b,ignore:O,isWaiting:v,note:t.note,context:t.name}),y&&y(a.join(","),t.name,t.note),n=[],E=null)}function w(){const a=l(g,S),K={target:s,targetProps:s?s.getBoundingClientRect():null,x:g.clientX,y:g.clientY,context:t.name,note:t.note,event:g};c.emit(a.join("+"),K),y&&y(a.join("+"),t.name,t.note),F=null,h=null,s=null,g=null,S=0}function q(){window.addEventListener("contextmenu",a=>{if(clearTimeout(F),h){clearTimeout(h),h=setTimeout(()=>h=null,m);return}if(S===e.maxClicks){w(),h=setTimeout(()=>h=null,m);return}a.preventDefault(),s=u(a.target,k),g=a,S++,F=setTimeout(w,m)}),document.addEventListener("click",a=>{if(clearTimeout(F),h){clearTimeout(h),h=setTimeout(()=>h=null,m);return}if(S===e.maxClicks){w(),h=setTimeout(()=>h=null,m);return}s=u(a.target,k),g=a,S++,F=setTimeout(w,m)})}function j(){document.addEventListener("keydown",a=>{if(clearTimeout(E),i.hasOwnProperty(a.code))n.push(o(a,i));else return;if(f&&f(a.key,t.name,t.note),e.keyIgnore){clearTimeout(e.keyIgnore),e.keyIgnore=setTimeout(()=>e.keyIgnore=null,d);return}if(T&&n.length===e.maxSequence){I(),e.keyIgnore=setTimeout(()=>e.keyIgnore=null,d);return}T?E=setTimeout(I,d):I()}),document.addEventListener("keypress",a=>{if(!i.hasOwnProperty(a.code)){if(clearTimeout(E),f&&f(a.key,t.name,t.note),e.keyIgnore){clearTimeout(e.keyIgnore),e.keyIgnore=setTimeout(()=>e.keyIgnore=null,d);return}if(n.push(o(a,i)),T&&n.length===e.maxSequence){I(),e.keyIgnore=setTimeout(()=>e.keyIgnore=null,d);return}T?E=setTimeout(I,d):I()}})}p.includes("mouse")&&q(),p.includes("keyboard")&&j()}function B(r){return r.split(",").map(t=>t.trim()).map(t=>t.split("+").map(i=>i.toUpperCase()).sort().join("+")).join(",")}function D(r,e){let{shiftKey:t,altKey:i,ctrlKey:o}=r,l=["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"],u=r.code.replace("Key","").replace("Digit",""),c=[];return o&&c.push("CTRL"),t&&c.push("SHIFT"),i&&c.push("ALT"),e.hasOwnProperty(u)?c.push(e[u].toUpperCase()):l.includes(u)||c.push(u.toUpperCase()),c.sort()}function U(r,e){let{shiftKey:t,altKey:i,ctrlKey:o,key:l,button:u}=r,c=["LEFT","MIDDLE","RIGHT"],y=`MOUSE-CLICK-${c[u]}-${e}`,f=[];return f.push(y),o&&f.push("CTRL"),t&&f.push("SHIFT"),i&&f.push("ALT"),f.sort()}function $(r,e){let t=r;for(;t&&!t.dataset[e];)if(t=t.parentNode,t===document||t===document.body)return null;return t}const x={ArrowLeft:"LEFT",ArrowUp:"UP",ArrowRight:"RIGHT",ArrowDown:"DOWN",Enter:"ENTER",NumpadEnter:"ENTER",Escape:"ESC",Backspace:"BACKSPACE",Space:"SPACE",Tab:"TAB",Backquote:"`",BracketLeft:"[",BracketRight:"]",Equal:"=",Slash:"/",Backslash:"\\",IntlBackslash:"`",F1:"F1",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",F10:"F10",F11:"F11",F12:"F12"};function N(r,e,t,i){return function(l){const u=i(),c=Object.keys(l);let y=!1;c.forEach(f=>{const m=Object.entries(l[f]);f===u&&(y=!0),r[f]={},m.forEach(([d,k])=>{const p=e(d);k instanceof Function&&(k=[k]),r[f][p]=k})}),y&&(t(),t(u))}}function H(r,e,t){return function(o){if(t.name===o){e.emit("shortcuts-error",`Context '${o}' can't be removed during is current active context. Change the context first`);return}if(!r[o]){e.emit("shortcuts-error",`Context '${o}' does not exist`);return}delete r[o]}}function R(r,e,t,i){return function(l=!1){const u=i.name;if(e.maxSequence=1,e.maxClicks=1,e.keyIgnore>=0&&(clearTimeout(e.keyIgnore),e.keyIgnore=null),!l){t.reset(),i.name=null;return}if(u!==l){if(!r[l]){t.emit("shortcuts-error",`Context '${l}' does not exist`);return}r[u]&&t.reset(),Object.entries(r[l]).forEach(([c,y])=>{if(c.includes("MOUSE-CLICK-")){let[,,,m]=c.split("-"),d=parseInt(m);e.maxClicks<d&&(e.maxClicks=d)}else{let m=c.split(",").length;e.maxSequence<m&&(e.maxSequence=m)}y.forEach(m=>t.on(c,m))}),i.name=l}}}function W(r={}){const e=M(),t={name:null,note:null},i=r.onShortcut&&typeof r.onShortcut=="function"?r.onShortcut:!1,o=r.streamKeys&&typeof r.streamKeys=="function"?r.streamKeys:!1,l={mouseWait:r.mouseWait?r.mouseWait:320,maxClicks:1,keyWait:r.keyWait?r.keyWait:480,maxSequence:1,clickTarget:r.clickTarget?r.clickTarget:"click",listenFor:r.listenFor&&Array.isArray(r.listenFor)?r.listenFor:["mouse","keyboard"],keyIgnore:null},u={},c=()=>t.name,y=()=>t.note,f=(d=null)=>{(typeof d=="string"||d==null)&&(t.note=d)};return P({specialChars:x,readKeyEvent:D,readMouseEvent:U,findTarget:$,ev:e,exposeShortcut:i,streamKeys:o},l,t),{load:N(u,B,R(u,l,e,t),c),unload:H(u,e,t),changeContext:R(u,l,e,t),pause:()=>e.stop(),resume:()=>e.start(),listContexts:()=>Object.keys(u),getContext:c,getNote:y,setNote:f}}W.getDefaults=()=>({mouseWait:320,keyWait:480,clickTarget:"click",listenFor:["mouse","keyboard"],onShortcut:!1,streamKeys:!1});const G={onShortcut(r,e,t){console.log("-- RESULTS --->"),console.log("Shortcut",r),console.log("Context:",e),t&&console.log("Note:",t)}},C=W(G);C.load({general:{q:[()=>console.log("Q was clicked")],"r,o,s":()=>console.log("ROS was clicked"),"mouse-click-left-2":()=>console.log("Mouse left click 2"),r:[({isWaiting:r})=>{r()||console.log("R was clicked")}],"shift+w":[({wait:r,end:e,ignore:t,isWaiting:i,note:o})=>{t(),i()?(console.log("END"),e()):(console.log("WAIT"),r())},()=>console.log("W")]}});C.changeContext("general");C.setNote("some");
|
package/dist/index.html
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>Vite App</title>
|
|
8
|
-
<style>
|
|
9
|
-
.block {
|
|
10
|
-
width: 100px;
|
|
11
|
-
height: 100px;
|
|
12
|
-
background-color: red;
|
|
13
|
-
}
|
|
14
|
-
.big-btn {
|
|
15
|
-
width: 200px;
|
|
16
|
-
height: 200px;
|
|
17
|
-
margin-left: 320px;
|
|
18
|
-
background-color: skyblue;
|
|
19
|
-
border-radius: 10px;
|
|
20
|
-
}
|
|
21
|
-
</style>
|
|
22
|
-
<script type="module" crossorigin src="/assets/index-3c4377c6.js"></script>
|
|
23
|
-
</head>
|
|
24
|
-
<body>
|
|
25
|
-
|
|
26
|
-
<div class="block" data-click="red-block">
|
|
27
|
-
<span>hello</span>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<button class="big-btn" data-click="mega-button" draggable>Mega button</button>
|
|
31
|
-
</body>
|
|
32
|
-
</html>
|
package/dist/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/src/findTarget.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
function findTarget ( target, dataName ) {
|
|
5
|
-
let t = target
|
|
6
|
-
while ( t && !t.dataset[dataName] ) {
|
|
7
|
-
t = t.parentNode;
|
|
8
|
-
if ( t === document ) return null
|
|
9
|
-
if ( t === document.body ) return null
|
|
10
|
-
}
|
|
11
|
-
return t
|
|
12
|
-
} // findTarget func.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export default findTarget
|
|
17
|
-
|
|
18
|
-
|
package/src/specialChars.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
'ArrowLeft' : 'LEFT'
|
|
3
|
-
, 'ArrowUp' : 'UP'
|
|
4
|
-
, 'ArrowRight' : 'RIGHT'
|
|
5
|
-
, 'ArrowDown' : 'DOWN'
|
|
6
|
-
, 'Enter' : 'ENTER'
|
|
7
|
-
, 'NumpadEnter' : 'ENTER'
|
|
8
|
-
, 'Escape' : 'ESC'
|
|
9
|
-
, 'Backspace' : 'BACKSPACE'
|
|
10
|
-
, 'Space' : 'SPACE'
|
|
11
|
-
, 'Tab' : 'TAB'
|
|
12
|
-
, 'Backquote' : '`'
|
|
13
|
-
, 'BracketLeft' : '['
|
|
14
|
-
, 'BracketRight': ']'
|
|
15
|
-
, 'Equal' : '='
|
|
16
|
-
, 'Slash' : '/'
|
|
17
|
-
, 'Backslash' : '\\'
|
|
18
|
-
, 'IntlBackslash' : '`'
|
|
19
|
-
, 'F1' : 'F1'
|
|
20
|
-
, 'F2' : 'F2'
|
|
21
|
-
, 'F3' : 'F3'
|
|
22
|
-
, 'F4' : 'F4'
|
|
23
|
-
, 'F5' : 'F5'
|
|
24
|
-
, 'F6' : 'F6'
|
|
25
|
-
, 'F7' : 'F7'
|
|
26
|
-
, 'F8' : 'F8'
|
|
27
|
-
, 'F9' : 'F9'
|
|
28
|
-
, 'F10' : 'F10'
|
|
29
|
-
, 'F11' : 'F11'
|
|
30
|
-
, 'F12' : 'F12'
|
|
31
|
-
}
|