diff --git a/hmr-listen.tsx b/hmr-listen.tsx index 4ec21be..9a444a8 100644 --- a/hmr-listen.tsx +++ b/hmr-listen.tsx @@ -1,4 +1,6 @@ -import { type StateCapture } from "./hmr-react.tsx"; +type Processor = (filename:string)=>void; +const Processors:Set = new Set(); +export const Process =(p:Processor)=>Processors.add(p) const FileListeners = new Map() as Mapvoid>>; export const FileListen =(inPath:string, inHandler:()=>void)=> @@ -15,56 +17,7 @@ Socket.addEventListener('message', async(event:{data:string})=> // send the updated members to any listeners for that file const reImport = await import(document.location.origin+event.data+"?reload="+Math.random()); FileListeners.get(event.data)?.forEach(reExport=>reExport(reImport)); - HMR.update(); + Processors.forEach(p=>p(event.data)) }); Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HMR socket lost")}) -const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000); - -/* - -Each custom component is secretly modified to have an extra state and id. -When there is an HMR update, this state is changed, forcing it to re-render. - -Each *user-created* React.useState is secretly modified and accompanied by an ID. -Every time its state is set, the HMR.statesNew map for this ID is set to contain the new state and updater. -When a component is removed, any of it's states in HMR.statesNew are also removed. -(HMR.statesNew is the "running total" of all states currently at play). - ---- - -When a state is interacted with: -- statesNew for this id is set -- the internal state is also set in the traditional way - -When there is an HMR update: -- All custom components are re-rendered... - for each useState(value) call that then happens in the re-render: - - if there is a "statesOld" value for this state, use that and ignore the passed value, otherwise use the passed value - - if this state has not been interacted with since the last reload (statesNew is empty at this id), set statesNew with whatever is in statesOld -- statesNew is moved into *statesOld* -- statesNew is cleared. - -*/ - -const HMR = -{ - reloads:1, - RegisteredComponents: new Map() as Mapvoid>, - statesNew: new Map() as Map, - statesOld: new Map() as Map, - wireframe: false, - RegisterComponent(reactID:string, value:()=>void):void - { - this.RegisteredComponents.set(reactID, value); - }, - update() - { - this.reloads++; - this.RegisteredComponents.forEach(handler=>handler()); - this.RegisteredComponents.clear(); - this.statesOld = this.statesNew; - this.statesNew = new Map(); - } -}; - -export {HMR}; \ No newline at end of file +const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000); \ No newline at end of file diff --git a/hmr-react.tsx b/hmr-react.tsx index b47bb8a..444bc11 100644 --- a/hmr-react.tsx +++ b/hmr-react.tsx @@ -1,5 +1,56 @@ import * as ReactParts from "react-original"; -import { HMR } from "./hmr-listen.tsx"; +import { Process } from "./hmr-listen.tsx"; + + +/* + +Each custom component is secretly modified to have an extra state and id. +When there is an HMR update, this state is changed, forcing it to re-render. + +Each *user-created* React.useState is secretly modified and accompanied by an ID. +Every time its state is set, the HMR.statesNew map for this ID is set to contain the new state and updater. +When a component is removed, any of it's states in HMR.statesNew are also removed. +(HMR.statesNew is the "running total" of all states currently at play). + +--- + +When a state is interacted with: +- statesNew for this id is set +- the internal state is also set in the traditional way + +When there is an HMR update: +- All custom components are re-rendered... + for each useState(value) call that then happens in the re-render: + - if there is a "statesOld" value for this state, use that and ignore the passed value, otherwise use the passed value + - if this state has not been interacted with since the last reload (statesNew is empty at this id), set statesNew with whatever is in statesOld +- statesNew is moved into *statesOld* +- statesNew is cleared. + +*/ +const HMR = +{ + reloads:1, + RegisteredComponents: new Map() as Mapvoid>, + statesNew: new Map() as Map, + statesOld: new Map() as Map, + wireframe: false, + RegisterComponent(reactID:string, value:()=>void):void + { + this.RegisteredComponents.set(reactID, value); + }, + update() + { + this.reloads++; + this.RegisteredComponents.forEach(handler=>handler()); + this.RegisteredComponents.clear(); + this.statesOld = this.statesNew; + this.statesNew = new Map(); + } +}; +Process(()=>HMR.update()) + + + export type StateType = boolean|number|string|Record export type StateCapture = {state:StateType, set:ReactParts.StateUpdater, reload:number};