You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
1.6 KiB
65 lines
1.6 KiB
import React, { useEffect, useRef } from 'react'
|
|
|
|
interface UseStyleOptions {
|
|
selector?: string;
|
|
styles: React.CSSProperties & { [key: `--${string}`]: string };
|
|
}
|
|
|
|
const applyStyles = (element: HTMLElement, styles: React.CSSProperties) => {
|
|
Object.entries(styles).forEach(([ key, value ]) => {
|
|
element.style.setProperty(key, value as string)
|
|
})
|
|
}
|
|
|
|
const removeStyles = (element: HTMLElement, styles: React.CSSProperties) => {
|
|
Object.keys(styles).forEach(key => {
|
|
element.style.removeProperty(key)
|
|
})
|
|
}
|
|
|
|
function useInlineStyle({ selector, styles }: UseStyleOptions) {
|
|
const elementRef = useRef<HTMLElement | null>(null)
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
let targetElement: HTMLElement | null = null
|
|
|
|
const manageStyles = () => {
|
|
targetElement = selector ? document.querySelector<HTMLElement>(selector) : elementRef.current
|
|
|
|
if (!targetElement) return
|
|
|
|
applyStyles(targetElement, styles)
|
|
|
|
return () => {
|
|
if (targetElement) {
|
|
removeStyles(targetElement, styles)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selector) {
|
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
manageStyles()
|
|
} else {
|
|
document.addEventListener('DOMContentLoaded', manageStyles)
|
|
return () => {
|
|
document.removeEventListener('DOMContentLoaded', manageStyles)
|
|
}
|
|
}
|
|
} else {
|
|
manageStyles()
|
|
}
|
|
|
|
return () => {
|
|
if (targetElement) {
|
|
removeStyles(targetElement, styles)
|
|
}
|
|
}
|
|
}, [ selector, styles ])
|
|
|
|
return elementRef
|
|
}
|
|
|
|
export default useInlineStyle
|