@stonecrop/utilities 0.2.5
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/README.md +3 -0
- package/dist/utilities.js +333 -0
- package/dist/utilities.js.map +1 -0
- package/dist/utilities.umd.cjs +2 -0
- package/dist/utilities.umd.cjs.map +1 -0
- package/package.json +50 -0
- package/src/composables/keyboard.ts +440 -0
- package/src/index.ts +7 -0
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stonecrop/utilities",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/utilities.js",
|
|
9
|
+
"require": "./dist/utilities.umd.cjs"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/utilities.js",
|
|
13
|
+
"module": "dist/utilities.js",
|
|
14
|
+
"types": "src/index",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/*",
|
|
17
|
+
"src/**/*.ts"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"vue": "^3.2.47"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@histoire/plugin-vue": "^0.16.1",
|
|
24
|
+
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
|
25
|
+
"@typescript-eslint/parser": "^5.59.5",
|
|
26
|
+
"@vitejs/plugin-vue": "^4.2.1",
|
|
27
|
+
"@vueuse/core": "^9.13.0",
|
|
28
|
+
"cypress": "^12.11.0",
|
|
29
|
+
"eslint": "^8.40.0",
|
|
30
|
+
"eslint-config-prettier": "^8.8.0",
|
|
31
|
+
"eslint-plugin-vue": "^9.11.1",
|
|
32
|
+
"histoire": "^0.16.1",
|
|
33
|
+
"typescript": "^5.0.4",
|
|
34
|
+
"vite": "^4.3.5",
|
|
35
|
+
"vue-router": "^4"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20.11.0"
|
|
39
|
+
},
|
|
40
|
+
"umd": "dist/utilities.umd.cjs",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc -b && vite build",
|
|
43
|
+
"dev": "vite",
|
|
44
|
+
"lint": "eslint . --ext .ts,.vue",
|
|
45
|
+
"preview": "vite preview",
|
|
46
|
+
"story:build": "histoire build",
|
|
47
|
+
"story:dev": "histoire dev",
|
|
48
|
+
"story:preview": "histoire preview"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { onMounted, onBeforeUnmount } from 'vue'
|
|
2
|
+
import { useElementVisibility } from '@vueuse/core'
|
|
3
|
+
|
|
4
|
+
import type { KeyboardNavigationOptions, KeypressHandlers } from 'types'
|
|
5
|
+
|
|
6
|
+
// helper functions
|
|
7
|
+
const isVisible = (element: HTMLElement) => {
|
|
8
|
+
let isVisible = useElementVisibility(element).value
|
|
9
|
+
isVisible = isVisible && element.offsetHeight > 0
|
|
10
|
+
return isVisible
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const isFocusable = (element: HTMLElement) => {
|
|
14
|
+
return element.tabIndex >= 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// navigation functions
|
|
18
|
+
const getUpCell = (event: KeyboardEvent) => {
|
|
19
|
+
const $target = event.target as HTMLElement
|
|
20
|
+
return _getUpCell($target)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const _getUpCell = (element: HTMLElement): HTMLElement | undefined => {
|
|
24
|
+
let $upCell: HTMLElement | undefined
|
|
25
|
+
if (element instanceof HTMLTableCellElement) {
|
|
26
|
+
const $prevRow = element.parentElement?.previousElementSibling as HTMLTableRowElement
|
|
27
|
+
if ($prevRow) {
|
|
28
|
+
const $prevRowCells = Array.from($prevRow.children)
|
|
29
|
+
const $prevCell = $prevRowCells[element.cellIndex] as HTMLElement
|
|
30
|
+
if ($prevCell) {
|
|
31
|
+
$upCell = $prevCell
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} else if (element instanceof HTMLTableRowElement) {
|
|
35
|
+
const $prevRow = element.previousElementSibling as HTMLTableRowElement
|
|
36
|
+
if ($prevRow) {
|
|
37
|
+
$upCell = $prevRow
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
// handle other contexts
|
|
41
|
+
}
|
|
42
|
+
if ($upCell && (!isFocusable($upCell) || !isVisible($upCell))) {
|
|
43
|
+
return _getUpCell($upCell)
|
|
44
|
+
}
|
|
45
|
+
return $upCell
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const getTopCell = (event: KeyboardEvent) => {
|
|
49
|
+
const $target = event.target as HTMLElement
|
|
50
|
+
let $topCell: HTMLElement | undefined
|
|
51
|
+
if ($target instanceof HTMLTableCellElement) {
|
|
52
|
+
const $table = $target.parentElement?.parentElement
|
|
53
|
+
if ($table) {
|
|
54
|
+
const $firstRow = $table.firstElementChild
|
|
55
|
+
const $navCell = $firstRow.children[$target.cellIndex] as HTMLElement
|
|
56
|
+
if ($navCell) {
|
|
57
|
+
$topCell = $navCell
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else if ($target instanceof HTMLTableRowElement) {
|
|
61
|
+
const $table = $target.parentElement as HTMLTableElement
|
|
62
|
+
if ($table) {
|
|
63
|
+
const $firstRow = $table.firstElementChild as HTMLTableRowElement
|
|
64
|
+
if ($firstRow) {
|
|
65
|
+
$topCell = $firstRow
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
// handle other contexts
|
|
70
|
+
}
|
|
71
|
+
if ($topCell && (!isFocusable($topCell) || !isVisible($topCell))) {
|
|
72
|
+
return _getDownCell($topCell)
|
|
73
|
+
}
|
|
74
|
+
return $topCell
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const getDownCell = (event: KeyboardEvent) => {
|
|
78
|
+
const $target = event.target as HTMLElement
|
|
79
|
+
return _getDownCell($target)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const _getDownCell = (element: HTMLElement): HTMLElement | undefined => {
|
|
83
|
+
let $downCell: HTMLElement | undefined
|
|
84
|
+
if (element instanceof HTMLTableCellElement) {
|
|
85
|
+
const $nextRow = element.parentElement?.nextElementSibling
|
|
86
|
+
if ($nextRow) {
|
|
87
|
+
const $nextRowCells = Array.from($nextRow.children)
|
|
88
|
+
const $nextCell = $nextRowCells[element.cellIndex] as HTMLElement
|
|
89
|
+
if ($nextCell) {
|
|
90
|
+
$downCell = $nextCell
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else if (element instanceof HTMLTableRowElement) {
|
|
94
|
+
const $nextRow = element.nextElementSibling as HTMLTableRowElement
|
|
95
|
+
if ($nextRow) {
|
|
96
|
+
$downCell = $nextRow
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// handle other contexts
|
|
100
|
+
}
|
|
101
|
+
if ($downCell && (!isFocusable($downCell) || !isVisible($downCell))) {
|
|
102
|
+
return _getDownCell($downCell)
|
|
103
|
+
}
|
|
104
|
+
return $downCell
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const getBottomCell = (event: KeyboardEvent) => {
|
|
108
|
+
const $target = event.target as HTMLElement
|
|
109
|
+
let $bottomCell: HTMLElement | undefined
|
|
110
|
+
if ($target instanceof HTMLTableCellElement) {
|
|
111
|
+
const $table = $target.parentElement?.parentElement
|
|
112
|
+
if ($table) {
|
|
113
|
+
const $lastRow = $table.lastElementChild
|
|
114
|
+
const $navCell = $lastRow.children[$target.cellIndex] as HTMLElement
|
|
115
|
+
if ($navCell) {
|
|
116
|
+
$bottomCell = $navCell
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
} else if ($target instanceof HTMLTableRowElement) {
|
|
120
|
+
const $table = $target.parentElement as HTMLTableElement
|
|
121
|
+
if ($table) {
|
|
122
|
+
const $lastRow = $table.lastElementChild as HTMLTableRowElement
|
|
123
|
+
if ($lastRow) {
|
|
124
|
+
$bottomCell = $lastRow
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
// handle other contexts
|
|
129
|
+
}
|
|
130
|
+
if ($bottomCell && (!isFocusable($bottomCell) || !isVisible($bottomCell))) {
|
|
131
|
+
return _getUpCell($bottomCell)
|
|
132
|
+
}
|
|
133
|
+
return $bottomCell
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const getPrevCell = (event: KeyboardEvent) => {
|
|
137
|
+
const $target = event.target as HTMLElement
|
|
138
|
+
return _getPrevCell($target)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const _getPrevCell = (element: HTMLElement): HTMLElement | undefined => {
|
|
142
|
+
let $prevCell: HTMLElement | undefined
|
|
143
|
+
if (element.previousElementSibling) {
|
|
144
|
+
$prevCell = element.previousElementSibling as HTMLElement
|
|
145
|
+
} else {
|
|
146
|
+
const $prevRow = element.parentElement?.previousElementSibling
|
|
147
|
+
$prevCell = $prevRow?.lastElementChild as HTMLElement
|
|
148
|
+
}
|
|
149
|
+
if ($prevCell && (!isFocusable($prevCell) || !isVisible($prevCell))) {
|
|
150
|
+
return _getPrevCell($prevCell)
|
|
151
|
+
}
|
|
152
|
+
return $prevCell
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const getNextCell = (event: KeyboardEvent) => {
|
|
156
|
+
const $target = event.target as HTMLElement
|
|
157
|
+
return _getNextCell($target)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const _getNextCell = (element: HTMLElement): HTMLElement | undefined => {
|
|
161
|
+
let $nextCell: HTMLElement | undefined
|
|
162
|
+
if (element.nextElementSibling) {
|
|
163
|
+
$nextCell = element.nextElementSibling as HTMLElement
|
|
164
|
+
} else {
|
|
165
|
+
const $nextRow = element.parentElement?.nextElementSibling
|
|
166
|
+
$nextCell = $nextRow?.firstElementChild as HTMLElement
|
|
167
|
+
}
|
|
168
|
+
if ($nextCell && (!isFocusable($nextCell) || !isVisible($nextCell))) {
|
|
169
|
+
return _getNextCell($nextCell)
|
|
170
|
+
}
|
|
171
|
+
return $nextCell
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const getFirstCell = (event: KeyboardEvent) => {
|
|
175
|
+
const $target = event.target as HTMLElement
|
|
176
|
+
const $parent = $target.parentElement
|
|
177
|
+
const $firstCell = $parent.firstElementChild as HTMLElement | null
|
|
178
|
+
if ($firstCell && (!isFocusable($firstCell) || !isVisible($firstCell))) {
|
|
179
|
+
return _getNextCell($firstCell)
|
|
180
|
+
}
|
|
181
|
+
return $firstCell
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const getLastCell = (event: KeyboardEvent) => {
|
|
185
|
+
const $target = event.target as HTMLElement
|
|
186
|
+
const $parent = $target.parentElement
|
|
187
|
+
const $lastCell = $parent.lastElementChild as HTMLElement | null
|
|
188
|
+
if ($lastCell && (!isFocusable($lastCell) || !isVisible($lastCell))) {
|
|
189
|
+
return _getPrevCell($lastCell)
|
|
190
|
+
}
|
|
191
|
+
return $lastCell
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const modifierKeys = ['alt', 'control', 'shift', 'meta']
|
|
195
|
+
|
|
196
|
+
const eventKeyMap = {
|
|
197
|
+
ArrowUp: 'up',
|
|
198
|
+
ArrowDown: 'down',
|
|
199
|
+
ArrowLeft: 'left',
|
|
200
|
+
ArrowRight: 'right',
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export const defaultKeypressHandlers: KeypressHandlers = {
|
|
204
|
+
'keydown.up': (event: KeyboardEvent) => {
|
|
205
|
+
const $upCell = getUpCell(event)
|
|
206
|
+
if ($upCell) {
|
|
207
|
+
event.preventDefault()
|
|
208
|
+
event.stopPropagation()
|
|
209
|
+
$upCell.focus()
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
'keydown.down': (event: KeyboardEvent) => {
|
|
213
|
+
const $downCell = getDownCell(event)
|
|
214
|
+
if ($downCell) {
|
|
215
|
+
event.preventDefault()
|
|
216
|
+
event.stopPropagation()
|
|
217
|
+
$downCell.focus()
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
'keydown.left': (event: KeyboardEvent) => {
|
|
221
|
+
const $prevCell = getPrevCell(event)
|
|
222
|
+
// prevent default edit-cell behaviour on first cell
|
|
223
|
+
event.preventDefault()
|
|
224
|
+
event.stopPropagation()
|
|
225
|
+
if ($prevCell) {
|
|
226
|
+
$prevCell.focus()
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
'keydown.right': (event: KeyboardEvent) => {
|
|
230
|
+
const $nextCell = getNextCell(event)
|
|
231
|
+
// prevent default edit-cell behaviour on last cell
|
|
232
|
+
event.preventDefault()
|
|
233
|
+
event.stopPropagation()
|
|
234
|
+
if ($nextCell) {
|
|
235
|
+
$nextCell.focus()
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
'keydown.control.up': (event: KeyboardEvent) => {
|
|
239
|
+
const $topCell = getTopCell(event)
|
|
240
|
+
if ($topCell) {
|
|
241
|
+
event.preventDefault()
|
|
242
|
+
event.stopPropagation()
|
|
243
|
+
$topCell.focus()
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
'keydown.control.down': (event: KeyboardEvent) => {
|
|
247
|
+
const $bottomCell = getBottomCell(event)
|
|
248
|
+
if ($bottomCell) {
|
|
249
|
+
event.preventDefault()
|
|
250
|
+
event.stopPropagation()
|
|
251
|
+
$bottomCell.focus()
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
'keydown.control.left': (event: KeyboardEvent) => {
|
|
255
|
+
const $firstCell = getFirstCell(event)
|
|
256
|
+
if ($firstCell) {
|
|
257
|
+
event.preventDefault()
|
|
258
|
+
event.stopPropagation()
|
|
259
|
+
$firstCell.focus()
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
'keydown.control.right': (event: KeyboardEvent) => {
|
|
263
|
+
const $lastCell = getLastCell(event)
|
|
264
|
+
if ($lastCell) {
|
|
265
|
+
event.preventDefault()
|
|
266
|
+
event.stopPropagation()
|
|
267
|
+
$lastCell.focus()
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
'keydown.end': (event: KeyboardEvent) => {
|
|
271
|
+
const $lastCell = getLastCell(event)
|
|
272
|
+
if ($lastCell) {
|
|
273
|
+
event.preventDefault()
|
|
274
|
+
event.stopPropagation()
|
|
275
|
+
$lastCell.focus()
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
'keydown.enter': (event: KeyboardEvent) => {
|
|
279
|
+
const $target = event.target as HTMLElement
|
|
280
|
+
if ($target instanceof HTMLTableCellElement) {
|
|
281
|
+
event.preventDefault()
|
|
282
|
+
event.stopPropagation()
|
|
283
|
+
const $downCell = getDownCell(event)
|
|
284
|
+
if ($downCell) {
|
|
285
|
+
$downCell.focus()
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
// handle other contexts
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
'keydown.shift.enter': (event: KeyboardEvent) => {
|
|
292
|
+
const $target = event.target as HTMLElement
|
|
293
|
+
if ($target instanceof HTMLTableCellElement) {
|
|
294
|
+
event.preventDefault()
|
|
295
|
+
event.stopPropagation()
|
|
296
|
+
const $upCell = getUpCell(event)
|
|
297
|
+
if ($upCell) {
|
|
298
|
+
$upCell.focus()
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
// handle other contexts
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
'keydown.home': (event: KeyboardEvent) => {
|
|
305
|
+
const $firstCell = getFirstCell(event)
|
|
306
|
+
if ($firstCell) {
|
|
307
|
+
event.preventDefault()
|
|
308
|
+
event.stopPropagation()
|
|
309
|
+
$firstCell.focus()
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
'keydown.tab': (event: KeyboardEvent) => {
|
|
313
|
+
const $nextCell = getNextCell(event)
|
|
314
|
+
if ($nextCell) {
|
|
315
|
+
event.preventDefault()
|
|
316
|
+
event.stopPropagation()
|
|
317
|
+
$nextCell.focus()
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
'keydown.shift.tab': (event: KeyboardEvent) => {
|
|
321
|
+
const $prevCell = getPrevCell(event)
|
|
322
|
+
if ($prevCell) {
|
|
323
|
+
event.preventDefault()
|
|
324
|
+
event.stopPropagation()
|
|
325
|
+
$prevCell.focus()
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export function useKeyboardNav(options: KeyboardNavigationOptions[]) {
|
|
331
|
+
const getSelectors = (option: KeyboardNavigationOptions) => {
|
|
332
|
+
// get parent element
|
|
333
|
+
let $parent: Element | null = null
|
|
334
|
+
if (option.parent) {
|
|
335
|
+
if (typeof option.parent === 'string') {
|
|
336
|
+
$parent = document.querySelector(option.parent)
|
|
337
|
+
} else if (option.parent instanceof Element) {
|
|
338
|
+
$parent = option.parent
|
|
339
|
+
} else {
|
|
340
|
+
$parent = option.parent.value
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// generate a list of selector(s)
|
|
345
|
+
let selectors: Element[] = []
|
|
346
|
+
|
|
347
|
+
if (option.selectors) {
|
|
348
|
+
if (typeof option.selectors === 'string') {
|
|
349
|
+
selectors = $parent
|
|
350
|
+
? Array.from($parent.querySelectorAll(option.selectors))
|
|
351
|
+
: Array.from(document.querySelectorAll(option.selectors))
|
|
352
|
+
} else if (option.selectors instanceof Element) {
|
|
353
|
+
selectors.push(option.selectors)
|
|
354
|
+
} else {
|
|
355
|
+
if (Array.isArray(option.selectors.value)) {
|
|
356
|
+
for (const element of option.selectors.value) {
|
|
357
|
+
if (element instanceof Element) {
|
|
358
|
+
selectors.push(element)
|
|
359
|
+
} else {
|
|
360
|
+
selectors.push(element.$el as Element)
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
selectors.push(option.selectors.value)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
const $children = Array.from($parent.children)
|
|
369
|
+
selectors = $children.filter((selector: HTMLElement) => {
|
|
370
|
+
// ignore elements not in the tab order or are not visible
|
|
371
|
+
return isFocusable(selector) && isVisible(selector)
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return selectors
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const getEventListener = (option: KeyboardNavigationOptions) => {
|
|
379
|
+
return (event: KeyboardEvent) => {
|
|
380
|
+
const activeKey = (eventKeyMap[event.key] as string) || event.key.toLowerCase()
|
|
381
|
+
if (modifierKeys.includes(activeKey)) return // ignore modifier key presses
|
|
382
|
+
|
|
383
|
+
const handlers = option.handlers || defaultKeypressHandlers
|
|
384
|
+
for (const key of Object.keys(handlers)) {
|
|
385
|
+
const [eventType, ...keys] = key.split('.')
|
|
386
|
+
if (eventType !== 'keydown') {
|
|
387
|
+
continue
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (keys.includes(activeKey)) {
|
|
391
|
+
const listener = handlers[key]
|
|
392
|
+
|
|
393
|
+
// check if the handler has modifiers, and if the modifier is active;
|
|
394
|
+
// this is to ensure exact key-press matches
|
|
395
|
+
const hasModifier = keys.filter(key => modifierKeys.includes(key))
|
|
396
|
+
const isModifierActive = modifierKeys.some(key => {
|
|
397
|
+
const modifierKey = key.charAt(0).toUpperCase() + key.slice(1)
|
|
398
|
+
return event.getModifierState(modifierKey)
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
if (hasModifier.length > 0) {
|
|
402
|
+
if (isModifierActive) {
|
|
403
|
+
for (const modifier of modifierKeys) {
|
|
404
|
+
if (keys.includes(modifier)) {
|
|
405
|
+
// docs: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState
|
|
406
|
+
const modifierKey = modifier.charAt(0).toUpperCase() + modifier.slice(1)
|
|
407
|
+
if (event.getModifierState(modifierKey)) {
|
|
408
|
+
listener(event)
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
if (!isModifierActive) {
|
|
415
|
+
listener(event)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
onMounted(() => {
|
|
424
|
+
for (const option of options) {
|
|
425
|
+
const selectors = getSelectors(option)
|
|
426
|
+
for (const selector of selectors) {
|
|
427
|
+
selector.addEventListener('keydown', getEventListener(option))
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
onBeforeUnmount(() => {
|
|
433
|
+
for (const option of options) {
|
|
434
|
+
const selectors = getSelectors(option)
|
|
435
|
+
for (const selector of selectors) {
|
|
436
|
+
selector.removeEventListener('keydown', getEventListener(option))
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
})
|
|
440
|
+
}
|