@peter.naydenov/shortcuts 2.1.0 → 3.0.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 +24 -0
- package/How..to.make.plugins.md +41 -0
- package/Migration.guide.md +77 -0
- package/README-v.2.x.x.md +375 -0
- package/README.md +108 -58
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.js +25 -0
- package/cypress/support/component-index.html +14 -0
- package/cypress/support/component.js +27 -0
- package/cypress/support/e2e.js +20 -0
- package/dist/shortcuts.cjs +1 -0
- package/dist/shortcuts.esm.mjs +1 -0
- package/dist/shortcuts.umd.js +1 -0
- package/package.json +32 -19
- package/rollup.config.js +40 -0
- package/src/main.js +81 -30
- package/src/methods/_normalizeWithPlugins.js +25 -0
- package/src/methods/_readShortcutWithPlugins.js +24 -0
- package/src/methods/_systemAction.js +25 -0
- package/src/methods/changeContext.js +20 -26
- package/src/methods/index.js +7 -13
- package/src/methods/load.js +21 -14
- package/src/plugins/click/_findTarget.js +20 -0
- package/src/plugins/click/_listenDOM.js +117 -0
- package/src/plugins/click/_normalizeShortcutName.js +44 -0
- package/src/plugins/click/_readClickEvent.js +24 -0
- package/src/plugins/click/_registerShortcutEvents.js +30 -0
- package/src/plugins/click/index.js +74 -0
- package/src/plugins/key/_listenDOM.js +138 -0
- package/src/plugins/key/_normalizeShortcutName.js +31 -0
- package/src/{methods → plugins/key}/_readKeyEvent.js +2 -3
- package/src/plugins/key/_registerShortcutEvents.js +28 -0
- package/src/plugins/key/index.js +76 -0
- package/test/01-general.cy.js +189 -154
- package/src/methods/_findTarget.js +0 -19
- package/src/methods/_listen.js +0 -210
- package/src/methods/_readMouseEvent.js +0 -24
- package/src/methods/_readShortcut.js +0 -17
- /package/src/{methods → plugins/key}/_specialChars.js +0 -0
package/README.md
CHANGED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|

|
|
5
|
+

|
|
6
|
+

