|
|
@@ -1,4 +1,4 @@ |
|
|
|
import { useState, useRef, useEffect } from "react"; |
|
|
|
import { useState, useRef, useEffect, useCallback } from "react"; |
|
|
|
|
|
|
|
const focusUrlParamName = 'focus' |
|
|
|
const focusChangedEventName = "focus-changed" |
|
|
@@ -16,31 +16,51 @@ function triggerElementFocused(elementKey?: string) { |
|
|
|
window.dispatchEvent(focusChangeEvent) |
|
|
|
} |
|
|
|
|
|
|
|
export function useFocusedElement(elementKey: string) { |
|
|
|
export function useFocusedElement<ElementType extends HTMLElement>(elementKey: string) { |
|
|
|
const [isFocusedElement, setFocusedElement] = useState(false) |
|
|
|
const focusedClass = isFocusedElement ? focusedElementClassName : '' |
|
|
|
const elementRef = useRef<HTMLSpanElement>(null) |
|
|
|
const elementRef = useRef<ElementType>(null) |
|
|
|
|
|
|
|
function focusElement() { |
|
|
|
const focusElement = useCallback(() => { |
|
|
|
triggerElementFocused(isFocusedElement ? undefined : elementKey) |
|
|
|
} |
|
|
|
}, [isFocusedElement, elementKey]) |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
function getFocusedState() { |
|
|
|
function updateFocusedState() { |
|
|
|
const params = new URLSearchParams(window.location.search) |
|
|
|
const focusedElement = params.get(focusUrlParamName) |
|
|
|
const focused: boolean = focusedElement && focusedElement == elementKey || false |
|
|
|
setFocusedElement(focused) |
|
|
|
} |
|
|
|
|
|
|
|
getFocusedState() |
|
|
|
addEventListener(focusChangedEventName, getFocusedState) |
|
|
|
updateFocusedState() |
|
|
|
addEventListener(focusChangedEventName, updateFocusedState) |
|
|
|
return () => { |
|
|
|
removeEventListener(focusChangedEventName, getFocusedState) |
|
|
|
removeEventListener(focusChangedEventName, updateFocusedState) |
|
|
|
} |
|
|
|
}, [elementKey, setFocusedElement]) |
|
|
|
}, [elementKey, setFocusedElement, focusElement]) |
|
|
|
|
|
|
|
isFocusedElement && elementRef.current?.scrollIntoView() |
|
|
|
|
|
|
|
return {isFocusedElement, focusedClass, elementRef, focusElement} |
|
|
|
} |
|
|
|
|
|
|
|
export function useAutoFocus<ElementType extends HTMLElement>(elementKey: string) { |
|
|
|
const {elementRef, focusedClass, focusElement} = useFocusedElement<ElementType>(elementKey); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
let cleanup = () => {} |
|
|
|
if (elementRef.current) { |
|
|
|
const elem = elementRef.current |
|
|
|
elem.onclick = focusElement |
|
|
|
const classNameBackup = elem.className |
|
|
|
elem.className += ' ' + focusedClass |
|
|
|
cleanup = () => { |
|
|
|
elem.className = classNameBackup |
|
|
|
} |
|
|
|
} |
|
|
|
return cleanup |
|
|
|
}, [elementRef, focusedClass, focusElement]) |
|
|
|
|
|
|
|
return elementRef |
|
|
|
} |