-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathTableCorner.tsx
More file actions
120 lines (109 loc) · 3.6 KB
/
Copy pathTableCorner.tsx
File metadata and controls
120 lines (109 loc) · 3.6 KB
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
import type { ChangeEvent, CSSProperties, KeyboardEvent, ReactNode } from 'react'
import { useCallback, useContext, useEffect, useRef } from 'react'
import { SetTableCornerSizeContext } from '../../contexts/TableCornerSizeContext.js'
import { useCellFocus } from '../../hooks/useCellFocus.js'
interface Props {
checked?: boolean
children?: ReactNode
onCheckboxPress?: () => void
pendingSelectionGesture?: boolean
style?: CSSProperties
ariaColIndex: number
ariaRowIndex: number
}
export default function TableCorner({ children, checked, onCheckboxPress, pendingSelectionGesture, style, ariaColIndex, ariaRowIndex }: Props) {
const { tabIndex, navigateToCell, focusIfNeeded } = useCellFocus({ ariaColIndex, ariaRowIndex })
const setTableCornerSize = useContext(SetTableCornerSizeContext)
// Focus the cell if needed. We use an effect, as it acts on the DOM element after render.
const ref = useRef<HTMLTableCellElement | null>(null)
useEffect(() => {
focusIfNeeded?.(ref.current)
}, [focusIfNeeded])
const handleClick = useCallback(() => {
navigateToCell?.()
onCheckboxPress?.()
}, [onCheckboxPress, navigateToCell])
const handleKeyDown = useCallback((event: KeyboardEvent) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault()
// TODO: let the event propagate?
event.stopPropagation()
onCheckboxPress?.()
}
}, [onCheckboxPress])
const showCheckBox = checked !== undefined
const disabledCheckbox = onCheckboxPress === undefined
const onChange = useCallback((e: ChangeEvent) => {
e.preventDefault()
}, [])
const trackSize = useCallback((tableCorner: HTMLTableCellElement | null) => {
if (!setTableCornerSize) {
// Size tracking is disabled intentionally when no callback is provided.
return
}
if (!tableCorner) {
return
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!window.ResizeObserver) {
// for jsdom
return
}
// Use an arrow function to get correct tableCorner type (not null)
// eslint-disable-next-line func-style
const updateTableCornerSize = () => {
setTableCornerSize(tableCorner)
}
// run once
updateTableCornerSize()
// listener
const resizeObserver = new window.ResizeObserver(([entry]) => {
if (!entry) {
console.warn('ResizeObserver entry is not available.')
return
}
updateTableCornerSize()
})
resizeObserver.observe(tableCorner)
return () => {
resizeObserver.unobserve(tableCorner)
resizeObserver.disconnect()
}
/* Track the size of the table corner */
}, [setTableCornerSize])
const refCallback = useCallback((tableCorner: HTMLTableCellElement | null) => {
ref.current = tableCorner
const removeSizeTracking = trackSize(tableCorner)
return removeSizeTracking
}, [trackSize])
return (
<td
ref={refCallback}
style={style}
onClick={handleClick}
onKeyDown={handleKeyDown}
aria-checked={checked}
aria-rowindex={ariaRowIndex}
aria-colindex={ariaColIndex}
aria-disabled={disabledCheckbox}
tabIndex={tabIndex}
>
{
showCheckBox
? (
<input
type="checkbox"
onChange={onChange}
readOnly={disabledCheckbox}
disabled={disabledCheckbox}
aria-busy={pendingSelectionGesture}
checked={checked}
role="presentation"
tabIndex={-1}
/>
)
: <span>{children}</span>
}
</td>
)
}