Extracted generic FocusedElement hook

This commit is contained in:
Dejvino 2023-05-25 06:42:30 +02:00
parent df2204cb45
commit 6dff62d61c
2 changed files with 45 additions and 37 deletions

View File

@ -0,0 +1,42 @@
import { useState, useRef, useEffect } from "react";
const focusUrlParamName = 'focus'
const focusChangedEventName = "focus-changed"
const focusedElementClassName = 'focused-element'
function triggerElementFocused(elementKey: string) {
const url = new URL(window.location.href);
url.searchParams.set(focusUrlParamName, elementKey);
const focusChangeEvent = new Event(focusChangedEventName);
history.pushState({}, "", url);
window.dispatchEvent(focusChangeEvent)
}
export function useFocusedElement(elementKey: string) {
const [isFocusedElement, setFocusedElement] = useState(false);
const focusedClass = isFocusedElement ? focusedElementClassName : ''
const elementRef = useRef<HTMLSpanElement>(null)
function focusElement() {
triggerElementFocused(elementKey)
}
useEffect(() => {
function getFocusedState() {
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)
return () => {
removeEventListener(focusChangedEventName, getFocusedState)
}
}, [elementKey, setFocusedElement])
isFocusedElement && elementRef.current?.scrollIntoView()
return {isFocusedElement, focusedClass, elementRef, focusElement}
}

View File

@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import Container from 'react-bootstrap/Container';
import { useFocusedElement } from '../FocusedElement';
export type Props = {
title: string,
@ -8,47 +9,12 @@ export type Props = {
style?: 'primary' | 'light'
}
const focusChangedEventName = "focus-changed"
function useFocusedElement(elementKey: string) {
const [isFocusedElement, setFocusedElement] = useState(false);
const focusedClass = isFocusedElement ? 'focused-element' : ''
const elementRef = useRef<HTMLSpanElement>(null)
useEffect(() => {
function getFocusedState() {
const params = new URLSearchParams(window.location.search)
const focusedElement = params.get('focus')
const focused: boolean = focusedElement && focusedElement == elementKey || false
setFocusedElement(focused)
}
getFocusedState()
addEventListener(focusChangedEventName, getFocusedState)
return () => {
removeEventListener(focusChangedEventName, getFocusedState)
}
}, [elementKey, setFocusedElement])
isFocusedElement && elementRef.current?.scrollIntoView()
return {isFocusedElement, focusedClass, elementRef}
}
function setFocusedElement(elementKey: string) {
const url = new URL(window.location.href);
url.searchParams.set('focus', elementKey);
const focusChangeEvent = new Event(focusChangedEventName);
history.pushState({}, "", url);
window.dispatchEvent(focusChangeEvent)
}
function Tag(props: {text: string}) {
const tagKey = 'tag_' + props.text;
const {focusedClass, elementRef} = useFocusedElement(tagKey)
const {elementRef, focusedClass, focusElement} = useFocusedElement(tagKey)
return (
<span ref={elementRef}
onClick={() => setFocusedElement(tagKey)}
onClick={focusElement}
className={`badge text-bg-light ${focusedClass}`}>{props.text}</span>
)
}