@stonecrop/utilities 0.31.0 → 0.33.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/dist/tsdoc-metadata.json +1 -1
- package/dist/utilities.js +400 -267
- package/dist/utilities.js.map +1 -1
- package/package.json +28 -25
- package/dist/assets/sample_data/coa.json +0 -2362
- package/dist/assets/sample_data/financials.json +0 -252
- package/dist/assets/sample_data/forecast.json +0 -2792
- package/dist/assets/sample_data/forecast_items.json +0 -126
- package/dist/assets/sample_data/http_logs.json +0 -252
- package/dist/assets/sample_data/inbox.json +0 -355
- package/dist/assets/sample_data/parts.json +0 -1322
- package/dist/assets/sample_data/repos.json +0 -1142
- package/dist/src/composables/keyboard.d.ts +0 -13
- package/dist/src/composables/keyboard.d.ts.map +0 -1
- package/dist/src/composables/keyboard.js +0 -503
- package/dist/src/composables/visibility/index.d.ts +0 -24
- package/dist/src/composables/visibility/index.d.ts.map +0 -1
- package/dist/src/composables/visibility/index.js +0 -47
- package/dist/src/index.d.ts +0 -11
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -8
- package/dist/src/types/index.d.ts +0 -18
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/index.js +0 -0
- package/dist/utilities.tsbuildinfo +0 -1
- package/src/assets/sample_data/coa.json +0 -2362
- package/src/assets/sample_data/financials.json +0 -252
- package/src/assets/sample_data/forecast.json +0 -2792
- package/src/assets/sample_data/forecast_items.json +0 -126
- package/src/assets/sample_data/http_logs.json +0 -252
- package/src/assets/sample_data/inbox.json +0 -355
- package/src/assets/sample_data/parts.json +0 -1322
- package/src/assets/sample_data/repos.json +0 -1142
- package/src/composables/keyboard.ts +0 -499
- package/src/composables/visibility/index.ts +0 -68
- package/src/index.ts +0 -13
- package/src/types/index.ts +0 -28
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { KeyboardNavigationOptions, KeypressHandlers } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Default keypress handlers for keyboard navigation
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export declare const defaultKeypressHandlers: KeypressHandlers;
|
|
7
|
-
/**
|
|
8
|
-
* Keyboard navigation composable
|
|
9
|
-
* @param options - Keyboard navigation options
|
|
10
|
-
* @public
|
|
11
|
-
*/
|
|
12
|
-
export declare function useKeyboardNav(options: KeyboardNavigationOptions[]): void;
|
|
13
|
-
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/composables/keyboard.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAmN3E;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,gBA+HrC,CAAA;AAoBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,yBAAyB,EAAE,QA+HlE"}
|
|
@@ -1,503 +0,0 @@
|
|
|
1
|
-
import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
2
|
-
import { useFocusWithin } from '@vueuse/core';
|
|
3
|
-
import { useElementVisibility } from './visibility';
|
|
4
|
-
// helper functions
|
|
5
|
-
const isVisible = (element) => {
|
|
6
|
-
let visible = useElementVisibility(element).value;
|
|
7
|
-
visible = visible && element.offsetHeight > 0;
|
|
8
|
-
return visible;
|
|
9
|
-
};
|
|
10
|
-
const isFocusable = (element) => {
|
|
11
|
-
return element.tabIndex >= 0;
|
|
12
|
-
};
|
|
13
|
-
// navigation functions
|
|
14
|
-
const getUpCell = (event) => {
|
|
15
|
-
if (!(event.target instanceof HTMLElement))
|
|
16
|
-
return undefined;
|
|
17
|
-
return getUpCellEl(event.target);
|
|
18
|
-
};
|
|
19
|
-
const getUpCellEl = (element) => {
|
|
20
|
-
let $upCell;
|
|
21
|
-
if (element instanceof HTMLTableCellElement) {
|
|
22
|
-
const $prevSibling = element.parentElement?.previousElementSibling;
|
|
23
|
-
if ($prevSibling instanceof HTMLTableRowElement) {
|
|
24
|
-
const $prevRowCells = Array.from($prevSibling.children);
|
|
25
|
-
const $cellEl = $prevRowCells[element.cellIndex];
|
|
26
|
-
if ($cellEl instanceof HTMLElement) {
|
|
27
|
-
$upCell = $cellEl;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else if (element instanceof HTMLTableRowElement) {
|
|
32
|
-
const $prevSibling = element.previousElementSibling;
|
|
33
|
-
if ($prevSibling instanceof HTMLTableRowElement) {
|
|
34
|
-
$upCell = $prevSibling;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
// handle other contexts
|
|
39
|
-
}
|
|
40
|
-
if ($upCell && (!isFocusable($upCell) || !isVisible($upCell))) {
|
|
41
|
-
return getUpCellEl($upCell);
|
|
42
|
-
}
|
|
43
|
-
return $upCell;
|
|
44
|
-
};
|
|
45
|
-
const getTopCell = (event) => {
|
|
46
|
-
if (!(event.target instanceof HTMLElement))
|
|
47
|
-
return undefined;
|
|
48
|
-
const $target = event.target;
|
|
49
|
-
let $topCell;
|
|
50
|
-
if ($target instanceof HTMLTableCellElement) {
|
|
51
|
-
const $table = $target.parentElement?.parentElement;
|
|
52
|
-
if ($table) {
|
|
53
|
-
const $firstRow = $table.firstElementChild;
|
|
54
|
-
const $navEl = $firstRow?.children[$target.cellIndex];
|
|
55
|
-
if ($navEl instanceof HTMLElement) {
|
|
56
|
-
$topCell = $navEl;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else if ($target instanceof HTMLTableRowElement) {
|
|
61
|
-
const $parent = $target.parentElement;
|
|
62
|
-
if ($parent) {
|
|
63
|
-
const $firstEl = $parent.firstElementChild;
|
|
64
|
-
if ($firstEl instanceof HTMLTableRowElement) {
|
|
65
|
-
$topCell = $firstEl;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// handle other contexts
|
|
71
|
-
}
|
|
72
|
-
if ($topCell && (!isFocusable($topCell) || !isVisible($topCell))) {
|
|
73
|
-
return getDownCellEl($topCell);
|
|
74
|
-
}
|
|
75
|
-
return $topCell;
|
|
76
|
-
};
|
|
77
|
-
const getDownCell = (event) => {
|
|
78
|
-
if (!(event.target instanceof HTMLElement))
|
|
79
|
-
return undefined;
|
|
80
|
-
return getDownCellEl(event.target);
|
|
81
|
-
};
|
|
82
|
-
const getDownCellEl = (element) => {
|
|
83
|
-
let $downCell;
|
|
84
|
-
if (element instanceof HTMLTableCellElement) {
|
|
85
|
-
const $nextSibling = element.parentElement?.nextElementSibling;
|
|
86
|
-
if ($nextSibling) {
|
|
87
|
-
const $nextRowCells = Array.from($nextSibling.children);
|
|
88
|
-
const $cellEl = $nextRowCells[element.cellIndex];
|
|
89
|
-
if ($cellEl instanceof HTMLElement) {
|
|
90
|
-
$downCell = $cellEl;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else if (element instanceof HTMLTableRowElement) {
|
|
95
|
-
const $nextSibling = element.nextElementSibling;
|
|
96
|
-
if ($nextSibling instanceof HTMLTableRowElement) {
|
|
97
|
-
$downCell = $nextSibling;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
// handle other contexts
|
|
102
|
-
}
|
|
103
|
-
if ($downCell && (!isFocusable($downCell) || !isVisible($downCell))) {
|
|
104
|
-
return getDownCellEl($downCell);
|
|
105
|
-
}
|
|
106
|
-
return $downCell;
|
|
107
|
-
};
|
|
108
|
-
const getBottomCell = (event) => {
|
|
109
|
-
if (!(event.target instanceof HTMLElement))
|
|
110
|
-
return undefined;
|
|
111
|
-
const $target = event.target;
|
|
112
|
-
let $bottomCell;
|
|
113
|
-
if ($target instanceof HTMLTableCellElement) {
|
|
114
|
-
const $table = $target.parentElement?.parentElement;
|
|
115
|
-
if ($table) {
|
|
116
|
-
const $lastRow = $table.lastElementChild;
|
|
117
|
-
const $navEl = $lastRow?.children[$target.cellIndex];
|
|
118
|
-
if ($navEl instanceof HTMLElement) {
|
|
119
|
-
$bottomCell = $navEl;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else if ($target instanceof HTMLTableRowElement) {
|
|
124
|
-
const $parent = $target.parentElement;
|
|
125
|
-
if ($parent) {
|
|
126
|
-
const $lastEl = $parent.lastElementChild;
|
|
127
|
-
if ($lastEl instanceof HTMLTableRowElement) {
|
|
128
|
-
$bottomCell = $lastEl;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
// handle other contexts
|
|
134
|
-
}
|
|
135
|
-
if ($bottomCell && (!isFocusable($bottomCell) || !isVisible($bottomCell))) {
|
|
136
|
-
return getUpCellEl($bottomCell);
|
|
137
|
-
}
|
|
138
|
-
return $bottomCell;
|
|
139
|
-
};
|
|
140
|
-
const getPrevCell = (event) => {
|
|
141
|
-
if (!(event.target instanceof HTMLElement))
|
|
142
|
-
return undefined;
|
|
143
|
-
return getPrevCellEl(event.target);
|
|
144
|
-
};
|
|
145
|
-
const getPrevCellEl = (element) => {
|
|
146
|
-
let $prevCell;
|
|
147
|
-
const $prevSibling = element.previousElementSibling;
|
|
148
|
-
if ($prevSibling instanceof HTMLElement) {
|
|
149
|
-
$prevCell = $prevSibling;
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
const $prevRow = element.parentElement?.previousElementSibling;
|
|
153
|
-
const $lastEl = $prevRow?.lastElementChild;
|
|
154
|
-
if ($lastEl instanceof HTMLElement) {
|
|
155
|
-
$prevCell = $lastEl;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
if ($prevCell && (!isFocusable($prevCell) || !isVisible($prevCell))) {
|
|
159
|
-
return getPrevCellEl($prevCell);
|
|
160
|
-
}
|
|
161
|
-
return $prevCell;
|
|
162
|
-
};
|
|
163
|
-
const getNextCell = (event) => {
|
|
164
|
-
if (!(event.target instanceof HTMLElement))
|
|
165
|
-
return undefined;
|
|
166
|
-
return getNextCellEl(event.target);
|
|
167
|
-
};
|
|
168
|
-
const getNextCellEl = (element) => {
|
|
169
|
-
let $nextCell;
|
|
170
|
-
const $nextSibling = element.nextElementSibling;
|
|
171
|
-
if ($nextSibling instanceof HTMLElement) {
|
|
172
|
-
$nextCell = $nextSibling;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
const $nextRow = element.parentElement?.nextElementSibling;
|
|
176
|
-
const $firstEl = $nextRow?.firstElementChild;
|
|
177
|
-
if ($firstEl instanceof HTMLElement) {
|
|
178
|
-
$nextCell = $firstEl;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if ($nextCell && (!isFocusable($nextCell) || !isVisible($nextCell))) {
|
|
182
|
-
return getNextCellEl($nextCell);
|
|
183
|
-
}
|
|
184
|
-
return $nextCell;
|
|
185
|
-
};
|
|
186
|
-
const getFirstCell = (event) => {
|
|
187
|
-
if (!(event.target instanceof HTMLElement))
|
|
188
|
-
return undefined;
|
|
189
|
-
const $parent = event.target.parentElement;
|
|
190
|
-
const $firstEl = $parent?.firstElementChild;
|
|
191
|
-
const $firstCell = $firstEl instanceof HTMLElement ? $firstEl : null;
|
|
192
|
-
if ($firstCell && (!isFocusable($firstCell) || !isVisible($firstCell))) {
|
|
193
|
-
return getNextCellEl($firstCell);
|
|
194
|
-
}
|
|
195
|
-
return $firstCell;
|
|
196
|
-
};
|
|
197
|
-
const getLastCell = (event) => {
|
|
198
|
-
if (!(event.target instanceof HTMLElement))
|
|
199
|
-
return undefined;
|
|
200
|
-
const $parent = event.target.parentElement;
|
|
201
|
-
const $lastEl = $parent?.lastElementChild;
|
|
202
|
-
const $lastCell = $lastEl instanceof HTMLElement ? $lastEl : null;
|
|
203
|
-
if ($lastCell && (!isFocusable($lastCell) || !isVisible($lastCell))) {
|
|
204
|
-
return getPrevCellEl($lastCell);
|
|
205
|
-
}
|
|
206
|
-
return $lastCell;
|
|
207
|
-
};
|
|
208
|
-
const modifierKeys = ['alt', 'control', 'shift', 'meta'];
|
|
209
|
-
const eventKeyMap = {
|
|
210
|
-
ArrowUp: 'up',
|
|
211
|
-
ArrowDown: 'down',
|
|
212
|
-
ArrowLeft: 'left',
|
|
213
|
-
ArrowRight: 'right',
|
|
214
|
-
};
|
|
215
|
-
/**
|
|
216
|
-
* Default keypress handlers for keyboard navigation
|
|
217
|
-
* @public
|
|
218
|
-
*/
|
|
219
|
-
export const defaultKeypressHandlers = {
|
|
220
|
-
'keydown.up': (event) => {
|
|
221
|
-
const $upCell = getUpCell(event);
|
|
222
|
-
if ($upCell) {
|
|
223
|
-
event.preventDefault();
|
|
224
|
-
event.stopPropagation();
|
|
225
|
-
$upCell.focus();
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
'keydown.down': (event) => {
|
|
229
|
-
const $downCell = getDownCell(event);
|
|
230
|
-
if ($downCell) {
|
|
231
|
-
event.preventDefault();
|
|
232
|
-
event.stopPropagation();
|
|
233
|
-
$downCell.focus();
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
'keydown.left': (event) => {
|
|
237
|
-
const $prevCell = getPrevCell(event);
|
|
238
|
-
// prevent default edit-cell behaviour on first cell
|
|
239
|
-
event.preventDefault();
|
|
240
|
-
event.stopPropagation();
|
|
241
|
-
if ($prevCell) {
|
|
242
|
-
$prevCell.focus();
|
|
243
|
-
}
|
|
244
|
-
},
|
|
245
|
-
'keydown.right': (event) => {
|
|
246
|
-
const $nextCell = getNextCell(event);
|
|
247
|
-
// prevent default edit-cell behaviour on last cell
|
|
248
|
-
event.preventDefault();
|
|
249
|
-
event.stopPropagation();
|
|
250
|
-
if ($nextCell) {
|
|
251
|
-
$nextCell.focus();
|
|
252
|
-
}
|
|
253
|
-
},
|
|
254
|
-
'keydown.control.up': (event) => {
|
|
255
|
-
const $topCell = getTopCell(event);
|
|
256
|
-
if ($topCell) {
|
|
257
|
-
event.preventDefault();
|
|
258
|
-
event.stopPropagation();
|
|
259
|
-
$topCell.focus();
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
'keydown.control.down': (event) => {
|
|
263
|
-
const $bottomCell = getBottomCell(event);
|
|
264
|
-
if ($bottomCell) {
|
|
265
|
-
event.preventDefault();
|
|
266
|
-
event.stopPropagation();
|
|
267
|
-
$bottomCell.focus();
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
'keydown.control.left': (event) => {
|
|
271
|
-
const $firstCell = getFirstCell(event);
|
|
272
|
-
if ($firstCell) {
|
|
273
|
-
event.preventDefault();
|
|
274
|
-
event.stopPropagation();
|
|
275
|
-
$firstCell.focus();
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
'keydown.control.right': (event) => {
|
|
279
|
-
const $lastCell = getLastCell(event);
|
|
280
|
-
if ($lastCell) {
|
|
281
|
-
event.preventDefault();
|
|
282
|
-
event.stopPropagation();
|
|
283
|
-
$lastCell.focus();
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
'keydown.end': (event) => {
|
|
287
|
-
const $lastCell = getLastCell(event);
|
|
288
|
-
if ($lastCell) {
|
|
289
|
-
event.preventDefault();
|
|
290
|
-
event.stopPropagation();
|
|
291
|
-
$lastCell.focus();
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
'keydown.enter': (event) => {
|
|
295
|
-
if (!(event.target instanceof HTMLElement))
|
|
296
|
-
return;
|
|
297
|
-
const $target = event.target;
|
|
298
|
-
if ($target instanceof HTMLTableCellElement) {
|
|
299
|
-
event.preventDefault();
|
|
300
|
-
event.stopPropagation();
|
|
301
|
-
const $downCell = getDownCell(event);
|
|
302
|
-
if ($downCell) {
|
|
303
|
-
$downCell.focus();
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
// handle other contexts
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
'keydown.shift.enter': (event) => {
|
|
311
|
-
if (!(event.target instanceof HTMLElement))
|
|
312
|
-
return;
|
|
313
|
-
const $target = event.target;
|
|
314
|
-
if ($target instanceof HTMLTableCellElement) {
|
|
315
|
-
event.preventDefault();
|
|
316
|
-
event.stopPropagation();
|
|
317
|
-
const $upCell = getUpCell(event);
|
|
318
|
-
if ($upCell) {
|
|
319
|
-
$upCell.focus();
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
// handle other contexts
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
'keydown.home': (event) => {
|
|
327
|
-
const $firstCell = getFirstCell(event);
|
|
328
|
-
if ($firstCell) {
|
|
329
|
-
event.preventDefault();
|
|
330
|
-
event.stopPropagation();
|
|
331
|
-
$firstCell.focus();
|
|
332
|
-
}
|
|
333
|
-
},
|
|
334
|
-
'keydown.tab': (event) => {
|
|
335
|
-
const $nextCell = getNextCell(event);
|
|
336
|
-
if ($nextCell) {
|
|
337
|
-
event.preventDefault();
|
|
338
|
-
event.stopPropagation();
|
|
339
|
-
$nextCell.focus();
|
|
340
|
-
}
|
|
341
|
-
},
|
|
342
|
-
'keydown.shift.tab': (event) => {
|
|
343
|
-
const $prevCell = getPrevCell(event);
|
|
344
|
-
if ($prevCell) {
|
|
345
|
-
event.preventDefault();
|
|
346
|
-
event.stopPropagation();
|
|
347
|
-
$prevCell.focus();
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
};
|
|
351
|
-
/**
|
|
352
|
-
* Gets the parent element from a keyboard navigation option.
|
|
353
|
-
* @internal
|
|
354
|
-
*/
|
|
355
|
-
function getParentElement(option) {
|
|
356
|
-
let $parent = null;
|
|
357
|
-
if (option.parent) {
|
|
358
|
-
if (typeof option.parent === 'string') {
|
|
359
|
-
$parent = document.querySelector(option.parent);
|
|
360
|
-
}
|
|
361
|
-
else if (option.parent instanceof HTMLElement) {
|
|
362
|
-
$parent = option.parent;
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
$parent = option.parent.value;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return $parent;
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Keyboard navigation composable
|
|
372
|
-
* @param options - Keyboard navigation options
|
|
373
|
-
* @public
|
|
374
|
-
*/
|
|
375
|
-
export function useKeyboardNav(options) {
|
|
376
|
-
const getSelectorsFromOption = (option) => {
|
|
377
|
-
// assumes that option.selectors is provided
|
|
378
|
-
const $parent = getParentElement(option);
|
|
379
|
-
let selectors = [];
|
|
380
|
-
if (typeof option.selectors === 'string') {
|
|
381
|
-
selectors = $parent
|
|
382
|
-
? Array.from($parent.querySelectorAll(option.selectors))
|
|
383
|
-
: Array.from(document.querySelectorAll(option.selectors));
|
|
384
|
-
}
|
|
385
|
-
else if (Array.isArray(option.selectors)) {
|
|
386
|
-
for (const element of option.selectors) {
|
|
387
|
-
if (element instanceof HTMLElement) {
|
|
388
|
-
selectors.push(element);
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- Vue component $el is typed as any; shape guaranteed by VNode contract
|
|
392
|
-
selectors.push(element.$el);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
else if (option.selectors instanceof HTMLElement) {
|
|
397
|
-
selectors.push(option.selectors);
|
|
398
|
-
}
|
|
399
|
-
else if (option.selectors?.value) {
|
|
400
|
-
if (Array.isArray(option.selectors.value)) {
|
|
401
|
-
for (const element of option.selectors.value) {
|
|
402
|
-
if (element instanceof HTMLElement) {
|
|
403
|
-
selectors.push(element);
|
|
404
|
-
}
|
|
405
|
-
else {
|
|
406
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- Vue component $el is typed as any; shape guaranteed by VNode contract
|
|
407
|
-
selectors.push(element.$el);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
selectors.push(option.selectors.value);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return selectors;
|
|
416
|
-
};
|
|
417
|
-
const getSelectors = (option) => {
|
|
418
|
-
const $parent = getParentElement(option);
|
|
419
|
-
let selectors = [];
|
|
420
|
-
if (option.selectors) {
|
|
421
|
-
selectors = getSelectorsFromOption(option);
|
|
422
|
-
}
|
|
423
|
-
else if ($parent) {
|
|
424
|
-
// TODO: what should happen if no parent or selectors are provided?
|
|
425
|
-
const $children = Array.from($parent.children).filter((el) => el instanceof HTMLElement);
|
|
426
|
-
selectors = $children.filter(selector => {
|
|
427
|
-
// ignore elements not in the tab order or are not visible
|
|
428
|
-
return isFocusable(selector) && isVisible(selector);
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
return selectors;
|
|
432
|
-
};
|
|
433
|
-
const getEventListener = (option) => {
|
|
434
|
-
return (event) => {
|
|
435
|
-
const activeKey = eventKeyMap[event.key] || event.key.toLowerCase();
|
|
436
|
-
if (modifierKeys.includes(activeKey))
|
|
437
|
-
return; // ignore modifier key presses
|
|
438
|
-
const handlers = option.handlers || defaultKeypressHandlers;
|
|
439
|
-
for (const key of Object.keys(handlers)) {
|
|
440
|
-
const [eventType, ...keys] = key.split('.');
|
|
441
|
-
if (eventType !== 'keydown') {
|
|
442
|
-
continue;
|
|
443
|
-
}
|
|
444
|
-
if (keys.includes(activeKey)) {
|
|
445
|
-
const listener = handlers[key];
|
|
446
|
-
// check if the handler has modifiers, and if the modifier is active;
|
|
447
|
-
// this is to ensure exact key-press matches
|
|
448
|
-
const hasModifier = keys.filter(k => modifierKeys.includes(k));
|
|
449
|
-
const isModifierActive = modifierKeys.some(mk => {
|
|
450
|
-
const modifierKey = mk.charAt(0).toUpperCase() + mk.slice(1);
|
|
451
|
-
return event.getModifierState(modifierKey);
|
|
452
|
-
});
|
|
453
|
-
if (hasModifier.length > 0) {
|
|
454
|
-
if (isModifierActive) {
|
|
455
|
-
for (const modifier of modifierKeys) {
|
|
456
|
-
if (keys.includes(modifier)) {
|
|
457
|
-
// docs: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState
|
|
458
|
-
const modifierKey = modifier.charAt(0).toUpperCase() + modifier.slice(1);
|
|
459
|
-
if (event.getModifierState(modifierKey)) {
|
|
460
|
-
listener(event);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
else {
|
|
467
|
-
if (!isModifierActive) {
|
|
468
|
-
listener(event);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
};
|
|
475
|
-
const watchStopHandlers = [];
|
|
476
|
-
onMounted(() => {
|
|
477
|
-
for (const option of options) {
|
|
478
|
-
const $parent = getParentElement(option);
|
|
479
|
-
const selectors = getSelectors(option);
|
|
480
|
-
const listener = getEventListener(option);
|
|
481
|
-
const listenerElements = $parent
|
|
482
|
-
? [$parent] // watch for focus recursively within the parent element
|
|
483
|
-
: selectors; // watch for focus on each selector element TODO: too much JS?
|
|
484
|
-
for (const element of listenerElements) {
|
|
485
|
-
const { focused } = useFocusWithin(ref(element));
|
|
486
|
-
const stopHandler = watch(focused, value => {
|
|
487
|
-
if (value) {
|
|
488
|
-
element.addEventListener('keydown', listener);
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
element.removeEventListener('keydown', listener);
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
watchStopHandlers.push(stopHandler);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
});
|
|
498
|
-
onBeforeUnmount(() => {
|
|
499
|
-
for (const stopHandler of watchStopHandlers) {
|
|
500
|
-
stopHandler();
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { type ConfigurableWindow, type MaybeComputedElementRef } from '@vueuse/core';
|
|
2
|
-
import { type MaybeRefOrGetter } from 'vue';
|
|
3
|
-
export interface UseElementVisibilityOptions extends ConfigurableWindow {
|
|
4
|
-
scrollTarget?: MaybeRefOrGetter<HTMLElement | undefined | null>;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Tracks the visibility of an element within the viewport.
|
|
8
|
-
*
|
|
9
|
-
* Compatibility version to get Stonecrop keyboard navigation to work. This function is a copy of the
|
|
10
|
-
* `useElementVisibility` function from VueUse v9.13.0, with the `IntersectionObserver` API removed.
|
|
11
|
-
*
|
|
12
|
-
* This version uses the `getBoundingClientRect` method to determine if an element is visible
|
|
13
|
-
* in the viewport. This is less performant than the `IntersectionObserver` API, but it is
|
|
14
|
-
* more compatible.
|
|
15
|
-
*
|
|
16
|
-
* Note: the newer versions of the VueUse dependencies imported here are sufficient for this composable.
|
|
17
|
-
* (Last verified: v10.9.0 on May 2, 2024)
|
|
18
|
-
*
|
|
19
|
-
* @see https://v9-13-0.vueuse.org/core/useElementVisibility
|
|
20
|
-
* @param element - Element to track visibility for
|
|
21
|
-
* @param options - Configuration options (window, scrollTarget)
|
|
22
|
-
*/
|
|
23
|
-
export declare function useElementVisibility(element: MaybeComputedElementRef, { window, scrollTarget }?: UseElementVisibilityOptions): import("vue").Ref<boolean, boolean>;
|
|
24
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/composables/visibility/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAI5B,MAAM,cAAc,CAAA;AACrB,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAEvD,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;IACtE,YAAY,CAAC,EAAE,gBAAgB,CAAC,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC,CAAA;CAC/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,uBAAuB,EAChC,EAAE,MAAsB,EAAE,YAAY,EAAE,GAAE,2BAAgC,uCAmC1E"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { defaultWindow, unrefElement, useEventListener, } from '@vueuse/core';
|
|
2
|
-
import { ref, watch } from 'vue';
|
|
3
|
-
/**
|
|
4
|
-
* Tracks the visibility of an element within the viewport.
|
|
5
|
-
*
|
|
6
|
-
* Compatibility version to get Stonecrop keyboard navigation to work. This function is a copy of the
|
|
7
|
-
* `useElementVisibility` function from VueUse v9.13.0, with the `IntersectionObserver` API removed.
|
|
8
|
-
*
|
|
9
|
-
* This version uses the `getBoundingClientRect` method to determine if an element is visible
|
|
10
|
-
* in the viewport. This is less performant than the `IntersectionObserver` API, but it is
|
|
11
|
-
* more compatible.
|
|
12
|
-
*
|
|
13
|
-
* Note: the newer versions of the VueUse dependencies imported here are sufficient for this composable.
|
|
14
|
-
* (Last verified: v10.9.0 on May 2, 2024)
|
|
15
|
-
*
|
|
16
|
-
* @see https://v9-13-0.vueuse.org/core/useElementVisibility
|
|
17
|
-
* @param element - Element to track visibility for
|
|
18
|
-
* @param options - Configuration options (window, scrollTarget)
|
|
19
|
-
*/
|
|
20
|
-
export function useElementVisibility(element, { window = defaultWindow, scrollTarget } = {}) {
|
|
21
|
-
const elementIsVisible = ref(false);
|
|
22
|
-
const testBounding = () => {
|
|
23
|
-
if (!window)
|
|
24
|
-
return;
|
|
25
|
-
const document = window.document;
|
|
26
|
-
const el = unrefElement(element);
|
|
27
|
-
if (!el) {
|
|
28
|
-
elementIsVisible.value = false;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
const rect = el.getBoundingClientRect();
|
|
32
|
-
elementIsVisible.value =
|
|
33
|
-
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
34
|
-
rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&
|
|
35
|
-
rect.bottom >= 0 &&
|
|
36
|
-
rect.right >= 0;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
watch(() => unrefElement(element), () => testBounding(), { immediate: true, flush: 'post' });
|
|
40
|
-
if (window) {
|
|
41
|
-
useEventListener(scrollTarget || window, 'scroll', testBounding, {
|
|
42
|
-
capture: false,
|
|
43
|
-
passive: true,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return elementIsVisible;
|
|
47
|
-
}
|
package/dist/src/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { App } from 'vue';
|
|
2
|
-
import { defaultKeypressHandlers, useKeyboardNav } from './composables/keyboard';
|
|
3
|
-
export type * from './types';
|
|
4
|
-
/**
|
|
5
|
-
* Install all utility components
|
|
6
|
-
* @param _app - Vue app instance
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
declare function install(_app: App): void;
|
|
10
|
-
export { defaultKeypressHandlers, install, useKeyboardNav };
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAChF,mBAAmB,SAAS,CAAA;AAE5B;;;;GAIG;AACH,iBAAS,OAAO,CAAC,IAAI,EAAE,GAAG,QAAkB;AAE5C,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
package/dist/src/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { defaultKeypressHandlers, useKeyboardNav } from './composables/keyboard';
|
|
2
|
-
/**
|
|
3
|
-
* Install all utility components
|
|
4
|
-
* @param _app - Vue app instance
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
function install(_app /* options */) { }
|
|
8
|
-
export { defaultKeypressHandlers, install, useKeyboardNav };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { ComponentPublicInstance, Ref } from 'vue';
|
|
2
|
-
/**
|
|
3
|
-
* Key press handlers
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export type KeypressHandlers = {
|
|
7
|
-
[key: string]: (ev: KeyboardEvent) => any;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Keyboard navigation options
|
|
11
|
-
* @public
|
|
12
|
-
*/
|
|
13
|
-
export type KeyboardNavigationOptions = {
|
|
14
|
-
parent?: string | HTMLElement | Readonly<Ref<HTMLElement | null>>;
|
|
15
|
-
selectors?: string | HTMLElement | HTMLElement[] | ComponentPublicInstance[] | Readonly<Ref<HTMLElement | null>> | Readonly<Ref<HTMLElement[] | null>> | Readonly<Ref<ComponentPublicInstance[] | null>>;
|
|
16
|
-
handlers?: KeypressHandlers;
|
|
17
|
-
};
|
|
18
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAElD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,aAAa,KAAK,GAAG,CAAA;CACzC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IAGvC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAA;IACjE,SAAS,CAAC,EACP,MAAM,GACN,WAAW,GACX,WAAW,EAAE,GACb,uBAAuB,EAAE,GACzB,QAAQ,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,GACjC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,CAAC,GACnC,QAAQ,CAAC,GAAG,CAAC,uBAAuB,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC3B,CAAA"}
|
package/dist/src/types/index.js
DELETED
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"6.0.3"}
|