-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathRovingFocusGroup.ts
127 lines (114 loc) · 3.63 KB
/
RovingFocusGroup.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { createProvideScope } from '@oku-ui/provide'
import type { CollectionPropsType } from '@oku-ui/collection'
import { createCollection } from '@oku-ui/collection'
import type { Ref } from 'vue'
import { defineComponent, h, toRefs } from 'vue'
import { useForwardRef } from '@oku-ui/use-composable'
import { primitiveProps } from '@oku-ui/primitive'
import { OkuRovingFocusGroupImpl, rovingFocusGroupImplProps } from './RovingFocusGroupImpl'
import type { RovingFocusGroupImplElement, RovingFocusGroupImplIntrinsicElement, RovingFocusGroupImplProps } from './RovingFocusGroupImpl'
import { scopedProps } from './types'
import type { Direction, Orientation } from './utils'
const GROUP_NAME = 'OkuRovingFocusGroup'
export interface ItemData extends CollectionPropsType {
id: string
focusable: boolean
active: boolean
}
export const { CollectionItemSlot, CollectionProvider, CollectionSlot, useCollection, createCollectionScope } = createCollection<
HTMLSpanElement,
ItemData
>(GROUP_NAME, {
id: {
type: String,
},
focusable: {
type: Boolean,
},
active: {
type: Boolean,
},
})
const [createRovingFocusGroupProvide, createRovingFocusGroupScope] = createProvideScope(
GROUP_NAME,
[createCollectionScope],
)
// RovingFocusGroupOptions extends
type RovingProvideValue = {
/**
* The orientation of the group.
* Mainly so arrow navigation is done accordingly (left & right vs. up & down)
*/
orientation?: Ref<Orientation | undefined>
/**
* The direction of navigation between items.
*/
dir?: Ref<Direction | undefined>
/**
* Whether keyboard navigation should loop around
* @defaultValue false
*/
loop?: Ref<boolean | undefined>
currentTabStopId: Ref<string>
onItemFocus(tabStopId: string): void
onItemShiftTab(): void
onFocusableItemAdd(): void
onFocusableItemRemove(): void
}
export const [rovingFocusProvider, useRovingFocusInject]
= createRovingFocusGroupProvide<RovingProvideValue>(GROUP_NAME)
export type RovingFocusGroupIntrinsicElement = RovingFocusGroupImplIntrinsicElement
export type RovingFocusGroupElement = RovingFocusGroupImplElement
export interface RovingFocusGroupProps extends RovingFocusGroupImplProps { }
export const rovingFocusGroupProps = {
...rovingFocusGroupImplProps,
}
const rovingFocusGroup = defineComponent({
name: GROUP_NAME,
components: {
OkuRovingFocusGroupImpl,
CollectionProvider,
CollectionSlot,
CollectionItemSlot,
},
inheritAttrs: false,
props: {
...rovingFocusGroupProps.props,
...scopedProps,
...primitiveProps,
},
emits: rovingFocusGroupProps.emits,
setup(props, { slots, attrs }) {
const { currentTabStopId, dir, loop, orientation, defaultCurrentTabStopId, asChild } = toRefs(props)
const forwardedRef = useForwardRef()
return () => {
return h(CollectionProvider, {
scope: props.scopeOkuRovingFocusGroup,
}, {
default: () => h(CollectionSlot, {
scope: props.scopeOkuRovingFocusGroup,
}, {
default: () => h(OkuRovingFocusGroupImpl, {
...attrs,
asChild: asChild.value,
currentTabStopId: currentTabStopId?.value,
defaultCurrentTabStopId: defaultCurrentTabStopId?.value,
dir: dir?.value,
loop: loop?.value,
orientation: orientation?.value,
ref: forwardedRef,
}, slots),
}),
})
}
},
})
// TODO: https://github.com/vuejs/core/pull/7444 after delete
const OkuRovingFocusGroup = rovingFocusGroup as typeof rovingFocusGroup &
(new () => {
$props: Partial<RovingFocusGroupElement>
})
export {
OkuRovingFocusGroup,
createRovingFocusGroupScope,
}