/
useDateTimeField.ts
61 lines (51 loc) · 1.73 KB
/
useDateTimeField.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
import { HTMLAttributes } from 'react'
import { usePress } from '../../interactions/press'
import { useFocusManager } from '../../libs/focus'
import { useUniqId } from '../../libs/uniq-id'
import { AriaLabelingProps } from '../../shared/types'
export interface UseDateTimeFieldProps extends AriaLabelingProps {
id?: string
'aria-controls'?: string
'aria-haspopup'?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog'
'aria-invalid'?: boolean | 'false' | 'true' | 'grammar' | 'spelling'
}
export interface UseDateTimeFieldResult {
fieldProps: HTMLAttributes<HTMLElement>
segmentProps: HTMLAttributes<HTMLElement>
}
export function useDateTimeField(props: UseDateTimeFieldProps): UseDateTimeFieldResult {
const { focusNext } = useFocusManager()
const id = useUniqId(props.id)
const { pressProps } = usePress({
onPressStart: (event) => {
const { currentTarget, target, source } = event
const { activeElement } = document
if (source !== 'mouse') {
return
}
if (
!currentTarget.contains(activeElement) ||
(target !== activeElement && target !== currentTarget)
) {
focusNext({ from: target as HTMLElement, tabbable: true })
}
},
})
const fieldProps: HTMLAttributes<HTMLElement> = {
...pressProps,
role: 'group',
id,
'aria-label': props['aria-label'],
'aria-labelledby': props['aria-labelledby'],
}
const segmentProps: HTMLAttributes<HTMLElement> = {
'aria-controls': props['aria-controls'],
'aria-haspopup': props['aria-haspopup'],
'aria-invalid': props['aria-invalid'],
'aria-labelledby': fieldProps['aria-labelledby'] || fieldProps.id,
}
return {
fieldProps,
segmentProps,
}
}