Extract hooks folder
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { useState, useRef, useEffect, useCallback } from "react";
|
||||
|
||||
const focusUrlParamName = 'focus'
|
||||
const focusChangedEventName = "focus-changed"
|
||||
const focusedElementClassName = 'focused-element'
|
||||
|
||||
function triggerElementFocused(elementKey?: string) {
|
||||
const url = new URL(window.location.href);
|
||||
if (elementKey) {
|
||||
url.searchParams.set(focusUrlParamName, elementKey)
|
||||
} else {
|
||||
url.searchParams.delete(focusUrlParamName)
|
||||
}
|
||||
const focusChangeEvent = new Event(focusChangedEventName)
|
||||
history.pushState({}, "", url);
|
||||
window.dispatchEvent(focusChangeEvent)
|
||||
}
|
||||
|
||||
export function useFocusedElement<ElementType extends HTMLElement>(elementKey: string) {
|
||||
const [isFocusedElement, setFocusedElement] = useState(false)
|
||||
const focusedClass = isFocusedElement ? focusedElementClassName : ''
|
||||
const elementRef = useRef<ElementType>(null)
|
||||
|
||||
const focusElement = useCallback(() => {
|
||||
triggerElementFocused(isFocusedElement ? undefined : elementKey)
|
||||
}, [isFocusedElement, elementKey])
|
||||
|
||||
useEffect(() => {
|
||||
function updateFocusedState() {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const focusedElement = params.get(focusUrlParamName)
|
||||
const focused: boolean = focusedElement && focusedElement == elementKey || false
|
||||
setFocusedElement(focused)
|
||||
}
|
||||
|
||||
updateFocusedState()
|
||||
addEventListener(focusChangedEventName, updateFocusedState)
|
||||
return () => {
|
||||
removeEventListener(focusChangedEventName, updateFocusedState)
|
||||
}
|
||||
}, [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 = (evt) => {
|
||||
evt.stopPropagation()
|
||||
focusElement()
|
||||
}
|
||||
const classNameBackup = elem.className
|
||||
elem.className += ' focusable ' + focusedClass
|
||||
cleanup = () => {
|
||||
elem.className = classNameBackup
|
||||
}
|
||||
}
|
||||
return cleanup
|
||||
}, [elementRef, focusedClass, focusElement])
|
||||
|
||||
return elementRef
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
'use client'
|
||||
import React, { useContext } from 'react';
|
||||
import { createContext } from 'react';
|
||||
import { personalData } from '../../PersonalData';
|
||||
import { PersonalData } from '../../PersonalDataTypes';
|
||||
|
||||
export const PersonContext = createContext(personalData);
|
||||
|
||||
export function PersonProvider({ children }) {
|
||||
return (
|
||||
<PersonContext.Provider value={personalData}>
|
||||
{children}
|
||||
</PersonContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const usePersonContext = (): PersonalData => useContext(PersonContext)
|
||||
Reference in New Issue
Block a user