Files
headlessui/packages/@headlessui-react/src/internal/focus-sentinel.tsx
T
Robin Malfait 76dd10ea55 Sort imports automatically (#2741)
* add `prettier-plugin-organize-imports` and `prettier-plugin-tailwindcss`

* format

* bump Tailwind CSS

* format playgrounds using updated Tailwind CSS and Prettier plugins

* use import syntax
2023-09-11 18:36:30 +02:00

52 lines
1.3 KiB
TypeScript

import React, { FocusEvent as ReactFocusEvent, useState } from 'react'
import { useIsMounted } from '../hooks/use-is-mounted'
import { Features, Hidden } from './hidden'
interface FocusSentinelProps {
onFocus(): boolean
}
export function FocusSentinel({ onFocus }: FocusSentinelProps) {
let [enabled, setEnabled] = useState(true)
let mounted = useIsMounted()
if (!enabled) return null
return (
<Hidden
as="button"
type="button"
features={Features.Focusable}
onFocus={(event: ReactFocusEvent) => {
event.preventDefault()
let frame: ReturnType<typeof requestAnimationFrame>
let tries = 50
function forwardFocus() {
// Prevent infinite loops
if (tries-- <= 0) {
if (frame) cancelAnimationFrame(frame)
return
}
// Try to move focus to the correct element. This depends on the implementation
// of `onFocus` of course since it would be different for each place we use it in.
if (onFocus()) {
cancelAnimationFrame(frame)
if (!mounted.current) return
setEnabled(false)
return
}
// Retry
frame = requestAnimationFrame(forwardFocus)
}
frame = requestAnimationFrame(forwardFocus)
}}
/>
)
}