/// import type { ComponentType } from 'react'; import React, { useState, useRef, useEffect } from 'react'; export function createComponentHmrWrapper

>( OriginalComponent: ComponentType

, hotData: { Component?: ComponentType

; setComponent?: (NewComponent: ComponentType

) => void; } ): ComponentType

{ return import.meta.hot ? (props) => { const [WrappedComponent, setComponent] = useState( () => hotData.Component ?? OriginalComponent ); const isMountedRef = useRef(false); useEffect(() => { hotData.setComponent = (NewComponent) => { hotData.Component = NewComponent; if (isMountedRef.current) { setComponent(() => NewComponent); } }; }, [setComponent]); useEffect(() => { isMountedRef.current = true; return () => { isMountedRef.current = false; }; }, []); return ; } : OriginalComponent; } type CustomElementClass = typeof HTMLElement; const replaceMethodsOnElement = ( elementNode: Element, newClass: CustomElementClass ) => { const instanceDescriptors = Object.getOwnPropertyDescriptors(newClass); for (const [name, descriptor] of Object.entries(instanceDescriptors)) { if (name !== 'length' && name !== 'name' && name !== 'prototype') { Object.defineProperty(elementNode.constructor, name, descriptor); } } const instanceSymbols = Object.getOwnPropertySymbols(newClass); for (const symbol of instanceSymbols) { //@ts-expect-error using symbol as index Object.defineProperty(elementNode, symbol, instanceDescriptors[symbol]); } const prototypeDescriptors = Object.getOwnPropertyDescriptors( newClass.prototype ); for (const [name, descriptor] of Object.entries(prototypeDescriptors)) { Object.defineProperty(elementNode, name, descriptor); } const prototypeSymbols = Object.getOwnPropertySymbols(newClass.prototype); for (const symbol of prototypeSymbols) { //@ts-expect-error using symbol as index Object.defineProperty(elementNode, symbol, prototypeDescriptors[symbol]); } }; function visitPrototypeChain( rootClass: CustomElementClass, visitFn: (chainClass: CustomElementClass) => void ) { const inheritanceArray = [rootClass]; let currentClass = Object.getPrototypeOf(rootClass); while (currentClass !== HTMLElement) { inheritanceArray.unshift(currentClass); currentClass = Object.getPrototypeOf(currentClass); } for (const classForVisiting of inheritanceArray) { visitFn(classForVisiting); } } export function applyCustomElementHmr( elementNode: Element, NewElementClass: CustomElementClass ) { visitPrototypeChain(NewElementClass, (classInheritance) => { replaceMethodsOnElement(elementNode, classInheritance); }); }