({
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledby,
children,
flat,
})
| 251 | ` |
| 252 | |
| 253 | const Root: React.FC<TreeViewProps> = ({ |
| 254 | 'aria-label': ariaLabel, |
| 255 | 'aria-labelledby': ariaLabelledby, |
| 256 | children, |
| 257 | flat, |
| 258 | }) => { |
| 259 | const containerRef = React.useRef<HTMLUListElement>(null) |
| 260 | const mouseDownRef = React.useRef<boolean>(false) |
| 261 | const [ariaLiveMessage, setAriaLiveMessage] = React.useState('') |
| 262 | const announceUpdate = React.useCallback((message: string) => { |
| 263 | setAriaLiveMessage(message) |
| 264 | }, []) |
| 265 | |
| 266 | const onMouseDown = useCallback(() => { |
| 267 | mouseDownRef.current = true |
| 268 | }, []) |
| 269 | |
| 270 | useEffect(() => { |
| 271 | function onMouseUp() { |
| 272 | mouseDownRef.current = false |
| 273 | } |
| 274 | document.addEventListener('mouseup', onMouseUp) |
| 275 | return () => { |
| 276 | document.removeEventListener('mouseup', onMouseUp) |
| 277 | } |
| 278 | }, []) |
| 279 | |
| 280 | useRovingTabIndex({containerRef, mouseDownRef}) |
| 281 | useTypeahead({ |
| 282 | containerRef, |
| 283 | onFocusChange: element => { |
| 284 | if (element instanceof HTMLElement) { |
| 285 | element.focus() |
| 286 | } |
| 287 | }, |
| 288 | }) |
| 289 | |
| 290 | const expandedStateCache = React.useRef<Map<string, boolean> | null>(null) |
| 291 | |
| 292 | if (expandedStateCache.current === null) { |
| 293 | expandedStateCache.current = new Map() |
| 294 | } |
| 295 | |
| 296 | return ( |
| 297 | <RootContext.Provider |
| 298 | value={{ |
| 299 | announceUpdate, |
| 300 | expandedStateCache, |
| 301 | }} |
| 302 | > |
| 303 | <> |
| 304 | <VisuallyHidden role="status" aria-live="polite" aria-atomic="true"> |
| 305 | {ariaLiveMessage} |
| 306 | </VisuallyHidden> |
| 307 | <UlBox |
| 308 | ref={containerRef} |
| 309 | role="tree" |
| 310 | aria-label={ariaLabel} |
nothing calls this directly
no test coverage detected