|
|
5
7
|
|
|
6
8
|
|
|
9
|
+
|
|
10
|
+
Describe all page activities as list of shortcuts wrapped in contexts. Switch among available contexts.
|
|
11
|
+
Library has a plugin system to extend the possible `shortcut names`/`event coverage`. Plugins role is to convert DOM events to shortcut strings, then the core part will trigger the action functions related to the shortcut. At the moment we have 2 plugins:
|
|
12
|
+
- `key` - converts keyboard events to shortcut names;
|
|
13
|
+
- `click` - converts mouse events to shortcut names;
|
|
7
14
|
|
|
8
|
-
|
|
15
|
+
Planned work on the plugins for `scroll`, `drag-drop`, `input-change`, etc...
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
## What's new?
|
|
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;
|
|
19
|
-
|
|
20
|
-
|
|
21
19
|
## Shortcut Description Rules
|
|
22
20
|
The shortcuts definition includes a context name and a set of rules(object). The rules are a set of key-value pairs. The key is a shortcut name and the value is a function or array of functions, to be executed when the shortcut is triggered (action function).
|
|
23
21
|
|
|
@@ -42,14 +40,28 @@ The shortcuts definition includes a context name and a set of rules(object). The
|
|
|
42
40
|
]
|
|
43
41
|
}
|
|
44
42
|
}
|
|
43
|
+
// shortcutName after v.3.0.0 have a plugin prefix. - 'pluginPrefix:shortcutName'.
|
|
44
|
+
// For example: 'key:s+alt' - for 's+alt' shortcut that is handled by 'key' plugin.
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Load a shortcut definition by calling `load` method.
|
|
48
48
|
|
|
49
49
|
```js
|
|
50
|
-
|
|
50
|
+
// for es6 module projects:
|
|
51
|
+
include { shortcuts, pluginKey, pluginClick } from '@peter.naydenov/shortcuts'
|
|
52
|
+
// for commonjs projects:
|
|
53
|
+
const { shortcuts, pluginKey, pluginClick } = require('@peter.naydenov/shortcuts')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
51
57
|
const short = shortcuts ();
|
|
58
|
+
// Load a needed plugins
|
|
59
|
+
// short.enablePlugin ( pluginCode, ?pluginOptions )
|
|
60
|
+
short.enablePlugin ( pluginKey )
|
|
61
|
+
short.enablePlugin ( pluginClick )
|
|
62
|
+
// Load a shortcut definition
|
|
52
63
|
short.load ( shortcutDefinition )
|
|
64
|
+
|
|
53
65
|
```
|
|
54
66
|
|
|
55
67
|
Shortcuts are working only if contex is active. To activate a context call `changeContext` method.
|
|
@@ -102,39 +114,45 @@ short.getNote ()
|
|
|
102
114
|
|
|
103
115
|
|
|
104
116
|
|
|
105
|
-
##
|
|
117
|
+
## Plugin 'click' Shortcut Descriptions
|
|
106
118
|
Mouse event name is build from the following parts:
|
|
107
119
|
```js
|
|
108
|
-
//
|
|
120
|
+
// click:<mouse button>-<number of clicks>-<modifier key>-<modifier key>-<modifier key>
|
|
109
121
|
// example:
|
|
110
|
-
//
|
|
111
|
-
//
|
|
122
|
+
// click: left-2 -> for double click with left mouse button
|
|
123
|
+
// click: right-3 -> for triple click with right mouse button
|
|
112
124
|
|
|
113
125
|
// mouse button options: left, right, middle
|
|
114
126
|
```
|
|
115
127
|
|
|
116
|
-
The modifier keys `ctrl`, `alt`, and `shift` are supported. They are added to the mouse event by sign
|
|
128
|
+
The modifier keys `ctrl`, `alt`, and `shift` are supported. They are added to the mouse event by sign `-`:
|
|
117
129
|
|
|
118
130
|
```js
|
|
119
131
|
// example:
|
|
120
|
-
//
|
|
132
|
+
// click: left-1-ctrl -> for single click with left mouse button and ctrl key pressed
|
|
121
133
|
```
|
|
122
|
-
|
|
134
|
+
|
|
135
|
+
Order of describing click event and modifier keys is not important.
|
|
123
136
|
|
|
124
137
|
```js
|
|
125
138
|
// example:
|
|
126
|
-
//
|
|
139
|
+
// click: ctrl-left-1 -> same as above
|
|
127
140
|
|
|
128
141
|
// These 3 descriptions are equal:
|
|
129
|
-
//
|
|
130
|
-
// alt
|
|
131
|
-
//
|
|
142
|
+
// click: left-1-ctrl-alt-shift
|
|
143
|
+
// click: alt-shift-left-1-ctrl
|
|
144
|
+
// click: left-1-shift-ctrl-alt
|
|
132
145
|
```
|
|
133
146
|
|
|
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.
|
|
147
|
+
Multiple clicks are detected automatically by time interval between clicks. The default interval is 320ms but you can change it by setting `mouseWait` click plugin option.
|
|
148
|
+
```js
|
|
149
|
+
short.enablePlugin ( pluginClick, { mouseWait: 500 }) // set the interval to 500ms
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Read more in section `Options`.
|
|
135
153
|
|
|
136
154
|
|
|
137
|
-
## Define a
|
|
155
|
+
## Define a Click Targets
|
|
138
156
|
Target HTML elements for `shortcuts` are defined by `data-click` attribute. The value of the attribute is the name of the target. Example:
|
|
139
157
|
|
|
140
158
|
```html
|
|
@@ -142,7 +160,7 @@ Target HTML elements for `shortcuts` are defined by `data-click` attribute. The
|
|
|
142
160
|
<!-- target name is 'id' -->
|
|
143
161
|
```
|
|
144
162
|
|
|
145
|
-
Attribute is customizable by setting `clickTarget` option. Read more in section `Options`.
|
|
163
|
+
Attribute is customizable by setting `clickTarget` click plugin option. Read more in section `Options`.
|
|
146
164
|
|
|
147
165
|
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
166
|
|
|
@@ -155,17 +173,18 @@ Using a <a> tag is a special case. It's always recognized as a target, and alway
|
|
|
155
173
|
```html
|
|
156
174
|
<a href="#">Click me</a>
|
|
157
175
|
<!-- Recognized as a target and will not wait for more then 1 click -->
|
|
158
|
-
<!-- Take care for the action from shortcut `
|
|
176
|
+
<!-- Take care for the action from shortcut `click: left-1`. -->
|
|
159
177
|
```
|
|
160
178
|
|
|
161
|
-
Clicking on <a> tag will
|
|
179
|
+
Clicking on <a> tag will execute default browser behaviour. In your `click:left-1` action function you can take the control. Example:
|
|
162
180
|
|
|
163
181
|
```js
|
|
164
182
|
{
|
|
165
183
|
contextName : {
|
|
166
|
-
'
|
|
167
|
-
if ( target.tagName === 'A' ) { //
|
|
168
|
-
|
|
184
|
+
'click:left-1' : function ( {target, event} ) {
|
|
185
|
+
if ( target.tagName === 'A' ) { // To prevent default action on <a> tag
|
|
186
|
+
event.preventDefault ()
|
|
187
|
+
// do something...
|
|
169
188
|
}
|
|
170
189
|
}
|
|
171
190
|
}
|
|
@@ -174,35 +193,35 @@ Clicking on <a> tag will not execute anything. All events are blocked by default
|
|
|
174
193
|
|
|
175
194
|
|
|
176
195
|
|
|
177
|
-
##
|
|
196
|
+
## Plugin 'key' Event Descriptions
|
|
178
197
|
Keyboard event description contains a key name and a modifier keys if they are used. The modifier keys `ctrl`, `alt`, and `shift` are supported. They are added to the keyboard event by sign `+`:
|
|
179
198
|
|
|
180
199
|
```js
|
|
181
200
|
// example:
|
|
182
|
-
// ctrl+alt+shift+a -> for key 'a' with ctrl, alt and shift keys pressed
|
|
201
|
+
// key: ctrl+alt+shift+a -> for key 'a' with ctrl, alt and shift keys pressed
|
|
183
202
|
```
|
|
184
203
|
|
|
185
204
|
Keyboard event description support a shortcut sequenses. These means that you can press a sequence of keys to trigger a shortcut. The sequence elements are separated by sign "," ( coma ):
|
|
186
205
|
|
|
187
206
|
```js
|
|
188
207
|
// example:
|
|
189
|
-
// a,b,c -> for key 'a' then key 'b' then key 'c'
|
|
208
|
+
// key: a,b,c -> for key 'a' then key 'b' then key 'c'
|
|
190
209
|
|
|
191
|
-
// g+shift,o,t,o -> for key 'g' with shift, then key 'o', then key 't' then key 'o'
|
|
210
|
+
// key: g+shift,o,t,o -> for key 'g' with shift, then key 'o', then key 't' then key 'o'
|
|
192
211
|
```
|
|
193
212
|
|
|
194
213
|
Order of describing keyboard event and modifier keys is not important, but sequence elements are:
|
|
195
214
|
|
|
196
215
|
```js
|
|
197
216
|
// example:
|
|
198
|
-
// a+ctrl,l,o,t -> a with ctrl, then l, then o, then t
|
|
217
|
+
// key: a+ctrl,l,o,t -> a with ctrl, then l, then o, then t
|
|
199
218
|
// this is equal to:
|
|
200
|
-
// ctrl+a,l,o,t
|
|
219
|
+
// key: ctrl+a,l,o,t
|
|
201
220
|
// but not equal to:
|
|
202
|
-
// ctrl+a,o,t,l
|
|
221
|
+
// key: ctrl+a,o,t,l
|
|
203
222
|
```
|
|
204
223
|
|
|
205
|
-
Keyboard sequence is detected automatically by time interval between key presses. The default interval is 480ms but you can change it by setting `keyWait` option. Read more in section `Options`.
|
|
224
|
+
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`.
|
|
206
225
|
|
|
207
226
|
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`.
|
|
208
227
|
|
|
@@ -224,19 +243,19 @@ Special characters that are available for your shortcut descriptions:
|
|
|
224
243
|
- ']' - close square bracket key
|
|
225
244
|
- '`' - backtick key
|
|
226
245
|
|
|
227
|
-
**Warning**: For keys with two symbols, in shortcut description use the lower one. Examples: Use '=' instead of '+', use '/' instead of '?', etc. Modifier keys are available for special characters too.
|
|
246
|
+
**Warning**: For keys with two symbols(look at the keyboard), in shortcut description use the lower one. Examples: Use '=' instead of '+', use '/' instead of '?', etc. Modifier keys are available for special characters too.
|
|
228
247
|
|
|
229
248
|
**Warining**: Some of the shortcuts are used by OS and the browswer, so they are not available.
|
|
230
249
|
|
|
231
250
|
|
|
232
251
|
|
|
233
252
|
## Action Functions
|
|
234
|
-
Action functions are called when a shortcut is triggered.
|
|
253
|
+
Action functions are called when a shortcut is triggered. There is a difference among plugin action functions. Arguments are slightly different.
|
|
235
254
|
|
|
236
255
|
|
|
237
256
|
|
|
238
257
|
### Keyboard Action Functions
|
|
239
|
-
Description of
|
|
258
|
+
Description of `key` plugin action functions is:
|
|
240
259
|
```js
|
|
241
260
|
function myKeyHandler ({
|
|
242
261
|
context // (string) Name of the current context;
|
|
@@ -255,7 +274,7 @@ function myKeyHandler ({
|
|
|
255
274
|
|
|
256
275
|
|
|
257
276
|
### Mouse Action Functions
|
|
258
|
-
|
|
277
|
+
Click plugin action functions can be described like:
|
|
259
278
|
|
|
260
279
|
```js
|
|
261
280
|
function myMouseHandler ({
|
|
@@ -283,16 +302,23 @@ Description of the methods of shortcut instance:
|
|
|
283
302
|
```js
|
|
284
303
|
load : 'Load and extend a shortcut definition.'
|
|
285
304
|
, unload : 'Remove a shortcut context with all its shortcuts.'
|
|
286
|
-
|
|
305
|
+
|
|
306
|
+
, enablePlugin : 'Enable a plugin.'
|
|
307
|
+
, disablePlugin : 'Disable a plugin.'
|
|
308
|
+
, mutePlugin : 'Mute a plugin. All events for the plugin will be ignored.'
|
|
309
|
+
, unmutePlugin : 'Unmute a plugin. All events for the plugin will be listened again.'
|
|
310
|
+
|
|
311
|
+
, changeContext : 'Switch to existing shortcut context or shitch off the context(if no argument).'
|
|
312
|
+
, getContext : 'Return a name of current context or null if there is no context selected'
|
|
287
313
|
, emit : 'Trigger a shortcut or custom event programmatically.'
|
|
288
314
|
, pause : 'Stop listening for shortcuts.'
|
|
289
315
|
, resume : 'Resume listening for shortcuts.'
|
|
290
316
|
, listContexts : 'Return list of available contexts.'
|
|
291
|
-
,
|
|
317
|
+
, listShortcuts : 'Return list of shortcuts per context.'
|
|
292
318
|
, getNote : `Return a name of current note or null if note isn't set`
|
|
293
319
|
, setNote : 'Set a note to current context.'
|
|
294
320
|
, setDependencies : 'Set dependencies that will be available in action functions.'
|
|
295
|
-
, getDependencies : 'Return dependencies object.'
|
|
321
|
+
, getDependencies : 'Return a dependencies object.'
|
|
296
322
|
```
|
|
297
323
|
|
|
298
324
|
### How to 'pause' and 'resume'?
|
|
@@ -310,27 +336,44 @@ short.resume ('*') // will resume all shortcuts
|
|
|
310
336
|
|
|
311
337
|
## Options
|
|
312
338
|
|
|
313
|
-
|
|
339
|
+
Shortcut receives `options` during the start. Here is the list of available options:
|
|
314
340
|
|
|
315
341
|
```js
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
342
|
+
onShortcut : 'Callback function that is called when a shortcut is triggered. Default value - false'
|
|
343
|
+
```
|
|
344
|
+
```js
|
|
345
|
+
const short = shortcut ({onShortcut: (shortcut) => console.log(shortcut) }) // Log in console each triggered shortcut
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
### Plugin 'key' options
|
|
351
|
+
```js
|
|
352
|
+
keyWait : 'Timeout for entering shortcut sequence in ms. Default value - 480'
|
|
321
353
|
, streamKeys : 'False or a callback function that is called when a key is pressed. Default value - false'
|
|
322
354
|
```
|
|
323
355
|
|
|
324
|
-
You can request default list of options with their default values:
|
|
325
356
|
|
|
357
|
+
|
|
358
|
+
### Plugin 'click' options
|
|
326
359
|
```js
|
|
327
|
-
|
|
328
|
-
|
|
360
|
+
mouseWait : 'Timeout for entering multiple mouse events. Default value - 320.'
|
|
361
|
+
, clickTarget : 'Data attribute name to recognize click items in HTML. Default value - click' // data attribute 'click' means attribute ( data-click='someName' )
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Plugin options are provided as a second argument during the plugin enabling. It's look like this:
|
|
365
|
+
|
|
366
|
+
```js
|
|
367
|
+
short.enablePlugin ( pluginKey, {
|
|
368
|
+
keyWait: 500 // set the interval to 500ms
|
|
369
|
+
, streamKeys: (key) => console.log(key) // Log in console each pressed key
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
short.enablePlugin ( pluginClick, {
|
|
373
|
+
mouseWait: 200 // set the interval between multiple clicks to 200ms
|
|
374
|
+
, clickTarget: 'puk' // data attribute 'puk' means attribute ( data-puk='someName' )
|
|
375
|
+
})
|
|
329
376
|
|
|
330
|
-
// start a shortcuts with default options
|
|
331
|
-
const short = shortcuts ()
|
|
332
|
-
const short = shortcuts ( shortcuts.getDefaults () ) // same as above
|
|
333
|
-
// The idea behind getDefaults is to see what options are available and what are their default values.
|
|
334
377
|
```
|
|
335
378
|
|
|
336
379
|
|
|
@@ -359,6 +402,13 @@ const short = shortcuts ( shortcuts.getDefaults () ) // same as above
|
|
|
359
402
|
|
|
360
403
|
|
|
361
404
|
|
|
405
|
+
## Links
|
|
406
|
+
|
|
407
|
+
- [History of changes](https://github.com/PeterNaydenov/shortcuts/blob/main/Changelog.md)
|
|
408
|
+
- [Migration guide](https://github.com/PeterNaydenov/shortcuts/blob/main/Migration.guide.md)
|
|
409
|
+
- [How to make a plugin](https://github.com/PeterNaydenov/shortcuts/blob/main/How.to.make.plugins.md)
|
|
410
|
+
|
|
411
|
+
|
|
362
412
|
|
|
363
413
|
## Credits
|
|
364
414
|
'@peter.naydenov/shortcuts' was created and supported by Peter Naydenov.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ***********************************************
|
|
2
|
+
// This example commands.js shows you how to
|
|
3
|
+
// create various custom commands and overwrite
|
|
4
|
+
// existing commands.
|
|
5
|
+
//
|
|
6
|
+
// For more comprehensive examples of custom
|
|
7
|
+
// commands please read more here:
|
|
8
|
+
// https://on.cypress.io/custom-commands
|
|
9
|
+
// ***********************************************
|
|
10
|
+
//
|
|
11
|
+
//
|
|
12
|
+
// -- This is a parent command --
|
|
13
|
+
// Cypress.Commands.add('login', (email, password) => { ... })
|
|
14
|
+
//
|
|
15
|
+
//
|
|
16
|
+
// -- This is a child command --
|
|
17
|
+
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
|
18
|
+
//
|
|
19
|
+
//
|
|
20
|
+
// -- This is a dual command --
|
|
21
|
+
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
|
22
|
+
//
|
|
23
|
+
//
|
|
24
|
+
// -- This will overwrite an existing command --
|
|
25
|
+
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
7
|
+
<title>Components App</title>
|
|
8
|
+
<!-- Used by Next.js to inject CSS. -->
|
|
9
|
+
<div id="__next_css__DO_NOT_USE__"></div>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div data-cy-root></div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ***********************************************************
|
|
2
|
+
// This example support/component.js is processed and
|
|
3
|
+
// loaded automatically before your test files.
|
|
4
|
+
//
|
|
5
|
+
// This is a great place to put global configuration and
|
|
6
|
+
// behavior that modifies Cypress.
|
|
7
|
+
//
|
|
8
|
+
// You can change the location of this file or turn off
|
|
9
|
+
// automatically serving support files with the
|
|
10
|
+
// 'supportFile' configuration option.
|
|
11
|
+
//
|
|
12
|
+
// You can read more here:
|
|
13
|
+
// https://on.cypress.io/configuration
|
|
14
|
+
// ***********************************************************
|
|
15
|
+
|
|
16
|
+
// Import commands.js using ES2015 syntax:
|
|
17
|
+
import './commands'
|
|
18
|
+
|
|
19
|
+
// Alternatively you can use CommonJS syntax:
|
|
20
|
+
// require('./commands')
|
|
21
|
+
|
|
22
|
+
import { mount } from 'cypress/react18'
|
|
23
|
+
|
|
24
|
+
Cypress.Commands.add('mount', mount)
|
|
25
|
+
|
|
26
|
+
// Example use:
|
|
27
|
+
// cy.mount(<MyComponent />)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ***********************************************************
|
|
2
|
+
// This example support/e2e.js is processed and
|
|
3
|
+
// loaded automatically before your test files.
|
|
4
|
+
//
|
|
5
|
+
// This is a great place to put global configuration and
|
|
6
|
+
// behavior that modifies Cypress.
|
|
7
|
+
//
|
|
8
|
+
// You can change the location of this file or turn off
|
|
9
|
+
// automatically serving support files with the
|
|
10
|
+
// 'supportFile' configuration option.
|
|
11
|
+
//
|
|
12
|
+
// You can read more here:
|
|
13
|
+
// https://on.cypress.io/configuration
|
|
14
|
+
// ***********************************************************
|
|
15
|
+
|
|
16
|
+
// Import commands.js using ES2015 syntax:
|
|
17
|
+
import './commands'
|
|
18
|
+
|
|
19
|
+
// Alternatively you can use CommonJS syntax:
|
|
20
|
+
// require('./commands')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var t=require("@peter.naydenov/notice");var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach((e=>{Object.entries(n[e]).forEach((([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)}))}))}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0],i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex((e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0)))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o}=e,{ev:r}=t;return function(t=!1){const i=o.name;if(!t)return r.reset(),void(o.name=null);i!==t&&(n[t]?(n[i]&&r.reset(),o.name=t,e.plugins.forEach((e=>e.contextChange(t))),Object.entries(n[t]).forEach((([t,e])=>{e.forEach((e=>r.on(t,e)))})),r.on("*",((...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)}))):r.emit("@shortcuts-error",`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map((([t,e])=>t))}return Object.keys(n).map((t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map((([t,e])=>t)),e}))}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map((t=>t.getPrefix().toUpperCase()));let c=!1;Object.entries(t).forEach((([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach((([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map(((t,e)=>c.startsWith(t)?e:null)).filter((t=>null!==t));if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r}))})),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o}=e,{ev:r}=t;return function(t){n.name!==t?o[t]?delete o[t]:r.emit("shortcuts-error",`Context '${t}' does not exist`):r.emit("shortcuts-error",`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map((t=>t.trim())).map((t=>t.split("+").map((t=>t.trim())).sort().join("+"))).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=t.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),e.hasOwnProperty(i)?s.push(e[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach((([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)})),n)}function i(){return{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 s(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:s(t,e,r.parentNode)}function c(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map((t=>t.trim())).forEach((t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)})),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function u(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function l(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach((([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)})),n)}exports.pluginClick=function(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,a={ev:t.ev,_findTarget:s,_readClickEvent:u,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(c);let p=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let l=null,a=null,m=null,p=null,h=0;function f(){const t=r(a,h),e={target:l,targetProps:l?l.getBoundingClientRect():null,x:a.clientX,y:a.clientY,context:c.name,note:c.note,event:a,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,p=null,l=null,a=null,h=0}function d(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout((()=>p=null),u))):(l=o(t,e,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,h++,h>=r?(f(),void(r>1&&(p=setTimeout((()=>p=null),u)))):void(m=setTimeout(f,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout((()=>p=null),u))):(l=o(t,e,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,h++,h>=r?(f(),void(r>1&&(p=setTimeout((()=>p=null),u)))):void(m=setTimeout(f,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1)}}}(a,m),h=l(a,m);h>0&&p.start();const f={getPrefix:()=>"click",shortcutName:t=>c(t),contextChange:()=>{h=l(a,m),h<1&&p.stop(),h>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>{p.stop(),m=null,f=null}};return Object.freeze(f),f},exports.pluginKey=function(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:l}=e,{inAPI:a}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys,exposeShortcut:l};a._normalizeWithPlugins(n);let h=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:l}=u;let a=[],m=null,p=!0,h=!1;const f=()=>p=!1,d=()=>p=!0,g=()=>h=!0,x=()=>!1===p;function y(){let t=a.map((t=>[t.join("+")]));const e={wait:f,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!p){let o=t.at(-1);n.emit(o,e),h&&(t=t.slice(0,-1),h=!1)}if(p){const o=`KEY:${t.join(",")}`;n.emit(o,e),a=[],m=null}}function C(e){if(clearTimeout(m),o.hasOwnProperty(e.code))return a.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):p&&a.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):void(p?m=setTimeout(y,l):y())}function k(e){if(!o.hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));if(a.push(r(e,o)),p&&a.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));p?m=setTimeout(y,l):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",k),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",k),e.active=!1)}}}(m,p),f=r(m,p);f>0&&h.start();const d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{f=r(m,p),f<1&&h.stop(),f>0&&h.start()},mute:()=>h.stop(),unmute:()=>h.start(),destroy:()=>{h.stop(),p=null,d=null}};return Object.freeze(d),d},exports.shortcuts=function(n={}){const o=t(),r={},i={},s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut},c={ev:o,inAPI:r,API:i,extra:{}};return i.enablePlugin=(t,e={})=>{const n=t.name;if(-1===r._systemAction(n,"none")){let n;n=t(c,s,e),s.plugins.push(n)}},i.disablePlugin=t=>{const e=r._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter(((t,n)=>n!==e)))},i.mutePlugin=t=>r._systemAction(t,"mute"),i.unmutePlugin=t=>r._systemAction(t,"unmute"),i.getContext=()=>s.currentContext.name,i.getNote=()=>s.currentContext.note,i.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},i.pause=(t="*")=>{let e=r._readShortcutWithPlugins(t);o.stop(e)},i.resume=(t="*")=>{const e=r._readShortcutWithPlugins(t);o.start(e)},i.emit=(t,...e)=>o.emit(r._readShortcutWithPlugins(t),...e),i.listContexts=()=>Object.keys(s.shortcuts),i.setDependencies=t=>c.extra={...c.extra,...t},i.getDependencies=()=>c.extra,Object.entries(e).forEach((([t,e])=>{t.startsWith("_")?r[t]=e(c,s):i[t]=e(c,s)})),i};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"@peter.naydenov/notice";var e={_normalizeWithPlugins:function(t,e){return function(t){const n=e.shortcuts;Object.keys(n).forEach((e=>{Object.entries(n[e]).forEach((([o,r])=>{const i=t(o);i!==o&&(delete n[e][o],n[e][i]=r)}))}))}},_readShortcutWithPlugins:function(t,e){return function(n){const{inAPI:o}=t,r=n.split(":")[0],i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=e.plugins[i].shortcutName(n)),s}},_systemAction:function(t,e){return function(t,n,o=null){return e.plugins.findIndex((e=>e.getPrefix()===t&&(e[n]&&e[n](o),!0)))}},changeContext:function(t,e){const{shortcuts:n,currentContext:o}=e,{ev:r}=t;return function(t=!1){const i=o.name;if(!t)return r.reset(),void(o.name=null);i!==t&&(n[t]?(n[i]&&r.reset(),o.name=t,e.plugins.forEach((e=>e.contextChange(t))),Object.entries(n[t]).forEach((([t,e])=>{e.forEach((e=>r.on(t,e)))})),r.on("*",((...t)=>{e.exposeShortcut&&e.exposeShortcut(...t)}))):r.emit("@shortcuts-error",`Context '${t}' does not exist`))}},listShortcuts:function(t,e){const n=e.shortcuts;return function(t=null){if(null!=t){let e=n[t];return null==e?null:Object.entries(e).map((([t,e])=>t))}return Object.keys(n).map((t=>{let e={};return e.context=t,e.shortcuts=Object.entries(n[t]).map((([t,e])=>t)),e}))}},load:function(t,e){const{shortcuts:n,plugins:o}=e,{API:{changeContext:r,getContext:i}}=t;return function(t){const e=i(),s=o.map((t=>t.getPrefix().toUpperCase()));let c=!1;Object.entries(t).forEach((([t,r])=>{t===e&&(c=!0),n[t]={},Object.entries(r).forEach((([e,r])=>{let i=e,c=e.toUpperCase().trim(),u=s.map(((t,e)=>c.startsWith(t)?e:null)).filter((t=>null!==t));if(u.length){let t=u[0];i=o[t].shortcutName(e)}r instanceof Function&&(r=[r]),n[t][i]=r}))})),c&&(r(),r(e))}},unload:function(t,e){const{currentContext:n,shortcuts:o}=e,{ev:r}=t;return function(t){n.name!==t?o[t]?delete o[t]:r.emit("shortcuts-error",`Context '${t}' does not exist`):r.emit("shortcuts-error",`Context '${t}' can't be removed during is current active context. Change the context first`)}}};function n(t){const e=t.toUpperCase(),n=/KEY\s*\:/i.test(e),o=e.indexOf(":");if(!n)return t;return`KEY:${e.slice(o+1).split(",").map((t=>t.trim())).map((t=>t.split("+").map((t=>t.trim())).sort().join("+"))).join(",")}`}function o(t,e){let{shiftKey:n,altKey:o,ctrlKey:r}=t,i=t.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),e.hasOwnProperty(i)?s.push(e[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}function r(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach((([t,e])=>{if(!o.test(t))return;n++;let i=t.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)})),n)}function i(){return{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 s(t,e,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:l}=e,{inAPI:a}=t,m={ev:t.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:t,regex:/KEY\s*\:/i},p={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys,exposeShortcut:l};a._normalizeWithPlugins(n);let h=function(t,e){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=t,{currentContext:s,streamKeys:c,listenOptions:u}=e,{keyWait:l}=u;let a=[],m=null,p=!0,h=!1;const f=()=>p=!1,d=()=>p=!0,g=()=>h=!0,x=()=>!1===p;function y(){let t=a.map((t=>[t.join("+")]));const e={wait:f,end:d,ignore:g,isWaiting:x,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!p){let o=t.at(-1);n.emit(o,e),h&&(t=t.slice(0,-1),h=!1)}if(p){const o=`KEY:${t.join(",")}`;n.emit(o,e),a=[],m=null}}function C(e){if(clearTimeout(m),o.hasOwnProperty(e.code))return a.push(r(e,o)),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):p&&a.length===u.maxSequence?(y(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):void(p?m=setTimeout(y,l):y())}function k(e){if(!o.hasOwnProperty(e.code)){if(clearTimeout(m),c&&c({key:e.key,context:s.name,note:s.note,dependencies:t.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));if(a.push(r(e,o)),p&&a.length===u.maxSequence)return y(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));p?m=setTimeout(y,l):y()}}return{start:function(){e.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",k),e.active=!0)},stop:function(){e.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",k),e.active=!1)}}}(m,p),f=r(m,p);f>0&&h.start();const d={getPrefix:()=>"key",shortcutName:t=>n(t),contextChange:t=>{f=r(m,p),f<1&&h.stop(),f>0&&h.start()},mute:()=>h.stop(),unmute:()=>h.start(),destroy:()=>{h.stop(),p=null,d=null}};return Object.freeze(d),d}function c(t,e,n){const{listenOptions:{clickTarget:o}}=e;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:c(t,e,r.parentNode)}function u(t){const e=t.toUpperCase(),n=/CLICK\s*\:/i.test(e),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=e.indexOf(":");return n?(e.slice(u+1).trim().split("-").map((t=>t.trim())).forEach((t=>{o.includes(t)?i=t:r.includes(t)?s.push(t):isNaN(t)||(c=t)})),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):t}function l(t,e){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=t,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${e}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function a(t,e){let n=0;const{regex:o}=t,{listenOptions:r,currentContext:{name:i},shortcuts:s}=e;return null==i?0:(Object.entries(s[i]).forEach((([t,e])=>{if(!o.test(t))return;n++;let[,i]=t.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)})),n)}function m(t,e,n){let{currentContext:o,shortcuts:r}=e,{inAPI:i}=t,s={ev:t.ev,_findTarget:c,_readClickEvent:l,mainDependencies:t,regex:/CLICK\s*\:/i},m={currentContext:o,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(u);let p=function(t,e){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=t,{listenOptions:s,currentContext:c}=e,{mouseWait:u}=s;let l=null,a=null,m=null,p=null,h=0;function f(){const t=r(a,h),e={target:l,targetProps:l?l.getBoundingClientRect():null,x:a.clientX,y:a.clientY,context:c.name,note:c.note,event:a,dependencies:i.extra,type:"click"};n.emit(t,e),m=null,p=null,l=null,a=null,h=0}function d(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout((()=>p=null),u))):(l=o(t,e,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,h++,h>=r?(f(),void(r>1&&(p=setTimeout((()=>p=null),u)))):void(m=setTimeout(f,u)))}function g(n){let r=s.maxClicks;return clearTimeout(m),p?(clearTimeout(p),void(p=setTimeout((()=>p=null),u))):(l=o(t,e,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,h++,h>=r?(f(),void(r>1&&(p=setTimeout((()=>p=null),u)))):void(m=setTimeout(f,u)))}return{start:function(){e.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),e.active=!0)},stop:function(){e.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),e.active=!1)}}}(s,m),h=a(s,m);h>0&&p.start();const f={getPrefix:()=>"click",shortcutName:t=>u(t),contextChange:()=>{h=a(s,m),h<1&&p.stop(),h>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>{p.stop(),m=null,f=null}};return Object.freeze(f),f}function p(n={}){const o=t(),r={},i={},s={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!n.onShortcut||"function"!=typeof n.onShortcut)&&n.onShortcut},c={ev:o,inAPI:r,API:i,extra:{}};return i.enablePlugin=(t,e={})=>{const n=t.name;if(-1===r._systemAction(n,"none")){let n;n=t(c,s,e),s.plugins.push(n)}},i.disablePlugin=t=>{const e=r._systemAction(t,"destroy");-1!==e&&(s.plugins=s.plugins.filter(((t,n)=>n!==e)))},i.mutePlugin=t=>r._systemAction(t,"mute"),i.unmutePlugin=t=>r._systemAction(t,"unmute"),i.getContext=()=>s.currentContext.name,i.getNote=()=>s.currentContext.note,i.setNote=(t=null)=>{"string"!=typeof t&&null!=t||(s.currentContext.note=t)},i.pause=(t="*")=>{let e=r._readShortcutWithPlugins(t);o.stop(e)},i.resume=(t="*")=>{const e=r._readShortcutWithPlugins(t);o.start(e)},i.emit=(t,...e)=>o.emit(r._readShortcutWithPlugins(t),...e),i.listContexts=()=>Object.keys(s.shortcuts),i.setDependencies=t=>c.extra={...c.extra,...t},i.getDependencies=()=>c.extra,Object.entries(e).forEach((([t,e])=>{t.startsWith("_")?r[t]=e(c,s):i[t]=e(c,s)})),i}export{m as pluginClick,s as pluginKey,p as shortcuts};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).shortcuts={})}(this,(function(e){"use strict";var t={_normalizeWithPlugins:function(e,t){return function(e){const n=t.shortcuts;Object.keys(n).forEach((t=>{Object.entries(n[t]).forEach((([o,r])=>{const i=e(o);i!==o&&(delete n[t][o],n[t][i]=r)}))}))}},_readShortcutWithPlugins:function(e,t){return function(n){const{inAPI:o}=e,r=n.split(":")[0],i=o._systemAction(r,"none");let s=n;return-1!==i&&(s=t.plugins[i].shortcutName(n)),s}},_systemAction:function(e,t){return function(e,n,o=null){return t.plugins.findIndex((t=>t.getPrefix()===e&&(t[n]&&t[n](o),!0)))}},changeContext:function(e,t){const{shortcuts:n,currentContext:o}=t,{ev:r}=e;return function(e=!1){const i=o.name;if(!e)return r.reset(),void(o.name=null);i!==e&&(n[e]?(n[i]&&r.reset(),o.name=e,t.plugins.forEach((t=>t.contextChange(e))),Object.entries(n[e]).forEach((([e,t])=>{t.forEach((t=>r.on(e,t)))})),r.on("*",((...e)=>{t.exposeShortcut&&t.exposeShortcut(...e)}))):r.emit("@shortcuts-error",`Context '${e}' does not exist`))}},listShortcuts:function(e,t){const n=t.shortcuts;return function(e=null){if(null!=e){let t=n[e];return null==t?null:Object.entries(t).map((([e,t])=>e))}return Object.keys(n).map((e=>{let t={};return t.context=e,t.shortcuts=Object.entries(n[e]).map((([e,t])=>e)),t}))}},load:function(e,t){const{shortcuts:n,plugins:o}=t,{API:{changeContext:r,getContext:i}}=e;return function(e){const t=i(),s=o.map((e=>e.getPrefix().toUpperCase()));let c=!1;Object.entries(e).forEach((([e,r])=>{e===t&&(c=!0),n[e]={},Object.entries(r).forEach((([t,r])=>{let i=t,c=t.toUpperCase().trim(),u=s.map(((e,t)=>c.startsWith(e)?t:null)).filter((e=>null!==e));if(u.length){let e=u[0];i=o[e].shortcutName(t)}r instanceof Function&&(r=[r]),n[e][i]=r}))})),c&&(r(),r(t))}},unload:function(e,t){const{currentContext:n,shortcuts:o}=t,{ev:r}=e;return function(e){n.name!==e?o[e]?delete o[e]:r.emit("shortcuts-error",`Context '${e}' does not exist`):r.emit("shortcuts-error",`Context '${e}' can't be removed during is current active context. Change the context first`)}}};function n(e){const t=e.toUpperCase(),n=/KEY\s*\:/i.test(t),o=t.indexOf(":");if(!n)return e;return`KEY:${t.slice(o+1).split(",").map((e=>e.trim())).map((e=>e.split("+").map((e=>e.trim())).sort().join("+"))).join(",")}`}function o(e,t){let{shiftKey:n,altKey:o,ctrlKey:r}=e,i=e.code.replace("Key","").replace("Digit",""),s=[];return r&&s.push("CTRL"),n&&s.push("SHIFT"),o&&s.push("ALT"),t.hasOwnProperty(i)?s.push(t[i].toUpperCase()):["ControlLeft","ControlRight","ShiftLeft","ShiftRight","AltLeft","AltRight","Meta"].includes(i)||s.push(i.toUpperCase()),s.sort()}function r(e,t){let n=0;const{regex:o}=e,{listenOptions:r,currentContext:{name:i},shortcuts:s}=t;return null==i?0:(Object.entries(s[i]).forEach((([e,t])=>{if(!o.test(e))return;n++;let i=e.slice(4).split(",").length;r.maxSequence<i&&(r.maxSequence=i)})),n)}function i(){return{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 s(e,t,n){const{listenOptions:{clickTarget:o}}=t;let r=n;return r===document||r===document.body?null:r.dataset[o]||"A"===r.nodeName?r:s(e,t,r.parentNode)}function c(e){const t=e.toUpperCase(),n=/CLICK\s*\:/i.test(t),o=["LEFT","MIDDLE","RIGHT"],r=["ALT","SHIFT","CTRL"];let i=null,s=[],c=0,u=t.indexOf(":");return n?(t.slice(u+1).trim().split("-").map((e=>e.trim())).forEach((e=>{o.includes(e)?i=e:r.includes(e)?s.push(e):isNaN(e)||(c=e)})),`CLICK:${i}-${c}${s.length>0?"-":""}${s.sort().join("-")}`):e}function u(e,t){let{shiftKey:n,altKey:o,ctrlKey:r,key:i,button:s}=e,c=`CLICK:${["LEFT","MIDDLE","RIGHT"][s]}-${t}`,u=[];return r&&u.push("CTRL"),n&&u.push("SHIFT"),o&&u.push("ALT"),u.length>0?`${c}${u.length>0?"-":""}${u.sort().join("-")}`:`${c}`}function l(e,t){let n=0;const{regex:o}=e,{listenOptions:r,currentContext:{name:i},shortcuts:s}=t;return null==i?0:(Object.entries(s[i]).forEach((([e,t])=>{if(!o.test(e))return;n++;let[,i]=e.slice(6).split("-");r.maxClicks<i&&(r.maxClicks=i)})),n)}e.pluginClick=function(e,t,n){let{currentContext:o,shortcuts:r}=t,{inAPI:i}=e,a={ev:e.ev,_findTarget:s,_readClickEvent:u,mainDependencies:e,regex:/CLICK\s*\:/i},f={currentContext:o,shortcuts:r,listenOptions:{mouseWait:n.mouseWait?n.mouseWait:320,maxClicks:1,clickTarget:n.clickTarget?n.clickTarget:"click"}};i._normalizeWithPlugins(c);let m=function(e,t){const{ev:n,_findTarget:o,_readClickEvent:r,mainDependencies:i}=e,{listenOptions:s,currentContext:c}=t,{mouseWait:u}=s;let l=null,a=null,f=null,m=null,p=0;function h(){const e=r(a,p),t={target:l,targetProps:l?l.getBoundingClientRect():null,x:a.clientX,y:a.clientY,context:c.name,note:c.note,event:a,dependencies:i.extra,type:"click"};n.emit(e,t),f=null,m=null,l=null,a=null,p=0}function d(n){let r=s.maxClicks;return clearTimeout(f),m?(clearTimeout(m),void(m=setTimeout((()=>m=null),u))):(l=o(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,p++,p>=r?(h(),void(r>1&&(m=setTimeout((()=>m=null),u)))):void(f=setTimeout(h,u)))}function g(n){let r=s.maxClicks;return clearTimeout(f),m?(clearTimeout(m),void(m=setTimeout((()=>m=null),u))):(l=o(e,t,n.target),l&&l.dataset.hasOwnProperty("quickClick")&&(r=1),l&&"A"===l.tagName&&(r=1),a=n,p++,p>=r?(h(),void(r>1&&(m=setTimeout((()=>m=null),u)))):void(f=setTimeout(h,u)))}return{start:function(){t.active||(window.addEventListener("contextmenu",g),document.addEventListener("click",d),t.active=!0)},stop:function(){t.active&&(window.removeEventListener("contextmenu",g),document.removeEventListener("click",d),t.active=!1)}}}(a,f),p=l(a,f);p>0&&m.start();const h={getPrefix:()=>"click",shortcutName:e=>c(e),contextChange:()=>{p=l(a,f),p<1&&m.stop(),p>0&&m.start()},mute:()=>m.stop(),unmute:()=>m.start(),destroy:()=>{m.stop(),f=null,h=null}};return Object.freeze(h),h},e.pluginKey=function(e,t,s={}){let{currentContext:c,shortcuts:u,exposeShortcut:l}=t,{inAPI:a}=e,f={ev:e.ev,_specialChars:i,_readKeyEvent:o,mainDependencies:e,regex:/KEY\s*\:/i},m={currentContext:c,shortcuts:u,active:!1,listenOptions:{keyWait:s.keyWait?s.keyWait:480,maxSequence:1,keyIgnore:null},streamKeys:!(!s.streamKeys||"function"!=typeof s.streamKeys)&&s.streamKeys,exposeShortcut:l};a._normalizeWithPlugins(n);let p=function(e,t){const{ev:n,_specialChars:o,_readKeyEvent:r,mainDependencies:i}=e,{currentContext:s,streamKeys:c,listenOptions:u}=t,{keyWait:l}=u;let a=[],f=null,m=!0,p=!1;const h=()=>m=!1,d=()=>m=!0,g=()=>p=!0,y=()=>!1===m;function x(){let e=a.map((e=>[e.join("+")]));const t={wait:h,end:d,ignore:g,isWaiting:y,note:s.note,context:s.name,dependencies:i.extra,type:"key"};if(!m){let o=e.at(-1);n.emit(o,t),p&&(e=e.slice(0,-1),p=!1)}if(m){const o=`KEY:${e.join(",")}`;n.emit(o,t),a=[],f=null}}function C(t){if(clearTimeout(f),o.hasOwnProperty(t.code))return a.push(r(t,o)),c&&c({key:t.key,context:s.name,note:s.note,dependencies:e.extra}),u.keyIgnore?(clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):m&&a.length===u.maxSequence?(x(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l))):void(m?f=setTimeout(x,l):x())}function k(t){if(!o.hasOwnProperty(t.code)){if(clearTimeout(f),c&&c({key:t.key,context:s.name,note:s.note,dependencies:e.extra}),u.keyIgnore)return clearTimeout(u.keyIgnore),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));if(a.push(r(t,o)),m&&a.length===u.maxSequence)return x(),void(u.keyIgnore=setTimeout((()=>u.keyIgnore=null),l));m?f=setTimeout(x,l):x()}}return{start:function(){t.active||(document.addEventListener("keydown",C),document.addEventListener("keypress",k),t.active=!0)},stop:function(){t.active&&(document.removeEventListener("keydown",C),document.removeEventListener("keypress",k),t.active=!1)}}}(f,m),h=r(f,m);h>0&&p.start();const d={getPrefix:()=>"key",shortcutName:e=>n(e),contextChange:e=>{h=r(f,m),h<1&&p.stop(),h>0&&p.start()},mute:()=>p.stop(),unmute:()=>p.start(),destroy:()=>{p.stop(),m=null,d=null}};return Object.freeze(d),d},e.shortcuts=function(e={}){const n=new function(){let e={"*":[]},t={},n=[],o=!1,r="";return{on:function(t,n){e[t]||(e[t]=[]),e[t].push(n)},once:function(e,n){"*"!==e&&(t[e]||(t[e]=[]),t[e].push(n))},off:function(n,o){if(o)return e[n]&&(e[n]=e[n].filter((e=>e!==o))),t[n]&&(t[n]=t[n].filter((e=>e!==o))),e[n]&&0===e[n].length&&delete e[n],void(t[n]&&0===t[n].length&&delete e[n]);t[n]&&delete t[n],e[n]&&delete e[n]},reset:function(){e={"*":[]},t={},n=[]},emit:function(){const[i,...s]=arguments;function c(t){"*"!==t&&(n.includes(t)||(e[t].forEach((e=>e(...s))),e["*"].forEach((e=>e(i,...s)))))}if(o&&(console.log(`${r} Event "${i}" was triggered.`),s.length>0&&(console.log("Arguments:"),console.log(...s),console.log("^----"))),"*"!==i){if(t[i]){if(n.includes(i))return;t[i].forEach((e=>e(...s))),delete t[i]}e[i]&&c(i)}else Object.keys(e).forEach((e=>c(e)))},stop:function(o){if("*"!==o)n.push(o);else{const o=Object.keys(e),r=Object.keys(t);n=[...r,...o]}},start:function(e){n="*"!==e?n.filter((t=>e!=t)):[]},debug:function(e,t){o=!!e,t&&"string"==typeof t&&(r=t)}}},o={},r={},i={currentContext:{name:null,note:null},shortcuts:{},plugins:[],exposeShortcut:!(!e.onShortcut||"function"!=typeof e.onShortcut)&&e.onShortcut},s={ev:n,inAPI:o,API:r,extra:{}};return r.enablePlugin=(e,t={})=>{const n=e.name;if(-1===o._systemAction(n,"none")){let n;n=e(s,i,t),i.plugins.push(n)}},r.disablePlugin=e=>{const t=o._systemAction(e,"destroy");-1!==t&&(i.plugins=i.plugins.filter(((e,n)=>n!==t)))},r.mutePlugin=e=>o._systemAction(e,"mute"),r.unmutePlugin=e=>o._systemAction(e,"unmute"),r.getContext=()=>i.currentContext.name,r.getNote=()=>i.currentContext.note,r.setNote=(e=null)=>{"string"!=typeof e&&null!=e||(i.currentContext.note=e)},r.pause=(e="*")=>{let t=o._readShortcutWithPlugins(e);n.stop(t)},r.resume=(e="*")=>{const t=o._readShortcutWithPlugins(e);n.start(t)},r.emit=(e,...t)=>n.emit(o._readShortcutWithPlugins(e),...t),r.listContexts=()=>Object.keys(i.shortcuts),r.setDependencies=e=>s.extra={...s.extra,...e},r.getDependencies=()=>s.extra,Object.entries(t).forEach((([e,t])=>{e.startsWith("_")?o[e]=t(s,i):r[e]=t(s,i)})),r}}));
|
package/package.json
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/shortcuts",
|
|
3
|
-
"version": "2.1.0",
|
|
4
3
|
"description": "Context control of shortcuts based on keyboard and mouse events",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"mouse",
|
|
10
|
-
"click"
|
|
11
|
-
],
|
|
12
|
-
"main": "src/main.js",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Peter Naydenov",
|
|
7
|
+
"main": "./dist/shortcuts.umd.js",
|
|
13
8
|
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/shortcuts.esm.mjs",
|
|
12
|
+
"require": "./dist/shortcuts.cjs",
|
|
13
|
+
"default": "./dist/shortcuts.umd.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json",
|
|
16
|
+
"./dist/*": "./dist/*",
|
|
17
|
+
"./src/*": "./src/*"
|
|
18
|
+
},
|
|
14
19
|
"scripts": {
|
|
15
20
|
"dev": "vite",
|
|
16
|
-
"build": "
|
|
21
|
+
"build": "rollup -c",
|
|
17
22
|
"test": "cypress open --component --browser chrome test"
|
|
18
23
|
},
|
|
19
24
|
"repository": {
|
|
@@ -21,18 +26,26 @@
|
|
|
21
26
|
"url": "git+https://github.com/PeterNaydenov/shortcuts"
|
|
22
27
|
},
|
|
23
28
|
"dependencies": {
|
|
24
|
-
"@peter.naydenov/notice": "^2.2.
|
|
29
|
+
"@peter.naydenov/notice": "^2.2.3"
|
|
25
30
|
},
|
|
26
31
|
"devDependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
33
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
34
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
35
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
36
|
+
"ask-for-promise": "^2.0.3",
|
|
37
|
+
"chai": "^5.1.0",
|
|
38
|
+
"cypress": "^13.6.6",
|
|
39
|
+
"mocha": "^10.3.0",
|
|
32
40
|
"react": "^18.2.0",
|
|
33
41
|
"react-dom": "^18.2.0",
|
|
34
|
-
"vite": "^
|
|
42
|
+
"vite": "^5.1.5"
|
|
35
43
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
44
|
+
"keywords": [
|
|
45
|
+
"shortcut",
|
|
46
|
+
"key",
|
|
47
|
+
"keyboard",
|
|
48
|
+
"mouse",
|
|
49
|
+
"click"
|
|
50
|
+
]
|
|
38
51
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import resolve from '@rollup/plugin-node-resolve'
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs'
|
|
3
|
+
import terser from '@rollup/plugin-terser';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
// browser-friendly UMD build
|
|
8
|
+
{
|
|
9
|
+
input: 'src/main.js',
|
|
10
|
+
output: {
|
|
11
|
+
name: 'shortcuts',
|
|
12
|
+
file: 'dist/shortcuts.umd.js',
|
|
13
|
+
format: 'umd',
|
|
14
|
+
globals : {
|
|
15
|
+
'@peter.naydenov/notice': 'notice'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
plugins: [
|
|
19
|
+
resolve(), // so Rollup can find `ms`
|
|
20
|
+
commonjs() // so Rollup can convert `ms` to an ES module
|
|
21
|
+
, terser()
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// CommonJS (for Node) and ES module (for bundlers) build.
|
|
26
|
+
// (We could have three entries in the configuration array
|
|
27
|
+
// instead of two, but it's quicker to generate multiple
|
|
28
|
+
// builds from a single configuration where possible, using
|
|
29
|
+
// an array for the `output` option, where we can specify
|
|
30
|
+
// `file` and `format` for each target)
|
|
31
|
+
{
|
|
32
|
+
input: 'src/main.js',
|
|
33
|
+
external: ['@peter.naydenov/notice'],
|
|
34
|
+
output: [
|
|
35
|
+
{ file: 'dist/shortcuts.cjs' , format: 'cjs' },
|
|
36
|
+
{ file: 'dist/shortcuts.esm.mjs', format: 'es' }
|
|
37
|
+
],
|
|
38
|
+
plugins: [ terser() ]
|
|
39
|
+
}
|
|
40
|
+
];
|