import { useAppDispatch } from 'domains/store' import { setSeamlyContainerElement } from 'domains/store/slice' import { useCallback, useRef } from 'preact/hooks' import { focusElement, runIfElementContainsOrHasFocus, } from 'ui/utils/general-utils' import { useSeamlyStateContext, useSkiplinkElement, useSkiplinkTarget, } from './seamly-state-hooks' export const timeout = (ms = 0) => new Promise((resolve) => { setTimeout(resolve, ms) }) const focusWithRaf = (el) => { requestAnimationFrame(async () => { await timeout(180) // wait for next 3 ticks const focusEl = typeof el === 'string' ? document.getElementById(el) : el focusElement(focusEl) }) } export const useSeamlyContainerElement = () => { const { seamlyContainerElement } = useSeamlyStateContext() const dispatch = useAppDispatch() const dispatchSeamlyContainerElement = useCallback( (element: any): void => { dispatch(setSeamlyContainerElement(element)) }, [dispatch], ) return [seamlyContainerElement, dispatchSeamlyContainerElement] } export const useElementFocusingById = (elementId) => useCallback(() => { focusWithRaf(elementId) }, [elementId]) export const useSkiplinkElementFocusing = () => { const skiplinkElementId = useSkiplinkElement() return useElementFocusingById(skiplinkElementId) } export const useSkiplinkTargetFocusing = () => { const skiplinkTargetId = useSkiplinkTarget() return useElementFocusingById(skiplinkTargetId) } export const useWindowOpenButtonFocusing = () => { const { windowOpenButtonId } = useSeamlyStateContext() return useElementFocusingById(windowOpenButtonId) } export const useFocusIfSeamlyContainedFocus = () => { const containerElementRef = useRef< HTMLElement | ((_element: any) => void) | null >(null) const [seamlyContainerElement] = useSeamlyContainerElement() containerElementRef.current = seamlyContainerElement return useCallback((elementToFocus) => { const focusFn = () => { focusWithRaf(elementToFocus) } runIfElementContainsOrHasFocus(containerElementRef.current, focusFn) }, []) }