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