pulse-ui-client 0.1.49 → 0.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -137,6 +137,7 @@ interface ServerNavigateToMessage {
137
137
  type: "navigate_to";
138
138
  path: string;
139
139
  replace: boolean;
140
+ hard: boolean;
140
141
  }
141
142
  interface ServerJsExecMessage {
142
143
  type: "js_exec";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{Fragment as e,Suspense as t,cloneElement as n,createContext as r,createElement as i,forwardRef as a,isValidElement as o,lazy as s,useCallback as c,useContext as l,useEffect as u,useMemo as d,useRef as f,useState as p}from"react";import{jsx as m,jsxs as h}from"react/jsx-runtime";import{useLocation as g,useNavigate as _,useParams as ee}from"react-router";import{io as v}from"socket.io-client";var y=class extends Error{constructor(e){super(e),this.name=`PulseChannelResetError`}};function te(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID().replace(/-/g,``):Math.random().toString(16).slice(2)+Math.random().toString(16).slice(2)}function ne(e){if(e instanceof Error)return e.message;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function re(e){return typeof e.responseTo==`string`}function ie(e){return typeof e.event==`string`}var ae=class{handlers=new Map;pending=new Map;backlog=[];closed=!1;constructor(e,t){this.client=e,this.id=t}emit(e,t){this.ensureOpen(),this.client.sendMessage({type:`channel_message`,channel:this.id,event:e,payload:t})}request(e,t){this.ensureOpen();let n=te();return new Promise((r,i)=>{this.pending.set(n,{resolve:r,reject:i}),this.client.sendMessage({type:`channel_message`,channel:this.id,event:e,payload:t,requestId:n})})}on(e,t){this.ensureOpen();let n=this.handlers.get(e);return n||(n=new Set,this.handlers.set(e,n)),n.add(t),this.flushBacklog(e),()=>{let n=this.handlers.get(e);n&&(n.delete(t),n.size===0&&this.handlers.delete(e))}}handleServerMessage(e){return re(e)?(this.resolvePending(e),this.closed):this.closed?!0:ie(e)?e.event===`__close__`?(this.close(new y(`Channel closed by server`)),!0):(e.requestId?this.dispatchRequest(e):this.dispatchEvent(e),this.closed):this.closed}handleDisconnect(e){this.close(e)}dispose(e){this.close(e)}ensureOpen(){if(this.closed)throw new y(`Channel is closed`)}flushBacklog(e){if(this.backlog.length===0)return;let t=[];for(let n of this.backlog)n.event===e?this.dispatchEvent(n):t.push(n);this.backlog=t}dispatchEvent(e){let t=this.handlers.get(e.event);if(!t||t.size===0){this.backlog.push(e);return}for(let n of t)try{let t=n(e.payload);t&&typeof t.then==`function`&&t.catch(e=>{console.error(`Pulse channel handler error`,e)})}catch(e){console.error(`Pulse channel handler error`,e)}}async dispatchRequest(e){let t=this.handlers.get(e.event),n,r;if(t&&t.size>0)for(let i of t)try{let t=i(e.payload);if(n=await Promise.resolve(t),n!==void 0)break}catch(e){r=e;break}if(r){this.client.sendMessage({type:`channel_message`,channel:this.id,event:void 0,responseTo:e.requestId,error:ne(r)});return}this.client.sendMessage({type:`channel_message`,channel:this.id,event:void 0,responseTo:e.requestId,payload:n})}resolvePending(e){let t=e.responseTo?this.pending.get(e.responseTo):void 0;t&&(this.pending.delete(e.responseTo),e.error!==void 0&&e.error!==null?t.reject(new y(String(e.error))):t.resolve(e.payload))}close(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e);this.pending.clear(),this.handlers.clear(),this.backlog=[]}}};const oe=a(function({onSubmit:e,action:t,...n},r){return m(`form`,{...n,action:t,ref:r,onSubmit:c(n=>b({event:n,action:t,onSubmit:e}),[t,e])})});async function b({event:e,action:t,onSubmit:n,formData:r,force:i}){if(n?.(e),!i&&e.defaultPrevented)return;let a=e.currentTarget;e.preventDefault();let o=e.nativeEvent;r||=new FormData(a,o.submitter);let s=new URL(t,window.location.href);try{await fetch(s,{method:`POST`,credentials:`include`,body:r})}catch(e){if(process.env.NODE_ENV!==`production`)console.error(`[Pulse] Form submission failed`,e);else throw e}}function se({params:e,request:t}){let{"*":n=``,...r}=e,i=new URL(t.url);return{hash:i.hash,pathname:i.pathname,query:i.search,queryParams:Object.fromEntries(i.searchParams.entries()),pathParams:r,catchall:n.length>1?n.split(`/`):[]}}function x(){function e(e,t){return n=>{let r={};for(let t of e)r[t]=n[t];if(t)for(let e in t){let i=t[e];r[e]=i(n)}return r}}return e}const ce=e=>e.tagName.toLowerCase(),le=[`id`,`className`,`tagName`,`localName`,`clientHeight`,`clientLeft`,`clientTop`,`clientWidth`,`scrollHeight`,`scrollLeft`,`scrollTop`,`scrollWidth`,`slot`],ue=[`autofocus`,`tabIndex`,`nonce`],de=[`accessKey`,`accessKeyLabel`,`autocapitalize`,`dir`,`draggable`,`hidden`,`inert`,`lang`,`offsetHeight`,`offsetLeft`,`offsetTop`,`offsetWidth`,`popover`,`spellcheck`,`title`,`translate`,`writingSuggestions`,`contentEditable`,`enterKeyHint`,`isContentEditable`,`inputMode`],S=x()(le,{tagName:ce}),C=x()(ue),fe=x()(de);function w(e){return{...S(e),...C(e),...fe(e)}}function T(e,t){let n=x()(e,t);return e=>({...w(e),...n(e)})}const pe=T([`hash`,`host`,`hostname`,`href`,`origin`,`password`,`pathname`,`port`,`protocol`,`search`,`target`,`download`,`rel`,`hreflang`,`type`,`username`,`ping`,`referrerPolicy`,`text`]),me=T([`alt`,`coords`,`download`,`hash`,`host`,`hostname`,`href`,`origin`,`password`,`pathname`,`port`,`protocol`,`rel`,`search`,`shape`,`target`,`username`,`ping`,`referrerPolicy`]),E=T([`autoplay`,`controls`,`crossOrigin`,`currentSrc`,`currentTime`,`defaultMuted`,`defaultPlaybackRate`,`duration`,`ended`,`loop`,`muted`,`networkState`,`paused`,`playbackRate`,`preload`,`readyState`,`seeking`,`src`,`volume`,`preservesPitch`]),he=e=>E(e),ge=T([`disabled`,`name`,`type`,`value`,`formAction`,`formEnctype`,`formMethod`,`formNoValidate`,`formTarget`,`popoverTargetAction`]),_e=T([`value`]),ve=T([`height`,`src`,`type`,`width`,`align`,`name`]),ye=T([`disabled`,`name`,`type`,`validationMessage`,`willValidate`]),be=T([`acceptCharset`,`action`,`autocomplete`,`encoding`,`enctype`,`length`,`method`,`name`,`noValidate`,`target`,`rel`]),xe=T([`allow`,`allowFullscreen`,`height`,`name`,`referrerPolicy`,`src`,`srcdoc`,`width`,`align`,`frameBorder`,`longDesc`,`marginHeight`,`marginWidth`,`scrolling`,`sandbox`]),Se=T([`alt`,`crossOrigin`,`decoding`,`height`,`isMap`,`loading`,`naturalHeight`,`naturalWidth`,`referrerPolicy`,`sizes`,`src`,`srcset`,`useMap`,`width`,`align`,`border`,`complete`,`hspace`,`longDesc`,`lowsrc`,`name`,`vspace`,`x`,`y`,`fetchPriority`]),Ce=T(`accept.alt.autocomplete.checked.defaultChecked.defaultValue.dirName.disabled.height.indeterminate.max.maxLength.min.minLength.multiple.name.pattern.placeholder.readOnly.required.selectionDirection.selectionEnd.selectionStart.size.src.step.type.value.valueAsNumber.width.align.capture.formAction.formEnctype.formMethod.formNoValidate.formTarget.useMap.validationMessage.willValidate.popoverTargetAction`.split(`.`)),we=T([`htmlFor`]),Te=T([`value`,`type`]),Ee=T([`as`,`crossOrigin`,`disabled`,`fetchPriority`,`href`,`hreflang`,`imageSizes`,`imageSrcset`,`integrity`,`media`,`referrerPolicy`,`rel`,`type`,`charset`,`rev`,`target`,`sizes`]),De=T([`name`]),Oe=T([`high`,`low`,`max`,`min`,`optimum`,`value`]),D=T([`cite`,`dateTime`]),ke=T([`reversed`,`start`,`type`,`compact`]),Ae=T([`data`,`height`,`name`,`type`,`useMap`,`width`,`validationMessage`,`willValidate`,`align`,`archive`,`border`,`code`,`codeBase`,`codeType`,`declare`,`hspace`,`standby`,`vspace`]),je=T([`disabled`,`label`]),Me=T([`defaultSelected`,`disabled`,`index`,`label`,`selected`,`text`,`value`]),Ne=T([`defaultValue`,`name`,`type`,`value`,`htmlFor`,`validationMessage`,`willValidate`]),Pe=T([`max`,`position`,`value`]),O=T([`cite`]),Fe=e=>w(e),Ie=x()([`async`,`crossOrigin`,`defer`,`fetchPriority`,`integrity`,`noModule`,`referrerPolicy`,`src`,`text`,`type`,`charset`],{event:e=>e.event,htmlFor:e=>e.htmlFor}),Le=e=>({...w(e),...Ie(e)}),Re=T([`autocomplete`,`disabled`,`length`,`multiple`,`name`,`required`,`selectedIndex`,`size`,`type`,`value`,`validationMessage`,`willValidate`]),ze=T([`name`]),Be=T([`height`,`media`,`sizes`,`src`,`srcset`,`type`,`width`]),Ve=T([`align`]),k=T([`abbr`,`cellIndex`,`colSpan`,`headers`,`rowSpan`,`scope`,`align`,`axis`,`bgColor`,`ch`,`chOff`,`height`,`noWrap`,`vAlign`,`width`]),A=T([`span`,`align`,`ch`,`chOff`,`vAlign`,`width`]),He=T([`align`,`bgColor`,`border`,`cellPadding`,`cellSpacing`,`frame`,`rules`,`summary`,`width`]),Ue=T([`rowIndex`,`sectionRowIndex`,`align`,`bgColor`,`ch`,`chOff`,`vAlign`]),j=T([`align`,`ch`,`chOff`,`vAlign`]),We=e=>w(e),Ge=T([`autocomplete`,`cols`,`defaultValue`,`dirName`,`disabled`,`maxLength`,`minLength`,`name`,`placeholder`,`readOnly`,`required`,`rows`,`selectionDirection`,`selectionEnd`,`selectionStart`,`value`,`wrap`,`textLength`,`validationMessage`,`willValidate`]),Ke=T([`dateTime`]),qe=T([`default`,`kind`,`label`,`readyState`,`src`,`srclang`]),Je=x()([`height`,`poster`,`videoHeight`,`videoWidth`,`width`,`playsInline`]),Ye=e=>({...E(e),...Je(e)}),Xe=T([`clear`]),Ze=T([`href`,`target`]),Qe=T([`aLink`,`background`,`bgColor`,`link`,`text`,`vLink`]),$e=T([`compact`]),et=T([`open`]),tt=T([`open`,`returnValue`]),nt=T([`align`]),rt=e=>w(e),M=T([`align`]),it=T([`align`,`color`,`noShade`,`size`,`width`]),at=T([`version`]),ot=e=>w(e),st=T([`content`,`httpEquiv`,`name`,`scheme`]),ct=T([`align`]),lt=e=>w(e),ut=T([`width`]),dt=e=>w(e),ft=T([`media`,`type`,`disabled`]),pt=T([`text`]),mt=T([`compact`,`type`]);function N(e){return{...S(e),...C(e)}}function P(e,t){let n=x()(e,t);return e=>({...N(e),...n(e)})}const F={A:pe,AREA:me,AUDIO:he,BASE:Ze,BLOCKQUOTE:O,Q:O,BODY:Qe,BR:Xe,BUTTON:ge,CANVAS:w,CAPTION:Ve,CITE:Fe,COL:A,COLGROUP:A,DATA:_e,DETAILS:et,DIALOG:tt,DIV:nt,DL:$e,EMBED:ve,FIELDSET:ye,FORM:be,H1:M,H2:M,H3:M,H4:M,H5:M,H6:M,HEAD:rt,HR:it,HTML:at,IFRAME:xe,IMG:Se,INPUT:Ce,LABEL:we,LI:Te,LINK:Ee,MAP:De,MENU:ot,META:st,METER:Oe,INS:D,DEL:D,OBJECT:Ae,OL:ke,OPTGROUP:je,OPTION:Me,OUTPUT:Ne,P:ct,PICTURE:lt,PRE:ut,PROGRESS:Pe,SCRIPT:Le,SELECT:Re,SLOT:ze,SOURCE:Be,SPAN:dt,STYLE:ft,TABLE:He,TBODY:j,THEAD:j,TFOOT:j,TD:k,TH:k,TEMPLATE:We,TEXTAREA:Ge,TIME:Ke,TITLE:pt,TR:Ue,TRACK:qe,UL:mt,VIDEO:Ye,SVG:P([`x`,`y`,`width`,`height`,`currentScale`,`currentTranslate`]),CIRCLE:P([`cx`,`cy`,`r`]),ELLIPSE:P([`cx`,`cy`,`rx`,`ry`]),LINE:P([`x1`,`y1`,`x2`,`y2`]),PATH:P([`pathLength`]),RECT:P([`x`,`y`,`width`,`height`,`rx`,`ry`]),POLYGON:P([`points`]),POLYLINE:P([`points`]),TEXT:P([`x`,`y`,`dx`,`dy`,`rotate`,`textLength`,`lengthAdjust`]),TSPAN:P([`x`,`y`,`dx`,`dy`,`rotate`,`textLength`,`lengthAdjust`]),IMAGE:P([`x`,`y`,`width`,`height`,`href`,`preserveAspectRatio`,`crossOrigin`]),USE:P([`x`,`y`,`width`,`height`,`href`]),DEFS:P([]),G:P([]),LINEARGRADIENT:P([`x1`,`y1`,`x2`,`y2`,`gradientUnits`,`gradientTransform`,`spreadMethod`]),RADIALGRADIENT:P([`cx`,`cy`,`r`,`fx`,`fy`,`fr`,`gradientUnits`,`gradientTransform`,`spreadMethod`]),STOP:P([`offset`]),PATTERN:P([`x`,`y`,`width`,`height`,`patternUnits`,`patternContentUnits`,`patternTransform`,`preserveAspectRatio`,`href`]),CLIPPATH:P([`clipPathUnits`]),MASK:P([`x`,`y`,`width`,`height`,`maskUnits`,`maskContentUnits`])};function ht(e){let t=F[e.tagName.toUpperCase()];if(t)return t(e);throw Error(`Unexpected HTML element tag: ${e.tagName} (update .web/custom/serialize.ts)`)}function gt(e){let t=F[e.tagName.toUpperCase()];return t?t(e):N(e)}function I(e){return e instanceof HTMLElement?ht(e):e instanceof SVGElement?gt(e):S(e)}const _t=e=>I(e.target),L=e=>e.relatedTarget?I(e.relatedTarget):null;function R(e,t){return x()(e,{target:_t,...t||{}})}const z=[`target`,`bubbles`,`cancelable`,`defaultPrevented`,`eventPhase`,`isTrusted`,`timeStamp`,`type`],B=[...z,`detail`],V=[...B,`altKey`,`button`,`buttons`,`clientX`,`clientY`,`ctrlKey`,`metaKey`,`movementX`,`movementY`,`pageX`,`pageY`,`screenX`,`screenY`,`shiftKey`],vt=[...V,`pointerId`,`pressure`,`tangentialPressure`,`tiltX`,`tiltY`,`twist`,`width`,`height`,`pointerType`,`isPrimary`],yt=R(z),bt=R(B),xt=R(V,{relatedTarget:L}),St=R(z,{clipboardData:e=>U(e.clipboardData)}),Ct=R([...z,`data`]),wt=R(V,{relatedTarget:L,dataTransfer:e=>U(e.dataTransfer)}),Tt=R(vt,{relatedTarget:L}),Et=R(z,{relatedTarget:L}),Dt=R(z),Ot=R(z),kt=R(z),At=R([...B,`altKey`,`ctrlKey`,`code`,`key`,`locale`,`location`,`metaKey`,`repeat`,`shiftKey`]),jt=R([...B,`altKey`,`ctrlKey`,`metaKey`,`shiftKey`,`changedTouches`,`targetTouches`,`touches`],{changedTouches:e=>H(e.changedTouches),targetTouches:e=>H(e.targetTouches),touches:e=>H(e.touches)}),Mt=R([...V,`deltaMode`,`deltaX`,`deltaY`,`deltaZ`],{relatedTarget:L}),Nt=R([...z,`animationName`,`elapsedTime`,`pseudoElement`]),Pt=R([...z,`oldState`,`newState`]),Ft=R([...z,`elapsedTime`,`propertyName`,`pseudoElement`]);function H(e){return Array.from(e).map(e=>({target:I(e.target),identifier:e.identifier,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,pageX:e.pageX,pageY:e.pageY}))}function U(e){if(!e)return null;let t=[];if(e.items)for(let n=0;n<e.items.length;n++){let r=e.items[n];t.push({kind:r.kind,type:r.type})}return{drop_effect:e.dropEffect,effect_allowed:e.effectAllowed,items:t,types:Array.from(e.types||[])}}const W={};function G(e,t,n){for(let r of t)e[r]=n}G(W,[`pointerdown`,`pointermove`,`pointerup`,`pointercancel`,`gotpointercapture`,`lostpointercapture`,`pointerenter`,`pointerleave`,`pointerover`,`pointerout`],Tt),G(W,[`click`,`contextmenu`,`dblclick`,`mousedown`,`mouseenter`,`mouseleave`,`mousemove`,`mouseout`,`mouseover`,`mouseup`],xt),G(W,[`drag`,`dragend`,`dragenter`,`dragexit`,`dragleave`,`dragover`,`dragstart`,`drop`],wt),G(W,[`keydown`,`keypress`,`keyup`],At),G(W,[`focus`,`blur`],Et),G(W,[`change`,`input`],kt),G(W,[`invalid`],Ot),G(W,[`reset`,`submit`],Dt),G(W,[`copy`,`cut`,`paste`],St),G(W,[`compositionend`,`compositionstart`,`compositionupdate`],Ct),G(W,[`touchcancel`,`touchend`,`touchmove`,`touchstart`],jt),G(W,[`scroll`],bt),G(W,[`wheel`],Mt),G(W,[`animationstart`,`animationend`,`animationiteration`],Nt),G(W,[`transitionend`],Ft),G(W,[`toggle`],Pt);function It(e){if(e&&typeof e==`object`&&`nativeEvent`in e&&typeof e.isDefaultPrevented==`function`){let t=e;if(typeof t.type!=`string`)return e;let n=W[t.type.toLowerCase()];return n?n(t):yt(t)}return e}function K(e){let t=new Map,n=[],r=[],i=[],a=[],o=0;function s(e,c){if(e==null||typeof e==`string`||typeof e==`boolean`)return e;if(typeof e==`number`){if(Number.isNaN(e)){let e=c?` in '${c}'`:``;throw Error(`Cannot serialize NaN${e}. NaN and Infinity are not supported because they cannot be serialized to JSON.`)}if(!Number.isFinite(e)){let t=e>0?`Infinity`:`-Infinity`,n=c?` in '${c}'`:``;throw Error(`Cannot serialize ${t}${n}. NaN and Infinity are not supported because they cannot be serialized to JSON.`)}return e}let l=o++,u=t.get(e);if(u!==void 0)return n.push(l),u;if(t.set(e,l),e instanceof Date)return r.push(l),e.getTime();if(Array.isArray(e)){let t=e.length,n=Array(t);for(let r=0;r<t;r++)n[r]=s(e[r],c);return n}if(e instanceof Map){a.push(l);let t={};for(let[n,r]of e.entries())t[String(n)]=s(r,String(n));return t}if(e instanceof Set){i.push(l);let t=e.size,n=Array(t),r=0;for(let t of e)n[r]=s(t,c),r+=1;return n}if(typeof e==`object`){let t={},n=Object.keys(e);for(let r=0;r<n.length;r++){let i=n[r];t[i]=s(e[i],i)}return t}throw Error(`Unsupported value in serialization: ${e}`)}let c=s(e);return[[n,r,i,a],c]}function q(e,t){let[[n,r,i,a],o]=e,s=new Set(n),c=new Set(r),l=new Set(i),u=new Set(a),d=[];function f(e){let n=d.length;if(s.has(n))return d.push(null),d[e];if(c.has(n)){let t=new Date(e);return d.push(t),t}if(e==null||typeof e==`number`||typeof e==`string`||typeof e==`boolean`)return t?.coerceNullsToUndefined?e??void 0:e;if(Array.isArray(e)){if(l.has(n)){let t=new Set;d.push(t);for(let n=0;n<e.length;n++)t.add(f(e[n]));return t}let t=e.length,r=Array(t);d.push(r);for(let n=0;n<t;n++)r[n]=f(e[n]);return r}if(typeof e==`object`){if(u.has(n)){let t=new Map;d.push(t);let n=Object.keys(e);for(let r=0;r<n.length;r++){let i=n[r];t.set(i,f(e[i]))}return t}let t={};d.push(t);let r=Object.keys(e);for(let n=0;n<r.length;n++){let i=r[n];t[i]=f(e[i])}return t}throw Error(`Unsupported value in deserialization: ${e}`)}return f(o)}var Lt=class{#activeViews;#socket=null;#messageQueue;#connectionListeners=new Set;#serverErrors=new Map;#serverErrorListeners=new Set;#channels=new Map;#url;#frameworkNavigate;#directives;#connectionStatusConfig;#hasConnectedOnce=!1;#connectingTimeout=null;#errorTimeout=null;#currentStatus=`ok`;constructor(e,t,n,r){if(this.#url=e,this.#directives=t,this.#frameworkNavigate=n,this.#socket=null,this.#activeViews=new Map,this.#messageQueue=[],this.#connectionStatusConfig=r,typeof window<`u`&&typeof sessionStorage<`u`){let e=sessionStorage.getItem(`__PULSE_DIRECTIVES`);if(e)try{this.#directives=JSON.parse(e)}catch{}}}setDirectives(e){this.#directives=e}isConnected(){return this.#socket?.connected??!1}#clearTimeouts(){this.#connectingTimeout&&=(clearTimeout(this.#connectingTimeout),null),this.#errorTimeout&&=(clearTimeout(this.#errorTimeout),null)}#setStatus(e){this.#clearTimeouts(),this.#currentStatus=e,this.#notifyConnectionListeners(e)}#handleConnected(){this.#hasConnectedOnce=!0,this.#setStatus(`ok`)}#setInitialConnectionStatus(){this.#setStatus(`ok`),this.#connectingTimeout=setTimeout(()=>{this.#setStatus(`connecting`),this.#errorTimeout=setTimeout(()=>{this.#setStatus(`error`)},this.#connectionStatusConfig.initialErrorDelay)},this.#connectionStatusConfig.initialConnectingDelay)}#handleDisconnected(){this.#setStatus(`reconnecting`),this.#errorTimeout=setTimeout(()=>{this.#setStatus(`error`)},this.#connectionStatusConfig.reconnectErrorDelay)}async connect(){if(!this.#socket)return this.#hasConnectedOnce||this.#setInitialConnectionStatus(),new Promise((e,t)=>{let n=v(this.#url,{transports:[`websocket`,`webtransport`],auth:this.#directives.socketio?.auth,extraHeaders:this.#directives.socketio?.headers});this.#socket=n,n.on(`connect`,()=>{console.log(`[SocketIOTransport] Connected:`,this.#socket?.id);for(let[e,t]of this.#activeViews)n.emit(`message`,K({type:`mount`,path:e,routeInfo:t.routeInfo}));for(let e of this.#messageQueue)e.type===`mount`&&this.#activeViews.has(e.path)||e.type!==`navigate`&&n.emit(`message`,K(e));this.#messageQueue=[],this.#handleConnected(),e()}),n.on(`connect_error`,e=>{console.error(`[SocketIOTransport] Connection failed:`,e),this.#handleDisconnected(),t(e)}),n.on(`disconnect`,()=>{console.log(`[SocketIOTransport] Disconnected`),this.#handleTransportDisconnect(),this.#handleDisconnected()}),n.on(`message`,e=>this.#handleServerMessage(q(e,{coerceNullsToUndefined:!0})))})}onConnectionChange(e){return this.#connectionListeners.add(e),e(this.#currentStatus),()=>{this.#connectionListeners.delete(e)}}#notifyConnectionListeners(e){for(let t of this.#connectionListeners)t(e)}onServerError(e){this.#serverErrorListeners.add(e);for(let[t,n]of this.#serverErrors)e(t,n);return()=>{this.#serverErrorListeners.delete(e)}}#notifyServerError(e,t){for(let n of this.#serverErrorListeners)n(e,t)}sendMessage(e){this.isConnected()?this.#socket.emit(`message`,K(e)):this.#messageQueue.push(e)}mountView(e,t){if(this.#activeViews.has(e))throw Error(`Path ${e} is already mounted`);this.#activeViews.set(e,t),this.sendMessage({type:`mount`,path:e,routeInfo:t.routeInfo})}navigate(e,t){this.sendMessage({type:`navigate`,path:e,routeInfo:t})}unmount(e){this.sendMessage({type:`unmount`,path:e}),this.#activeViews.delete(e)}disconnect(){this.#clearTimeouts(),this.#socket?.disconnect(),this.#socket=null,this.#messageQueue=[],this.#connectionListeners.clear(),this.#activeViews.clear(),this.#serverErrors.clear(),this.#serverErrorListeners.clear();for(let{bridge:e}of this.#channels.values())e.dispose(new y(`Client disconnected`));this.#channels.clear(),this.#currentStatus=`ok`,this.#hasConnectedOnce=!1}#handleServerMessage(e){switch(e.type){case`vdom_init`:{let t=this.#activeViews.get(e.path);if(!t)return;t&&t.onInit(e),this.#serverErrors.has(e.path)&&(this.#serverErrors.delete(e.path),this.#notifyServerError(e.path,null));break}case`vdom_update`:{let t=this.#activeViews.get(e.path);if(!t)return;t.onUpdate(e.ops),this.#serverErrors.has(e.path)&&(this.#serverErrors.delete(e.path),this.#notifyServerError(e.path,null));break}case`server_error`:if(!this.#activeViews.has(e.path))return;this.#serverErrors.set(e.path,e.error),this.#notifyServerError(e.path,e.error);break;case`api_call`:this.#performApiCall(e);break;case`navigate_to`:{let t=!!e.replace,n=e.path||``;if(n.startsWith(`//`)&&(n=`${window.location.protocol}${n}`),/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(n))if(n.startsWith(`http://`)||n.startsWith(`https://`))try{let e=new URL(n);if(e.origin===window.location.origin){let n=`${e.pathname}${e.search}${e.hash}`;this.#frameworkNavigate(n,{replace:t})}else t?window.location.replace(n):window.location.assign(n)}catch{t?window.location.replace(n):window.location.assign(n)}else t?window.location.replace(n):window.location.assign(n);else this.#frameworkNavigate(n,{replace:t});break}case`channel_message`:this.#routeChannelMessage(e);break;case`js_exec`:this.#handleJsExec(e);break;default:console.error(`Unexpected message:`,e)}}async#performApiCall(e){try{let t=await fetch(e.url,{method:e.method||`GET`,headers:{...e.headers||{},...e.body!=null&&!(`content-type`in(e.headers||{}))?{"content-type":`application/json`}:{}},body:e.body==null?void 0:typeof e.body==`string`?e.body:JSON.stringify(e.body),credentials:e.credentials||`include`}),n={};t.headers.forEach((e,t)=>{n[t]=e});let r=null;r=(t.headers.get(`content-type`)||``).includes(`application/json`)?await t.json().catch(()=>null):await t.text().catch(()=>null);let i={type:`api_result`,id:e.id,ok:t.ok,status:t.status,headers:n,body:r};this.sendMessage(i)}catch(t){let n={type:`api_result`,id:e.id,ok:!1,status:0,headers:{},body:{error:String(t)}};this.sendMessage(n)}}invokeCallback(e,t,n){this.sendMessage({type:`callback`,path:e,callback:t,args:n.map(It)})}#handleJsExec(e){let t=this.#activeViews.get(e.path);if(!t?.onJsExec){console.warn(`[Pulse] No onJsExec handler for path: ${e.path}`),this.#sendJsResult(e.id,void 0,`No JS executor registered`);return}t.onJsExec(e)}sendJsResult(e,t,n){this.#sendJsResult(e,t,n)}#sendJsResult(e,t,n){let r={type:`js_result`,id:e,result:t,error:n};this.sendMessage(r)}acquireChannel(e){let t=this.#ensureChannelEntry(e);return t.refCount+=1,t.bridge}releaseChannel(e){let t=this.#channels.get(e);t&&(t.refCount=Math.max(0,t.refCount-1),t.refCount===0&&(t.bridge.dispose(new y(`Channel released`)),this.sendMessage({type:`channel_message`,channel:e,event:`__close__`,payload:{reason:`refcount_zero`}}),this.#channels.delete(e)))}#ensureChannelEntry(e){let t=this.#channels.get(e);return t||(t={bridge:new ae(this,e),refCount:0},this.#channels.set(e,t)),t}#routeChannelMessage(e){let t=this.#ensureChannelEntry(e.channel);t.bridge.handleServerMessage(e)&&t.refCount===0&&this.#channels.delete(e.channel)}#handleTransportDisconnect(){for(let e of this.#channels.values())e.bridge.handleDisconnect(new y(`Connection lost`))}};const J=`$$fragment`;function Rt(e){return typeof e==`object`&&!!e}function zt(e){return typeof e==`object`&&!!e&&e.tag.startsWith(`$$`)&&e.tag!==J}const Y=`$js:`;var Bt=class{#callbacks;#callbackCache;#renderPropKeys;#jsexprPaths;#callbackList;#client;#path;#registry;constructor(e,t,n=[],r=[],i={},a=[]){this.#client=e,this.#path=t,this.#registry=i,this.#callbacks=new Set(n),this.#callbackCache=new Map,this.#renderPropKeys=new Set(r),this.#jsexprPaths=new Set(a),this.#callbackList=[...this.#callbacks].sort()}getObject(e){let t=this.#registry[e];if(t===void 0)throw Error(`[Pulse] Unknown registry key: ${e}`);return t}evaluateJsExpr(e){return Function(`get_object`,`return ${e}`)(e=>this.getObject(e))}hasCallbackPath(e){return this.#callbacks.has(e)}hasRenderPropPath(e){return this.#renderPropKeys.has(e)}hasAnyCallbackUnder(e){if(e===``)return this.#callbackList.length>0;let t=this.#lowerBound(this.#callbackList,e);return t<this.#callbackList.length&&this.#callbackList[t].startsWith(e)}applyCallbackDelta(e){if(e.remove)for(let t of e.remove)this.#callbacks.delete(t),this.#callbackCache.delete(t);if(e.add)for(let t of e.add)this.#callbacks.add(t);this.#callbackList=[...this.#callbacks].sort()}applyRenderPropsDelta(e){if(e.remove)for(let t of e.remove)this.#renderPropKeys.delete(t);if(e.add)for(let t of e.add)this.#renderPropKeys.add(t)}applyJsExprPathsDelta(e){if(e.remove)for(let t of e.remove)this.#jsexprPaths.delete(t);if(e.add)for(let t of e.add)this.#jsexprPaths.add(t)}getCallback(e,t){let n=this.#propPath(e,t),r=this.#callbackCache.get(n);return r||(r=(...e)=>this.#client.invokeCallback(this.#path,n,e),this.#callbackCache.set(n,r)),r}renderNode(t,n=``){if(t==null||typeof t==`boolean`||typeof t==`number`)return t;if(typeof t==`string`){if(t.startsWith(Y)){let e=t.slice(4);return this.evaluateJsExpr(e)}return t}if(Rt(t)){let{tag:r,props:a={},children:o=[]}=t,s={};for(let[e,t]of Object.entries(a))s[e]=this.transformValue(n,e,t);t.key&&(s.key=t.key);let c=[];for(let e=0;e<o.length;e+=1){let t=o[e],r=n?`${n}.${e}`:String(e);c.push(this.renderNode(t,r))}if(zt(t)){let e=t.tag.slice(2),n=this.#registry[e];if(!n)throw Error(`Could not find component ${e}. This is a Pulse internal error.`);return i(n,s,...c)}return i(r===J?e:r,s,...c)}return process.env.NODE_ENV!==`production`&&console.error(`Unknown VDOM node type:`,t),null}#propPath(e,t){return e?`${e}.${t}`:t}transformValue(e,t,n){let r=this.#propPath(e,t);if(this.#callbacks.has(r))return this.getCallback(e,t);if(this.#renderPropKeys.has(r))return this.renderNode(n,r);if(typeof n==`string`&&n.startsWith(Y)){let e=n.slice(4);return this.evaluateJsExpr(e)}return n}init(e){this.#callbacks=new Set(e.callbacks);for(let e of Array.from(this.#callbackCache.keys()))this.#callbacks.has(e)||this.#callbackCache.delete(e);return this.#callbackList=[...this.#callbacks].sort(),this.#renderPropKeys=new Set(e.render_props),this.#jsexprPaths=new Set(e.jsexpr_paths),this.renderNode(e.vdom)}#ensureChildrenArray(e){let t=e.props?.children;return t==null?[]:Array.isArray(t)?t.slice():[t]}applyUpdates(e,t){let r=e;for(let e of t){if(e.type===`update_callbacks`){this.applyCallbackDelta(e.data);continue}if(e.type===`update_render_props`){this.applyRenderPropsDelta(e.data);continue}if(e.type===`update_jsexpr_paths`){this.applyJsExprPathsDelta(e.data);continue}let t=e.path.split(`.`).filter(e=>e.length>0),a=(r,o,s)=>{if(o<t.length){this.#assertIsElement(r,t,o);let e=r,i=t[o],c=+i,l=s?`${s}.${i}`:i;if(Number.isNaN(c)){let t=e.props??{},r=t[i];return n(e,{...t,[i]:a(r,o+1,l)})}else{let t=this.#ensureChildrenArray(e),r=t[c];return t[c]=a(r,o+1,l),n(e,void 0,...t)}}switch(e.type){case`replace`:return this.renderNode(e.data,e.path);case`update_props`:{this.#assertIsElement(r,t,o);let a=r,c={...a.props??{}},l=e.data;if(l.remove&&l.remove.length>0)for(let e of l.remove)e in c&&delete c[e];if(l.set)for(let[e,t]of Object.entries(l.set))c[e]=this.transformValue(s,e,t);return(l.remove?.length??0)>0?(c.key=a.key,c.ref=a.ref,i(a.type,c,...this.#ensureChildrenArray(a))):n(a,c)}case`reconciliation`:{this.#assertIsElement(r,t,o);let i=r,a=this.#ensureChildrenArray(i),c=[],[l,u]=e.new,[d,f]=e.reuse,p=-1,m=-1,h=-1,g=-1;l.length>0&&(p=l[0],h=0),d.length>0&&(m=d[0],g=0);for(let t=0;t<e.N;++t)if(t===p){let e=u[h],n=s?`${s}.${t}`:String(t);c.push(this.renderNode(e,n)),p=h<l.length-1?l[++h]:-1}else if(t===m){let e=a[f[g]],n=s?`${s}.${t}`:String(t);this.hasAnyCallbackUnder(n)&&(e=this.#rebindCallbacksInSubtree(e,n)),c.push(e),m=g<d.length-1?d[++g]:-1}else c.push(a[t]);return n(i,null,...c)}default:throw Error(`[Pulse renderer] Unknown update type: ${e?.type}`)}};r=a(r,0,``)}return r}#assertIsElement(e,t,n){if(process.env.NODE_ENV!==`production`&&!o(e))throw console.error(`Invalid node:`,e),Error(`Invalid node at path ${t.slice(0,n).join(`.`)}`);return!0}#rebindCallbacksInSubtree(e,t){if(!o(e))return e;let r=e,i=r.props??{},a={...i};for(let e of Object.keys(i)){let n=t?`${t}.${e}`:e;this.hasCallbackPath(n)&&(a[e]=this.getCallback(t,e)),this.hasRenderPropPath(n)&&this.hasAnyCallbackUnder(n)&&(a[e]=this.#rebindCallbacksInSubtree(i[e],n))}return n(r,a,...this.#ensureChildrenArray(r).map((e,n)=>{let r=t?`${t}.${n}`:String(n);return this.hasAnyCallbackUnder(r)?this.#rebindCallbacksInSubtree(e,r):e}))}#lowerBound(e,t){let n=0,r=e.length;for(;n<r;){let i=n+r>>>1;e[i]<t?n=i+1:r=i}return n}};function Vt(e,n){let r=s(e);return({children:e,...i})=>m(t,{fallback:n,children:m(r,{...i,children:e})})}const X=r(null),Z=r(null),Q=()=>{let e=l(X);if(!e)throw Error(`usePulseClient must be used within a PulseProvider`);return e},Ht=e=>{let t=l(Z);if(!t)throw Error(`usePulsePrerender must be used within a PulseProvider`);let n=t.views[e];if(!n)throw Error(`No prerender found for '${e}'`);return n},$=typeof window<`u`;function Ut({children:e,config:t,prerender:n}){let[r,i]=p(`ok`),a=_(),{directives:o}=n,s=d(()=>new Lt(t.serverAddress,o,a,t.connectionStatus),[t.serverAddress,a,t.connectionStatus]);u(()=>s.setDirectives(o),[s,o]),u(()=>{if(!$)return;let e=s.onConnectionChange(e=>{i(e)});return s.connect(),()=>{e(),s.disconnect()}},[s]);let c=(()=>{switch(r){case`connecting`:return`Connecting...`;case`reconnecting`:return`Reconnecting...`;case`error`:return`Failed to connect to the server.`;default:return null}})();return m(X.Provider,{value:s,children:h(Z.Provider,{value:n,children:[c&&m(`div`,{style:{position:`fixed`,bottom:`20px`,right:`20px`,backgroundColor:r===`error`?`red`:`#666`,color:`white`,padding:`10px`,borderRadius:`5px`,zIndex:1e3},children:c}),e]})})}function Wt({path:e,registry:t}){let n=Q(),r=Ht(e),i=d(()=>new Bt(n,e,r.callbacks,r.render_props,t,r.jsexpr_paths),[n,e,t]),[a,o]=p(()=>i.init(r)),[s,c]=p(null),l=g(),h=ee(),_=d(()=>{let{"*":e=``,...t}=h,n=new URLSearchParams(l.search);return{hash:l.hash,pathname:l.pathname,query:l.search,queryParams:Object.fromEntries(n.entries()),pathParams:t,catchall:e.length>0?e.split(`/`):[]}},[l.hash,l.pathname,l.search,JSON.stringify(h)]);u(()=>{if($){n.mountView(e,{routeInfo:_,onInit:e=>{o(i.init(e))},onUpdate:e=>{o(t=>t==null?t:i.applyUpdates(t,e))},onJsExec:e=>{let t,r=null;try{t=i.evaluateJsExpr(e.code)}catch(e){r=e instanceof Error?e.message:String(e)}n.sendJsResult(e.id,t,r)}});let t=n.onServerError((t,n)=>{t===e&&c(n)});return()=>{t(),n.unmount(e)}}},[n,i,e]),u(()=>{$&&n.navigate(e,_)},[n,e,_]);let v=f(!1);return u(()=>(v.current?o(i.init(r)):v.current=!0,()=>{v.current=!1}),[r,i]),s?m(Gt,{error:s}):a}function Gt({error:e}){return h(`div`,{style:{padding:16,border:`1px solid #e00`,background:`#fff5f5`,color:`#900`,fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`,whiteSpace:`pre-wrap`},children:[h(`div`,{style:{fontWeight:700,marginBottom:8},children:[`Server Error during `,e.phase]}),e.message&&m(`div`,{children:e.message}),e.stack&&h(`details`,{open:!0,style:{marginTop:8},children:[m(`summary`,{children:`Stack trace`}),m(`pre`,{style:{margin:0},children:e.stack})]})]})}function Kt(e){let t=Q(),n=d(()=>{if(!e)throw Error(`usePulseChannel requires a non-empty channelId`);return t.acquireChannel(e)},[t,e]);return u(()=>()=>{t.releaseChannel(e)},[t,e]),n}export{y as PulseChannelResetError,oe as PulseForm,Ut as PulseProvider,Wt as PulseView,Vt as RenderLazy,q as deserialize,se as extractServerRouteInfo,K as serialize,b as submitForm,Kt as usePulseChannel,Q as usePulseClient};
1
+ import{Fragment as e,Suspense as t,cloneElement as n,createContext as r,createElement as i,forwardRef as a,isValidElement as o,lazy as s,useCallback as c,useContext as l,useEffect as u,useMemo as d,useRef as f,useState as p}from"react";import{jsx as m,jsxs as h}from"react/jsx-runtime";import{useLocation as g,useNavigate as _,useParams as ee}from"react-router";import{io as v}from"socket.io-client";var y=class extends Error{constructor(e){super(e),this.name=`PulseChannelResetError`}};function te(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID().replace(/-/g,``):Math.random().toString(16).slice(2)+Math.random().toString(16).slice(2)}function ne(e){if(e instanceof Error)return e.message;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function re(e){return typeof e.responseTo==`string`}function ie(e){return typeof e.event==`string`}var ae=class{handlers=new Map;pending=new Map;backlog=[];closed=!1;constructor(e,t){this.client=e,this.id=t}emit(e,t){this.ensureOpen(),this.client.sendMessage({type:`channel_message`,channel:this.id,event:e,payload:t})}request(e,t){this.ensureOpen();let n=te();return new Promise((r,i)=>{this.pending.set(n,{resolve:r,reject:i}),this.client.sendMessage({type:`channel_message`,channel:this.id,event:e,payload:t,requestId:n})})}on(e,t){this.ensureOpen();let n=this.handlers.get(e);return n||(n=new Set,this.handlers.set(e,n)),n.add(t),this.flushBacklog(e),()=>{let n=this.handlers.get(e);n&&(n.delete(t),n.size===0&&this.handlers.delete(e))}}handleServerMessage(e){return re(e)?(this.resolvePending(e),this.closed):this.closed?!0:ie(e)?e.event===`__close__`?(this.close(new y(`Channel closed by server`)),!0):(e.requestId?this.dispatchRequest(e):this.dispatchEvent(e),this.closed):this.closed}handleDisconnect(e){this.close(e)}dispose(e){this.close(e)}ensureOpen(){if(this.closed)throw new y(`Channel is closed`)}flushBacklog(e){if(this.backlog.length===0)return;let t=[];for(let n of this.backlog)n.event===e?this.dispatchEvent(n):t.push(n);this.backlog=t}dispatchEvent(e){let t=this.handlers.get(e.event);if(!t||t.size===0){this.backlog.push(e);return}for(let n of t)try{let t=n(e.payload);t&&typeof t.then==`function`&&t.catch(e=>{console.error(`Pulse channel handler error`,e)})}catch(e){console.error(`Pulse channel handler error`,e)}}async dispatchRequest(e){let t=this.handlers.get(e.event),n,r;if(t&&t.size>0)for(let i of t)try{let t=i(e.payload);if(n=await Promise.resolve(t),n!==void 0)break}catch(e){r=e;break}if(r){this.client.sendMessage({type:`channel_message`,channel:this.id,event:void 0,responseTo:e.requestId,error:ne(r)});return}this.client.sendMessage({type:`channel_message`,channel:this.id,event:void 0,responseTo:e.requestId,payload:n})}resolvePending(e){let t=e.responseTo?this.pending.get(e.responseTo):void 0;t&&(this.pending.delete(e.responseTo),e.error!==void 0&&e.error!==null?t.reject(new y(String(e.error))):t.resolve(e.payload))}close(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e);this.pending.clear(),this.handlers.clear(),this.backlog=[]}}};const oe=a(function({onSubmit:e,action:t,...n},r){return m(`form`,{...n,action:t,ref:r,onSubmit:c(n=>b({event:n,action:t,onSubmit:e}),[t,e])})});async function b({event:e,action:t,onSubmit:n,formData:r,force:i}){if(n?.(e),!i&&e.defaultPrevented)return;let a=e.currentTarget;e.preventDefault();let o=e.nativeEvent;r||=new FormData(a,o.submitter);let s=new URL(t,window.location.href);try{await fetch(s,{method:`POST`,credentials:`include`,body:r})}catch(e){if(process.env.NODE_ENV!==`production`)console.error(`[Pulse] Form submission failed`,e);else throw e}}function se({params:e,request:t}){let{"*":n=``,...r}=e,i=new URL(t.url);return{hash:i.hash,pathname:i.pathname,query:i.search,queryParams:Object.fromEntries(i.searchParams.entries()),pathParams:r,catchall:n.length>1?n.split(`/`):[]}}function x(){function e(e,t){return n=>{let r={};for(let t of e)r[t]=n[t];if(t)for(let e in t){let i=t[e];r[e]=i(n)}return r}}return e}const ce=e=>e.tagName.toLowerCase(),le=[`id`,`className`,`tagName`,`localName`,`clientHeight`,`clientLeft`,`clientTop`,`clientWidth`,`scrollHeight`,`scrollLeft`,`scrollTop`,`scrollWidth`,`slot`],ue=[`autofocus`,`tabIndex`,`nonce`],de=[`accessKey`,`accessKeyLabel`,`autocapitalize`,`dir`,`draggable`,`hidden`,`inert`,`lang`,`offsetHeight`,`offsetLeft`,`offsetTop`,`offsetWidth`,`popover`,`spellcheck`,`title`,`translate`,`writingSuggestions`,`contentEditable`,`enterKeyHint`,`isContentEditable`,`inputMode`],S=x()(le,{tagName:ce}),C=x()(ue),fe=x()(de);function w(e){return{...S(e),...C(e),...fe(e)}}function T(e,t){let n=x()(e,t);return e=>({...w(e),...n(e)})}const pe=T([`hash`,`host`,`hostname`,`href`,`origin`,`password`,`pathname`,`port`,`protocol`,`search`,`target`,`download`,`rel`,`hreflang`,`type`,`username`,`ping`,`referrerPolicy`,`text`]),me=T([`alt`,`coords`,`download`,`hash`,`host`,`hostname`,`href`,`origin`,`password`,`pathname`,`port`,`protocol`,`rel`,`search`,`shape`,`target`,`username`,`ping`,`referrerPolicy`]),E=T([`autoplay`,`controls`,`crossOrigin`,`currentSrc`,`currentTime`,`defaultMuted`,`defaultPlaybackRate`,`duration`,`ended`,`loop`,`muted`,`networkState`,`paused`,`playbackRate`,`preload`,`readyState`,`seeking`,`src`,`volume`,`preservesPitch`]),he=e=>E(e),ge=T([`disabled`,`name`,`type`,`value`,`formAction`,`formEnctype`,`formMethod`,`formNoValidate`,`formTarget`,`popoverTargetAction`]),_e=T([`value`]),ve=T([`height`,`src`,`type`,`width`,`align`,`name`]),ye=T([`disabled`,`name`,`type`,`validationMessage`,`willValidate`]),be=T([`acceptCharset`,`action`,`autocomplete`,`encoding`,`enctype`,`length`,`method`,`name`,`noValidate`,`target`,`rel`]),xe=T([`allow`,`allowFullscreen`,`height`,`name`,`referrerPolicy`,`src`,`srcdoc`,`width`,`align`,`frameBorder`,`longDesc`,`marginHeight`,`marginWidth`,`scrolling`,`sandbox`]),Se=T([`alt`,`crossOrigin`,`decoding`,`height`,`isMap`,`loading`,`naturalHeight`,`naturalWidth`,`referrerPolicy`,`sizes`,`src`,`srcset`,`useMap`,`width`,`align`,`border`,`complete`,`hspace`,`longDesc`,`lowsrc`,`name`,`vspace`,`x`,`y`,`fetchPriority`]),Ce=T(`accept.alt.autocomplete.checked.defaultChecked.defaultValue.dirName.disabled.height.indeterminate.max.maxLength.min.minLength.multiple.name.pattern.placeholder.readOnly.required.selectionDirection.selectionEnd.selectionStart.size.src.step.type.value.valueAsNumber.width.align.capture.formAction.formEnctype.formMethod.formNoValidate.formTarget.useMap.validationMessage.willValidate.popoverTargetAction`.split(`.`)),we=T([`htmlFor`]),Te=T([`value`,`type`]),Ee=T([`as`,`crossOrigin`,`disabled`,`fetchPriority`,`href`,`hreflang`,`imageSizes`,`imageSrcset`,`integrity`,`media`,`referrerPolicy`,`rel`,`type`,`charset`,`rev`,`target`,`sizes`]),De=T([`name`]),Oe=T([`high`,`low`,`max`,`min`,`optimum`,`value`]),D=T([`cite`,`dateTime`]),ke=T([`reversed`,`start`,`type`,`compact`]),Ae=T([`data`,`height`,`name`,`type`,`useMap`,`width`,`validationMessage`,`willValidate`,`align`,`archive`,`border`,`code`,`codeBase`,`codeType`,`declare`,`hspace`,`standby`,`vspace`]),je=T([`disabled`,`label`]),Me=T([`defaultSelected`,`disabled`,`index`,`label`,`selected`,`text`,`value`]),Ne=T([`defaultValue`,`name`,`type`,`value`,`htmlFor`,`validationMessage`,`willValidate`]),Pe=T([`max`,`position`,`value`]),O=T([`cite`]),Fe=e=>w(e),Ie=x()([`async`,`crossOrigin`,`defer`,`fetchPriority`,`integrity`,`noModule`,`referrerPolicy`,`src`,`text`,`type`,`charset`],{event:e=>e.event,htmlFor:e=>e.htmlFor}),Le=e=>({...w(e),...Ie(e)}),Re=T([`autocomplete`,`disabled`,`length`,`multiple`,`name`,`required`,`selectedIndex`,`size`,`type`,`value`,`validationMessage`,`willValidate`]),ze=T([`name`]),Be=T([`height`,`media`,`sizes`,`src`,`srcset`,`type`,`width`]),Ve=T([`align`]),k=T([`abbr`,`cellIndex`,`colSpan`,`headers`,`rowSpan`,`scope`,`align`,`axis`,`bgColor`,`ch`,`chOff`,`height`,`noWrap`,`vAlign`,`width`]),A=T([`span`,`align`,`ch`,`chOff`,`vAlign`,`width`]),He=T([`align`,`bgColor`,`border`,`cellPadding`,`cellSpacing`,`frame`,`rules`,`summary`,`width`]),Ue=T([`rowIndex`,`sectionRowIndex`,`align`,`bgColor`,`ch`,`chOff`,`vAlign`]),j=T([`align`,`ch`,`chOff`,`vAlign`]),We=e=>w(e),Ge=T([`autocomplete`,`cols`,`defaultValue`,`dirName`,`disabled`,`maxLength`,`minLength`,`name`,`placeholder`,`readOnly`,`required`,`rows`,`selectionDirection`,`selectionEnd`,`selectionStart`,`value`,`wrap`,`textLength`,`validationMessage`,`willValidate`]),Ke=T([`dateTime`]),qe=T([`default`,`kind`,`label`,`readyState`,`src`,`srclang`]),Je=x()([`height`,`poster`,`videoHeight`,`videoWidth`,`width`,`playsInline`]),Ye=e=>({...E(e),...Je(e)}),Xe=T([`clear`]),Ze=T([`href`,`target`]),Qe=T([`aLink`,`background`,`bgColor`,`link`,`text`,`vLink`]),$e=T([`compact`]),et=T([`open`]),tt=T([`open`,`returnValue`]),nt=T([`align`]),rt=e=>w(e),M=T([`align`]),it=T([`align`,`color`,`noShade`,`size`,`width`]),at=T([`version`]),ot=e=>w(e),st=T([`content`,`httpEquiv`,`name`,`scheme`]),ct=T([`align`]),lt=e=>w(e),ut=T([`width`]),dt=e=>w(e),ft=T([`media`,`type`,`disabled`]),pt=T([`text`]),mt=T([`compact`,`type`]);function N(e){return{...S(e),...C(e)}}function P(e,t){let n=x()(e,t);return e=>({...N(e),...n(e)})}const F={A:pe,AREA:me,AUDIO:he,BASE:Ze,BLOCKQUOTE:O,Q:O,BODY:Qe,BR:Xe,BUTTON:ge,CANVAS:w,CAPTION:Ve,CITE:Fe,COL:A,COLGROUP:A,DATA:_e,DETAILS:et,DIALOG:tt,DIV:nt,DL:$e,EMBED:ve,FIELDSET:ye,FORM:be,H1:M,H2:M,H3:M,H4:M,H5:M,H6:M,HEAD:rt,HR:it,HTML:at,IFRAME:xe,IMG:Se,INPUT:Ce,LABEL:we,LI:Te,LINK:Ee,MAP:De,MENU:ot,META:st,METER:Oe,INS:D,DEL:D,OBJECT:Ae,OL:ke,OPTGROUP:je,OPTION:Me,OUTPUT:Ne,P:ct,PICTURE:lt,PRE:ut,PROGRESS:Pe,SCRIPT:Le,SELECT:Re,SLOT:ze,SOURCE:Be,SPAN:dt,STYLE:ft,TABLE:He,TBODY:j,THEAD:j,TFOOT:j,TD:k,TH:k,TEMPLATE:We,TEXTAREA:Ge,TIME:Ke,TITLE:pt,TR:Ue,TRACK:qe,UL:mt,VIDEO:Ye,SVG:P([`x`,`y`,`width`,`height`,`currentScale`,`currentTranslate`]),CIRCLE:P([`cx`,`cy`,`r`]),ELLIPSE:P([`cx`,`cy`,`rx`,`ry`]),LINE:P([`x1`,`y1`,`x2`,`y2`]),PATH:P([`pathLength`]),RECT:P([`x`,`y`,`width`,`height`,`rx`,`ry`]),POLYGON:P([`points`]),POLYLINE:P([`points`]),TEXT:P([`x`,`y`,`dx`,`dy`,`rotate`,`textLength`,`lengthAdjust`]),TSPAN:P([`x`,`y`,`dx`,`dy`,`rotate`,`textLength`,`lengthAdjust`]),IMAGE:P([`x`,`y`,`width`,`height`,`href`,`preserveAspectRatio`,`crossOrigin`]),USE:P([`x`,`y`,`width`,`height`,`href`]),DEFS:P([]),G:P([]),LINEARGRADIENT:P([`x1`,`y1`,`x2`,`y2`,`gradientUnits`,`gradientTransform`,`spreadMethod`]),RADIALGRADIENT:P([`cx`,`cy`,`r`,`fx`,`fy`,`fr`,`gradientUnits`,`gradientTransform`,`spreadMethod`]),STOP:P([`offset`]),PATTERN:P([`x`,`y`,`width`,`height`,`patternUnits`,`patternContentUnits`,`patternTransform`,`preserveAspectRatio`,`href`]),CLIPPATH:P([`clipPathUnits`]),MASK:P([`x`,`y`,`width`,`height`,`maskUnits`,`maskContentUnits`])};function ht(e){let t=F[e.tagName.toUpperCase()];if(t)return t(e);throw Error(`Unexpected HTML element tag: ${e.tagName} (update .web/custom/serialize.ts)`)}function gt(e){let t=F[e.tagName.toUpperCase()];return t?t(e):N(e)}function I(e){return e instanceof HTMLElement?ht(e):e instanceof SVGElement?gt(e):S(e)}const _t=e=>I(e.target),L=e=>e.relatedTarget?I(e.relatedTarget):null;function R(e,t){return x()(e,{target:_t,...t||{}})}const z=[`target`,`bubbles`,`cancelable`,`defaultPrevented`,`eventPhase`,`isTrusted`,`timeStamp`,`type`],B=[...z,`detail`],V=[...B,`altKey`,`button`,`buttons`,`clientX`,`clientY`,`ctrlKey`,`metaKey`,`movementX`,`movementY`,`pageX`,`pageY`,`screenX`,`screenY`,`shiftKey`],vt=[...V,`pointerId`,`pressure`,`tangentialPressure`,`tiltX`,`tiltY`,`twist`,`width`,`height`,`pointerType`,`isPrimary`],yt=R(z),bt=R(B),xt=R(V,{relatedTarget:L}),St=R(z,{clipboardData:e=>U(e.clipboardData)}),Ct=R([...z,`data`]),wt=R(V,{relatedTarget:L,dataTransfer:e=>U(e.dataTransfer)}),Tt=R(vt,{relatedTarget:L}),Et=R(z,{relatedTarget:L}),Dt=R(z),Ot=R(z),kt=R(z),At=R([...B,`altKey`,`ctrlKey`,`code`,`key`,`locale`,`location`,`metaKey`,`repeat`,`shiftKey`]),jt=R([...B,`altKey`,`ctrlKey`,`metaKey`,`shiftKey`,`changedTouches`,`targetTouches`,`touches`],{changedTouches:e=>H(e.changedTouches),targetTouches:e=>H(e.targetTouches),touches:e=>H(e.touches)}),Mt=R([...V,`deltaMode`,`deltaX`,`deltaY`,`deltaZ`],{relatedTarget:L}),Nt=R([...z,`animationName`,`elapsedTime`,`pseudoElement`]),Pt=R([...z,`oldState`,`newState`]),Ft=R([...z,`elapsedTime`,`propertyName`,`pseudoElement`]);function H(e){return Array.from(e).map(e=>({target:I(e.target),identifier:e.identifier,screenX:e.screenX,screenY:e.screenY,clientX:e.clientX,clientY:e.clientY,pageX:e.pageX,pageY:e.pageY}))}function U(e){if(!e)return null;let t=[];if(e.items)for(let n=0;n<e.items.length;n++){let r=e.items[n];t.push({kind:r.kind,type:r.type})}return{drop_effect:e.dropEffect,effect_allowed:e.effectAllowed,items:t,types:Array.from(e.types||[])}}const W={};function G(e,t,n){for(let r of t)e[r]=n}G(W,[`pointerdown`,`pointermove`,`pointerup`,`pointercancel`,`gotpointercapture`,`lostpointercapture`,`pointerenter`,`pointerleave`,`pointerover`,`pointerout`],Tt),G(W,[`click`,`contextmenu`,`dblclick`,`mousedown`,`mouseenter`,`mouseleave`,`mousemove`,`mouseout`,`mouseover`,`mouseup`],xt),G(W,[`drag`,`dragend`,`dragenter`,`dragexit`,`dragleave`,`dragover`,`dragstart`,`drop`],wt),G(W,[`keydown`,`keypress`,`keyup`],At),G(W,[`focus`,`blur`],Et),G(W,[`change`,`input`],kt),G(W,[`invalid`],Ot),G(W,[`reset`,`submit`],Dt),G(W,[`copy`,`cut`,`paste`],St),G(W,[`compositionend`,`compositionstart`,`compositionupdate`],Ct),G(W,[`touchcancel`,`touchend`,`touchmove`,`touchstart`],jt),G(W,[`scroll`],bt),G(W,[`wheel`],Mt),G(W,[`animationstart`,`animationend`,`animationiteration`],Nt),G(W,[`transitionend`],Ft),G(W,[`toggle`],Pt);function It(e){if(e&&typeof e==`object`&&`nativeEvent`in e&&typeof e.isDefaultPrevented==`function`){let t=e;if(typeof t.type!=`string`)return e;let n=W[t.type.toLowerCase()];return n?n(t):yt(t)}return e}function K(e){let t=new Map,n=[],r=[],i=[],a=[],o=0;function s(e,c){if(e==null||typeof e==`string`||typeof e==`boolean`)return e;if(typeof e==`number`){if(Number.isNaN(e)){let e=c?` in '${c}'`:``;throw Error(`Cannot serialize NaN${e}. NaN and Infinity are not supported because they cannot be serialized to JSON.`)}if(!Number.isFinite(e)){let t=e>0?`Infinity`:`-Infinity`,n=c?` in '${c}'`:``;throw Error(`Cannot serialize ${t}${n}. NaN and Infinity are not supported because they cannot be serialized to JSON.`)}return e}let l=o++,u=t.get(e);if(u!==void 0)return n.push(l),u;if(t.set(e,l),e instanceof Date)return r.push(l),e.getTime();if(Array.isArray(e)){let t=e.length,n=Array(t);for(let r=0;r<t;r++)n[r]=s(e[r],c);return n}if(e instanceof Map){a.push(l);let t={};for(let[n,r]of e.entries())t[String(n)]=s(r,String(n));return t}if(e instanceof Set){i.push(l);let t=e.size,n=Array(t),r=0;for(let t of e)n[r]=s(t,c),r+=1;return n}if(typeof e==`object`){let t={},n=Object.keys(e);for(let r=0;r<n.length;r++){let i=n[r];t[i]=s(e[i],i)}return t}throw Error(`Unsupported value in serialization: ${e}`)}let c=s(e);return[[n,r,i,a],c]}function q(e,t){let[[n,r,i,a],o]=e,s=new Set(n),c=new Set(r),l=new Set(i),u=new Set(a),d=[];function f(e){let n=d.length;if(s.has(n))return d.push(null),d[e];if(c.has(n)){let t=new Date(e);return d.push(t),t}if(e==null||typeof e==`number`||typeof e==`string`||typeof e==`boolean`)return t?.coerceNullsToUndefined?e??void 0:e;if(Array.isArray(e)){if(l.has(n)){let t=new Set;d.push(t);for(let n=0;n<e.length;n++)t.add(f(e[n]));return t}let t=e.length,r=Array(t);d.push(r);for(let n=0;n<t;n++)r[n]=f(e[n]);return r}if(typeof e==`object`){if(u.has(n)){let t=new Map;d.push(t);let n=Object.keys(e);for(let r=0;r<n.length;r++){let i=n[r];t.set(i,f(e[i]))}return t}let t={};d.push(t);let r=Object.keys(e);for(let n=0;n<r.length;n++){let i=r[n];t[i]=f(e[i])}return t}throw Error(`Unsupported value in deserialization: ${e}`)}return f(o)}var Lt=class{#activeViews;#socket=null;#messageQueue;#connectionListeners=new Set;#serverErrors=new Map;#serverErrorListeners=new Set;#channels=new Map;#url;#frameworkNavigate;#directives;#connectionStatusConfig;#hasConnectedOnce=!1;#connectingTimeout=null;#errorTimeout=null;#currentStatus=`ok`;constructor(e,t,n,r){if(this.#url=e,this.#directives=t,this.#frameworkNavigate=n,this.#socket=null,this.#activeViews=new Map,this.#messageQueue=[],this.#connectionStatusConfig=r,typeof window<`u`&&typeof sessionStorage<`u`){let e=sessionStorage.getItem(`__PULSE_DIRECTIVES`);if(e)try{this.#directives=JSON.parse(e)}catch{}}}setDirectives(e){this.#directives=e}isConnected(){return this.#socket?.connected??!1}#clearTimeouts(){this.#connectingTimeout&&=(clearTimeout(this.#connectingTimeout),null),this.#errorTimeout&&=(clearTimeout(this.#errorTimeout),null)}#setStatus(e){this.#clearTimeouts(),this.#currentStatus=e,this.#notifyConnectionListeners(e)}#handleConnected(){this.#hasConnectedOnce=!0,this.#setStatus(`ok`)}#setInitialConnectionStatus(){this.#setStatus(`ok`),this.#connectingTimeout=setTimeout(()=>{this.#setStatus(`connecting`),this.#errorTimeout=setTimeout(()=>{this.#setStatus(`error`)},this.#connectionStatusConfig.initialErrorDelay)},this.#connectionStatusConfig.initialConnectingDelay)}#handleDisconnected(){this.#setStatus(`reconnecting`),this.#errorTimeout=setTimeout(()=>{this.#setStatus(`error`)},this.#connectionStatusConfig.reconnectErrorDelay)}async connect(){if(!this.#socket)return this.#hasConnectedOnce||this.#setInitialConnectionStatus(),new Promise((e,t)=>{let n=v(this.#url,{transports:[`websocket`,`webtransport`],auth:this.#directives.socketio?.auth,extraHeaders:this.#directives.socketio?.headers});this.#socket=n,n.on(`connect`,()=>{console.log(`[SocketIOTransport] Connected:`,this.#socket?.id);for(let[e,t]of this.#activeViews)n.emit(`message`,K({type:`mount`,path:e,routeInfo:t.routeInfo}));for(let e of this.#messageQueue)e.type===`mount`&&this.#activeViews.has(e.path)||e.type!==`navigate`&&n.emit(`message`,K(e));this.#messageQueue=[],this.#handleConnected(),e()}),n.on(`connect_error`,e=>{console.error(`[SocketIOTransport] Connection failed:`,e),this.#handleDisconnected(),t(e)}),n.on(`disconnect`,()=>{console.log(`[SocketIOTransport] Disconnected`),this.#handleTransportDisconnect(),this.#handleDisconnected()}),n.on(`message`,e=>this.#handleServerMessage(q(e,{coerceNullsToUndefined:!0})))})}onConnectionChange(e){return this.#connectionListeners.add(e),e(this.#currentStatus),()=>{this.#connectionListeners.delete(e)}}#notifyConnectionListeners(e){for(let t of this.#connectionListeners)t(e)}onServerError(e){this.#serverErrorListeners.add(e);for(let[t,n]of this.#serverErrors)e(t,n);return()=>{this.#serverErrorListeners.delete(e)}}#notifyServerError(e,t){for(let n of this.#serverErrorListeners)n(e,t)}sendMessage(e){this.isConnected()?this.#socket.emit(`message`,K(e)):this.#messageQueue.push(e)}mountView(e,t){if(this.#activeViews.has(e))throw Error(`Path ${e} is already mounted`);this.#activeViews.set(e,t),this.sendMessage({type:`mount`,path:e,routeInfo:t.routeInfo})}navigate(e,t){this.sendMessage({type:`navigate`,path:e,routeInfo:t})}unmount(e){this.sendMessage({type:`unmount`,path:e}),this.#activeViews.delete(e)}disconnect(){this.#clearTimeouts(),this.#socket?.disconnect(),this.#socket=null,this.#messageQueue=[],this.#connectionListeners.clear(),this.#activeViews.clear(),this.#serverErrors.clear(),this.#serverErrorListeners.clear();for(let{bridge:e}of this.#channels.values())e.dispose(new y(`Client disconnected`));this.#channels.clear(),this.#currentStatus=`ok`,this.#hasConnectedOnce=!1}#handleServerMessage(e){switch(e.type){case`vdom_init`:{let t=this.#activeViews.get(e.path);if(!t)return;t&&t.onInit(e),this.#serverErrors.has(e.path)&&(this.#serverErrors.delete(e.path),this.#notifyServerError(e.path,null));break}case`vdom_update`:{let t=this.#activeViews.get(e.path);if(!t)return;t.onUpdate(e.ops),this.#serverErrors.has(e.path)&&(this.#serverErrors.delete(e.path),this.#notifyServerError(e.path,null));break}case`server_error`:if(!this.#activeViews.has(e.path))return;this.#serverErrors.set(e.path,e.error),this.#notifyServerError(e.path,e.error);break;case`api_call`:this.#performApiCall(e);break;case`navigate_to`:{let t=!!e.replace,n=e.path||``;n.startsWith(`//`)&&(n=`${window.location.protocol}${n}`);let r=()=>t?window.location.replace(n):window.location.assign(n);if(e.hard){r();break}if(!/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(n)){this.#frameworkNavigate(n,{replace:t});break}if(/^https?:\/\//.test(n))try{let e=new URL(n);if(e.origin===window.location.origin){this.#frameworkNavigate(`${e.pathname}${e.search}${e.hash}`,{replace:t});break}}catch{}r();break}case`channel_message`:this.#routeChannelMessage(e);break;case`js_exec`:this.#handleJsExec(e);break;default:console.error(`Unexpected message:`,e)}}async#performApiCall(e){try{let t=await fetch(e.url,{method:e.method||`GET`,headers:{...e.headers||{},...e.body!=null&&!(`content-type`in(e.headers||{}))?{"content-type":`application/json`}:{}},body:e.body==null?void 0:typeof e.body==`string`?e.body:JSON.stringify(e.body),credentials:e.credentials||`include`}),n={};t.headers.forEach((e,t)=>{n[t]=e});let r=null;r=(t.headers.get(`content-type`)||``).includes(`application/json`)?await t.json().catch(()=>null):await t.text().catch(()=>null);let i={type:`api_result`,id:e.id,ok:t.ok,status:t.status,headers:n,body:r};this.sendMessage(i)}catch(t){let n={type:`api_result`,id:e.id,ok:!1,status:0,headers:{},body:{error:String(t)}};this.sendMessage(n)}}invokeCallback(e,t,n){this.sendMessage({type:`callback`,path:e,callback:t,args:n.map(It)})}#handleJsExec(e){let t=this.#activeViews.get(e.path);if(!t?.onJsExec){console.warn(`[Pulse] No onJsExec handler for path: ${e.path}`),this.#sendJsResult(e.id,void 0,`No JS executor registered`);return}t.onJsExec(e)}sendJsResult(e,t,n){this.#sendJsResult(e,t,n)}#sendJsResult(e,t,n){let r={type:`js_result`,id:e,result:t,error:n};this.sendMessage(r)}acquireChannel(e){let t=this.#ensureChannelEntry(e);return t.refCount+=1,t.bridge}releaseChannel(e){let t=this.#channels.get(e);t&&(t.refCount=Math.max(0,t.refCount-1),t.refCount===0&&(t.bridge.dispose(new y(`Channel released`)),this.sendMessage({type:`channel_message`,channel:e,event:`__close__`,payload:{reason:`refcount_zero`}}),this.#channels.delete(e)))}#ensureChannelEntry(e){let t=this.#channels.get(e);return t||(t={bridge:new ae(this,e),refCount:0},this.#channels.set(e,t)),t}#routeChannelMessage(e){let t=this.#ensureChannelEntry(e.channel);t.bridge.handleServerMessage(e)&&t.refCount===0&&this.#channels.delete(e.channel)}#handleTransportDisconnect(){for(let e of this.#channels.values())e.bridge.handleDisconnect(new y(`Connection lost`))}};const J=`$$fragment`;function Rt(e){return typeof e==`object`&&!!e}function zt(e){return typeof e==`object`&&!!e&&e.tag.startsWith(`$$`)&&e.tag!==J}const Y=`$js:`;var Bt=class{#callbacks;#callbackCache;#renderPropKeys;#jsexprPaths;#callbackList;#client;#path;#registry;constructor(e,t,n=[],r=[],i={},a=[]){this.#client=e,this.#path=t,this.#registry=i,this.#callbacks=new Set(n),this.#callbackCache=new Map,this.#renderPropKeys=new Set(r),this.#jsexprPaths=new Set(a),this.#callbackList=[...this.#callbacks].sort()}getObject(e){let t=this.#registry[e];if(t===void 0)throw Error(`[Pulse] Unknown registry key: ${e}`);return t}evaluateJsExpr(e){return Function(`get_object`,`return ${e}`)(e=>this.getObject(e))}hasCallbackPath(e){return this.#callbacks.has(e)}hasRenderPropPath(e){return this.#renderPropKeys.has(e)}hasAnyCallbackUnder(e){if(e===``)return this.#callbackList.length>0;let t=this.#lowerBound(this.#callbackList,e);return t<this.#callbackList.length&&this.#callbackList[t].startsWith(e)}applyCallbackDelta(e){if(e.remove)for(let t of e.remove)this.#callbacks.delete(t),this.#callbackCache.delete(t);if(e.add)for(let t of e.add)this.#callbacks.add(t);this.#callbackList=[...this.#callbacks].sort()}applyRenderPropsDelta(e){if(e.remove)for(let t of e.remove)this.#renderPropKeys.delete(t);if(e.add)for(let t of e.add)this.#renderPropKeys.add(t)}applyJsExprPathsDelta(e){if(e.remove)for(let t of e.remove)this.#jsexprPaths.delete(t);if(e.add)for(let t of e.add)this.#jsexprPaths.add(t)}getCallback(e,t){let n=this.#propPath(e,t),r=this.#callbackCache.get(n);return r||(r=(...e)=>this.#client.invokeCallback(this.#path,n,e),this.#callbackCache.set(n,r)),r}renderNode(t,n=``){if(t==null||typeof t==`boolean`||typeof t==`number`)return t;if(typeof t==`string`){if(t.startsWith(Y)){let e=t.slice(4);return this.evaluateJsExpr(e)}return t}if(Rt(t)){let{tag:r,props:a={},children:o=[]}=t,s={};for(let[e,t]of Object.entries(a))s[e]=this.transformValue(n,e,t);t.key&&(s.key=t.key);let c=[];for(let e=0;e<o.length;e+=1){let t=o[e],r=n?`${n}.${e}`:String(e);c.push(this.renderNode(t,r))}if(zt(t)){let e=t.tag.slice(2),n=this.#registry[e];if(!n)throw Error(`Could not find component ${e}. This is a Pulse internal error.`);return i(n,s,...c)}return i(r===J?e:r,s,...c)}return process.env.NODE_ENV!==`production`&&console.error(`Unknown VDOM node type:`,t),null}#propPath(e,t){return e?`${e}.${t}`:t}transformValue(e,t,n){let r=this.#propPath(e,t);if(this.#callbacks.has(r))return this.getCallback(e,t);if(this.#renderPropKeys.has(r))return this.renderNode(n,r);if(typeof n==`string`&&n.startsWith(Y)){let e=n.slice(4);return this.evaluateJsExpr(e)}return n}init(e){this.#callbacks=new Set(e.callbacks);for(let e of Array.from(this.#callbackCache.keys()))this.#callbacks.has(e)||this.#callbackCache.delete(e);return this.#callbackList=[...this.#callbacks].sort(),this.#renderPropKeys=new Set(e.render_props),this.#jsexprPaths=new Set(e.jsexpr_paths),this.renderNode(e.vdom)}#ensureChildrenArray(e){let t=e.props?.children;return t==null?[]:Array.isArray(t)?t.slice():[t]}applyUpdates(e,t){let r=e;for(let e of t){if(e.type===`update_callbacks`){this.applyCallbackDelta(e.data);continue}if(e.type===`update_render_props`){this.applyRenderPropsDelta(e.data);continue}if(e.type===`update_jsexpr_paths`){this.applyJsExprPathsDelta(e.data);continue}let t=e.path.split(`.`).filter(e=>e.length>0),a=(r,o,s)=>{if(o<t.length){this.#assertIsElement(r,t,o);let e=r,i=t[o],c=+i,l=s?`${s}.${i}`:i;if(Number.isNaN(c)){let t=e.props??{},r=t[i];return n(e,{...t,[i]:a(r,o+1,l)})}else{let t=this.#ensureChildrenArray(e),r=t[c];return t[c]=a(r,o+1,l),n(e,void 0,...t)}}switch(e.type){case`replace`:return this.renderNode(e.data,e.path);case`update_props`:{this.#assertIsElement(r,t,o);let a=r,c={...a.props??{}},l=e.data;if(l.remove&&l.remove.length>0)for(let e of l.remove)e in c&&delete c[e];if(l.set)for(let[e,t]of Object.entries(l.set))c[e]=this.transformValue(s,e,t);return(l.remove?.length??0)>0?(c.key=a.key,c.ref=a.ref,i(a.type,c,...this.#ensureChildrenArray(a))):n(a,c)}case`reconciliation`:{this.#assertIsElement(r,t,o);let i=r,a=this.#ensureChildrenArray(i),c=[],[l,u]=e.new,[d,f]=e.reuse,p=-1,m=-1,h=-1,g=-1;l.length>0&&(p=l[0],h=0),d.length>0&&(m=d[0],g=0);for(let t=0;t<e.N;++t)if(t===p){let e=u[h],n=s?`${s}.${t}`:String(t);c.push(this.renderNode(e,n)),p=h<l.length-1?l[++h]:-1}else if(t===m){let e=a[f[g]],n=s?`${s}.${t}`:String(t);this.hasAnyCallbackUnder(n)&&(e=this.#rebindCallbacksInSubtree(e,n)),c.push(e),m=g<d.length-1?d[++g]:-1}else c.push(a[t]);return n(i,null,...c)}default:throw Error(`[Pulse renderer] Unknown update type: ${e?.type}`)}};r=a(r,0,``)}return r}#assertIsElement(e,t,n){if(process.env.NODE_ENV!==`production`&&!o(e))throw console.error(`Invalid node:`,e),Error(`Invalid node at path ${t.slice(0,n).join(`.`)}`);return!0}#rebindCallbacksInSubtree(e,t){if(!o(e))return e;let r=e,i=r.props??{},a={...i};for(let e of Object.keys(i)){let n=t?`${t}.${e}`:e;this.hasCallbackPath(n)&&(a[e]=this.getCallback(t,e)),this.hasRenderPropPath(n)&&this.hasAnyCallbackUnder(n)&&(a[e]=this.#rebindCallbacksInSubtree(i[e],n))}return n(r,a,...this.#ensureChildrenArray(r).map((e,n)=>{let r=t?`${t}.${n}`:String(n);return this.hasAnyCallbackUnder(r)?this.#rebindCallbacksInSubtree(e,r):e}))}#lowerBound(e,t){let n=0,r=e.length;for(;n<r;){let i=n+r>>>1;e[i]<t?n=i+1:r=i}return n}};function Vt(e,n){let r=s(e);return({children:e,...i})=>m(t,{fallback:n,children:m(r,{...i,children:e})})}const X=r(null),Z=r(null),Q=()=>{let e=l(X);if(!e)throw Error(`usePulseClient must be used within a PulseProvider`);return e},Ht=e=>{let t=l(Z);if(!t)throw Error(`usePulsePrerender must be used within a PulseProvider`);let n=t.views[e];if(!n)throw Error(`No prerender found for '${e}'`);return n},$=typeof window<`u`;function Ut({children:e,config:t,prerender:n}){let[r,i]=p(`ok`),a=_(),{directives:o}=n,s=d(()=>new Lt(t.serverAddress,o,a,t.connectionStatus),[t.serverAddress,a,t.connectionStatus]);u(()=>s.setDirectives(o),[s,o]),u(()=>{if(!$)return;let e=s.onConnectionChange(e=>{i(e)});return s.connect(),()=>{e(),s.disconnect()}},[s]);let c=(()=>{switch(r){case`connecting`:return`Connecting...`;case`reconnecting`:return`Reconnecting...`;case`error`:return`Failed to connect to the server.`;default:return null}})();return m(X.Provider,{value:s,children:h(Z.Provider,{value:n,children:[c&&m(`div`,{style:{position:`fixed`,bottom:`20px`,right:`20px`,backgroundColor:r===`error`?`red`:`#666`,color:`white`,padding:`10px`,borderRadius:`5px`,zIndex:1e3},children:c}),e]})})}function Wt({path:e,registry:t}){let n=Q(),r=Ht(e),i=d(()=>new Bt(n,e,r.callbacks,r.render_props,t,r.jsexpr_paths),[n,e,t]),[a,o]=p(()=>i.init(r)),[s,c]=p(null),l=g(),h=ee(),_=d(()=>{let{"*":e=``,...t}=h,n=new URLSearchParams(l.search);return{hash:l.hash,pathname:l.pathname,query:l.search,queryParams:Object.fromEntries(n.entries()),pathParams:t,catchall:e.length>0?e.split(`/`):[]}},[l.hash,l.pathname,l.search,JSON.stringify(h)]);u(()=>{if($){n.mountView(e,{routeInfo:_,onInit:e=>{o(i.init(e))},onUpdate:e=>{o(t=>t==null?t:i.applyUpdates(t,e))},onJsExec:e=>{let t,r=null;try{t=i.evaluateJsExpr(e.code)}catch(e){r=e instanceof Error?e.message:String(e)}n.sendJsResult(e.id,t,r)}});let t=n.onServerError((t,n)=>{t===e&&c(n)});return()=>{t(),n.unmount(e)}}},[n,i,e]),u(()=>{$&&n.navigate(e,_)},[n,e,_]);let v=f(!1);return u(()=>(v.current?o(i.init(r)):v.current=!0,()=>{v.current=!1}),[r,i]),s?m(Gt,{error:s}):a}function Gt({error:e}){return h(`div`,{style:{padding:16,border:`1px solid #e00`,background:`#fff5f5`,color:`#900`,fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`,whiteSpace:`pre-wrap`},children:[h(`div`,{style:{fontWeight:700,marginBottom:8},children:[`Server Error during `,e.phase]}),e.message&&m(`div`,{children:e.message}),e.stack&&h(`details`,{open:!0,style:{marginTop:8},children:[m(`summary`,{children:`Stack trace`}),m(`pre`,{style:{margin:0},children:e.stack})]})]})}function Kt(e){let t=Q(),n=d(()=>{if(!e)throw Error(`usePulseChannel requires a non-empty channelId`);return t.acquireChannel(e)},[t,e]);return u(()=>()=>{t.releaseChannel(e)},[t,e]),n}export{y as PulseChannelResetError,oe as PulseForm,Ut as PulseProvider,Wt as PulseView,Vt as RenderLazy,q as deserialize,se as extractServerRouteInfo,K as serialize,b as submitForm,Kt as usePulseChannel,Q as usePulseClient};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["client: PulseSocketIOClient","id: string","remaining: ServerChannelRequestMessage[]","response: any","error: any","PulseForm","out: any","formExtractor","elementExtractors: Record<string, (elt: any) => object>","eventExtractorMap: { [key: string]: (evt: any) => object }","refs: number[]","dates: number[]","sets: number[]","maps: number[]","process","rec: Record<string, any>","objects: Array<any>","result","keys","result: Record<string, any>","#url","#directives","#frameworkNavigate","#socket","#activeViews","#messageQueue","#connectionStatusConfig","#connectingTimeout","#errorTimeout","#clearTimeouts","#currentStatus","#notifyConnectionListeners","#hasConnectedOnce","#setStatus","#setInitialConnectionStatus","#handleConnected","#handleDisconnected","#handleTransportDisconnect","#handleServerMessage","#connectionListeners","#serverErrorListeners","#serverErrors","#channels","#notifyServerError","#performApiCall","#routeChannelMessage","#handleJsExec","headersObj: Record<string, string>","body: any","reply: ClientApiResultMessage","#sendJsResult","msg: ClientJsResultMessage","#ensureChannelEntry","#client","#path","#registry","#callbacks","#callbackCache","#renderPropKeys","#jsexprPaths","#callbackList","#lowerBound","#propPath","newProps: Record<string, any>","newTree: ReactNode","#assertIsElement","#ensureChildrenArray","nextProps: Record<string, any>","#rebindCallbacksInSubtree","result: any","error: string | null"],"sources":["../src/channel.ts","../src/form.tsx","../src/helpers.ts","../src/serialize/extractor.ts","../src/serialize/elements.ts","../src/serialize/events.ts","../src/serialize/serializer.ts","../src/client.tsx","../src/vdom.ts","../src/renderer.tsx","../src/pulse.tsx","../src/usePulseChannel.ts"],"sourcesContent":["import type { PulseSocketIOClient } from \"./client\";\nimport type {\n\tServerChannelMessage,\n\tServerChannelRequestMessage,\n\tServerChannelResponseMessage,\n} from \"./messages\";\n\nexport class PulseChannelResetError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"PulseChannelResetError\";\n\t}\n}\n\nexport type ChannelEventHandler = (payload: any) => any | Promise<any>;\n\ninterface PendingRequest {\n\tresolve: (value: any) => void;\n\treject: (error: any) => void;\n}\n\nfunction randomId(): string {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\");\n\t}\n\treturn Math.random().toString(16).slice(2) + Math.random().toString(16).slice(2);\n}\n\nfunction formatError(error: unknown): string {\n\tif (error instanceof Error) return error.message;\n\tif (typeof error === \"string\") return error;\n\ttry {\n\t\treturn JSON.stringify(error);\n\t} catch {\n\t\treturn String(error);\n\t}\n}\n\nfunction isServerResponseMessage(\n\tmessage: ServerChannelMessage,\n): message is ServerChannelResponseMessage {\n\treturn typeof (message as ServerChannelResponseMessage).responseTo === \"string\";\n}\n\nfunction isServerRequestMessage(\n\tmessage: ServerChannelMessage,\n): message is ServerChannelRequestMessage {\n\treturn typeof (message as ServerChannelRequestMessage).event === \"string\";\n}\n\nexport class ChannelBridge {\n\tprivate handlers = new Map<string, Set<ChannelEventHandler>>();\n\tprivate pending = new Map<string, PendingRequest>();\n\tprivate backlog: ServerChannelRequestMessage[] = [];\n\tprivate closed = false;\n\n\tconstructor(\n\t\tprivate client: PulseSocketIOClient,\n\t\tpublic readonly id: string,\n\t) {}\n\n\temit(event: string, payload?: any): void {\n\t\tthis.ensureOpen();\n\t\tthis.client.sendMessage({\n\t\t\ttype: \"channel_message\",\n\t\t\tchannel: this.id,\n\t\t\tevent,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\trequest(event: string, payload?: any): Promise<any> {\n\t\tthis.ensureOpen();\n\t\tconst requestId = randomId();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pending.set(requestId, { resolve, reject });\n\t\t\tthis.client.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: this.id,\n\t\t\t\tevent,\n\t\t\t\tpayload,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t});\n\t}\n\n\ton(event: string, handler: ChannelEventHandler): () => void {\n\t\tthis.ensureOpen();\n\t\tlet bucket = this.handlers.get(event);\n\t\tif (!bucket) {\n\t\t\tbucket = new Set();\n\t\t\tthis.handlers.set(event, bucket);\n\t\t}\n\t\tbucket.add(handler);\n\t\tthis.flushBacklog(event);\n\t\treturn () => {\n\t\t\tconst set = this.handlers.get(event);\n\t\t\tif (!set) return;\n\t\t\tset.delete(handler);\n\t\t\tif (set.size === 0) {\n\t\t\t\tthis.handlers.delete(event);\n\t\t\t}\n\t\t};\n\t}\n\n\thandleServerMessage(message: ServerChannelMessage): boolean {\n\t\tif (isServerResponseMessage(message)) {\n\t\t\tthis.resolvePending(message);\n\t\t\treturn this.closed;\n\t\t}\n\t\tif (this.closed) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!isServerRequestMessage(message)) {\n\t\t\treturn this.closed;\n\t\t}\n\n\t\tif (message.event === \"__close__\") {\n\t\t\tthis.close(new PulseChannelResetError(\"Channel closed by server\"));\n\t\t\treturn true;\n\t\t}\n\t\tif (message.requestId) {\n\t\t\tvoid this.dispatchRequest(\n\t\t\t\tmessage as ServerChannelRequestMessage & {\n\t\t\t\t\trequestId: string;\n\t\t\t\t},\n\t\t\t);\n\t\t} else {\n\t\t\tthis.dispatchEvent(message);\n\t\t}\n\t\treturn this.closed;\n\t}\n\n\thandleDisconnect(reason: PulseChannelResetError): void {\n\t\tthis.close(reason);\n\t}\n\n\tdispose(reason: PulseChannelResetError): void {\n\t\tthis.close(reason);\n\t}\n\n\tprivate ensureOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new PulseChannelResetError(\"Channel is closed\");\n\t\t}\n\t}\n\n\tprivate flushBacklog(event: string): void {\n\t\tif (this.backlog.length === 0) return;\n\t\tconst remaining: ServerChannelRequestMessage[] = [];\n\t\tfor (const item of this.backlog) {\n\t\t\tif (item.event === event) {\n\t\t\t\tthis.dispatchEvent(item);\n\t\t\t} else {\n\t\t\t\tremaining.push(item);\n\t\t\t}\n\t\t}\n\t\tthis.backlog = remaining;\n\t}\n\n\tprivate dispatchEvent(message: ServerChannelRequestMessage): void {\n\t\tconst handlers = this.handlers.get(message.event);\n\t\tif (!handlers || handlers.size === 0) {\n\t\t\tthis.backlog.push(message);\n\t\t\treturn;\n\t\t}\n\t\tfor (const handler of handlers) {\n\t\t\ttry {\n\t\t\t\tconst result = handler(message.payload);\n\t\t\t\tif (result && typeof (result as Promise<any>).then === \"function\") {\n\t\t\t\t\tvoid (result as Promise<any>).catch((err) => {\n\t\t\t\t\t\tconsole.error(\"Pulse channel handler error\", err);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"Pulse channel handler error\", err);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async dispatchRequest(\n\t\tmessage: ServerChannelRequestMessage & { requestId: string },\n\t): Promise<void> {\n\t\tconst handlers = this.handlers.get(message.event);\n\t\tlet response: any;\n\t\tlet error: any;\n\t\tif (handlers && handlers.size > 0) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = handler(message.payload);\n\t\t\t\t\tresponse = await Promise.resolve(result);\n\t\t\t\t\tif (response !== undefined) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\terror = err;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (error) {\n\t\t\tthis.client.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: this.id,\n\t\t\t\tevent: undefined,\n\t\t\t\tresponseTo: message.requestId,\n\t\t\t\terror: formatError(error),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.client.sendMessage({\n\t\t\ttype: \"channel_message\",\n\t\t\tchannel: this.id,\n\t\t\tevent: undefined,\n\t\t\tresponseTo: message.requestId,\n\t\t\tpayload: response,\n\t\t});\n\t}\n\n\tprivate resolvePending(message: ServerChannelResponseMessage): void {\n\t\tconst entry = message.responseTo ? this.pending.get(message.responseTo) : undefined;\n\t\tif (!entry) {\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.responseTo!);\n\t\tif (message.error !== undefined && message.error !== null) {\n\t\t\tentry.reject(new PulseChannelResetError(String(message.error)));\n\t\t} else {\n\t\t\tentry.resolve(message.payload);\n\t\t}\n\t}\n\n\tprivate close(reason: PulseChannelResetError): void {\n\t\tif (this.closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.closed = true;\n\t\tfor (const request of this.pending.values()) {\n\t\t\trequest.reject(reason);\n\t\t}\n\t\tthis.pending.clear();\n\t\tthis.handlers.clear();\n\t\tthis.backlog = [];\n\t\t// No-op: owning client manages registry lifecycle.\n\t}\n}\n","import { type ComponentPropsWithoutRef, type FormEvent, forwardRef, useCallback } from \"react\";\n\nexport type PulseFormProps = ComponentPropsWithoutRef<\"form\"> & {\n\taction: string;\n};\n\n/**\n * PulseForm intercepts native form submissions and sends them through fetch so the\n * surrounding Pulse view stays mounted. Server-side handlers are still invoked via\n * the form action endpoint and reactive updates propagate over the socket.\n */\nexport const PulseForm = forwardRef<HTMLFormElement, PulseFormProps>(function PulseForm(\n\t{ onSubmit, action, ...rest },\n\tref,\n) {\n\treturn (\n\t\t<form\n\t\t\t{...rest}\n\t\t\taction={action}\n\t\t\tref={ref}\n\t\t\tonSubmit={useCallback(\n\t\t\t\t(event: FormEvent<HTMLFormElement>) => submitForm({ event, action, onSubmit }),\n\t\t\t\t[action, onSubmit],\n\t\t\t)}\n\t\t/>\n\t);\n});\n\ninterface SubmitForm {\n\tevent: FormEvent<HTMLFormElement>;\n\taction: string;\n\tonSubmit?: PulseFormProps[\"onSubmit\"];\n\tformData?: FormData;\n\tforce?: boolean;\n}\n\nexport async function submitForm({ event, action, onSubmit, formData, force }: SubmitForm) {\n\tonSubmit?.(event);\n\tif (!force && event.defaultPrevented) {\n\t\treturn;\n\t}\n\tconst form = event.currentTarget;\n\tevent.preventDefault();\n\tconst nativeEvent = event.nativeEvent as SubmitEvent;\n\tif (!formData) {\n\t\tformData = new FormData(form, nativeEvent.submitter);\n\t}\n\tconst url = new URL(action, window.location.href);\n\ttry {\n\t\tawait fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\t// Required for our hosting scenarios of same host + different ports or 2 subdomains\n\t\t\tcredentials: \"include\",\n\t\t\tbody: formData,\n\t\t});\n\t} catch (err) {\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.error(\"[Pulse] Form submission failed\", err);\n\t\t} else {\n\t\t\tthrow err;\n\t\t}\n\t}\n}\n","import type { LoaderFunctionArgs } from \"react-router\";\n\nexport interface RouteInfo {\n\tpathname: string;\n\thash: string;\n\tquery: string;\n\tqueryParams: Record<string, string>;\n\tpathParams: Record<string, string | undefined>;\n\tcatchall: string[];\n}\n\nexport function extractServerRouteInfo({ params, request }: LoaderFunctionArgs) {\n\tconst { \"*\": catchall = \"\", ...pathParams } = params;\n\tconst parsedUrl = new URL(request.url);\n\n\treturn {\n\t\thash: parsedUrl.hash,\n\t\tpathname: parsedUrl.pathname,\n\t\tquery: parsedUrl.search,\n\t\tqueryParams: Object.fromEntries(parsedUrl.searchParams.entries()),\n\t\tpathParams,\n\t\tcatchall: catchall.length > 1 ? catchall.split(\"/\") : [],\n\t} satisfies RouteInfo;\n}\n","type Simplify<T> = { [K in keyof T]: T[K] } & {};\n\nexport function createExtractor<T extends object>() {\n\tfunction _createExtractor<\n\t\tconst K extends readonly (keyof T)[],\n\t\tC extends Partial<Record<K[number] | string, (src: T) => any>>,\n\t>(keys: K, computed?: C) {\n\t\treturn (\n\t\t\tsrc: T,\n\t\t): Simplify<\n\t\t\tPick<T, K[number]> & {\n\t\t\t\t[P in keyof C]-?: C[P] extends (...args: any) => infer R ? R : never;\n\t\t\t}\n\t\t> => {\n\t\t\tconst out: any = {};\n\t\t\tfor (const key of keys) {\n\t\t\t\tout[key as string] = (src as any)[key as string];\n\t\t\t}\n\t\t\tif (computed) {\n\t\t\t\tfor (const key in computed) {\n\t\t\t\t\tconst fn = computed[key]!;\n\t\t\t\t\tout[key] = fn(src);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn out;\n\t\t};\n\t}\n\treturn _createExtractor;\n}\n","import { createExtractor } from \"./extractor\";\n\n// Base extractors (camelCase) similar to events.ts style\nconst lowerTagName = (e: Element) => e.tagName.toLowerCase();\n\nconst ELEMENT_KEYS = [\n\t\"id\",\n\t\"className\",\n\t\"tagName\",\n\t\"localName\",\n\t\"clientHeight\",\n\t\"clientLeft\",\n\t\"clientTop\",\n\t\"clientWidth\",\n\t\"scrollHeight\",\n\t\"scrollLeft\",\n\t\"scrollTop\",\n\t\"scrollWidth\",\n\t\"slot\",\n] as const satisfies readonly (keyof Element)[];\n\nconst HTML_OR_SVG_KEYS = [\n\t\"autofocus\",\n\t\"tabIndex\",\n\t\"nonce\",\n] as const satisfies readonly (keyof HTMLOrSVGElement)[];\n\nconst HTML_ELEMENT_BASE_KEYS = [\n\t\"accessKey\",\n\t\"accessKeyLabel\",\n\t\"autocapitalize\",\n\t\"dir\",\n\t\"draggable\",\n\t\"hidden\",\n\t\"inert\",\n\t\"lang\",\n\t\"offsetHeight\",\n\t\"offsetLeft\",\n\t\"offsetTop\",\n\t\"offsetWidth\",\n\t\"popover\",\n\t\"spellcheck\",\n\t\"title\",\n\t\"translate\",\n\t\"writingSuggestions\",\n\t\"contentEditable\",\n\t\"enterKeyHint\",\n\t\"isContentEditable\",\n\t\"inputMode\",\n] as const satisfies readonly (keyof HTMLElement)[];\n\nconst extractElementBase = createExtractor<Element>()(ELEMENT_KEYS, {\n\ttagName: lowerTagName,\n});\n\nconst extractHTMLOrSVGElement = createExtractor<HTMLOrSVGElement>()(HTML_OR_SVG_KEYS);\n\nconst extractHTMLElementBaseOnly = createExtractor<HTMLElement>()(HTML_ELEMENT_BASE_KEYS);\n\nfunction extractHTMLElementBase(elt: HTMLElement) {\n\treturn {\n\t\t...extractElementBase(elt),\n\t\t...extractHTMLOrSVGElement(elt as HTMLOrSVGElement),\n\t\t...extractHTMLElementBaseOnly(elt),\n\t};\n}\n\n// Helper to compose per-element extractors with the shared base\nfunction withBase<T extends HTMLElement>(\n\tkeys: readonly (keyof T)[],\n\tcomputed?: Partial<Record<string, (src: T) => any>>,\n) {\n\tconst only = createExtractor<T>()(keys, computed as any);\n\treturn (elt: T) => ({ ...extractHTMLElementBase(elt), ...only(elt) });\n}\n\nconst HTML_ANCHOR_KEYS = [\n\t\"hash\",\n\t\"host\",\n\t\"hostname\",\n\t\"href\",\n\t\"origin\",\n\t\"password\",\n\t\"pathname\",\n\t\"port\",\n\t\"protocol\",\n\t\"search\",\n\t\"target\",\n\t\"download\",\n\t\"rel\",\n\t\"hreflang\",\n\t\"type\",\n\t\"username\",\n\t\"ping\",\n\t\"referrerPolicy\",\n\t\"text\",\n] as const satisfies readonly (keyof HTMLAnchorElement)[];\nconst anchorExtractor = withBase<HTMLAnchorElement>(HTML_ANCHOR_KEYS);\n\nconst HTML_AREA_KEYS = [\n\t\"alt\",\n\t\"coords\",\n\t\"download\",\n\t\"hash\",\n\t\"host\",\n\t\"hostname\",\n\t\"href\",\n\t\"origin\",\n\t\"password\",\n\t\"pathname\",\n\t\"port\",\n\t\"protocol\",\n\t\"rel\",\n\t\"search\",\n\t\"shape\",\n\t\"target\",\n\t\"username\",\n\t\"ping\",\n\t\"referrerPolicy\",\n] as const satisfies readonly (keyof HTMLAreaElement)[];\nconst areaExtractor = withBase<HTMLAreaElement>(HTML_AREA_KEYS);\n\nconst HTML_MEDIA_KEYS = [\n\t\"autoplay\",\n\t\"controls\",\n\t\"crossOrigin\",\n\t\"currentSrc\",\n\t\"currentTime\",\n\t\"defaultMuted\",\n\t\"defaultPlaybackRate\",\n\t\"duration\",\n\t\"ended\",\n\t\"loop\",\n\t\"muted\",\n\t\"networkState\",\n\t\"paused\",\n\t\"playbackRate\",\n\t\"preload\",\n\t\"readyState\",\n\t\"seeking\",\n\t\"src\",\n\t\"volume\",\n\t\"preservesPitch\",\n] as const satisfies readonly (keyof HTMLMediaElement)[];\nconst mediaExtractor = withBase<HTMLMediaElement>(HTML_MEDIA_KEYS);\n\nconst audioExtractor = (elt: HTMLAudioElement) => mediaExtractor(elt);\n\nconst HTML_BUTTON_KEYS = [\n\t\"disabled\",\n\t\"name\",\n\t\"type\",\n\t\"value\",\n\t\"formAction\",\n\t\"formEnctype\",\n\t\"formMethod\",\n\t\"formNoValidate\",\n\t\"formTarget\",\n\t\"popoverTargetAction\",\n] as const satisfies readonly (keyof HTMLButtonElement)[];\nconst buttonExtractor = withBase<HTMLButtonElement>(HTML_BUTTON_KEYS);\n\nconst HTML_DATA_KEYS = [\"value\"] as const satisfies readonly (keyof HTMLDataElement)[];\nconst dataExtractor = withBase<HTMLDataElement>(HTML_DATA_KEYS);\n\nconst HTML_EMBED_KEYS = [\n\t\"height\",\n\t\"src\",\n\t\"type\",\n\t\"width\",\n\t\"align\",\n\t\"name\",\n] as const satisfies readonly (keyof HTMLEmbedElement)[];\nconst embedExtractor = withBase<HTMLEmbedElement>(HTML_EMBED_KEYS);\n\nconst HTML_FIELDSET_KEYS = [\n\t\"disabled\",\n\t\"name\",\n\t\"type\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLFieldSetElement)[];\nconst fieldsetExtractor = withBase<HTMLFieldSetElement>(HTML_FIELDSET_KEYS);\n\nconst HTML_FORM_KEYS = [\n\t\"acceptCharset\",\n\t\"action\",\n\t\"autocomplete\",\n\t\"encoding\",\n\t\"enctype\",\n\t\"length\",\n\t\"method\",\n\t\"name\",\n\t\"noValidate\",\n\t\"target\",\n\t\"rel\",\n] as const satisfies readonly (keyof HTMLFormElement)[];\nconst formExtractor = withBase<HTMLFormElement>(HTML_FORM_KEYS);\n\nconst HTML_IFRAME_KEYS = [\n\t\"allow\",\n\t\"allowFullscreen\",\n\t\"height\",\n\t\"name\",\n\t\"referrerPolicy\",\n\t\"src\",\n\t\"srcdoc\",\n\t\"width\",\n\t\"align\",\n\t\"frameBorder\",\n\t\"longDesc\",\n\t\"marginHeight\",\n\t\"marginWidth\",\n\t\"scrolling\",\n\t\"sandbox\",\n] as const satisfies readonly (keyof HTMLIFrameElement)[];\nconst iframeExtractor = withBase<HTMLIFrameElement>(HTML_IFRAME_KEYS);\n\nconst HTML_IMAGE_KEYS = [\n\t\"alt\",\n\t\"crossOrigin\",\n\t\"decoding\",\n\t\"height\",\n\t\"isMap\",\n\t\"loading\",\n\t\"naturalHeight\",\n\t\"naturalWidth\",\n\t\"referrerPolicy\",\n\t\"sizes\",\n\t\"src\",\n\t\"srcset\",\n\t\"useMap\",\n\t\"width\",\n\t\"align\",\n\t\"border\",\n\t\"complete\",\n\t\"hspace\",\n\t\"longDesc\",\n\t\"lowsrc\",\n\t\"name\",\n\t\"vspace\",\n\t\"x\",\n\t\"y\",\n\t\"fetchPriority\",\n] as const satisfies readonly (keyof HTMLImageElement)[];\nconst imageExtractor = withBase<HTMLImageElement>(HTML_IMAGE_KEYS);\n\nconst HTML_INPUT_KEYS = [\n\t\"accept\",\n\t\"alt\",\n\t\"autocomplete\",\n\t\"checked\",\n\t\"defaultChecked\",\n\t\"defaultValue\",\n\t\"dirName\",\n\t\"disabled\",\n\t\"height\",\n\t\"indeterminate\",\n\t\"max\",\n\t\"maxLength\",\n\t\"min\",\n\t\"minLength\",\n\t\"multiple\",\n\t\"name\",\n\t\"pattern\",\n\t\"placeholder\",\n\t\"readOnly\",\n\t\"required\",\n\t\"selectionDirection\",\n\t\"selectionEnd\",\n\t\"selectionStart\",\n\t\"size\",\n\t\"src\",\n\t\"step\",\n\t\"type\",\n\t\"value\",\n\t\"valueAsNumber\",\n\t\"width\",\n\t\"align\",\n\t\"capture\",\n\t\"formAction\",\n\t\"formEnctype\",\n\t\"formMethod\",\n\t\"formNoValidate\",\n\t\"formTarget\",\n\t\"useMap\",\n\t\"validationMessage\",\n\t\"willValidate\",\n\t\"popoverTargetAction\",\n] as const satisfies readonly (keyof HTMLInputElement)[];\nconst inputExtractor = withBase<HTMLInputElement>(HTML_INPUT_KEYS);\n\nconst HTML_LABEL_KEYS = [\"htmlFor\"] as const satisfies readonly (keyof HTMLLabelElement)[];\nconst labelExtractor = withBase<HTMLLabelElement>(HTML_LABEL_KEYS);\n\nconst HTML_LI_KEYS = [\"value\", \"type\"] as const satisfies readonly (keyof HTMLLIElement)[];\nconst liExtractor = withBase<HTMLLIElement>(HTML_LI_KEYS);\n\nconst HTML_LINK_KEYS = [\n\t\"as\",\n\t\"crossOrigin\",\n\t\"disabled\",\n\t\"fetchPriority\",\n\t\"href\",\n\t\"hreflang\",\n\t\"imageSizes\",\n\t\"imageSrcset\",\n\t\"integrity\",\n\t\"media\",\n\t\"referrerPolicy\",\n\t\"rel\",\n\t\"type\",\n\t\"charset\",\n\t\"rev\",\n\t\"target\",\n\t\"sizes\",\n] as const satisfies readonly (keyof HTMLLinkElement)[];\nconst linkExtractor = withBase<HTMLLinkElement>(HTML_LINK_KEYS);\n\nconst HTML_MAP_KEYS = [\"name\"] as const satisfies readonly (keyof HTMLMapElement)[];\nconst mapExtractor = withBase<HTMLMapElement>(HTML_MAP_KEYS);\n\nconst HTML_METER_KEYS = [\n\t\"high\",\n\t\"low\",\n\t\"max\",\n\t\"min\",\n\t\"optimum\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLMeterElement)[];\nconst meterExtractor = withBase<HTMLMeterElement>(HTML_METER_KEYS);\n\nconst HTML_MOD_KEYS = [\"cite\", \"dateTime\"] as const satisfies readonly (keyof HTMLModElement)[];\nconst modExtractor = withBase<HTMLModElement>(HTML_MOD_KEYS);\n\nconst HTML_OL_KEYS = [\n\t\"reversed\",\n\t\"start\",\n\t\"type\",\n\t\"compact\",\n] as const satisfies readonly (keyof HTMLOListElement)[];\nconst olistExtractor = withBase<HTMLOListElement>(HTML_OL_KEYS);\n\nconst HTML_OBJECT_KEYS = [\n\t\"data\",\n\t\"height\",\n\t\"name\",\n\t\"type\",\n\t\"useMap\",\n\t\"width\",\n\t\"validationMessage\",\n\t\"willValidate\",\n\t\"align\",\n\t\"archive\",\n\t\"border\",\n\t\"code\",\n\t\"codeBase\",\n\t\"codeType\",\n\t\"declare\",\n\t\"hspace\",\n\t\"standby\",\n\t\"vspace\",\n] as const satisfies readonly (keyof HTMLObjectElement)[];\nconst objectExtractor = withBase<HTMLObjectElement>(HTML_OBJECT_KEYS);\n\nconst HTML_OPTGROUP_KEYS = [\n\t\"disabled\",\n\t\"label\",\n] as const satisfies readonly (keyof HTMLOptGroupElement)[];\nconst optgroupExtractor = withBase<HTMLOptGroupElement>(HTML_OPTGROUP_KEYS);\n\nconst HTML_OPTION_KEYS = [\n\t\"defaultSelected\",\n\t\"disabled\",\n\t\"index\",\n\t\"label\",\n\t\"selected\",\n\t\"text\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLOptionElement)[];\nconst optionExtractor = withBase<HTMLOptionElement>(HTML_OPTION_KEYS);\n\nconst HTML_OUTPUT_KEYS = [\n\t\"defaultValue\",\n\t\"name\",\n\t\"type\",\n\t\"value\",\n\t\"htmlFor\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLOutputElement)[];\nconst outputExtractor = withBase<HTMLOutputElement>(HTML_OUTPUT_KEYS);\n\nconst HTML_PROGRESS_KEYS = [\n\t\"max\",\n\t\"position\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLProgressElement)[];\nconst progressExtractor = withBase<HTMLProgressElement>(HTML_PROGRESS_KEYS);\n\nconst HTML_QUOTE_KEYS = [\"cite\"] as const satisfies readonly (keyof HTMLQuoteElement)[];\nconst quoteExtractor = withBase<HTMLQuoteElement>(HTML_QUOTE_KEYS);\n\nconst citeExtractor = (elt: HTMLElement) => extractHTMLElementBase(elt);\n\nconst HTML_SCRIPT_KEYS = [\n\t\"async\",\n\t\"crossOrigin\",\n\t\"defer\",\n\t\"fetchPriority\",\n\t\"integrity\",\n\t\"noModule\",\n\t\"referrerPolicy\",\n\t\"src\",\n\t\"text\",\n\t\"type\",\n\t\"charset\",\n] as const satisfies readonly (keyof HTMLScriptElement)[];\nconst extractHTMLScriptOnly = createExtractor<HTMLScriptElement>()(HTML_SCRIPT_KEYS, {\n\tevent: (s) => (s as any).event,\n\thtmlFor: (s) => (s as any).htmlFor,\n});\nconst scriptExtractor = (elt: HTMLScriptElement) => ({\n\t...extractHTMLElementBase(elt),\n\t...extractHTMLScriptOnly(elt),\n});\n\nconst HTML_SELECT_KEYS = [\n\t\"autocomplete\",\n\t\"disabled\",\n\t\"length\",\n\t\"multiple\",\n\t\"name\",\n\t\"required\",\n\t\"selectedIndex\",\n\t\"size\",\n\t\"type\",\n\t\"value\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLSelectElement)[];\nconst selectExtractor = withBase<HTMLSelectElement>(HTML_SELECT_KEYS);\n\nconst HTML_SLOT_KEYS = [\"name\"] as const satisfies readonly (keyof HTMLSlotElement)[];\nconst slotExtractor = withBase<HTMLSlotElement>(HTML_SLOT_KEYS);\n\nconst HTML_SOURCE_KEYS = [\n\t\"height\",\n\t\"media\",\n\t\"sizes\",\n\t\"src\",\n\t\"srcset\",\n\t\"type\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLSourceElement)[];\nconst sourceExtractor = withBase<HTMLSourceElement>(HTML_SOURCE_KEYS);\n\nconst HTML_TABLE_CAPTION_KEYS = [\n\t\"align\",\n] as const satisfies readonly (keyof HTMLTableCaptionElement)[];\nconst tableCaptionExtractor = withBase<HTMLTableCaptionElement>(HTML_TABLE_CAPTION_KEYS);\n\nconst HTML_TABLE_CELL_KEYS = [\n\t\"abbr\",\n\t\"cellIndex\",\n\t\"colSpan\",\n\t\"headers\",\n\t\"rowSpan\",\n\t\"scope\",\n\t\"align\",\n\t\"axis\",\n\t\"bgColor\",\n\t\"ch\",\n\t\"chOff\",\n\t\"height\",\n\t\"noWrap\",\n\t\"vAlign\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableCellElement)[];\nconst tableCellExtractor = withBase<HTMLTableCellElement>(HTML_TABLE_CELL_KEYS);\n\nconst HTML_TABLE_COL_KEYS = [\n\t\"span\",\n\t\"align\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableColElement)[];\nconst tableColExtractor = withBase<HTMLTableColElement>(HTML_TABLE_COL_KEYS);\n\nconst HTML_TABLE_KEYS = [\n\t\"align\",\n\t\"bgColor\",\n\t\"border\",\n\t\"cellPadding\",\n\t\"cellSpacing\",\n\t\"frame\",\n\t\"rules\",\n\t\"summary\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableElement)[];\nconst tableExtractor = withBase<HTMLTableElement>(HTML_TABLE_KEYS);\n\nconst HTML_TR_KEYS = [\n\t\"rowIndex\",\n\t\"sectionRowIndex\",\n\t\"align\",\n\t\"bgColor\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n] as const satisfies readonly (keyof HTMLTableRowElement)[];\nconst tableRowExtractor = withBase<HTMLTableRowElement>(HTML_TR_KEYS);\n\nconst HTML_TSECTION_KEYS = [\n\t\"align\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n] as const satisfies readonly (keyof HTMLTableSectionElement)[];\nconst tableSectionExtractor = withBase<HTMLTableSectionElement>(HTML_TSECTION_KEYS);\n\nconst templateExtractor = (elt: HTMLTemplateElement) => extractHTMLElementBase(elt);\n\nconst HTML_TEXTAREA_KEYS = [\n\t\"autocomplete\",\n\t\"cols\",\n\t\"defaultValue\",\n\t\"dirName\",\n\t\"disabled\",\n\t\"maxLength\",\n\t\"minLength\",\n\t\"name\",\n\t\"placeholder\",\n\t\"readOnly\",\n\t\"required\",\n\t\"rows\",\n\t\"selectionDirection\",\n\t\"selectionEnd\",\n\t\"selectionStart\",\n\t\"value\",\n\t\"wrap\",\n\t\"textLength\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLTextAreaElement)[];\nconst textareaExtractor = withBase<HTMLTextAreaElement>(HTML_TEXTAREA_KEYS);\n\nconst HTML_TIME_KEYS = [\"dateTime\"] as const satisfies readonly (keyof HTMLTimeElement)[];\nconst timeExtractor = withBase<HTMLTimeElement>(HTML_TIME_KEYS);\n\nconst HTML_TRACK_KEYS = [\n\t\"default\",\n\t\"kind\",\n\t\"label\",\n\t\"readyState\",\n\t\"src\",\n\t\"srclang\",\n] as const satisfies readonly (keyof HTMLTrackElement)[];\nconst trackExtractor = withBase<HTMLTrackElement>(HTML_TRACK_KEYS);\n\nconst HTML_VIDEO_KEYS = [\n\t\"height\",\n\t\"poster\",\n\t\"videoHeight\",\n\t\"videoWidth\",\n\t\"width\",\n\t\"playsInline\",\n] as const satisfies readonly (keyof HTMLVideoElement)[];\nconst extractHTMLVideoOnly = createExtractor<HTMLVideoElement>()(HTML_VIDEO_KEYS);\nconst videoExtractor = (elt: HTMLVideoElement) => ({\n\t...mediaExtractor(elt),\n\t...extractHTMLVideoOnly(elt),\n});\n\nconst HTML_BR_KEYS = [\"clear\"] as const satisfies readonly (keyof HTMLBRElement)[];\nconst brExtractor = withBase<HTMLBRElement>(HTML_BR_KEYS);\n\nconst HTML_BASE_KEYS = [\"href\", \"target\"] as const satisfies readonly (keyof HTMLBaseElement)[];\nconst baseExtractor = withBase<HTMLBaseElement>(HTML_BASE_KEYS);\n\nconst HTML_BODY_KEYS = [\n\t\"aLink\",\n\t\"background\",\n\t\"bgColor\",\n\t\"link\",\n\t\"text\",\n\t\"vLink\",\n] as const satisfies readonly (keyof HTMLBodyElement)[];\nconst bodyExtractor = withBase<HTMLBodyElement>(HTML_BODY_KEYS);\n\nconst HTML_DLIST_KEYS = [\"compact\"] as const satisfies readonly (keyof HTMLDListElement)[];\nconst dlistExtractor = withBase<HTMLDListElement>(HTML_DLIST_KEYS);\n\nconst HTML_DETAILS_KEYS = [\"open\"] as const satisfies readonly (keyof HTMLDetailsElement)[];\nconst detailsExtractor = withBase<HTMLDetailsElement>(HTML_DETAILS_KEYS);\n\nconst HTML_DIALOG_KEYS = [\n\t\"open\",\n\t\"returnValue\",\n] as const satisfies readonly (keyof HTMLDialogElement)[];\nconst dialogExtractor = withBase<HTMLDialogElement>(HTML_DIALOG_KEYS);\n\nconst HTML_DIV_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLDivElement)[];\nconst divExtractor = withBase<HTMLDivElement>(HTML_DIV_KEYS);\n\nconst headExtractor = (elt: HTMLHeadElement) => extractHTMLElementBase(elt);\n\nconst HTML_HEADING_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLHeadingElement)[];\nconst headingExtractor = withBase<HTMLHeadingElement>(HTML_HEADING_KEYS);\n\nconst HTML_HR_KEYS = [\n\t\"align\",\n\t\"color\",\n\t\"noShade\",\n\t\"size\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLHRElement)[];\nconst hrExtractor = withBase<HTMLHRElement>(HTML_HR_KEYS);\n\nconst HTML_HTML_KEYS = [\"version\"] as const satisfies readonly (keyof HTMLHtmlElement)[];\nconst htmlExtractor = withBase<HTMLHtmlElement>(HTML_HTML_KEYS);\n\nconst menuExtractor = (elt: HTMLMenuElement) => extractHTMLElementBase(elt);\n\nconst HTML_META_KEYS = [\n\t\"content\",\n\t\"httpEquiv\",\n\t\"name\",\n\t\"scheme\",\n] as const satisfies readonly (keyof HTMLMetaElement)[];\nconst metaExtractor = withBase<HTMLMetaElement>(HTML_META_KEYS);\n\nconst HTML_P_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLParagraphElement)[];\nconst paragraphExtractor = withBase<HTMLParagraphElement>(HTML_P_KEYS);\n\nconst pictureExtractor = (elt: HTMLPictureElement) => extractHTMLElementBase(elt);\n\nconst HTML_PRE_KEYS = [\"width\"] as const satisfies readonly (keyof HTMLPreElement)[];\nconst preExtractor = withBase<HTMLPreElement>(HTML_PRE_KEYS);\n\nconst spanExtractor = (elt: HTMLSpanElement) => extractHTMLElementBase(elt);\n\nconst HTML_STYLE_KEYS = [\n\t\"media\",\n\t\"type\",\n\t\"disabled\",\n] as const satisfies readonly (keyof HTMLStyleElement)[];\nconst styleExtractor = withBase<HTMLStyleElement>(HTML_STYLE_KEYS);\n\nconst HTML_TITLE_KEYS = [\"text\"] as const satisfies readonly (keyof HTMLTitleElement)[];\nconst titleExtractor = withBase<HTMLTitleElement>(HTML_TITLE_KEYS);\n\nconst HTML_UL_KEYS = [\"compact\", \"type\"] as const satisfies readonly (keyof HTMLUListElement)[];\nconst ulistExtractor = withBase<HTMLUListElement>(HTML_UL_KEYS);\n\n// SVG element extractors\nfunction extractSVGElementBase(elt: SVGElement) {\n\treturn {\n\t\t...extractElementBase(elt),\n\t\t...extractHTMLOrSVGElement(elt as HTMLOrSVGElement),\n\t};\n}\n\n// Helper to compose per-SVG-element extractors with the shared base\nfunction withSVGBase<T extends SVGElement>(\n\tkeys: readonly (keyof T)[],\n\tcomputed?: Partial<Record<string, (src: T) => any>>,\n) {\n\tconst only = createExtractor<T>()(keys, computed as any);\n\treturn (elt: T) => ({ ...extractSVGElementBase(elt), ...only(elt) });\n}\n\nconst SVG_SVG_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"currentScale\",\n\t\"currentTranslate\",\n] as const satisfies readonly (keyof SVGSVGElement)[];\nconst svgExtractor = withSVGBase<SVGSVGElement>(SVG_SVG_KEYS);\n\nconst SVG_CIRCLE_KEYS = [\"cx\", \"cy\", \"r\"] as const satisfies readonly (keyof SVGCircleElement)[];\nconst circleExtractor = withSVGBase<SVGCircleElement>(SVG_CIRCLE_KEYS);\n\nconst SVG_ELLIPSE_KEYS = [\n\t\"cx\",\n\t\"cy\",\n\t\"rx\",\n\t\"ry\",\n] as const satisfies readonly (keyof SVGEllipseElement)[];\nconst ellipseExtractor = withSVGBase<SVGEllipseElement>(SVG_ELLIPSE_KEYS);\n\nconst SVG_LINE_KEYS = [\"x1\", \"y1\", \"x2\", \"y2\"] as const satisfies readonly (keyof SVGLineElement)[];\nconst lineExtractor = withSVGBase<SVGLineElement>(SVG_LINE_KEYS);\n\nconst SVG_PATH_KEYS = [\"pathLength\"] as const satisfies readonly (keyof SVGPathElement)[];\nconst pathExtractor = withSVGBase<SVGPathElement>(SVG_PATH_KEYS);\n\nconst SVG_RECT_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"rx\",\n\t\"ry\",\n] as const satisfies readonly (keyof SVGRectElement)[];\nconst rectExtractor = withSVGBase<SVGRectElement>(SVG_RECT_KEYS);\n\nconst SVG_POLYGON_KEYS = [\"points\"] as const satisfies readonly (keyof SVGPolygonElement)[];\nconst polygonExtractor = withSVGBase<SVGPolygonElement>(SVG_POLYGON_KEYS);\n\nconst SVG_POLYLINE_KEYS = [\"points\"] as const satisfies readonly (keyof SVGPolylineElement)[];\nconst polylineExtractor = withSVGBase<SVGPolylineElement>(SVG_POLYLINE_KEYS);\n\nconst SVG_TEXT_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"dx\",\n\t\"dy\",\n\t\"rotate\",\n\t\"textLength\",\n\t\"lengthAdjust\",\n] as const satisfies readonly (keyof SVGTextElement)[];\nconst textExtractor = withSVGBase<SVGTextElement>(SVG_TEXT_KEYS);\n\nconst SVG_TSPAN_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"dx\",\n\t\"dy\",\n\t\"rotate\",\n\t\"textLength\",\n\t\"lengthAdjust\",\n] as const satisfies readonly (keyof SVGTSpanElement)[];\nconst tspanExtractor = withSVGBase<SVGTSpanElement>(SVG_TSPAN_KEYS);\n\nconst SVG_IMAGE_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"href\",\n\t\"preserveAspectRatio\",\n\t\"crossOrigin\",\n] as const satisfies readonly (keyof SVGImageElement)[];\nconst svgImageExtractor = withSVGBase<SVGImageElement>(SVG_IMAGE_KEYS);\n\nconst SVG_USE_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"href\",\n] as const satisfies readonly (keyof SVGUseElement)[];\nconst useExtractor = withSVGBase<SVGUseElement>(SVG_USE_KEYS);\n\nconst SVG_DEFS_KEYS = [] as const satisfies readonly (keyof SVGDefsElement)[];\nconst defsExtractor = withSVGBase<SVGDefsElement>(SVG_DEFS_KEYS);\n\nconst SVG_GROUP_KEYS = [] as const satisfies readonly (keyof SVGGElement)[];\nconst gExtractor = withSVGBase<SVGGElement>(SVG_GROUP_KEYS);\n\nconst SVG_LINEAR_GRADIENT_KEYS = [\n\t\"x1\",\n\t\"y1\",\n\t\"x2\",\n\t\"y2\",\n\t\"gradientUnits\",\n\t\"gradientTransform\",\n\t\"spreadMethod\",\n] as const satisfies readonly (keyof SVGLinearGradientElement)[];\nconst linearGradientExtractor = withSVGBase<SVGLinearGradientElement>(SVG_LINEAR_GRADIENT_KEYS);\n\nconst SVG_RADIAL_GRADIENT_KEYS = [\n\t\"cx\",\n\t\"cy\",\n\t\"r\",\n\t\"fx\",\n\t\"fy\",\n\t\"fr\",\n\t\"gradientUnits\",\n\t\"gradientTransform\",\n\t\"spreadMethod\",\n] as const satisfies readonly (keyof SVGRadialGradientElement)[];\nconst radialGradientExtractor = withSVGBase<SVGRadialGradientElement>(SVG_RADIAL_GRADIENT_KEYS);\n\nconst SVG_STOP_KEYS = [\"offset\"] as const satisfies readonly (keyof SVGStopElement)[];\nconst stopExtractor = withSVGBase<SVGStopElement>(SVG_STOP_KEYS);\n\nconst SVG_PATTERN_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"patternUnits\",\n\t\"patternContentUnits\",\n\t\"patternTransform\",\n\t\"preserveAspectRatio\",\n\t\"href\",\n] as const satisfies readonly (keyof SVGPatternElement)[];\nconst patternExtractor = withSVGBase<SVGPatternElement>(SVG_PATTERN_KEYS);\n\nconst SVG_CLIP_PATH_KEYS = [\n\t\"clipPathUnits\",\n] as const satisfies readonly (keyof SVGClipPathElement)[];\nconst clipPathExtractor = withSVGBase<SVGClipPathElement>(SVG_CLIP_PATH_KEYS);\n\nconst SVG_MASK_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"maskUnits\",\n\t\"maskContentUnits\",\n] as const satisfies readonly (keyof SVGMaskElement)[];\nconst maskExtractor = withSVGBase<SVGMaskElement>(SVG_MASK_KEYS);\n\n// Map of tagName -> extractor (concise, like events.ts)\nconst elementExtractors: Record<string, (elt: any) => object> = {\n\tA: anchorExtractor,\n\tAREA: areaExtractor,\n\tAUDIO: audioExtractor,\n\tBASE: baseExtractor,\n\tBLOCKQUOTE: quoteExtractor,\n\tQ: quoteExtractor,\n\tBODY: bodyExtractor,\n\tBR: brExtractor,\n\tBUTTON: buttonExtractor,\n\tCANVAS: extractHTMLElementBase,\n\tCAPTION: tableCaptionExtractor,\n\tCITE: citeExtractor,\n\tCOL: tableColExtractor,\n\tCOLGROUP: tableColExtractor,\n\tDATA: dataExtractor,\n\tDETAILS: detailsExtractor,\n\tDIALOG: dialogExtractor,\n\tDIV: divExtractor,\n\tDL: dlistExtractor,\n\tEMBED: embedExtractor,\n\tFIELDSET: fieldsetExtractor,\n\tFORM: formExtractor,\n\tH1: headingExtractor,\n\tH2: headingExtractor,\n\tH3: headingExtractor,\n\tH4: headingExtractor,\n\tH5: headingExtractor,\n\tH6: headingExtractor,\n\tHEAD: headExtractor,\n\tHR: hrExtractor,\n\tHTML: htmlExtractor,\n\tIFRAME: iframeExtractor,\n\tIMG: imageExtractor,\n\tINPUT: inputExtractor,\n\tLABEL: labelExtractor,\n\tLI: liExtractor,\n\tLINK: linkExtractor,\n\tMAP: mapExtractor,\n\tMENU: menuExtractor,\n\tMETA: metaExtractor,\n\tMETER: meterExtractor,\n\tINS: modExtractor,\n\tDEL: modExtractor,\n\tOBJECT: objectExtractor,\n\tOL: olistExtractor,\n\tOPTGROUP: optgroupExtractor,\n\tOPTION: optionExtractor,\n\tOUTPUT: outputExtractor,\n\tP: paragraphExtractor,\n\tPICTURE: pictureExtractor,\n\tPRE: preExtractor,\n\tPROGRESS: progressExtractor,\n\tSCRIPT: scriptExtractor,\n\tSELECT: selectExtractor,\n\tSLOT: slotExtractor,\n\tSOURCE: sourceExtractor,\n\tSPAN: spanExtractor,\n\tSTYLE: styleExtractor,\n\tTABLE: tableExtractor,\n\tTBODY: tableSectionExtractor,\n\tTHEAD: tableSectionExtractor,\n\tTFOOT: tableSectionExtractor,\n\tTD: tableCellExtractor,\n\tTH: tableCellExtractor,\n\tTEMPLATE: templateExtractor,\n\tTEXTAREA: textareaExtractor,\n\tTIME: timeExtractor,\n\tTITLE: titleExtractor,\n\tTR: tableRowExtractor,\n\tTRACK: trackExtractor,\n\tUL: ulistExtractor,\n\tVIDEO: videoExtractor,\n\t// SVG elements\n\tSVG: svgExtractor,\n\tCIRCLE: circleExtractor,\n\tELLIPSE: ellipseExtractor,\n\tLINE: lineExtractor,\n\tPATH: pathExtractor,\n\tRECT: rectExtractor,\n\tPOLYGON: polygonExtractor,\n\tPOLYLINE: polylineExtractor,\n\tTEXT: textExtractor,\n\tTSPAN: tspanExtractor,\n\tIMAGE: svgImageExtractor,\n\tUSE: useExtractor,\n\tDEFS: defsExtractor,\n\tG: gExtractor,\n\tLINEARGRADIENT: linearGradientExtractor,\n\tRADIALGRADIENT: radialGradientExtractor,\n\tSTOP: stopExtractor,\n\tPATTERN: patternExtractor,\n\tCLIPPATH: clipPathExtractor,\n\tMASK: maskExtractor,\n};\n\nexport function extractHTMLElement(elt: HTMLElement): object {\n\tconst tagName = elt.tagName.toUpperCase();\n\n\tconst extractor = elementExtractors[tagName];\n\tif (extractor) {\n\t\treturn extractor(elt);\n\t}\n\tthrow new Error(`Unexpected HTML element tag: ${elt.tagName} (update .web/custom/serialize.ts)`);\n}\n\nexport function extractSVGElement(elt: SVGElement): object {\n\tconst tagName = elt.tagName.toUpperCase();\n\n\tconst extractor = elementExtractors[tagName];\n\tif (extractor) {\n\t\treturn extractor(elt);\n\t}\n\t// Fallback to base SVG element extractor for unknown SVG elements\n\treturn extractSVGElementBase(elt);\n}\n\nexport function extractElement(elt: Element): object {\n\tif (elt instanceof HTMLElement) {\n\t\treturn extractHTMLElement(elt);\n\t}\n\tif (elt instanceof SVGElement) {\n\t\treturn extractSVGElement(elt);\n\t}\n\t// Fallback for other Element types - use base element extractor\n\treturn extractElementBase(elt);\n}\n","/* === IMPORTANT === */\n\nimport type { MouseEvent, PointerEvent, SyntheticEvent, UIEvent } from \"react\";\nimport { extractElement } from \"./elements\";\nimport { createExtractor } from \"./extractor\";\n\n// Reusable computed mappers (helps bundlers/minifiers share references)\nconst mapTarget = (e: { target: EventTarget | null }) => extractElement(e.target as Element);\nconst mapRelated = (e: { relatedTarget: EventTarget | null }) =>\n\te.relatedTarget ? extractElement(e.relatedTarget as Element) : null;\n\nfunction makeExtractor<K extends readonly any[]>(\n\tkeys: K,\n\tcomputed?: Record<string, (evt: any) => any>,\n) {\n\treturn createExtractor<any>()(\n\t\tkeys as any,\n\t\t{\n\t\t\ttarget: mapTarget,\n\t\t\t...(computed || {}),\n\t\t} as any,\n\t);\n}\n\nconst SYNTHETIC_KEYS = [\n\t\"target\",\n\t\"bubbles\",\n\t\"cancelable\",\n\t\"defaultPrevented\",\n\t\"eventPhase\",\n\t\"isTrusted\",\n\t\"timeStamp\",\n\t\"type\",\n] as const satisfies readonly (keyof SyntheticEvent)[];\n\nconst UI_KEYS = [...SYNTHETIC_KEYS, \"detail\"] as const satisfies readonly (keyof UIEvent)[];\n\nconst MOUSE_KEYS = [\n\t...UI_KEYS,\n\t\"altKey\",\n\t\"button\",\n\t\"buttons\",\n\t\"clientX\",\n\t\"clientY\",\n\t\"ctrlKey\",\n\t\"metaKey\",\n\t\"movementX\",\n\t\"movementY\",\n\t\"pageX\",\n\t\"pageY\",\n\t\"screenX\",\n\t\"screenY\",\n\t\"shiftKey\",\n] as const satisfies readonly (keyof MouseEvent)[];\n\nconst POINTER_KEYS = [\n\t...MOUSE_KEYS,\n\t\"pointerId\",\n\t\"pressure\",\n\t\"tangentialPressure\",\n\t\"tiltX\",\n\t\"tiltY\",\n\t\"twist\",\n\t\"width\",\n\t\"height\",\n\t\"pointerType\",\n\t\"isPrimary\",\n] as const satisfies readonly (keyof PointerEvent)[];\n\nconst syntheticExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst uiExtractor = makeExtractor(UI_KEYS);\n\nconst mouseExtractor = makeExtractor(MOUSE_KEYS, { relatedTarget: mapRelated });\n\nconst clipboardExtractor = makeExtractor(SYNTHETIC_KEYS, {\n\tclipboardData: (e) => extractDataTransfer(e.clipboardData),\n});\n\nconst compositionExtractor = makeExtractor([...SYNTHETIC_KEYS, \"data\"] as const);\n\nconst dragExtractor = makeExtractor(MOUSE_KEYS, {\n\trelatedTarget: mapRelated,\n\tdataTransfer: (e) => extractDataTransfer(e.dataTransfer),\n});\n\nconst pointerExtractor = makeExtractor(POINTER_KEYS, {\n\trelatedTarget: mapRelated,\n});\n\nconst focusExtractor = makeExtractor(SYNTHETIC_KEYS, {\n\trelatedTarget: mapRelated,\n});\n\nconst formExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst invalidExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst changeExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst keyboardExtractor = makeExtractor([\n\t...UI_KEYS,\n\t\"altKey\",\n\t\"ctrlKey\",\n\t\"code\",\n\t\"key\",\n\t\"locale\",\n\t\"location\",\n\t\"metaKey\",\n\t\"repeat\",\n\t\"shiftKey\",\n] as const);\n\nconst touchExtractor = makeExtractor(\n\t[\n\t\t...UI_KEYS,\n\t\t\"altKey\",\n\t\t\"ctrlKey\",\n\t\t\"metaKey\",\n\t\t\"shiftKey\",\n\t\t\"changedTouches\",\n\t\t\"targetTouches\",\n\t\t\"touches\",\n\t] as const,\n\t{\n\t\tchangedTouches: (e) => mapTouchList(e.changedTouches),\n\t\ttargetTouches: (e) => mapTouchList(e.targetTouches),\n\t\ttouches: (e) => mapTouchList(e.touches),\n\t},\n);\n\nconst wheelExtractor = makeExtractor(\n\t[...MOUSE_KEYS, \"deltaMode\", \"deltaX\", \"deltaY\", \"deltaZ\"] as const,\n\t{\n\t\trelatedTarget: mapRelated,\n\t},\n);\n\nconst animationExtractor = makeExtractor([\n\t...SYNTHETIC_KEYS,\n\t\"animationName\",\n\t\"elapsedTime\",\n\t\"pseudoElement\",\n] as const);\n\nconst toggleExtractor = makeExtractor([...SYNTHETIC_KEYS, \"oldState\", \"newState\"] as const);\n\nconst transitionExtractor = makeExtractor([\n\t...SYNTHETIC_KEYS,\n\t\"elapsedTime\",\n\t\"propertyName\",\n\t\"pseudoElement\",\n] as const);\n\nfunction mapTouchList(list: any): any[] {\n\treturn Array.from(list as ArrayLike<any>).map((touch: any) => ({\n\t\ttarget: extractElement(touch.target as Element),\n\t\tidentifier: touch.identifier,\n\t\tscreenX: touch.screenX,\n\t\tscreenY: touch.screenY,\n\t\tclientX: touch.clientX,\n\t\tclientY: touch.clientY,\n\t\tpageX: touch.pageX,\n\t\tpageY: touch.pageY,\n\t}));\n}\n\n// Helper function to extract DataTransfer properties\nfunction extractDataTransfer(dt: DataTransfer | null): object | null {\n\tif (!dt) {\n\t\treturn null;\n\t}\n\tconst items = [];\n\tif (dt.items) {\n\t\tfor (let i = 0; i < dt.items.length; i++) {\n\t\t\tconst item = dt.items[i]!;\n\t\t\titems.push({\n\t\t\t\tkind: item.kind,\n\t\t\t\ttype: item.type,\n\t\t\t});\n\t\t}\n\t}\n\treturn {\n\t\tdrop_effect: dt.dropEffect,\n\t\teffect_allowed: dt.effectAllowed,\n\t\titems: items,\n\t\ttypes: Array.from(dt.types || []),\n\t};\n}\n\nconst eventExtractorMap: { [key: string]: (evt: any) => object } = {};\n\nfunction add(map: Record<string, any>, names: readonly string[], fn: any) {\n\tfor (const n of names) map[n] = fn;\n}\n\nadd(\n\teventExtractorMap,\n\t[\n\t\t\"pointerdown\",\n\t\t\"pointermove\",\n\t\t\"pointerup\",\n\t\t\"pointercancel\",\n\t\t\"gotpointercapture\",\n\t\t\"lostpointercapture\",\n\t\t\"pointerenter\",\n\t\t\"pointerleave\",\n\t\t\"pointerover\",\n\t\t\"pointerout\",\n\t],\n\tpointerExtractor,\n);\n\nadd(\n\teventExtractorMap,\n\t[\n\t\t\"click\",\n\t\t\"contextmenu\",\n\t\t\"dblclick\",\n\t\t\"mousedown\",\n\t\t\"mouseenter\",\n\t\t\"mouseleave\",\n\t\t\"mousemove\",\n\t\t\"mouseout\",\n\t\t\"mouseover\",\n\t\t\"mouseup\",\n\t],\n\tmouseExtractor,\n);\n\nadd(\n\teventExtractorMap,\n\t[\"drag\", \"dragend\", \"dragenter\", \"dragexit\", \"dragleave\", \"dragover\", \"dragstart\", \"drop\"],\n\tdragExtractor,\n);\n\nadd(eventExtractorMap, [\"keydown\", \"keypress\", \"keyup\"], keyboardExtractor);\nadd(eventExtractorMap, [\"focus\", \"blur\"], focusExtractor);\nadd(eventExtractorMap, [\"change\", \"input\"], changeExtractor);\nadd(eventExtractorMap, [\"invalid\"], invalidExtractor);\nadd(eventExtractorMap, [\"reset\", \"submit\"], formExtractor);\nadd(eventExtractorMap, [\"copy\", \"cut\", \"paste\"], clipboardExtractor);\nadd(\n\teventExtractorMap,\n\t[\"compositionend\", \"compositionstart\", \"compositionupdate\"],\n\tcompositionExtractor,\n);\nadd(eventExtractorMap, [\"touchcancel\", \"touchend\", \"touchmove\", \"touchstart\"], touchExtractor);\nadd(eventExtractorMap, [\"scroll\"], uiExtractor);\nadd(eventExtractorMap, [\"wheel\"], wheelExtractor);\nadd(\n\teventExtractorMap,\n\t[\"animationstart\", \"animationend\", \"animationiteration\"],\n\tanimationExtractor,\n);\nadd(eventExtractorMap, [\"transitionend\"], transitionExtractor);\nadd(eventExtractorMap, [\"toggle\"], toggleExtractor);\n\nexport function extractEvent(value: any): any {\n\t// Duck-typing for React's SyntheticEvent.\n\t// We check for properties that are unique to synthetic events.\n\tif (\n\t\tvalue &&\n\t\ttypeof value === \"object\" &&\n\t\t\"nativeEvent\" in value &&\n\t\ttypeof value.isDefaultPrevented === \"function\"\n\t) {\n\t\tconst evt = value as SyntheticEvent;\n\t\t// The `type` property is crucial for the lookup.\n\t\tif (typeof evt.type !== \"string\") {\n\t\t\treturn value;\n\t\t}\n\n\t\tconst extractor = eventExtractorMap[evt.type.toLowerCase()];\n\t\tif (extractor) {\n\t\t\treturn extractor(evt);\n\t\t}\n\n\t\t// Fallback for unknown event types: minimal synthetic extractor\n\t\treturn syntheticExtractor(evt);\n\t}\n\n\t// If it's not a duck-typed event, return it as is.\n\treturn value;\n}\n","export type Primitive = number | string | boolean | null | undefined;\nexport type JSON<T> = T | Array<JSON<T>> | { [K: string]: JSON<T> };\nexport type PlainJSON = JSON<Primitive>;\nexport type Serializable = any;\n\nexport type Serialized = [[number[], number[], number[], number[]], PlainJSON];\n\nexport function serialize(data: Serializable): Serialized {\n\tconst seen = new Map<any, number>();\n\tconst refs: number[] = [];\n\tconst dates: number[] = [];\n\tconst sets: number[] = [];\n\tconst maps: number[] = [];\n\n\t// Single global counter - increments once per node visit\n\tlet globalIndex = 0;\n\n\tfunction process(value: Serializable, context?: string): PlainJSON {\n\t\tif (value == null || typeof value === \"string\" || typeof value === \"boolean\") {\n\t\t\treturn value;\n\t\t}\n\n\t\tif (typeof value === \"number\") {\n\t\t\tif (Number.isNaN(value)) {\n\t\t\t\tconst ctx = context ? ` in '${context}'` : \"\";\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot serialize NaN${ctx}. NaN and Infinity are not supported because they cannot be serialized to JSON.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tconst kind = value > 0 ? \"Infinity\" : \"-Infinity\";\n\t\t\t\tconst ctx = context ? ` in '${context}'` : \"\";\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot serialize ${kind}${ctx}. NaN and Infinity are not supported because they cannot be serialized to JSON.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\tconst idx = globalIndex++;\n\t\tconst prevRef = seen.get(value);\n\t\tif (prevRef !== undefined) {\n\t\t\t// Make sure to push the current index, but use the ref's index as the value!\n\t\t\trefs.push(idx);\n\t\t\treturn prevRef;\n\t\t}\n\n\t\tseen.set(value, idx);\n\n\t\tif (value instanceof Date) {\n\t\t\tdates.push(idx);\n\t\t\treturn value.getTime();\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tconst length = value.length;\n\t\t\tconst result = new Array(length);\n\t\t\tfor (let i = 0; i < length; i++) {\n\t\t\t\tresult[i] = process(value[i], context);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tif (value instanceof Map) {\n\t\t\tmaps.push(idx);\n\t\t\tconst rec: Record<string, any> = {};\n\t\t\tfor (const [key, entry] of value.entries()) {\n\t\t\t\trec[String(key)] = process(entry, String(key));\n\t\t\t}\n\t\t\treturn rec;\n\t\t}\n\n\t\tif (value instanceof Set) {\n\t\t\tsets.push(idx);\n\t\t\tconst size = value.size;\n\t\t\tconst result = new Array(size);\n\t\t\tlet i = 0;\n\t\t\tfor (const entry of value) {\n\t\t\t\tresult[i] = process(entry, context);\n\t\t\t\ti += 1;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tif (typeof value === \"object\") {\n\t\t\tconst rec: Record<string, any> = {};\n\t\t\tconst keys = Object.keys(value);\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\trec[key] = process(value[key], key);\n\t\t\t}\n\t\t\treturn rec;\n\t\t}\n\n\t\tthrow new Error(`Unsupported value in serialization: ${value}`);\n\t}\n\n\tconst payload = process(data);\n\treturn [[refs, dates, sets, maps], payload];\n}\n\nexport interface DeserializationOptions {\n\tcoerceNullsToUndefined?: boolean;\n}\n\nexport function deserialize<Data extends Serializable = Serializable>(\n\tpayload: Serialized,\n\toptions?: DeserializationOptions,\n): Data {\n\tconst [[refsA, datesA, setsA, mapsA], data] = payload;\n\n\tconst refs = new Set(refsA);\n\tconst dates = new Set(datesA);\n\tconst sets = new Set(setsA);\n\tconst maps = new Set(mapsA);\n\n\tconst objects: Array<any> = [];\n\n\tfunction reconstruct(value: PlainJSON): any {\n\t\tconst idx = objects.length;\n\t\tif (refs.has(idx)) {\n\t\t\t// We increment the counter on refs during serialization. We're never\n\t\t\t// going to use this entry, so we can just push null.\n\t\t\tobjects.push(null);\n\t\t\treturn objects[value as number];\n\t\t}\n\n\t\tif (dates.has(idx)) {\n\t\t\tconst dt = new Date(value as number);\n\t\t\tobjects.push(dt);\n\t\t\treturn dt;\n\t\t}\n\n\t\tif (\n\t\t\tvalue == null ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\ttypeof value === \"string\" ||\n\t\t\ttypeof value === \"boolean\"\n\t\t) {\n\t\t\tif (options?.coerceNullsToUndefined) {\n\t\t\t\treturn value ?? undefined;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tif (sets.has(idx)) {\n\t\t\t\tconst result = new Set();\n\t\t\t\tobjects.push(result);\n\t\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\t\tresult.add(reconstruct(value[i]));\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tconst length = value.length;\n\t\t\tconst arr = new Array(length);\n\t\t\tobjects.push(arr);\n\t\t\tfor (let i = 0; i < length; i++) {\n\t\t\t\tarr[i] = reconstruct(value[i]);\n\t\t\t}\n\t\t\treturn arr;\n\t\t}\n\n\t\tif (typeof value === \"object\") {\n\t\t\tif (maps.has(idx)) {\n\t\t\t\tconst result = new Map<string, any>();\n\t\t\t\tobjects.push(result);\n\t\t\t\tconst keys = Object.keys(value);\n\t\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\t\tconst key = keys[i];\n\t\t\t\t\tresult.set(key, reconstruct(value[key]));\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tconst result: Record<string, any> = {};\n\t\t\tobjects.push(result);\n\t\t\tconst keys = Object.keys(value);\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tresult[key] = reconstruct(value[key]);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tthrow new Error(`Unsupported value in deserialization: ${value}`);\n\t}\n\n\treturn reconstruct(data);\n}\n","import type { NavigateFunction } from \"react-router\";\nimport { io, type Socket } from \"socket.io-client\";\nimport { ChannelBridge, PulseChannelResetError } from \"./channel\";\nimport type { RouteInfo } from \"./helpers\";\nimport type {\n\tClientApiResultMessage,\n\tClientJsResultMessage,\n\tClientMessage,\n\tServerApiCallMessage,\n\tServerChannelMessage,\n\tServerErrorInfo,\n\tServerJsExecMessage,\n\tServerMessage,\n} from \"./messages\";\nimport type { PulsePrerenderView } from \"./pulse\";\nimport { extractEvent } from \"./serialize/events\";\nimport { deserialize, serialize } from \"./serialize/serializer\";\nimport type { VDOMUpdate } from \"./vdom\";\n\nexport interface SocketIODirectives {\n\theaders?: Record<string, string>;\n\tauth?: Record<string, string>;\n}\nexport interface Directives {\n\theaders?: Record<string, string>;\n\tsocketio?: SocketIODirectives;\n}\nexport interface MountedView {\n\trouteInfo: RouteInfo;\n\tonInit: (view: PulsePrerenderView) => void;\n\tonUpdate: (ops: VDOMUpdate[]) => void;\n\tonJsExec?: (msg: ServerJsExecMessage) => void;\n}\nexport type ConnectionStatus = \"ok\" | \"connecting\" | \"reconnecting\" | \"error\";\nexport type ConnectionStatusListener = (status: ConnectionStatus) => void;\nexport type ServerErrorListener = (path: string, error: ServerErrorInfo | null) => void;\n\nexport interface PulseClient {\n\t// Connection management\n\tconnect(): Promise<void>;\n\tdisconnect(): void;\n\tisConnected(): boolean;\n\tonConnectionChange(listener: ConnectionStatusListener): () => void;\n\t// Messages\n\tnavigate(path: string, routeInfo: RouteInfo): Promise<void>;\n\tleave(path: string): Promise<void>;\n\tinvokeCallback(path: string, callback: string, args: any[]): Promise<void>;\n\t// VDOM subscription\n\tmountView(path: string, view: MountedView): () => void;\n}\n\nexport class PulseSocketIOClient {\n\t#activeViews: Map<string, MountedView>;\n\t#socket: Socket | null = null;\n\t#messageQueue: ClientMessage[];\n\t#connectionListeners: Set<ConnectionStatusListener> = new Set();\n\t#serverErrors: Map<string, ServerErrorInfo> = new Map();\n\t#serverErrorListeners: Set<ServerErrorListener> = new Set();\n\t#channels: Map<string, { bridge: ChannelBridge; refCount: number }> = new Map();\n\t#url: string;\n\t#frameworkNavigate: NavigateFunction;\n\t#directives: Directives;\n\t#connectionStatusConfig: {\n\t\tinitialConnectingDelay: number;\n\t\tinitialErrorDelay: number;\n\t\treconnectErrorDelay: number;\n\t};\n\t#hasConnectedOnce: boolean = false;\n\t#connectingTimeout: ReturnType<typeof setTimeout> | null = null;\n\t#errorTimeout: ReturnType<typeof setTimeout> | null = null;\n\t#currentStatus: ConnectionStatus = \"ok\";\n\n\tconstructor(\n\t\turl: string,\n\t\tdirectives: Directives,\n\t\tframeworkNavigate: NavigateFunction,\n\t\tconnectionStatusConfig: {\n\t\t\tinitialConnectingDelay: number;\n\t\t\tinitialErrorDelay: number;\n\t\t\treconnectErrorDelay: number;\n\t\t},\n\t) {\n\t\tthis.#url = url;\n\t\tthis.#directives = directives;\n\t\tthis.#frameworkNavigate = frameworkNavigate;\n\t\tthis.#socket = null;\n\t\tthis.#activeViews = new Map();\n\t\tthis.#messageQueue = [];\n\t\tthis.#connectionStatusConfig = connectionStatusConfig;\n\t\t// Load directives from sessionStorage\n\t\tif (typeof window !== \"undefined\" && typeof sessionStorage !== \"undefined\") {\n\t\t\tconst stored = sessionStorage.getItem(\"__PULSE_DIRECTIVES\");\n\t\t\tif (stored) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.#directives = JSON.parse(stored);\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore parse errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tpublic setDirectives(directives: Directives) {\n\t\tthis.#directives = directives;\n\t}\n\tpublic isConnected(): boolean {\n\t\treturn this.#socket?.connected ?? false;\n\t}\n\n\t#clearTimeouts(): void {\n\t\tif (this.#connectingTimeout) {\n\t\t\tclearTimeout(this.#connectingTimeout);\n\t\t\tthis.#connectingTimeout = null;\n\t\t}\n\t\tif (this.#errorTimeout) {\n\t\t\tclearTimeout(this.#errorTimeout);\n\t\t\tthis.#errorTimeout = null;\n\t\t}\n\t}\n\n\t#setStatus(status: ConnectionStatus): void {\n\t\tthis.#clearTimeouts();\n\t\tthis.#currentStatus = status;\n\t\tthis.#notifyConnectionListeners(status);\n\t}\n\n\t#handleConnected(): void {\n\t\tthis.#hasConnectedOnce = true;\n\t\tthis.#setStatus(\"ok\");\n\t}\n\n\t#setInitialConnectionStatus(): void {\n\t\t// Initial connection attempt - start with no message, then show connecting after delay\n\t\tthis.#setStatus(\"ok\");\n\t\tthis.#connectingTimeout = setTimeout(() => {\n\t\t\tthis.#setStatus(\"connecting\");\n\t\t\tthis.#errorTimeout = setTimeout(() => {\n\t\t\t\tthis.#setStatus(\"error\");\n\t\t\t}, this.#connectionStatusConfig.initialErrorDelay);\n\t\t}, this.#connectionStatusConfig.initialConnectingDelay);\n\t}\n\n\t#handleDisconnected(): void {\n\t\t// Reconnection after losing connection - show reconnecting immediately\n\t\tthis.#setStatus(\"reconnecting\");\n\t\tthis.#errorTimeout = setTimeout(() => {\n\t\t\tthis.#setStatus(\"error\");\n\t\t}, this.#connectionStatusConfig.reconnectErrorDelay);\n\t}\n\n\tpublic async connect(): Promise<void> {\n\t\tif (this.#socket) {\n\t\t\treturn;\n\t\t}\n\t\t// Start timing logic for connection attempt\n\t\tif (!this.#hasConnectedOnce) {\n\t\t\tthis.#setInitialConnectionStatus();\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst socket = io(this.#url, {\n\t\t\t\ttransports: [\"websocket\", \"webtransport\"],\n\t\t\t\tauth: this.#directives.socketio?.auth,\n\t\t\t\textraHeaders: this.#directives.socketio?.headers,\n\t\t\t});\n\t\t\tthis.#socket = socket;\n\n\t\t\tsocket.on(\"connect\", () => {\n\t\t\t\tconsole.log(\"[SocketIOTransport] Connected:\", this.#socket?.id);\n\t\t\t\t// Make sure to send a navigate payload for all the routes\n\t\t\t\tfor (const [path, route] of this.#activeViews) {\n\t\t\t\t\tsocket.emit(\n\t\t\t\t\t\t\"message\",\n\t\t\t\t\t\tserialize({\n\t\t\t\t\t\t\ttype: \"mount\",\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\trouteInfo: route.routeInfo,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tfor (const payload of this.#messageQueue) {\n\t\t\t\t\t// Already sent above\n\t\t\t\t\tif (payload.type === \"mount\" && this.#activeViews.has(payload.path)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// We're remounting all the routes, so no need to navigate\n\t\t\t\t\tif (payload.type === \"navigate\") {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tsocket.emit(\"message\", serialize(payload));\n\t\t\t\t}\n\t\t\t\tthis.#messageQueue = [];\n\n\t\t\t\tthis.#handleConnected();\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tsocket.on(\"connect_error\", (err) => {\n\t\t\t\tconsole.error(\"[SocketIOTransport] Connection failed:\", err);\n\t\t\t\tthis.#handleDisconnected();\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tsocket.on(\"disconnect\", () => {\n\t\t\t\tconsole.log(\"[SocketIOTransport] Disconnected\");\n\t\t\t\tthis.#handleTransportDisconnect();\n\t\t\t\tthis.#handleDisconnected();\n\t\t\t});\n\n\t\t\t// Wrap in an arrow function to avoid losing the `this` reference\n\t\t\tsocket.on(\"message\", (data) =>\n\t\t\t\tthis.#handleServerMessage(deserialize(data, { coerceNullsToUndefined: true })),\n\t\t\t);\n\t\t});\n\t}\n\n\tonConnectionChange(listener: ConnectionStatusListener): () => void {\n\t\tthis.#connectionListeners.add(listener);\n\t\t// Notify immediately with current status\n\t\tlistener(this.#currentStatus);\n\t\treturn () => {\n\t\t\tthis.#connectionListeners.delete(listener);\n\t\t};\n\t}\n\n\t#notifyConnectionListeners(status: ConnectionStatus): void {\n\t\tfor (const listener of this.#connectionListeners) {\n\t\t\tlistener(status);\n\t\t}\n\t}\n\n\tpublic onServerError(listener: ServerErrorListener): () => void {\n\t\tthis.#serverErrorListeners.add(listener);\n\t\t// Emit current errors to new listener\n\t\tfor (const [path, err] of this.#serverErrors) listener(path, err);\n\t\treturn () => {\n\t\t\tthis.#serverErrorListeners.delete(listener);\n\t\t};\n\t}\n\n\t#notifyServerError(path: string, error: ServerErrorInfo | null) {\n\t\tfor (const listener of this.#serverErrorListeners) listener(path, error);\n\t}\n\n\tpublic sendMessage(payload: ClientMessage) {\n\t\tif (this.isConnected()) {\n\t\t\t// console.log(\"[SocketIOTransport] Sending:\", payload);\n\t\t\tthis.#socket!.emit(\"message\", serialize(payload as any));\n\t\t} else {\n\t\t\t// console.log(\"[SocketIOTransport] Queuing message:\", payload);\n\t\t\tthis.#messageQueue.push(payload);\n\t\t}\n\t}\n\n\tpublic mountView(path: string, view: MountedView) {\n\t\tif (this.#activeViews.has(path)) {\n\t\t\tthrow new Error(`Path ${path} is already mounted`);\n\t\t}\n\t\tthis.#activeViews.set(path, view);\n\t\tvoid this.sendMessage({\n\t\t\ttype: \"mount\",\n\t\t\tpath,\n\t\t\trouteInfo: view.routeInfo,\n\t\t});\n\t}\n\n\tpublic navigate(path: string, routeInfo: RouteInfo) {\n\t\tthis.sendMessage({\n\t\t\ttype: \"navigate\",\n\t\t\tpath,\n\t\t\trouteInfo,\n\t\t});\n\t}\n\n\tpublic unmount(path: string) {\n\t\tvoid this.sendMessage({ type: \"unmount\", path });\n\t\tthis.#activeViews.delete(path);\n\t}\n\n\tpublic disconnect() {\n\t\tthis.#clearTimeouts();\n\t\tthis.#socket?.disconnect();\n\t\tthis.#socket = null;\n\t\tthis.#messageQueue = [];\n\t\tthis.#connectionListeners.clear();\n\t\tthis.#activeViews.clear();\n\t\tthis.#serverErrors.clear();\n\t\tthis.#serverErrorListeners.clear();\n\t\tfor (const { bridge } of this.#channels.values()) {\n\t\t\tbridge.dispose(new PulseChannelResetError(\"Client disconnected\"));\n\t\t}\n\t\tthis.#channels.clear();\n\t\tthis.#currentStatus = \"ok\";\n\t\tthis.#hasConnectedOnce = false;\n\t}\n\n\t#handleServerMessage(message: ServerMessage) {\n\t\t// console.log(\"[PulseClient] Received message:\", message);\n\t\tswitch (message.type) {\n\t\t\tcase \"vdom_init\": {\n\t\t\t\tconst route = this.#activeViews.get(message.path);\n\t\t\t\t// Ignore messages for paths that are not mounted\n\t\t\t\tif (!route) return;\n\t\t\t\tif (route) {\n\t\t\t\t\troute.onInit(message);\n\t\t\t\t}\n\t\t\t\t// Clear any prior error for this path on successful init\n\t\t\t\tif (this.#serverErrors.has(message.path)) {\n\t\t\t\t\tthis.#serverErrors.delete(message.path);\n\t\t\t\t\tthis.#notifyServerError(message.path, null);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"vdom_update\": {\n\t\t\t\tconst route = this.#activeViews.get(message.path);\n\t\t\t\tif (!route) return; // Not an active path; discard\n\t\t\t\troute.onUpdate(message.ops);\n\t\t\t\t// Clear any prior error for this path on successful update\n\t\t\t\tif (this.#serverErrors.has(message.path)) {\n\t\t\t\t\tthis.#serverErrors.delete(message.path);\n\t\t\t\t\tthis.#notifyServerError(message.path, null);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"server_error\": {\n\t\t\t\tif (!this.#activeViews.has(message.path)) return; // discard for inactive paths\n\t\t\t\tthis.#serverErrors.set(message.path, message.error);\n\t\t\t\tthis.#notifyServerError(message.path, message.error);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"api_call\": {\n\t\t\t\tvoid this.#performApiCall(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"navigate_to\": {\n\t\t\t\t// `navigate_to` is navigational; allow regardless of activeViews membership\n\t\t\t\tconst replace = !!message.replace;\n\t\t\t\tlet dest = message.path || \"\";\n\t\t\t\t// Normalize protocol-relative URLs to absolute\n\t\t\t\tif (dest.startsWith(\"//\")) dest = `${window.location.protocol}${dest}`;\n\t\t\t\tconst hasScheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(dest);\n\t\t\t\tif (hasScheme) {\n\t\t\t\t\tif (dest.startsWith(\"http://\") || dest.startsWith(\"https://\")) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst url = new URL(dest);\n\t\t\t\t\t\t\tif (url.origin === window.location.origin) {\n\t\t\t\t\t\t\t\tconst internal = `${url.pathname}${url.search}${url.hash}`;\n\t\t\t\t\t\t\t\tthis.#frameworkNavigate(internal, { replace });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (replace) window.location.replace(dest);\n\t\t\t\t\t\t\t\telse window.location.assign(dest);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (replace) window.location.replace(dest);\n\t\t\t\t\t\t\telse window.location.assign(dest);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// mailto:, tel:, data:, etc.\n\t\t\t\t\t\tif (replace) window.location.replace(dest);\n\t\t\t\t\t\telse window.location.assign(dest);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Relative or root-relative path → SPA navigate\n\t\t\t\t\tthis.#frameworkNavigate(dest, { replace });\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"channel_message\": {\n\t\t\t\tthis.#routeChannelMessage(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"js_exec\": {\n\t\t\t\tthis.#handleJsExec(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(\"Unexpected message:\", message);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #performApiCall(msg: ServerApiCallMessage) {\n\t\ttry {\n\t\t\tconst res = await fetch(msg.url, {\n\t\t\t\tmethod: msg.method || \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\t...(msg.headers || {}),\n\t\t\t\t\t...(msg.body != null && !(\"content-type\" in (msg.headers || {}))\n\t\t\t\t\t\t? { \"content-type\": \"application/json\" }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t\tbody:\n\t\t\t\t\tmsg.body != null\n\t\t\t\t\t\t? typeof msg.body === \"string\"\n\t\t\t\t\t\t\t? msg.body\n\t\t\t\t\t\t\t: JSON.stringify(msg.body)\n\t\t\t\t\t\t: undefined,\n\t\t\t\tcredentials: msg.credentials || \"include\",\n\t\t\t});\n\t\t\tconst headersObj: Record<string, string> = {};\n\t\t\tres.headers.forEach((v, k) => {\n\t\t\t\theadersObj[k] = v;\n\t\t\t});\n\t\t\tlet body: any = null;\n\t\t\tconst ct = res.headers.get(\"content-type\") || \"\";\n\t\t\tif (ct.includes(\"application/json\")) {\n\t\t\t\tbody = await res.json().catch(() => null);\n\t\t\t} else {\n\t\t\t\tbody = await res.text().catch(() => null);\n\t\t\t}\n\t\t\tconst reply: ClientApiResultMessage = {\n\t\t\t\ttype: \"api_result\",\n\t\t\t\tid: msg.id,\n\t\t\t\tok: res.ok,\n\t\t\t\tstatus: res.status,\n\t\t\t\theaders: headersObj,\n\t\t\t\tbody,\n\t\t\t};\n\t\t\tthis.sendMessage(reply);\n\t\t} catch (err) {\n\t\t\tconst reply: ClientApiResultMessage = {\n\t\t\t\ttype: \"api_result\",\n\t\t\t\tid: msg.id,\n\t\t\t\tok: false,\n\t\t\t\tstatus: 0,\n\t\t\t\theaders: {},\n\t\t\t\tbody: { error: String(err) },\n\t\t\t};\n\t\t\tthis.sendMessage(reply);\n\t\t}\n\t}\n\n\tpublic invokeCallback(path: string, callback: string, args: any[]) {\n\t\tthis.sendMessage({\n\t\t\ttype: \"callback\",\n\t\t\tpath,\n\t\t\tcallback,\n\t\t\targs: args.map(extractEvent),\n\t\t});\n\t}\n\n\t#handleJsExec(message: ServerJsExecMessage) {\n\t\tconst view = this.#activeViews.get(message.path);\n\t\tif (!view?.onJsExec) {\n\t\t\t// No handler registered - execute anyway and send result back\n\t\t\t// This shouldn't happen in practice as views should register handlers\n\t\t\tconsole.warn(`[Pulse] No onJsExec handler for path: ${message.path}`);\n\t\t\tthis.#sendJsResult(message.id, undefined, \"No JS executor registered\");\n\t\t\treturn;\n\t\t}\n\t\tview.onJsExec(message);\n\t}\n\n\tpublic sendJsResult(id: string, result: any, error: string | null) {\n\t\tthis.#sendJsResult(id, result, error);\n\t}\n\n\t#sendJsResult(id: string, result: any, error: string | null) {\n\t\tconst msg: ClientJsResultMessage = {\n\t\t\ttype: \"js_result\",\n\t\t\tid,\n\t\t\tresult,\n\t\t\terror,\n\t\t};\n\t\tthis.sendMessage(msg);\n\t}\n\n\tpublic acquireChannel(id: string): ChannelBridge {\n\t\tconst entry = this.#ensureChannelEntry(id);\n\t\tentry.refCount += 1;\n\t\treturn entry.bridge;\n\t}\n\n\tpublic releaseChannel(id: string): void {\n\t\tconst entry = this.#channels.get(id);\n\t\tif (!entry) {\n\t\t\treturn;\n\t\t}\n\t\tentry.refCount = Math.max(0, entry.refCount - 1);\n\t\tif (entry.refCount === 0) {\n\t\t\tentry.bridge.dispose(new PulseChannelResetError(\"Channel released\"));\n\t\t\tthis.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: id,\n\t\t\t\tevent: \"__close__\",\n\t\t\t\tpayload: { reason: \"refcount_zero\" },\n\t\t\t});\n\t\t\tthis.#channels.delete(id);\n\t\t}\n\t}\n\n\t#ensureChannelEntry(id: string): {\n\t\tbridge: ChannelBridge;\n\t\trefCount: number;\n\t} {\n\t\tlet entry = this.#channels.get(id);\n\t\tif (!entry) {\n\t\t\tentry = {\n\t\t\t\tbridge: new ChannelBridge(this, id),\n\t\t\t\trefCount: 0,\n\t\t\t};\n\t\t\tthis.#channels.set(id, entry);\n\t\t}\n\t\treturn entry;\n\t}\n\n\t#routeChannelMessage(message: ServerChannelMessage): void {\n\t\tconst entry = this.#ensureChannelEntry(message.channel);\n\t\tconst closed = entry.bridge.handleServerMessage(message);\n\t\tif (closed && entry.refCount === 0) {\n\t\t\tthis.#channels.delete(message.channel);\n\t\t}\n\t}\n\n\t#handleTransportDisconnect(): void {\n\t\tfor (const entry of this.#channels.values()) {\n\t\t\tentry.bridge.handleDisconnect(new PulseChannelResetError(\"Connection lost\"));\n\t\t}\n\t}\n}\n","import type { ComponentType } from \"react\";\n\n// Special prefixes for reserved node types\nexport const FRAGMENT_TAG = \"$$fragment\";\nexport const MOUNT_POINT_PREFIX = \"$$\";\n\n// export type LazyComponent = () => Promise<{ default: ComponentType<any> }>;\nexport type RegistryEntry = ComponentType<any>;\nexport type ComponentRegistry = Record<string, ComponentType<any>>;\n\nexport interface VDOMElement {\n\ttag: string;\n\tprops?: Record<string, any>;\n\tchildren?: VDOMNode[];\n\tkey?: string;\n\tlazy?: boolean;\n}\n\n// Primitive nodes that can be rendered\nexport type PrimitiveNode = string | number | boolean;\n\n// VDOMNode is either a primitive (string, number, boolean) or an element node.\n// Booleans are valid children in React but do not render anything.\n// Mount points are just UIElementNodes with tags starting with $$ComponentKey\nexport type VDOMNode = PrimitiveNode | VDOMElement;\n\nexport type VDOM = VDOMNode;\n\nexport interface VDOMUpdateBase {\n\ttype: string;\n\tpath: string; // Dot-separated path to the node\n}\n\nexport interface ReplaceUpdate extends VDOMUpdateBase {\n\ttype: \"replace\";\n\tdata: VDOMNode; // The new node\n}\n\nexport interface UpdatePropsUpdate extends VDOMUpdateBase {\n\ttype: \"update_props\";\n\tdata: {\n\t\tset?: Record<string, any>;\n\t\tremove?: string[];\n\t};\n}\n\nexport interface ReconciliationUpdate {\n\ttype: \"reconciliation\";\n\tpath: string;\n\tN: number;\n\tnew: [number[], VDOM[]];\n\treuse: [number[], number[]];\n}\n\nexport interface PathDelta {\n\tadd?: string[];\n\tremove?: string[];\n}\n\nexport interface UpdateCallbacksUpdate extends VDOMUpdateBase {\n\ttype: \"update_callbacks\";\n\tdata: PathDelta;\n}\n\nexport interface UpdateRenderPropsUpdate extends VDOMUpdateBase {\n\ttype: \"update_render_props\";\n\tdata: PathDelta;\n}\n\nexport interface UpdateJsExprPathsUpdate extends VDOMUpdateBase {\n\ttype: \"update_jsexpr_paths\";\n\tdata: PathDelta;\n}\n\nexport type VDOMUpdate =\n\t| ReplaceUpdate\n\t| UpdatePropsUpdate\n\t| ReconciliationUpdate\n\t| UpdateCallbacksUpdate\n\t| UpdateRenderPropsUpdate\n\t| UpdateJsExprPathsUpdate;\n\nexport type UpdateType = VDOMUpdate[\"type\"];\n\n// Utility functions for working with the UI tree structure\nexport function isElementNode(node: VDOMNode): node is VDOMElement {\n\t// Matches all non-text nodes\n\treturn typeof node === \"object\" && node !== null;\n}\n\nexport function isMountPointNode(node: VDOMNode): node is VDOMElement {\n\treturn (\n\t\ttypeof node === \"object\" &&\n\t\tnode !== null &&\n\t\tnode.tag.startsWith(MOUNT_POINT_PREFIX) &&\n\t\tnode.tag !== FRAGMENT_TAG\n\t);\n}\n\nexport function isTextNode(node: VDOMNode): node is string {\n\treturn typeof node === \"string\";\n}\n\nexport function isFragment(node: VDOMNode): boolean {\n\treturn typeof node === \"object\" && node !== null && node.tag === FRAGMENT_TAG;\n}\n","import {\n\ttype ComponentType,\n\tcloneElement,\n\tcreateElement,\n\ttype FC,\n\tFragment,\n\tisValidElement,\n\tlazy,\n\ttype PropsWithChildren,\n\ttype ReactElement,\n\ttype ReactNode,\n\tSuspense,\n} from \"react\";\nimport type { PulseSocketIOClient } from \"./client\";\nimport type { PulsePrerenderView } from \"./pulse\";\nimport type { ComponentRegistry, PathDelta, VDOMNode, VDOMUpdate } from \"./vdom\";\nimport { FRAGMENT_TAG, isElementNode, isMountPointNode, MOUNT_POINT_PREFIX } from \"./vdom\";\n\n// Prefix for JSExpr values - code is embedded after the colon\nconst JSEXPR_PREFIX = \"$js:\";\n\nexport class VDOMRenderer {\n\t#callbacks: Set<string>;\n\t#callbackCache: Map<string, (...args: any) => void>;\n\t#renderPropKeys: Set<string>;\n\t#jsexprPaths: Set<string>; // paths containing JS expressions\n\t#callbackList: string[];\n\t#client: PulseSocketIOClient;\n\t#path: string;\n\t#registry: Record<string, unknown>;\n\n\tconstructor(\n\t\tclient: PulseSocketIOClient,\n\t\tpath: string,\n\t\tinitialCallbacks: string[] = [],\n\t\tinitialRenderProps: string[] = [],\n\t\tregistry: Record<string, unknown> = {},\n\t\tinitialJsExprPaths: string[] = [],\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#path = path;\n\t\tthis.#registry = registry;\n\t\tthis.#callbacks = new Set(initialCallbacks);\n\t\tthis.#callbackCache = new Map();\n\t\tthis.#renderPropKeys = new Set(initialRenderProps);\n\t\tthis.#jsexprPaths = new Set(initialJsExprPaths);\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\t}\n\n\t/**\n\t * Get an object from the unified registry by its key (e.g., \"Button_1\").\n\t */\n\tgetObject(key: string): unknown {\n\t\tconst obj = this.#registry[key];\n\t\tif (obj === undefined) {\n\t\t\tthrow new Error(`[Pulse] Unknown registry key: ${key}`);\n\t\t}\n\t\treturn obj;\n\t}\n\n\t/**\n\t * Evaluate a JSExpr code string.\n\t * The code is expected to use get_object('key') calls to retrieve values from the registry.\n\t */\n\tevaluateJsExpr(code: string): unknown {\n\t\t// Create the get_object function that the code will call\n\t\tconst get_object = (key: string) => this.getObject(key);\n\t\t// Use Function constructor to avoid direct eval\n\t\t// The code is trusted (generated server-side) and uses get_object to access values\n\t\treturn new Function(\"get_object\", `return ${code}`)(get_object);\n\t}\n\n\t// Accessors used by update logic to determine which props need rebinding\n\thasCallbackPath(path: string) {\n\t\treturn this.#callbacks.has(path);\n\t}\n\n\thasRenderPropPath(path: string) {\n\t\treturn this.#renderPropKeys.has(path);\n\t}\n\n\thasAnyCallbackUnder(prefix: string): boolean {\n\t\tif (prefix === \"\") return this.#callbackList.length > 0;\n\t\tconst i = this.#lowerBound(this.#callbackList, prefix);\n\t\treturn i < this.#callbackList.length && this.#callbackList[i]!.startsWith(prefix);\n\t}\n\n\tapplyCallbackDelta(delta: PathDelta) {\n\t\t// Only update the internal callback path registry and cache. We rely on\n\t\t// accompanying update_props operations that contain the \"$cb\" placeholder\n\t\t// to trigger prop updates; transformValue will resolve to functions.\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#callbacks.delete(key);\n\t\t\t\tthis.#callbackCache.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#callbacks.add(key);\n\t\t\t}\n\t\t}\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\t}\n\n\tapplyRenderPropsDelta(delta: PathDelta) {\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#renderPropKeys.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#renderPropKeys.add(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tapplyJsExprPathsDelta(delta: PathDelta) {\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#jsexprPaths.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#jsexprPaths.add(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCallback(path: string, prop: string) {\n\t\tconst key = this.#propPath(path, prop);\n\t\tlet fn = this.#callbackCache.get(key);\n\t\tif (!fn) {\n\t\t\tfn = (...args: any[]) => this.#client.invokeCallback(this.#path, key, args);\n\t\t\tthis.#callbackCache.set(key, fn);\n\t\t}\n\t\treturn fn;\n\t}\n\n\trenderNode(node: VDOMNode, currentPath = \"\"): ReactNode {\n\t\t// Handle primitives early\n\t\tif (\n\t\t\tnode == null || // catches both null and undefined\n\t\t\ttypeof node === \"boolean\" ||\n\t\t\ttypeof node === \"number\"\n\t\t) {\n\t\t\treturn node;\n\t\t}\n\n\t\t// Check for JSExpr - \"$js:code\" format has code embedded in the value\n\t\tif (typeof node === \"string\") {\n\t\t\tif (node.startsWith(JSEXPR_PREFIX)) {\n\t\t\t\tconst jsExprCode = node.slice(JSEXPR_PREFIX.length);\n\t\t\t\treturn this.evaluateJsExpr(jsExprCode) as ReactNode;\n\t\t\t}\n\t\t\treturn node;\n\t\t}\n\n\t\t// Element nodes\n\t\tif (isElementNode(node)) {\n\t\t\tconst { tag, props = {}, children = [] } = node;\n\n\t\t\tconst newProps: Record<string, any> = {};\n\t\t\tfor (const [propName, propValue] of Object.entries(props)) {\n\t\t\t\tnewProps[propName] = this.transformValue(currentPath, propName, propValue);\n\t\t\t}\n\n\t\t\tif (node.key) {\n\t\t\t\tnewProps.key = node.key;\n\t\t\t}\n\n\t\t\tconst renderedChildren = [];\n\t\t\tfor (let index = 0; index < children.length; index += 1) {\n\t\t\t\tconst child = children[index]!;\n\t\t\t\tconst childPath = currentPath ? `${currentPath}.${index}` : String(index);\n\t\t\t\trenderedChildren.push(this.renderNode(child, childPath));\n\t\t\t}\n\n\t\t\tif (isMountPointNode(node)) {\n\t\t\t\tconst componentKey = node.tag.slice(MOUNT_POINT_PREFIX.length);\n\t\t\t\tconst Component = this.#registry[componentKey] as ComponentRegistry[string];\n\t\t\t\tif (!Component) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Could not find component ${componentKey}. This is a Pulse internal error.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn createElement(Component, newProps, ...renderedChildren);\n\t\t\t}\n\n\t\t\treturn createElement(tag === FRAGMENT_TAG ? Fragment : tag, newProps, ...renderedChildren);\n\t\t}\n\n\t\t// Fallback for unknown node types\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.error(\"Unknown VDOM node type:\", node);\n\t\t}\n\t\treturn null;\n\t}\n\n\t#propPath(path: string, prop: string) {\n\t\treturn path ? `${path}.${prop}` : prop;\n\t}\n\n\ttransformValue(path: string, key: string, value: any) {\n\t\tconst propPath = this.#propPath(path, key);\n\t\tif (this.#callbacks.has(propPath)) {\n\t\t\treturn this.getCallback(path, key);\n\t\t}\n\t\tif (this.#renderPropKeys.has(propPath)) {\n\t\t\treturn this.renderNode(value, propPath);\n\t\t}\n\t\t// Check for JSExpr - \"$js:code\" format has code embedded in the value\n\t\tif (typeof value === \"string\" && value.startsWith(JSEXPR_PREFIX)) {\n\t\t\tconst jsExprCode = value.slice(JSEXPR_PREFIX.length);\n\t\t\treturn this.evaluateJsExpr(jsExprCode);\n\t\t}\n\t\treturn value;\n\t}\n\n\tinit(view: PulsePrerenderView): ReactNode {\n\t\t// Set callbacks\n\t\tthis.#callbacks = new Set(view.callbacks);\n\t\t// prune stale cached callbacks\n\t\tfor (const k of Array.from(this.#callbackCache.keys())) {\n\t\t\tif (!this.#callbacks.has(k)) this.#callbackCache.delete(k);\n\t\t}\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\n\t\t// Set render props\n\t\tthis.#renderPropKeys = new Set(view.render_props);\n\n\t\t// Set JSExpr paths\n\t\tthis.#jsexprPaths = new Set(view.jsexpr_paths);\n\n\t\treturn this.renderNode(view.vdom);\n\t}\n\n\t#ensureChildrenArray(el: ReactElement): ReactNode[] {\n\t\tconst children = (el.props as any)?.children as ReactNode | undefined;\n\t\tif (children == null) return [];\n\t\treturn Array.isArray(children) ? children.slice() : [children];\n\t}\n\n\tapplyUpdates(initialTree: ReactNode, updates: VDOMUpdate[]): ReactNode {\n\t\tlet newTree: ReactNode = initialTree;\n\t\tfor (const update of updates) {\n\t\t\tif (update.type === \"update_callbacks\") {\n\t\t\t\tthis.applyCallbackDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (update.type === \"update_render_props\") {\n\t\t\t\tthis.applyRenderPropsDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (update.type === \"update_jsexpr_paths\") {\n\t\t\t\tthis.applyJsExprPathsDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst parts = update.path.split(\".\").filter((s) => s.length > 0);\n\n\t\t\tconst descend = (node: ReactNode, depth: number, path: string): ReactNode => {\n\t\t\t\tif (depth < parts.length) {\n\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\tconst element = node as ReactElement<Record<string, any> | null>;\n\t\t\t\t\tconst childKey = parts[depth]!;\n\t\t\t\t\tconst childIdx = +childKey;\n\t\t\t\t\tconst childPath = path ? `${path}.${childKey}` : childKey;\n\t\t\t\t\tif (!Number.isNaN(childIdx)) {\n\t\t\t\t\t\t// Regular child traversal\n\t\t\t\t\t\tconst childrenArr = this.#ensureChildrenArray(element);\n\t\t\t\t\t\tconst child = childrenArr[childIdx];\n\t\t\t\t\t\tchildrenArr[childIdx] = descend(child, depth + 1, childPath) as any;\n\t\t\t\t\t\treturn cloneElement(element, undefined, ...childrenArr);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Render prop traversal\n\t\t\t\t\t\tconst baseProps = (element.props ?? {}) as Record<string, any>;\n\t\t\t\t\t\tconst child = baseProps[childKey];\n\t\t\t\t\t\tconst props = {\n\t\t\t\t\t\t\t...baseProps,\n\t\t\t\t\t\t\t[childKey]: descend(child, depth + 1, childPath),\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn cloneElement(element, props);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch (update.type) {\n\t\t\t\t\tcase \"replace\": {\n\t\t\t\t\t\treturn this.renderNode(update.data, update.path);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update_props\": {\n\t\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\t\tconst element = node as ReactElement;\n\t\t\t\t\t\tconst currentProps = (element.props ?? {}) as Record<string, any>;\n\t\t\t\t\t\tconst nextProps: Record<string, any> = { ...currentProps };\n\t\t\t\t\t\tconst delta = update.data;\n\t\t\t\t\t\tif (delta.remove && delta.remove.length > 0) {\n\t\t\t\t\t\t\tfor (const key of delta.remove) {\n\t\t\t\t\t\t\t\tif (key in nextProps) {\n\t\t\t\t\t\t\t\t\tdelete nextProps[key];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (delta.set) {\n\t\t\t\t\t\t\tfor (const [k, v] of Object.entries(delta.set)) {\n\t\t\t\t\t\t\t\tnextProps[k] = this.transformValue(path, k, v);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If some props were removed, use `createElement` to fully override\n\t\t\t\t\t\t// the props, as `cloneElement` shallowly merges the new props with\n\t\t\t\t\t\t// the old ones.\n\t\t\t\t\t\tconst removedSomething = (delta.remove?.length ?? 0) > 0;\n\t\t\t\t\t\tif (removedSomething) {\n\t\t\t\t\t\t\t// Preserve key + ref\n\t\t\t\t\t\t\tnextProps.key = element.key;\n\t\t\t\t\t\t\tnextProps.ref = (element as any).ref;\n\t\t\t\t\t\t\treturn createElement(element.type, nextProps, ...this.#ensureChildrenArray(element));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Don't touch children. Key and ref are transferred by cloneElement.\n\t\t\t\t\t\t\treturn cloneElement(element, nextProps);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase \"reconciliation\": {\n\t\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\t\tconst element = node as ReactElement;\n\t\t\t\t\t\tconst prevChildren = this.#ensureChildrenArray(element);\n\t\t\t\t\t\tconst nextChildren = [];\n\n\t\t\t\t\t\tconst [newIndices, newContents] = update.new;\n\t\t\t\t\t\tconst [reuseIndices, reuseSources] = update.reuse;\n\n\t\t\t\t\t\tlet nextNew = -1,\n\t\t\t\t\t\t\tnextReuse = -1,\n\t\t\t\t\t\t\tnewIdx = -1,\n\t\t\t\t\t\t\treuseIdx = -1;\n\t\t\t\t\t\tif (newIndices.length > 0) {\n\t\t\t\t\t\t\tnextNew = newIndices[0];\n\t\t\t\t\t\t\tnewIdx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (reuseIndices.length > 0) {\n\t\t\t\t\t\t\tnextReuse = reuseIndices[0];\n\t\t\t\t\t\t\treuseIdx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let i = 0; i < update.N; ++i) {\n\t\t\t\t\t\t\tif (i === nextNew) {\n\t\t\t\t\t\t\t\tconst contents = newContents[newIdx];\n\t\t\t\t\t\t\t\tconst childPath = path ? `${path}.${i}` : String(i);\n\t\t\t\t\t\t\t\tnextChildren.push(this.renderNode(contents, childPath));\n\t\t\t\t\t\t\t\tnextNew = newIdx < newIndices.length - 1 ? newIndices[++newIdx] : -1;\n\t\t\t\t\t\t\t} else if (i === nextReuse) {\n\t\t\t\t\t\t\t\tconst srcIdx = reuseSources[reuseIdx];\n\t\t\t\t\t\t\t\tlet src = prevChildren[srcIdx];\n\t\t\t\t\t\t\t\tconst childPath = path ? `${path}.${i}` : String(i);\n\t\t\t\t\t\t\t\t// The node may have callbacks that need to be updated for this new path\n\t\t\t\t\t\t\t\tif (this.hasAnyCallbackUnder(childPath)) {\n\t\t\t\t\t\t\t\t\tsrc = this.#rebindCallbacksInSubtree(src, childPath);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tnextChildren.push(src);\n\t\t\t\t\t\t\t\tnextReuse = reuseIdx < reuseIndices.length - 1 ? reuseIndices[++reuseIdx] : -1;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// No need to rebind callbacks, the node hasn't moved\n\t\t\t\t\t\t\t\tnextChildren.push(prevChildren[i]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Pass null to reuse previous props\n\t\t\t\t\t\treturn cloneElement(element, null!, ...nextChildren);\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(`[Pulse renderer] Unknown update type: ${(update as any)?.type}`);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tnewTree = descend(newTree, 0, \"\");\n\t\t}\n\t\treturn newTree;\n\t}\n\n\t#assertIsElement(node: ReactNode, parts: string[], depth: number): node is ReactElement {\n\t\tif (process.env.NODE_ENV !== \"production\" && !isValidElement(node)) {\n\t\t\tconsole.error(\"Invalid node:\", node);\n\t\t\tthrow new Error(`Invalid node at path ${parts.slice(0, depth).join(\".\")}`);\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Rebind callback function props within a subtree after a path-changing move\n\t#rebindCallbacksInSubtree(node: ReactNode, path: string): ReactNode {\n\t\tif (!isValidElement(node)) return node;\n\t\tconst element = node as ReactElement<Record<string, any> | null>;\n\t\tconst baseProps = (element.props ?? {}) as Record<string, any>;\n\t\tconst nextProps: Record<string, any> = { ...baseProps };\n\n\t\t// Rebind only callback props; CSS refs are path-agnostic and render-props\n\t\t// are handled by the server-side renderer via explicit updates\n\t\tfor (const key of Object.keys(baseProps)) {\n\t\t\tconst propPath = path ? `${path}.${key}` : key;\n\t\t\tif (this.hasCallbackPath(propPath)) {\n\t\t\t\tnextProps[key] = this.getCallback(path, key);\n\t\t\t}\n\t\t\tif (this.hasRenderPropPath(propPath) && this.hasAnyCallbackUnder(propPath)) {\n\t\t\t\tnextProps[key] = this.#rebindCallbacksInSubtree(baseProps[key], propPath);\n\t\t\t}\n\t\t}\n\n\t\tconst children = this.#ensureChildrenArray(element).map((child, idx) => {\n\t\t\tconst childPath = path ? `${path}.${idx}` : String(idx);\n\t\t\tif (this.hasAnyCallbackUnder(childPath)) {\n\t\t\t\treturn this.#rebindCallbacksInSubtree(child, childPath);\n\t\t\t} else {\n\t\t\t\treturn child;\n\t\t\t}\n\t\t});\n\n\t\treturn cloneElement(element, nextProps, ...children);\n\t}\n\n\t// Binary-search lower bound for prefix matching on sorted callback paths\n\t#lowerBound(arr: string[], target: string): number {\n\t\tlet lo = 0;\n\t\tlet hi = arr.length;\n\t\twhile (lo < hi) {\n\t\t\tconst mid = (lo + hi) >>> 1;\n\t\t\tif (arr[mid]! < target) {\n\t\t\t\tlo = mid + 1;\n\t\t\t} else {\n\t\t\t\thi = mid;\n\t\t\t}\n\t\t}\n\t\treturn lo;\n\t}\n}\n\n// The `component` prop should be something like `() =>\n// import('~/path/to/component') (we'll need to remap if we're importing a named export and not the default)\nexport function RenderLazy(\n\tcomponent: () => Promise<{ default: ComponentType<any> }>,\n\tfallback?: ReactNode,\n): FC<PropsWithChildren<unknown>> {\n\tconst Component = lazy(component);\n\treturn ({ children, ...props }: PropsWithChildren<unknown>) => {\n\t\treturn (\n\t\t\t<Suspense fallback={fallback}>\n\t\t\t\t<Component {...props}>{children}</Component>\n\t\t\t</Suspense>\n\t\t);\n\t};\n}\n","import {\n\tcreateContext,\n\ttype ReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { useLocation, useNavigate, useParams } from \"react-router\";\nimport { type ConnectionStatus, type Directives, PulseSocketIOClient } from \"./client\";\nimport type { RouteInfo } from \"./helpers\";\nimport type { ServerErrorInfo } from \"./messages\";\nimport { VDOMRenderer } from \"./renderer\";\nimport type { VDOM } from \"./vdom\";\n\n// =================================================================\n// Types\n// =================================================================\n\nexport interface ConnectionStatusConfig {\n\tinitialConnectingDelay: number;\n\tinitialErrorDelay: number;\n\treconnectErrorDelay: number;\n}\n\nexport interface PulseConfig {\n\tserverAddress: string;\n\tconnectionStatus: ConnectionStatusConfig;\n}\n\nexport type PulsePrerenderView = {\n\tvdom: VDOM;\n\tcallbacks: string[];\n\trender_props: string[];\n\tjsexpr_paths: string[]; // paths containing JS expressions\n};\n\nexport type PulsePrerender = {\n\tviews: Record<string, PulsePrerenderView>;\n\tdirectives: Directives;\n};\n// =================================================================\n// Context and Hooks\n// =================================================================\n\n// Context for the client, provided by PulseProvider\nconst PulseClientContext = createContext<PulseSocketIOClient | null>(null);\nconst PulsePrerenderContext = createContext<PulsePrerender | null>(null);\n\nexport const usePulseClient = () => {\n\tconst client = useContext(PulseClientContext);\n\tif (!client) {\n\t\tthrow new Error(\"usePulseClient must be used within a PulseProvider\");\n\t}\n\treturn client;\n};\n\nexport const usePulsePrerender = (path: string) => {\n\tconst ctx = useContext(PulsePrerenderContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"usePulsePrerender must be used within a PulseProvider\");\n\t}\n\tconst view = ctx.views[path];\n\tif (!view) {\n\t\tthrow new Error(`No prerender found for '${path}'`);\n\t}\n\treturn view;\n};\n\n// =================================================================\n// Provider\n// =================================================================\n\nexport interface PulseProviderProps {\n\tchildren: ReactNode;\n\tconfig: PulseConfig;\n\tprerender: PulsePrerender;\n}\n\nconst inBrowser = typeof window !== \"undefined\";\n\nexport function PulseProvider({ children, config, prerender }: PulseProviderProps) {\n\tconst [status, setStatus] = useState<ConnectionStatus>(\"ok\");\n\tconst rrNavigate = useNavigate();\n\tconst { directives } = prerender;\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: another useEffect syncs the directives without recreating the client\n\tconst client = useMemo(() => {\n\t\treturn new PulseSocketIOClient(\n\t\t\tconfig.serverAddress,\n\t\t\tdirectives,\n\t\t\trrNavigate,\n\t\t\tconfig.connectionStatus,\n\t\t);\n\t}, [config.serverAddress, rrNavigate, config.connectionStatus]);\n\tuseEffect(() => client.setDirectives(directives), [client, directives]);\n\n\tuseEffect(() => {\n\t\tif (!inBrowser) return;\n\n\t\tconst handleConnectionChange = (newStatus: ConnectionStatus) => {\n\t\t\tsetStatus(newStatus);\n\t\t};\n\n\t\tconst unsubscribe = client.onConnectionChange(handleConnectionChange);\n\n\t\t// Start connection attempt\n\t\tclient.connect();\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tclient.disconnect();\n\t\t};\n\t}, [client]);\n\n\tconst getStatusMessage = () => {\n\t\tswitch (status) {\n\t\t\tcase \"connecting\":\n\t\t\t\treturn \"Connecting...\";\n\t\t\tcase \"reconnecting\":\n\t\t\t\treturn \"Reconnecting...\";\n\t\t\tcase \"error\":\n\t\t\t\treturn \"Failed to connect to the server.\";\n\t\t\t// \"ok\" falls through to default\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t};\n\n\tconst statusMessage = getStatusMessage();\n\n\treturn (\n\t\t<PulseClientContext.Provider value={client}>\n\t\t\t<PulsePrerenderContext.Provider value={prerender}>\n\t\t\t\t{statusMessage && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: \"fixed\",\n\t\t\t\t\t\t\tbottom: \"20px\",\n\t\t\t\t\t\t\tright: \"20px\",\n\t\t\t\t\t\t\tbackgroundColor: status === \"error\" ? \"red\" : \"#666\",\n\t\t\t\t\t\t\tcolor: \"white\",\n\t\t\t\t\t\t\tpadding: \"10px\",\n\t\t\t\t\t\t\tborderRadius: \"5px\",\n\t\t\t\t\t\t\tzIndex: 1000,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{statusMessage}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{children}\n\t\t\t</PulsePrerenderContext.Provider>\n\t\t</PulseClientContext.Provider>\n\t);\n}\n\n// =================================================================\n// View\n// =================================================================\n\nexport interface PulseViewProps {\n\tpath: string;\n\tregistry: Record<string, unknown>;\n}\n\nexport function PulseView({ path, registry }: PulseViewProps) {\n\tconst client = usePulseClient();\n\tconst initialView = usePulsePrerender(path);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: We only want to lose the renderer on unmount. initialView will change on every navigation with our current setup, so we hack around it with another useEffect below. This is not ideal and will be fixed in the future.\n\tconst renderer = useMemo(\n\t\t() =>\n\t\t\tnew VDOMRenderer(\n\t\t\t\tclient,\n\t\t\t\tpath,\n\t\t\t\tinitialView.callbacks,\n\t\t\t\tinitialView.render_props,\n\t\t\t\tregistry,\n\t\t\t\tinitialView.jsexpr_paths,\n\t\t\t),\n\t\t[client, path, registry],\n\t);\n\tconst [tree, setTree] = useState<ReactNode>(() => renderer.init(initialView));\n\tconst [serverError, setServerError] = useState<ServerErrorInfo | null>(null);\n\n\tconst location = useLocation();\n\tconst params = useParams();\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: using hacky deep equality for params\n\tconst routeInfo = useMemo(() => {\n\t\tconst { \"*\": catchall = \"\", ...pathParams } = params;\n\t\tconst queryParams = new URLSearchParams(location.search);\n\t\treturn {\n\t\t\thash: location.hash,\n\t\t\tpathname: location.pathname,\n\t\t\tquery: location.search,\n\t\t\tqueryParams: Object.fromEntries(queryParams.entries()),\n\t\t\tpathParams,\n\t\t\tcatchall: catchall.length > 0 ? catchall.split(\"/\") : [],\n\t\t} satisfies RouteInfo;\n\t}, [location.hash, location.pathname, location.search, JSON.stringify(params)]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: We don't want to unmount on navigation, so another useEffect sync the routeInfo on navigation.\n\tuseEffect(() => {\n\t\tif (inBrowser) {\n\t\t\tclient.mountView(path, {\n\t\t\t\trouteInfo,\n\t\t\t\tonInit: (view) => {\n\t\t\t\t\tsetTree(renderer.init(view));\n\t\t\t\t},\n\t\t\t\tonUpdate: (ops) => {\n\t\t\t\t\tsetTree((prev) => (prev == null ? prev : renderer.applyUpdates(prev, ops)));\n\t\t\t\t},\n\t\t\t\tonJsExec: (msg) => {\n\t\t\t\t\tlet result: any;\n\t\t\t\t\tlet error: string | null = null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = renderer.evaluateJsExpr(msg.code);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\terror = e instanceof Error ? e.message : String(e);\n\t\t\t\t\t}\n\t\t\t\t\tclient.sendJsResult(msg.id, result, error);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst offErr = client.onServerError((p, err) => {\n\t\t\t\tif (p === path) setServerError(err);\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\toffErr();\n\t\t\t\tclient.unmount(path);\n\t\t\t};\n\t\t}\n\t\t// routeInfo is NOT included here on purpose\n\t}, [client, renderer, path]);\n\n\tuseEffect(() => {\n\t\tif (inBrowser) {\n\t\t\tclient.navigate(path, routeInfo);\n\t\t}\n\t}, [client, path, routeInfo]);\n\t// Hack for our current prerendering setup on client-side navigation. Will be improved soon\n\tconst hasRendered = useRef(false);\n\tuseEffect(() => {\n\t\t// First rendering pass, no need to update the tree\n\t\tif (!hasRendered.current) {\n\t\t\thasRendered.current = true;\n\t\t}\n\t\t// 2nd+ rendering pass. Happens when a route stays mounted on navigation.\n\t\telse {\n\t\t\tsetTree(renderer.init(initialView));\n\t\t}\n\t\treturn () => {\n\t\t\thasRendered.current = false;\n\t\t};\n\t}, [initialView, renderer]);\n\n\tif (serverError) {\n\t\treturn <ServerError error={serverError} />;\n\t}\n\n\treturn tree;\n}\n\nfunction ServerError({ error }: { error: ServerErrorInfo }) {\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tpadding: 16,\n\t\t\t\tborder: \"1px solid #e00\",\n\t\t\t\tbackground: \"#fff5f5\",\n\t\t\t\tcolor: \"#900\",\n\t\t\t\tfontFamily:\n\t\t\t\t\t'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n\t\t\t\twhiteSpace: \"pre-wrap\",\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ fontWeight: 700, marginBottom: 8 }}>Server Error during {error.phase}</div>\n\t\t\t{error.message && <div>{error.message}</div>}\n\t\t\t{error.stack && (\n\t\t\t\t<details open style={{ marginTop: 8 }}>\n\t\t\t\t\t<summary>Stack trace</summary>\n\t\t\t\t\t<pre style={{ margin: 0 }}>{error.stack}</pre>\n\t\t\t\t</details>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useEffect, useMemo } from \"react\";\nimport type { ChannelBridge } from \"./channel\";\nimport { usePulseClient } from \"./pulse\";\n\nexport function usePulseChannel(channelId: string): ChannelBridge {\n\tconst client = usePulseClient();\n\tconst bridge = useMemo(() => {\n\t\tif (!channelId) {\n\t\t\tthrow new Error(\"usePulseChannel requires a non-empty channelId\");\n\t\t}\n\t\treturn client.acquireChannel(channelId);\n\t}, [client, channelId]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tclient.releaseChannel(channelId);\n\t\t};\n\t}, [client, channelId]);\n\n\treturn bridge;\n}\n"],"mappings":"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,SACA,WACA,OACA,OACA,WACA,OACA,SACA,WACA,WACA,OACA,WACA,MACA,SACA,QACA,SACA,WACA,OACA,iBACA,CAC8D,CAwBzD,EAAiB,EAtBC,CACvB,WACA,WACA,cACA,aACA,cACA,eACA,sBACA,WACA,QACA,OACA,QACA,eACA,SACA,eACA,UACA,aACA,UACA,MACA,SACA,iBACA,CACiE,CAE5D,GAAkB,GAA0B,EAAe,EAAI,CAc/D,GAAkB,EAZC,CACxB,WACA,OACA,OACA,QACA,aACA,cACA,aACA,iBACA,aACA,sBACA,CACoE,CAG/D,GAAgB,EADC,CAAC,QAAQ,CAC+B,CAUzD,GAAiB,EARC,CACvB,SACA,MACA,OACA,QACA,QACA,OACA,CACiE,CAS5D,GAAoB,EAPC,CAC1B,WACA,OACA,OACA,oBACA,eACA,CAC0E,CAerEC,GAAgB,EAbC,CACtB,gBACA,SACA,eACA,WACA,UACA,SACA,SACA,OACA,aACA,SACA,MACA,CAC8D,CAmBzD,GAAkB,EAjBC,CACxB,QACA,kBACA,SACA,OACA,iBACA,MACA,SACA,QACA,QACA,cACA,WACA,eACA,cACA,YACA,UACA,CACoE,CA6B/D,GAAiB,EA3BC,CACvB,MACA,cACA,WACA,SACA,QACA,UACA,gBACA,eACA,iBACA,QACA,MACA,SACA,SACA,QACA,QACA,SACA,WACA,SACA,WACA,SACA,OACA,SACA,IACA,IACA,gBACA,CACiE,CA6C5D,GAAiB,EA3CC,8ZA0CvB,CACiE,CAG5D,GAAiB,EADC,CAAC,UAAU,CAC+B,CAG5D,GAAc,EADC,CAAC,QAAS,OAAO,CACmB,CAqBnD,GAAgB,EAnBC,CACtB,KACA,cACA,WACA,gBACA,OACA,WACA,aACA,cACA,YACA,QACA,iBACA,MACA,OACA,UACA,MACA,SACA,QACA,CAC8D,CAGzD,GAAe,EADC,CAAC,OAAO,CAC8B,CAUtD,GAAiB,EARC,CACvB,OACA,MACA,MACA,MACA,UACA,QACA,CACiE,CAG5D,EAAe,EADC,CAAC,OAAQ,WAAW,CACkB,CAQtD,GAAiB,EANF,CACpB,WACA,QACA,OACA,UACA,CAC8D,CAsBzD,GAAkB,EApBC,CACxB,OACA,SACA,OACA,OACA,SACA,QACA,oBACA,eACA,QACA,UACA,SACA,OACA,WACA,WACA,UACA,SACA,UACA,SACA,CACoE,CAM/D,GAAoB,EAJC,CAC1B,WACA,QACA,CAC0E,CAWrE,GAAkB,EATC,CACxB,kBACA,WACA,QACA,QACA,WACA,OACA,QACA,CACoE,CAW/D,GAAkB,EATC,CACxB,eACA,OACA,OACA,QACA,UACA,oBACA,eACA,CACoE,CAO/D,GAAoB,EALC,CAC1B,MACA,WACA,QACA,CAC0E,CAGrE,EAAiB,EADC,CAAC,OAAO,CACkC,CAE5D,GAAiB,GAAqB,EAAuB,EAAI,CAejE,GAAwB,GAAoC,CAbzC,CACxB,QACA,cACA,QACA,gBACA,YACA,WACA,iBACA,MACA,OACA,OACA,UACA,CACoF,CACpF,MAAQ,GAAO,EAAU,MACzB,QAAU,GAAO,EAAU,QAC3B,CAAC,CACI,GAAmB,IAA4B,CACpD,GAAG,EAAuB,EAAI,CAC9B,GAAG,GAAsB,EAAI,CAC7B,EAgBK,GAAkB,EAdC,CACxB,eACA,WACA,SACA,WACA,OACA,WACA,gBACA,OACA,OACA,QACA,oBACA,eACA,CACoE,CAG/D,GAAgB,EADC,CAAC,OAAO,CACgC,CAWzD,GAAkB,EATC,CACxB,SACA,QACA,QACA,MACA,SACA,OACA,QACA,CACoE,CAK/D,GAAwB,EAHE,CAC/B,QACA,CACuF,CAmBlF,EAAqB,EAjBE,CAC5B,OACA,YACA,UACA,UACA,UACA,QACA,QACA,OACA,UACA,KACA,QACA,SACA,SACA,SACA,QACA,CAC8E,CAUzE,EAAoB,EARE,CAC3B,OACA,QACA,KACA,QACA,SACA,QACA,CAC2E,CAatE,GAAiB,EAXC,CACvB,QACA,UACA,SACA,cACA,cACA,QACA,QACA,UACA,QACA,CACiE,CAW5D,GAAoB,EATL,CACpB,WACA,kBACA,QACA,UACA,KACA,QACA,SACA,CACoE,CAQ/D,EAAwB,EANH,CAC1B,QAC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"}
1
+ {"version":3,"file":"index.js","names":["client: PulseSocketIOClient","id: string","remaining: ServerChannelRequestMessage[]","response: any","error: any","PulseForm","out: any","formExtractor","elementExtractors: Record<string, (elt: any) => object>","eventExtractorMap: { [key: string]: (evt: any) => object }","refs: number[]","dates: number[]","sets: number[]","maps: number[]","process","rec: Record<string, any>","objects: Array<any>","result","keys","result: Record<string, any>","#url","#directives","#frameworkNavigate","#socket","#activeViews","#messageQueue","#connectionStatusConfig","#connectingTimeout","#errorTimeout","#clearTimeouts","#currentStatus","#notifyConnectionListeners","#hasConnectedOnce","#setStatus","#setInitialConnectionStatus","#handleConnected","#handleDisconnected","#handleTransportDisconnect","#handleServerMessage","#connectionListeners","#serverErrorListeners","#serverErrors","#channels","#notifyServerError","#performApiCall","#routeChannelMessage","#handleJsExec","headersObj: Record<string, string>","body: any","reply: ClientApiResultMessage","#sendJsResult","msg: ClientJsResultMessage","#ensureChannelEntry","#client","#path","#registry","#callbacks","#callbackCache","#renderPropKeys","#jsexprPaths","#callbackList","#lowerBound","#propPath","newProps: Record<string, any>","newTree: ReactNode","#assertIsElement","#ensureChildrenArray","nextProps: Record<string, any>","#rebindCallbacksInSubtree","result: any","error: string | null"],"sources":["../src/channel.ts","../src/form.tsx","../src/helpers.ts","../src/serialize/extractor.ts","../src/serialize/elements.ts","../src/serialize/events.ts","../src/serialize/serializer.ts","../src/client.tsx","../src/vdom.ts","../src/renderer.tsx","../src/pulse.tsx","../src/usePulseChannel.ts"],"sourcesContent":["import type { PulseSocketIOClient } from \"./client\";\nimport type {\n\tServerChannelMessage,\n\tServerChannelRequestMessage,\n\tServerChannelResponseMessage,\n} from \"./messages\";\n\nexport class PulseChannelResetError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"PulseChannelResetError\";\n\t}\n}\n\nexport type ChannelEventHandler = (payload: any) => any | Promise<any>;\n\ninterface PendingRequest {\n\tresolve: (value: any) => void;\n\treject: (error: any) => void;\n}\n\nfunction randomId(): string {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n\t\treturn crypto.randomUUID().replace(/-/g, \"\");\n\t}\n\treturn Math.random().toString(16).slice(2) + Math.random().toString(16).slice(2);\n}\n\nfunction formatError(error: unknown): string {\n\tif (error instanceof Error) return error.message;\n\tif (typeof error === \"string\") return error;\n\ttry {\n\t\treturn JSON.stringify(error);\n\t} catch {\n\t\treturn String(error);\n\t}\n}\n\nfunction isServerResponseMessage(\n\tmessage: ServerChannelMessage,\n): message is ServerChannelResponseMessage {\n\treturn typeof (message as ServerChannelResponseMessage).responseTo === \"string\";\n}\n\nfunction isServerRequestMessage(\n\tmessage: ServerChannelMessage,\n): message is ServerChannelRequestMessage {\n\treturn typeof (message as ServerChannelRequestMessage).event === \"string\";\n}\n\nexport class ChannelBridge {\n\tprivate handlers = new Map<string, Set<ChannelEventHandler>>();\n\tprivate pending = new Map<string, PendingRequest>();\n\tprivate backlog: ServerChannelRequestMessage[] = [];\n\tprivate closed = false;\n\n\tconstructor(\n\t\tprivate client: PulseSocketIOClient,\n\t\tpublic readonly id: string,\n\t) {}\n\n\temit(event: string, payload?: any): void {\n\t\tthis.ensureOpen();\n\t\tthis.client.sendMessage({\n\t\t\ttype: \"channel_message\",\n\t\t\tchannel: this.id,\n\t\t\tevent,\n\t\t\tpayload,\n\t\t});\n\t}\n\n\trequest(event: string, payload?: any): Promise<any> {\n\t\tthis.ensureOpen();\n\t\tconst requestId = randomId();\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pending.set(requestId, { resolve, reject });\n\t\t\tthis.client.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: this.id,\n\t\t\t\tevent,\n\t\t\t\tpayload,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t});\n\t}\n\n\ton(event: string, handler: ChannelEventHandler): () => void {\n\t\tthis.ensureOpen();\n\t\tlet bucket = this.handlers.get(event);\n\t\tif (!bucket) {\n\t\t\tbucket = new Set();\n\t\t\tthis.handlers.set(event, bucket);\n\t\t}\n\t\tbucket.add(handler);\n\t\tthis.flushBacklog(event);\n\t\treturn () => {\n\t\t\tconst set = this.handlers.get(event);\n\t\t\tif (!set) return;\n\t\t\tset.delete(handler);\n\t\t\tif (set.size === 0) {\n\t\t\t\tthis.handlers.delete(event);\n\t\t\t}\n\t\t};\n\t}\n\n\thandleServerMessage(message: ServerChannelMessage): boolean {\n\t\tif (isServerResponseMessage(message)) {\n\t\t\tthis.resolvePending(message);\n\t\t\treturn this.closed;\n\t\t}\n\t\tif (this.closed) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!isServerRequestMessage(message)) {\n\t\t\treturn this.closed;\n\t\t}\n\n\t\tif (message.event === \"__close__\") {\n\t\t\tthis.close(new PulseChannelResetError(\"Channel closed by server\"));\n\t\t\treturn true;\n\t\t}\n\t\tif (message.requestId) {\n\t\t\tvoid this.dispatchRequest(\n\t\t\t\tmessage as ServerChannelRequestMessage & {\n\t\t\t\t\trequestId: string;\n\t\t\t\t},\n\t\t\t);\n\t\t} else {\n\t\t\tthis.dispatchEvent(message);\n\t\t}\n\t\treturn this.closed;\n\t}\n\n\thandleDisconnect(reason: PulseChannelResetError): void {\n\t\tthis.close(reason);\n\t}\n\n\tdispose(reason: PulseChannelResetError): void {\n\t\tthis.close(reason);\n\t}\n\n\tprivate ensureOpen(): void {\n\t\tif (this.closed) {\n\t\t\tthrow new PulseChannelResetError(\"Channel is closed\");\n\t\t}\n\t}\n\n\tprivate flushBacklog(event: string): void {\n\t\tif (this.backlog.length === 0) return;\n\t\tconst remaining: ServerChannelRequestMessage[] = [];\n\t\tfor (const item of this.backlog) {\n\t\t\tif (item.event === event) {\n\t\t\t\tthis.dispatchEvent(item);\n\t\t\t} else {\n\t\t\t\tremaining.push(item);\n\t\t\t}\n\t\t}\n\t\tthis.backlog = remaining;\n\t}\n\n\tprivate dispatchEvent(message: ServerChannelRequestMessage): void {\n\t\tconst handlers = this.handlers.get(message.event);\n\t\tif (!handlers || handlers.size === 0) {\n\t\t\tthis.backlog.push(message);\n\t\t\treturn;\n\t\t}\n\t\tfor (const handler of handlers) {\n\t\t\ttry {\n\t\t\t\tconst result = handler(message.payload);\n\t\t\t\tif (result && typeof (result as Promise<any>).then === \"function\") {\n\t\t\t\t\tvoid (result as Promise<any>).catch((err) => {\n\t\t\t\t\t\tconsole.error(\"Pulse channel handler error\", err);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"Pulse channel handler error\", err);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async dispatchRequest(\n\t\tmessage: ServerChannelRequestMessage & { requestId: string },\n\t): Promise<void> {\n\t\tconst handlers = this.handlers.get(message.event);\n\t\tlet response: any;\n\t\tlet error: any;\n\t\tif (handlers && handlers.size > 0) {\n\t\t\tfor (const handler of handlers) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = handler(message.payload);\n\t\t\t\t\tresponse = await Promise.resolve(result);\n\t\t\t\t\tif (response !== undefined) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\terror = err;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (error) {\n\t\t\tthis.client.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: this.id,\n\t\t\t\tevent: undefined,\n\t\t\t\tresponseTo: message.requestId,\n\t\t\t\terror: formatError(error),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.client.sendMessage({\n\t\t\ttype: \"channel_message\",\n\t\t\tchannel: this.id,\n\t\t\tevent: undefined,\n\t\t\tresponseTo: message.requestId,\n\t\t\tpayload: response,\n\t\t});\n\t}\n\n\tprivate resolvePending(message: ServerChannelResponseMessage): void {\n\t\tconst entry = message.responseTo ? this.pending.get(message.responseTo) : undefined;\n\t\tif (!entry) {\n\t\t\treturn;\n\t\t}\n\t\tthis.pending.delete(message.responseTo!);\n\t\tif (message.error !== undefined && message.error !== null) {\n\t\t\tentry.reject(new PulseChannelResetError(String(message.error)));\n\t\t} else {\n\t\t\tentry.resolve(message.payload);\n\t\t}\n\t}\n\n\tprivate close(reason: PulseChannelResetError): void {\n\t\tif (this.closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.closed = true;\n\t\tfor (const request of this.pending.values()) {\n\t\t\trequest.reject(reason);\n\t\t}\n\t\tthis.pending.clear();\n\t\tthis.handlers.clear();\n\t\tthis.backlog = [];\n\t\t// No-op: owning client manages registry lifecycle.\n\t}\n}\n","import { type ComponentPropsWithoutRef, type FormEvent, forwardRef, useCallback } from \"react\";\n\nexport type PulseFormProps = ComponentPropsWithoutRef<\"form\"> & {\n\taction: string;\n};\n\n/**\n * PulseForm intercepts native form submissions and sends them through fetch so the\n * surrounding Pulse view stays mounted. Server-side handlers are still invoked via\n * the form action endpoint and reactive updates propagate over the socket.\n */\nexport const PulseForm = forwardRef<HTMLFormElement, PulseFormProps>(function PulseForm(\n\t{ onSubmit, action, ...rest },\n\tref,\n) {\n\treturn (\n\t\t<form\n\t\t\t{...rest}\n\t\t\taction={action}\n\t\t\tref={ref}\n\t\t\tonSubmit={useCallback(\n\t\t\t\t(event: FormEvent<HTMLFormElement>) => submitForm({ event, action, onSubmit }),\n\t\t\t\t[action, onSubmit],\n\t\t\t)}\n\t\t/>\n\t);\n});\n\ninterface SubmitForm {\n\tevent: FormEvent<HTMLFormElement>;\n\taction: string;\n\tonSubmit?: PulseFormProps[\"onSubmit\"];\n\tformData?: FormData;\n\tforce?: boolean;\n}\n\nexport async function submitForm({ event, action, onSubmit, formData, force }: SubmitForm) {\n\tonSubmit?.(event);\n\tif (!force && event.defaultPrevented) {\n\t\treturn;\n\t}\n\tconst form = event.currentTarget;\n\tevent.preventDefault();\n\tconst nativeEvent = event.nativeEvent as SubmitEvent;\n\tif (!formData) {\n\t\tformData = new FormData(form, nativeEvent.submitter);\n\t}\n\tconst url = new URL(action, window.location.href);\n\ttry {\n\t\tawait fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\t// Required for our hosting scenarios of same host + different ports or 2 subdomains\n\t\t\tcredentials: \"include\",\n\t\t\tbody: formData,\n\t\t});\n\t} catch (err) {\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.error(\"[Pulse] Form submission failed\", err);\n\t\t} else {\n\t\t\tthrow err;\n\t\t}\n\t}\n}\n","import type { LoaderFunctionArgs } from \"react-router\";\n\nexport interface RouteInfo {\n\tpathname: string;\n\thash: string;\n\tquery: string;\n\tqueryParams: Record<string, string>;\n\tpathParams: Record<string, string | undefined>;\n\tcatchall: string[];\n}\n\nexport function extractServerRouteInfo({ params, request }: LoaderFunctionArgs) {\n\tconst { \"*\": catchall = \"\", ...pathParams } = params;\n\tconst parsedUrl = new URL(request.url);\n\n\treturn {\n\t\thash: parsedUrl.hash,\n\t\tpathname: parsedUrl.pathname,\n\t\tquery: parsedUrl.search,\n\t\tqueryParams: Object.fromEntries(parsedUrl.searchParams.entries()),\n\t\tpathParams,\n\t\tcatchall: catchall.length > 1 ? catchall.split(\"/\") : [],\n\t} satisfies RouteInfo;\n}\n","type Simplify<T> = { [K in keyof T]: T[K] } & {};\n\nexport function createExtractor<T extends object>() {\n\tfunction _createExtractor<\n\t\tconst K extends readonly (keyof T)[],\n\t\tC extends Partial<Record<K[number] | string, (src: T) => any>>,\n\t>(keys: K, computed?: C) {\n\t\treturn (\n\t\t\tsrc: T,\n\t\t): Simplify<\n\t\t\tPick<T, K[number]> & {\n\t\t\t\t[P in keyof C]-?: C[P] extends (...args: any) => infer R ? R : never;\n\t\t\t}\n\t\t> => {\n\t\t\tconst out: any = {};\n\t\t\tfor (const key of keys) {\n\t\t\t\tout[key as string] = (src as any)[key as string];\n\t\t\t}\n\t\t\tif (computed) {\n\t\t\t\tfor (const key in computed) {\n\t\t\t\t\tconst fn = computed[key]!;\n\t\t\t\t\tout[key] = fn(src);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn out;\n\t\t};\n\t}\n\treturn _createExtractor;\n}\n","import { createExtractor } from \"./extractor\";\n\n// Base extractors (camelCase) similar to events.ts style\nconst lowerTagName = (e: Element) => e.tagName.toLowerCase();\n\nconst ELEMENT_KEYS = [\n\t\"id\",\n\t\"className\",\n\t\"tagName\",\n\t\"localName\",\n\t\"clientHeight\",\n\t\"clientLeft\",\n\t\"clientTop\",\n\t\"clientWidth\",\n\t\"scrollHeight\",\n\t\"scrollLeft\",\n\t\"scrollTop\",\n\t\"scrollWidth\",\n\t\"slot\",\n] as const satisfies readonly (keyof Element)[];\n\nconst HTML_OR_SVG_KEYS = [\n\t\"autofocus\",\n\t\"tabIndex\",\n\t\"nonce\",\n] as const satisfies readonly (keyof HTMLOrSVGElement)[];\n\nconst HTML_ELEMENT_BASE_KEYS = [\n\t\"accessKey\",\n\t\"accessKeyLabel\",\n\t\"autocapitalize\",\n\t\"dir\",\n\t\"draggable\",\n\t\"hidden\",\n\t\"inert\",\n\t\"lang\",\n\t\"offsetHeight\",\n\t\"offsetLeft\",\n\t\"offsetTop\",\n\t\"offsetWidth\",\n\t\"popover\",\n\t\"spellcheck\",\n\t\"title\",\n\t\"translate\",\n\t\"writingSuggestions\",\n\t\"contentEditable\",\n\t\"enterKeyHint\",\n\t\"isContentEditable\",\n\t\"inputMode\",\n] as const satisfies readonly (keyof HTMLElement)[];\n\nconst extractElementBase = createExtractor<Element>()(ELEMENT_KEYS, {\n\ttagName: lowerTagName,\n});\n\nconst extractHTMLOrSVGElement = createExtractor<HTMLOrSVGElement>()(HTML_OR_SVG_KEYS);\n\nconst extractHTMLElementBaseOnly = createExtractor<HTMLElement>()(HTML_ELEMENT_BASE_KEYS);\n\nfunction extractHTMLElementBase(elt: HTMLElement) {\n\treturn {\n\t\t...extractElementBase(elt),\n\t\t...extractHTMLOrSVGElement(elt as HTMLOrSVGElement),\n\t\t...extractHTMLElementBaseOnly(elt),\n\t};\n}\n\n// Helper to compose per-element extractors with the shared base\nfunction withBase<T extends HTMLElement>(\n\tkeys: readonly (keyof T)[],\n\tcomputed?: Partial<Record<string, (src: T) => any>>,\n) {\n\tconst only = createExtractor<T>()(keys, computed as any);\n\treturn (elt: T) => ({ ...extractHTMLElementBase(elt), ...only(elt) });\n}\n\nconst HTML_ANCHOR_KEYS = [\n\t\"hash\",\n\t\"host\",\n\t\"hostname\",\n\t\"href\",\n\t\"origin\",\n\t\"password\",\n\t\"pathname\",\n\t\"port\",\n\t\"protocol\",\n\t\"search\",\n\t\"target\",\n\t\"download\",\n\t\"rel\",\n\t\"hreflang\",\n\t\"type\",\n\t\"username\",\n\t\"ping\",\n\t\"referrerPolicy\",\n\t\"text\",\n] as const satisfies readonly (keyof HTMLAnchorElement)[];\nconst anchorExtractor = withBase<HTMLAnchorElement>(HTML_ANCHOR_KEYS);\n\nconst HTML_AREA_KEYS = [\n\t\"alt\",\n\t\"coords\",\n\t\"download\",\n\t\"hash\",\n\t\"host\",\n\t\"hostname\",\n\t\"href\",\n\t\"origin\",\n\t\"password\",\n\t\"pathname\",\n\t\"port\",\n\t\"protocol\",\n\t\"rel\",\n\t\"search\",\n\t\"shape\",\n\t\"target\",\n\t\"username\",\n\t\"ping\",\n\t\"referrerPolicy\",\n] as const satisfies readonly (keyof HTMLAreaElement)[];\nconst areaExtractor = withBase<HTMLAreaElement>(HTML_AREA_KEYS);\n\nconst HTML_MEDIA_KEYS = [\n\t\"autoplay\",\n\t\"controls\",\n\t\"crossOrigin\",\n\t\"currentSrc\",\n\t\"currentTime\",\n\t\"defaultMuted\",\n\t\"defaultPlaybackRate\",\n\t\"duration\",\n\t\"ended\",\n\t\"loop\",\n\t\"muted\",\n\t\"networkState\",\n\t\"paused\",\n\t\"playbackRate\",\n\t\"preload\",\n\t\"readyState\",\n\t\"seeking\",\n\t\"src\",\n\t\"volume\",\n\t\"preservesPitch\",\n] as const satisfies readonly (keyof HTMLMediaElement)[];\nconst mediaExtractor = withBase<HTMLMediaElement>(HTML_MEDIA_KEYS);\n\nconst audioExtractor = (elt: HTMLAudioElement) => mediaExtractor(elt);\n\nconst HTML_BUTTON_KEYS = [\n\t\"disabled\",\n\t\"name\",\n\t\"type\",\n\t\"value\",\n\t\"formAction\",\n\t\"formEnctype\",\n\t\"formMethod\",\n\t\"formNoValidate\",\n\t\"formTarget\",\n\t\"popoverTargetAction\",\n] as const satisfies readonly (keyof HTMLButtonElement)[];\nconst buttonExtractor = withBase<HTMLButtonElement>(HTML_BUTTON_KEYS);\n\nconst HTML_DATA_KEYS = [\"value\"] as const satisfies readonly (keyof HTMLDataElement)[];\nconst dataExtractor = withBase<HTMLDataElement>(HTML_DATA_KEYS);\n\nconst HTML_EMBED_KEYS = [\n\t\"height\",\n\t\"src\",\n\t\"type\",\n\t\"width\",\n\t\"align\",\n\t\"name\",\n] as const satisfies readonly (keyof HTMLEmbedElement)[];\nconst embedExtractor = withBase<HTMLEmbedElement>(HTML_EMBED_KEYS);\n\nconst HTML_FIELDSET_KEYS = [\n\t\"disabled\",\n\t\"name\",\n\t\"type\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLFieldSetElement)[];\nconst fieldsetExtractor = withBase<HTMLFieldSetElement>(HTML_FIELDSET_KEYS);\n\nconst HTML_FORM_KEYS = [\n\t\"acceptCharset\",\n\t\"action\",\n\t\"autocomplete\",\n\t\"encoding\",\n\t\"enctype\",\n\t\"length\",\n\t\"method\",\n\t\"name\",\n\t\"noValidate\",\n\t\"target\",\n\t\"rel\",\n] as const satisfies readonly (keyof HTMLFormElement)[];\nconst formExtractor = withBase<HTMLFormElement>(HTML_FORM_KEYS);\n\nconst HTML_IFRAME_KEYS = [\n\t\"allow\",\n\t\"allowFullscreen\",\n\t\"height\",\n\t\"name\",\n\t\"referrerPolicy\",\n\t\"src\",\n\t\"srcdoc\",\n\t\"width\",\n\t\"align\",\n\t\"frameBorder\",\n\t\"longDesc\",\n\t\"marginHeight\",\n\t\"marginWidth\",\n\t\"scrolling\",\n\t\"sandbox\",\n] as const satisfies readonly (keyof HTMLIFrameElement)[];\nconst iframeExtractor = withBase<HTMLIFrameElement>(HTML_IFRAME_KEYS);\n\nconst HTML_IMAGE_KEYS = [\n\t\"alt\",\n\t\"crossOrigin\",\n\t\"decoding\",\n\t\"height\",\n\t\"isMap\",\n\t\"loading\",\n\t\"naturalHeight\",\n\t\"naturalWidth\",\n\t\"referrerPolicy\",\n\t\"sizes\",\n\t\"src\",\n\t\"srcset\",\n\t\"useMap\",\n\t\"width\",\n\t\"align\",\n\t\"border\",\n\t\"complete\",\n\t\"hspace\",\n\t\"longDesc\",\n\t\"lowsrc\",\n\t\"name\",\n\t\"vspace\",\n\t\"x\",\n\t\"y\",\n\t\"fetchPriority\",\n] as const satisfies readonly (keyof HTMLImageElement)[];\nconst imageExtractor = withBase<HTMLImageElement>(HTML_IMAGE_KEYS);\n\nconst HTML_INPUT_KEYS = [\n\t\"accept\",\n\t\"alt\",\n\t\"autocomplete\",\n\t\"checked\",\n\t\"defaultChecked\",\n\t\"defaultValue\",\n\t\"dirName\",\n\t\"disabled\",\n\t\"height\",\n\t\"indeterminate\",\n\t\"max\",\n\t\"maxLength\",\n\t\"min\",\n\t\"minLength\",\n\t\"multiple\",\n\t\"name\",\n\t\"pattern\",\n\t\"placeholder\",\n\t\"readOnly\",\n\t\"required\",\n\t\"selectionDirection\",\n\t\"selectionEnd\",\n\t\"selectionStart\",\n\t\"size\",\n\t\"src\",\n\t\"step\",\n\t\"type\",\n\t\"value\",\n\t\"valueAsNumber\",\n\t\"width\",\n\t\"align\",\n\t\"capture\",\n\t\"formAction\",\n\t\"formEnctype\",\n\t\"formMethod\",\n\t\"formNoValidate\",\n\t\"formTarget\",\n\t\"useMap\",\n\t\"validationMessage\",\n\t\"willValidate\",\n\t\"popoverTargetAction\",\n] as const satisfies readonly (keyof HTMLInputElement)[];\nconst inputExtractor = withBase<HTMLInputElement>(HTML_INPUT_KEYS);\n\nconst HTML_LABEL_KEYS = [\"htmlFor\"] as const satisfies readonly (keyof HTMLLabelElement)[];\nconst labelExtractor = withBase<HTMLLabelElement>(HTML_LABEL_KEYS);\n\nconst HTML_LI_KEYS = [\"value\", \"type\"] as const satisfies readonly (keyof HTMLLIElement)[];\nconst liExtractor = withBase<HTMLLIElement>(HTML_LI_KEYS);\n\nconst HTML_LINK_KEYS = [\n\t\"as\",\n\t\"crossOrigin\",\n\t\"disabled\",\n\t\"fetchPriority\",\n\t\"href\",\n\t\"hreflang\",\n\t\"imageSizes\",\n\t\"imageSrcset\",\n\t\"integrity\",\n\t\"media\",\n\t\"referrerPolicy\",\n\t\"rel\",\n\t\"type\",\n\t\"charset\",\n\t\"rev\",\n\t\"target\",\n\t\"sizes\",\n] as const satisfies readonly (keyof HTMLLinkElement)[];\nconst linkExtractor = withBase<HTMLLinkElement>(HTML_LINK_KEYS);\n\nconst HTML_MAP_KEYS = [\"name\"] as const satisfies readonly (keyof HTMLMapElement)[];\nconst mapExtractor = withBase<HTMLMapElement>(HTML_MAP_KEYS);\n\nconst HTML_METER_KEYS = [\n\t\"high\",\n\t\"low\",\n\t\"max\",\n\t\"min\",\n\t\"optimum\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLMeterElement)[];\nconst meterExtractor = withBase<HTMLMeterElement>(HTML_METER_KEYS);\n\nconst HTML_MOD_KEYS = [\"cite\", \"dateTime\"] as const satisfies readonly (keyof HTMLModElement)[];\nconst modExtractor = withBase<HTMLModElement>(HTML_MOD_KEYS);\n\nconst HTML_OL_KEYS = [\n\t\"reversed\",\n\t\"start\",\n\t\"type\",\n\t\"compact\",\n] as const satisfies readonly (keyof HTMLOListElement)[];\nconst olistExtractor = withBase<HTMLOListElement>(HTML_OL_KEYS);\n\nconst HTML_OBJECT_KEYS = [\n\t\"data\",\n\t\"height\",\n\t\"name\",\n\t\"type\",\n\t\"useMap\",\n\t\"width\",\n\t\"validationMessage\",\n\t\"willValidate\",\n\t\"align\",\n\t\"archive\",\n\t\"border\",\n\t\"code\",\n\t\"codeBase\",\n\t\"codeType\",\n\t\"declare\",\n\t\"hspace\",\n\t\"standby\",\n\t\"vspace\",\n] as const satisfies readonly (keyof HTMLObjectElement)[];\nconst objectExtractor = withBase<HTMLObjectElement>(HTML_OBJECT_KEYS);\n\nconst HTML_OPTGROUP_KEYS = [\n\t\"disabled\",\n\t\"label\",\n] as const satisfies readonly (keyof HTMLOptGroupElement)[];\nconst optgroupExtractor = withBase<HTMLOptGroupElement>(HTML_OPTGROUP_KEYS);\n\nconst HTML_OPTION_KEYS = [\n\t\"defaultSelected\",\n\t\"disabled\",\n\t\"index\",\n\t\"label\",\n\t\"selected\",\n\t\"text\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLOptionElement)[];\nconst optionExtractor = withBase<HTMLOptionElement>(HTML_OPTION_KEYS);\n\nconst HTML_OUTPUT_KEYS = [\n\t\"defaultValue\",\n\t\"name\",\n\t\"type\",\n\t\"value\",\n\t\"htmlFor\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLOutputElement)[];\nconst outputExtractor = withBase<HTMLOutputElement>(HTML_OUTPUT_KEYS);\n\nconst HTML_PROGRESS_KEYS = [\n\t\"max\",\n\t\"position\",\n\t\"value\",\n] as const satisfies readonly (keyof HTMLProgressElement)[];\nconst progressExtractor = withBase<HTMLProgressElement>(HTML_PROGRESS_KEYS);\n\nconst HTML_QUOTE_KEYS = [\"cite\"] as const satisfies readonly (keyof HTMLQuoteElement)[];\nconst quoteExtractor = withBase<HTMLQuoteElement>(HTML_QUOTE_KEYS);\n\nconst citeExtractor = (elt: HTMLElement) => extractHTMLElementBase(elt);\n\nconst HTML_SCRIPT_KEYS = [\n\t\"async\",\n\t\"crossOrigin\",\n\t\"defer\",\n\t\"fetchPriority\",\n\t\"integrity\",\n\t\"noModule\",\n\t\"referrerPolicy\",\n\t\"src\",\n\t\"text\",\n\t\"type\",\n\t\"charset\",\n] as const satisfies readonly (keyof HTMLScriptElement)[];\nconst extractHTMLScriptOnly = createExtractor<HTMLScriptElement>()(HTML_SCRIPT_KEYS, {\n\tevent: (s) => (s as any).event,\n\thtmlFor: (s) => (s as any).htmlFor,\n});\nconst scriptExtractor = (elt: HTMLScriptElement) => ({\n\t...extractHTMLElementBase(elt),\n\t...extractHTMLScriptOnly(elt),\n});\n\nconst HTML_SELECT_KEYS = [\n\t\"autocomplete\",\n\t\"disabled\",\n\t\"length\",\n\t\"multiple\",\n\t\"name\",\n\t\"required\",\n\t\"selectedIndex\",\n\t\"size\",\n\t\"type\",\n\t\"value\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLSelectElement)[];\nconst selectExtractor = withBase<HTMLSelectElement>(HTML_SELECT_KEYS);\n\nconst HTML_SLOT_KEYS = [\"name\"] as const satisfies readonly (keyof HTMLSlotElement)[];\nconst slotExtractor = withBase<HTMLSlotElement>(HTML_SLOT_KEYS);\n\nconst HTML_SOURCE_KEYS = [\n\t\"height\",\n\t\"media\",\n\t\"sizes\",\n\t\"src\",\n\t\"srcset\",\n\t\"type\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLSourceElement)[];\nconst sourceExtractor = withBase<HTMLSourceElement>(HTML_SOURCE_KEYS);\n\nconst HTML_TABLE_CAPTION_KEYS = [\n\t\"align\",\n] as const satisfies readonly (keyof HTMLTableCaptionElement)[];\nconst tableCaptionExtractor = withBase<HTMLTableCaptionElement>(HTML_TABLE_CAPTION_KEYS);\n\nconst HTML_TABLE_CELL_KEYS = [\n\t\"abbr\",\n\t\"cellIndex\",\n\t\"colSpan\",\n\t\"headers\",\n\t\"rowSpan\",\n\t\"scope\",\n\t\"align\",\n\t\"axis\",\n\t\"bgColor\",\n\t\"ch\",\n\t\"chOff\",\n\t\"height\",\n\t\"noWrap\",\n\t\"vAlign\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableCellElement)[];\nconst tableCellExtractor = withBase<HTMLTableCellElement>(HTML_TABLE_CELL_KEYS);\n\nconst HTML_TABLE_COL_KEYS = [\n\t\"span\",\n\t\"align\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableColElement)[];\nconst tableColExtractor = withBase<HTMLTableColElement>(HTML_TABLE_COL_KEYS);\n\nconst HTML_TABLE_KEYS = [\n\t\"align\",\n\t\"bgColor\",\n\t\"border\",\n\t\"cellPadding\",\n\t\"cellSpacing\",\n\t\"frame\",\n\t\"rules\",\n\t\"summary\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLTableElement)[];\nconst tableExtractor = withBase<HTMLTableElement>(HTML_TABLE_KEYS);\n\nconst HTML_TR_KEYS = [\n\t\"rowIndex\",\n\t\"sectionRowIndex\",\n\t\"align\",\n\t\"bgColor\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n] as const satisfies readonly (keyof HTMLTableRowElement)[];\nconst tableRowExtractor = withBase<HTMLTableRowElement>(HTML_TR_KEYS);\n\nconst HTML_TSECTION_KEYS = [\n\t\"align\",\n\t\"ch\",\n\t\"chOff\",\n\t\"vAlign\",\n] as const satisfies readonly (keyof HTMLTableSectionElement)[];\nconst tableSectionExtractor = withBase<HTMLTableSectionElement>(HTML_TSECTION_KEYS);\n\nconst templateExtractor = (elt: HTMLTemplateElement) => extractHTMLElementBase(elt);\n\nconst HTML_TEXTAREA_KEYS = [\n\t\"autocomplete\",\n\t\"cols\",\n\t\"defaultValue\",\n\t\"dirName\",\n\t\"disabled\",\n\t\"maxLength\",\n\t\"minLength\",\n\t\"name\",\n\t\"placeholder\",\n\t\"readOnly\",\n\t\"required\",\n\t\"rows\",\n\t\"selectionDirection\",\n\t\"selectionEnd\",\n\t\"selectionStart\",\n\t\"value\",\n\t\"wrap\",\n\t\"textLength\",\n\t\"validationMessage\",\n\t\"willValidate\",\n] as const satisfies readonly (keyof HTMLTextAreaElement)[];\nconst textareaExtractor = withBase<HTMLTextAreaElement>(HTML_TEXTAREA_KEYS);\n\nconst HTML_TIME_KEYS = [\"dateTime\"] as const satisfies readonly (keyof HTMLTimeElement)[];\nconst timeExtractor = withBase<HTMLTimeElement>(HTML_TIME_KEYS);\n\nconst HTML_TRACK_KEYS = [\n\t\"default\",\n\t\"kind\",\n\t\"label\",\n\t\"readyState\",\n\t\"src\",\n\t\"srclang\",\n] as const satisfies readonly (keyof HTMLTrackElement)[];\nconst trackExtractor = withBase<HTMLTrackElement>(HTML_TRACK_KEYS);\n\nconst HTML_VIDEO_KEYS = [\n\t\"height\",\n\t\"poster\",\n\t\"videoHeight\",\n\t\"videoWidth\",\n\t\"width\",\n\t\"playsInline\",\n] as const satisfies readonly (keyof HTMLVideoElement)[];\nconst extractHTMLVideoOnly = createExtractor<HTMLVideoElement>()(HTML_VIDEO_KEYS);\nconst videoExtractor = (elt: HTMLVideoElement) => ({\n\t...mediaExtractor(elt),\n\t...extractHTMLVideoOnly(elt),\n});\n\nconst HTML_BR_KEYS = [\"clear\"] as const satisfies readonly (keyof HTMLBRElement)[];\nconst brExtractor = withBase<HTMLBRElement>(HTML_BR_KEYS);\n\nconst HTML_BASE_KEYS = [\"href\", \"target\"] as const satisfies readonly (keyof HTMLBaseElement)[];\nconst baseExtractor = withBase<HTMLBaseElement>(HTML_BASE_KEYS);\n\nconst HTML_BODY_KEYS = [\n\t\"aLink\",\n\t\"background\",\n\t\"bgColor\",\n\t\"link\",\n\t\"text\",\n\t\"vLink\",\n] as const satisfies readonly (keyof HTMLBodyElement)[];\nconst bodyExtractor = withBase<HTMLBodyElement>(HTML_BODY_KEYS);\n\nconst HTML_DLIST_KEYS = [\"compact\"] as const satisfies readonly (keyof HTMLDListElement)[];\nconst dlistExtractor = withBase<HTMLDListElement>(HTML_DLIST_KEYS);\n\nconst HTML_DETAILS_KEYS = [\"open\"] as const satisfies readonly (keyof HTMLDetailsElement)[];\nconst detailsExtractor = withBase<HTMLDetailsElement>(HTML_DETAILS_KEYS);\n\nconst HTML_DIALOG_KEYS = [\n\t\"open\",\n\t\"returnValue\",\n] as const satisfies readonly (keyof HTMLDialogElement)[];\nconst dialogExtractor = withBase<HTMLDialogElement>(HTML_DIALOG_KEYS);\n\nconst HTML_DIV_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLDivElement)[];\nconst divExtractor = withBase<HTMLDivElement>(HTML_DIV_KEYS);\n\nconst headExtractor = (elt: HTMLHeadElement) => extractHTMLElementBase(elt);\n\nconst HTML_HEADING_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLHeadingElement)[];\nconst headingExtractor = withBase<HTMLHeadingElement>(HTML_HEADING_KEYS);\n\nconst HTML_HR_KEYS = [\n\t\"align\",\n\t\"color\",\n\t\"noShade\",\n\t\"size\",\n\t\"width\",\n] as const satisfies readonly (keyof HTMLHRElement)[];\nconst hrExtractor = withBase<HTMLHRElement>(HTML_HR_KEYS);\n\nconst HTML_HTML_KEYS = [\"version\"] as const satisfies readonly (keyof HTMLHtmlElement)[];\nconst htmlExtractor = withBase<HTMLHtmlElement>(HTML_HTML_KEYS);\n\nconst menuExtractor = (elt: HTMLMenuElement) => extractHTMLElementBase(elt);\n\nconst HTML_META_KEYS = [\n\t\"content\",\n\t\"httpEquiv\",\n\t\"name\",\n\t\"scheme\",\n] as const satisfies readonly (keyof HTMLMetaElement)[];\nconst metaExtractor = withBase<HTMLMetaElement>(HTML_META_KEYS);\n\nconst HTML_P_KEYS = [\"align\"] as const satisfies readonly (keyof HTMLParagraphElement)[];\nconst paragraphExtractor = withBase<HTMLParagraphElement>(HTML_P_KEYS);\n\nconst pictureExtractor = (elt: HTMLPictureElement) => extractHTMLElementBase(elt);\n\nconst HTML_PRE_KEYS = [\"width\"] as const satisfies readonly (keyof HTMLPreElement)[];\nconst preExtractor = withBase<HTMLPreElement>(HTML_PRE_KEYS);\n\nconst spanExtractor = (elt: HTMLSpanElement) => extractHTMLElementBase(elt);\n\nconst HTML_STYLE_KEYS = [\n\t\"media\",\n\t\"type\",\n\t\"disabled\",\n] as const satisfies readonly (keyof HTMLStyleElement)[];\nconst styleExtractor = withBase<HTMLStyleElement>(HTML_STYLE_KEYS);\n\nconst HTML_TITLE_KEYS = [\"text\"] as const satisfies readonly (keyof HTMLTitleElement)[];\nconst titleExtractor = withBase<HTMLTitleElement>(HTML_TITLE_KEYS);\n\nconst HTML_UL_KEYS = [\"compact\", \"type\"] as const satisfies readonly (keyof HTMLUListElement)[];\nconst ulistExtractor = withBase<HTMLUListElement>(HTML_UL_KEYS);\n\n// SVG element extractors\nfunction extractSVGElementBase(elt: SVGElement) {\n\treturn {\n\t\t...extractElementBase(elt),\n\t\t...extractHTMLOrSVGElement(elt as HTMLOrSVGElement),\n\t};\n}\n\n// Helper to compose per-SVG-element extractors with the shared base\nfunction withSVGBase<T extends SVGElement>(\n\tkeys: readonly (keyof T)[],\n\tcomputed?: Partial<Record<string, (src: T) => any>>,\n) {\n\tconst only = createExtractor<T>()(keys, computed as any);\n\treturn (elt: T) => ({ ...extractSVGElementBase(elt), ...only(elt) });\n}\n\nconst SVG_SVG_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"currentScale\",\n\t\"currentTranslate\",\n] as const satisfies readonly (keyof SVGSVGElement)[];\nconst svgExtractor = withSVGBase<SVGSVGElement>(SVG_SVG_KEYS);\n\nconst SVG_CIRCLE_KEYS = [\"cx\", \"cy\", \"r\"] as const satisfies readonly (keyof SVGCircleElement)[];\nconst circleExtractor = withSVGBase<SVGCircleElement>(SVG_CIRCLE_KEYS);\n\nconst SVG_ELLIPSE_KEYS = [\n\t\"cx\",\n\t\"cy\",\n\t\"rx\",\n\t\"ry\",\n] as const satisfies readonly (keyof SVGEllipseElement)[];\nconst ellipseExtractor = withSVGBase<SVGEllipseElement>(SVG_ELLIPSE_KEYS);\n\nconst SVG_LINE_KEYS = [\"x1\", \"y1\", \"x2\", \"y2\"] as const satisfies readonly (keyof SVGLineElement)[];\nconst lineExtractor = withSVGBase<SVGLineElement>(SVG_LINE_KEYS);\n\nconst SVG_PATH_KEYS = [\"pathLength\"] as const satisfies readonly (keyof SVGPathElement)[];\nconst pathExtractor = withSVGBase<SVGPathElement>(SVG_PATH_KEYS);\n\nconst SVG_RECT_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"rx\",\n\t\"ry\",\n] as const satisfies readonly (keyof SVGRectElement)[];\nconst rectExtractor = withSVGBase<SVGRectElement>(SVG_RECT_KEYS);\n\nconst SVG_POLYGON_KEYS = [\"points\"] as const satisfies readonly (keyof SVGPolygonElement)[];\nconst polygonExtractor = withSVGBase<SVGPolygonElement>(SVG_POLYGON_KEYS);\n\nconst SVG_POLYLINE_KEYS = [\"points\"] as const satisfies readonly (keyof SVGPolylineElement)[];\nconst polylineExtractor = withSVGBase<SVGPolylineElement>(SVG_POLYLINE_KEYS);\n\nconst SVG_TEXT_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"dx\",\n\t\"dy\",\n\t\"rotate\",\n\t\"textLength\",\n\t\"lengthAdjust\",\n] as const satisfies readonly (keyof SVGTextElement)[];\nconst textExtractor = withSVGBase<SVGTextElement>(SVG_TEXT_KEYS);\n\nconst SVG_TSPAN_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"dx\",\n\t\"dy\",\n\t\"rotate\",\n\t\"textLength\",\n\t\"lengthAdjust\",\n] as const satisfies readonly (keyof SVGTSpanElement)[];\nconst tspanExtractor = withSVGBase<SVGTSpanElement>(SVG_TSPAN_KEYS);\n\nconst SVG_IMAGE_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"href\",\n\t\"preserveAspectRatio\",\n\t\"crossOrigin\",\n] as const satisfies readonly (keyof SVGImageElement)[];\nconst svgImageExtractor = withSVGBase<SVGImageElement>(SVG_IMAGE_KEYS);\n\nconst SVG_USE_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"href\",\n] as const satisfies readonly (keyof SVGUseElement)[];\nconst useExtractor = withSVGBase<SVGUseElement>(SVG_USE_KEYS);\n\nconst SVG_DEFS_KEYS = [] as const satisfies readonly (keyof SVGDefsElement)[];\nconst defsExtractor = withSVGBase<SVGDefsElement>(SVG_DEFS_KEYS);\n\nconst SVG_GROUP_KEYS = [] as const satisfies readonly (keyof SVGGElement)[];\nconst gExtractor = withSVGBase<SVGGElement>(SVG_GROUP_KEYS);\n\nconst SVG_LINEAR_GRADIENT_KEYS = [\n\t\"x1\",\n\t\"y1\",\n\t\"x2\",\n\t\"y2\",\n\t\"gradientUnits\",\n\t\"gradientTransform\",\n\t\"spreadMethod\",\n] as const satisfies readonly (keyof SVGLinearGradientElement)[];\nconst linearGradientExtractor = withSVGBase<SVGLinearGradientElement>(SVG_LINEAR_GRADIENT_KEYS);\n\nconst SVG_RADIAL_GRADIENT_KEYS = [\n\t\"cx\",\n\t\"cy\",\n\t\"r\",\n\t\"fx\",\n\t\"fy\",\n\t\"fr\",\n\t\"gradientUnits\",\n\t\"gradientTransform\",\n\t\"spreadMethod\",\n] as const satisfies readonly (keyof SVGRadialGradientElement)[];\nconst radialGradientExtractor = withSVGBase<SVGRadialGradientElement>(SVG_RADIAL_GRADIENT_KEYS);\n\nconst SVG_STOP_KEYS = [\"offset\"] as const satisfies readonly (keyof SVGStopElement)[];\nconst stopExtractor = withSVGBase<SVGStopElement>(SVG_STOP_KEYS);\n\nconst SVG_PATTERN_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"patternUnits\",\n\t\"patternContentUnits\",\n\t\"patternTransform\",\n\t\"preserveAspectRatio\",\n\t\"href\",\n] as const satisfies readonly (keyof SVGPatternElement)[];\nconst patternExtractor = withSVGBase<SVGPatternElement>(SVG_PATTERN_KEYS);\n\nconst SVG_CLIP_PATH_KEYS = [\n\t\"clipPathUnits\",\n] as const satisfies readonly (keyof SVGClipPathElement)[];\nconst clipPathExtractor = withSVGBase<SVGClipPathElement>(SVG_CLIP_PATH_KEYS);\n\nconst SVG_MASK_KEYS = [\n\t\"x\",\n\t\"y\",\n\t\"width\",\n\t\"height\",\n\t\"maskUnits\",\n\t\"maskContentUnits\",\n] as const satisfies readonly (keyof SVGMaskElement)[];\nconst maskExtractor = withSVGBase<SVGMaskElement>(SVG_MASK_KEYS);\n\n// Map of tagName -> extractor (concise, like events.ts)\nconst elementExtractors: Record<string, (elt: any) => object> = {\n\tA: anchorExtractor,\n\tAREA: areaExtractor,\n\tAUDIO: audioExtractor,\n\tBASE: baseExtractor,\n\tBLOCKQUOTE: quoteExtractor,\n\tQ: quoteExtractor,\n\tBODY: bodyExtractor,\n\tBR: brExtractor,\n\tBUTTON: buttonExtractor,\n\tCANVAS: extractHTMLElementBase,\n\tCAPTION: tableCaptionExtractor,\n\tCITE: citeExtractor,\n\tCOL: tableColExtractor,\n\tCOLGROUP: tableColExtractor,\n\tDATA: dataExtractor,\n\tDETAILS: detailsExtractor,\n\tDIALOG: dialogExtractor,\n\tDIV: divExtractor,\n\tDL: dlistExtractor,\n\tEMBED: embedExtractor,\n\tFIELDSET: fieldsetExtractor,\n\tFORM: formExtractor,\n\tH1: headingExtractor,\n\tH2: headingExtractor,\n\tH3: headingExtractor,\n\tH4: headingExtractor,\n\tH5: headingExtractor,\n\tH6: headingExtractor,\n\tHEAD: headExtractor,\n\tHR: hrExtractor,\n\tHTML: htmlExtractor,\n\tIFRAME: iframeExtractor,\n\tIMG: imageExtractor,\n\tINPUT: inputExtractor,\n\tLABEL: labelExtractor,\n\tLI: liExtractor,\n\tLINK: linkExtractor,\n\tMAP: mapExtractor,\n\tMENU: menuExtractor,\n\tMETA: metaExtractor,\n\tMETER: meterExtractor,\n\tINS: modExtractor,\n\tDEL: modExtractor,\n\tOBJECT: objectExtractor,\n\tOL: olistExtractor,\n\tOPTGROUP: optgroupExtractor,\n\tOPTION: optionExtractor,\n\tOUTPUT: outputExtractor,\n\tP: paragraphExtractor,\n\tPICTURE: pictureExtractor,\n\tPRE: preExtractor,\n\tPROGRESS: progressExtractor,\n\tSCRIPT: scriptExtractor,\n\tSELECT: selectExtractor,\n\tSLOT: slotExtractor,\n\tSOURCE: sourceExtractor,\n\tSPAN: spanExtractor,\n\tSTYLE: styleExtractor,\n\tTABLE: tableExtractor,\n\tTBODY: tableSectionExtractor,\n\tTHEAD: tableSectionExtractor,\n\tTFOOT: tableSectionExtractor,\n\tTD: tableCellExtractor,\n\tTH: tableCellExtractor,\n\tTEMPLATE: templateExtractor,\n\tTEXTAREA: textareaExtractor,\n\tTIME: timeExtractor,\n\tTITLE: titleExtractor,\n\tTR: tableRowExtractor,\n\tTRACK: trackExtractor,\n\tUL: ulistExtractor,\n\tVIDEO: videoExtractor,\n\t// SVG elements\n\tSVG: svgExtractor,\n\tCIRCLE: circleExtractor,\n\tELLIPSE: ellipseExtractor,\n\tLINE: lineExtractor,\n\tPATH: pathExtractor,\n\tRECT: rectExtractor,\n\tPOLYGON: polygonExtractor,\n\tPOLYLINE: polylineExtractor,\n\tTEXT: textExtractor,\n\tTSPAN: tspanExtractor,\n\tIMAGE: svgImageExtractor,\n\tUSE: useExtractor,\n\tDEFS: defsExtractor,\n\tG: gExtractor,\n\tLINEARGRADIENT: linearGradientExtractor,\n\tRADIALGRADIENT: radialGradientExtractor,\n\tSTOP: stopExtractor,\n\tPATTERN: patternExtractor,\n\tCLIPPATH: clipPathExtractor,\n\tMASK: maskExtractor,\n};\n\nexport function extractHTMLElement(elt: HTMLElement): object {\n\tconst tagName = elt.tagName.toUpperCase();\n\n\tconst extractor = elementExtractors[tagName];\n\tif (extractor) {\n\t\treturn extractor(elt);\n\t}\n\tthrow new Error(`Unexpected HTML element tag: ${elt.tagName} (update .web/custom/serialize.ts)`);\n}\n\nexport function extractSVGElement(elt: SVGElement): object {\n\tconst tagName = elt.tagName.toUpperCase();\n\n\tconst extractor = elementExtractors[tagName];\n\tif (extractor) {\n\t\treturn extractor(elt);\n\t}\n\t// Fallback to base SVG element extractor for unknown SVG elements\n\treturn extractSVGElementBase(elt);\n}\n\nexport function extractElement(elt: Element): object {\n\tif (elt instanceof HTMLElement) {\n\t\treturn extractHTMLElement(elt);\n\t}\n\tif (elt instanceof SVGElement) {\n\t\treturn extractSVGElement(elt);\n\t}\n\t// Fallback for other Element types - use base element extractor\n\treturn extractElementBase(elt);\n}\n","/* === IMPORTANT === */\n\nimport type { MouseEvent, PointerEvent, SyntheticEvent, UIEvent } from \"react\";\nimport { extractElement } from \"./elements\";\nimport { createExtractor } from \"./extractor\";\n\n// Reusable computed mappers (helps bundlers/minifiers share references)\nconst mapTarget = (e: { target: EventTarget | null }) => extractElement(e.target as Element);\nconst mapRelated = (e: { relatedTarget: EventTarget | null }) =>\n\te.relatedTarget ? extractElement(e.relatedTarget as Element) : null;\n\nfunction makeExtractor<K extends readonly any[]>(\n\tkeys: K,\n\tcomputed?: Record<string, (evt: any) => any>,\n) {\n\treturn createExtractor<any>()(\n\t\tkeys as any,\n\t\t{\n\t\t\ttarget: mapTarget,\n\t\t\t...(computed || {}),\n\t\t} as any,\n\t);\n}\n\nconst SYNTHETIC_KEYS = [\n\t\"target\",\n\t\"bubbles\",\n\t\"cancelable\",\n\t\"defaultPrevented\",\n\t\"eventPhase\",\n\t\"isTrusted\",\n\t\"timeStamp\",\n\t\"type\",\n] as const satisfies readonly (keyof SyntheticEvent)[];\n\nconst UI_KEYS = [...SYNTHETIC_KEYS, \"detail\"] as const satisfies readonly (keyof UIEvent)[];\n\nconst MOUSE_KEYS = [\n\t...UI_KEYS,\n\t\"altKey\",\n\t\"button\",\n\t\"buttons\",\n\t\"clientX\",\n\t\"clientY\",\n\t\"ctrlKey\",\n\t\"metaKey\",\n\t\"movementX\",\n\t\"movementY\",\n\t\"pageX\",\n\t\"pageY\",\n\t\"screenX\",\n\t\"screenY\",\n\t\"shiftKey\",\n] as const satisfies readonly (keyof MouseEvent)[];\n\nconst POINTER_KEYS = [\n\t...MOUSE_KEYS,\n\t\"pointerId\",\n\t\"pressure\",\n\t\"tangentialPressure\",\n\t\"tiltX\",\n\t\"tiltY\",\n\t\"twist\",\n\t\"width\",\n\t\"height\",\n\t\"pointerType\",\n\t\"isPrimary\",\n] as const satisfies readonly (keyof PointerEvent)[];\n\nconst syntheticExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst uiExtractor = makeExtractor(UI_KEYS);\n\nconst mouseExtractor = makeExtractor(MOUSE_KEYS, { relatedTarget: mapRelated });\n\nconst clipboardExtractor = makeExtractor(SYNTHETIC_KEYS, {\n\tclipboardData: (e) => extractDataTransfer(e.clipboardData),\n});\n\nconst compositionExtractor = makeExtractor([...SYNTHETIC_KEYS, \"data\"] as const);\n\nconst dragExtractor = makeExtractor(MOUSE_KEYS, {\n\trelatedTarget: mapRelated,\n\tdataTransfer: (e) => extractDataTransfer(e.dataTransfer),\n});\n\nconst pointerExtractor = makeExtractor(POINTER_KEYS, {\n\trelatedTarget: mapRelated,\n});\n\nconst focusExtractor = makeExtractor(SYNTHETIC_KEYS, {\n\trelatedTarget: mapRelated,\n});\n\nconst formExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst invalidExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst changeExtractor = makeExtractor(SYNTHETIC_KEYS);\n\nconst keyboardExtractor = makeExtractor([\n\t...UI_KEYS,\n\t\"altKey\",\n\t\"ctrlKey\",\n\t\"code\",\n\t\"key\",\n\t\"locale\",\n\t\"location\",\n\t\"metaKey\",\n\t\"repeat\",\n\t\"shiftKey\",\n] as const);\n\nconst touchExtractor = makeExtractor(\n\t[\n\t\t...UI_KEYS,\n\t\t\"altKey\",\n\t\t\"ctrlKey\",\n\t\t\"metaKey\",\n\t\t\"shiftKey\",\n\t\t\"changedTouches\",\n\t\t\"targetTouches\",\n\t\t\"touches\",\n\t] as const,\n\t{\n\t\tchangedTouches: (e) => mapTouchList(e.changedTouches),\n\t\ttargetTouches: (e) => mapTouchList(e.targetTouches),\n\t\ttouches: (e) => mapTouchList(e.touches),\n\t},\n);\n\nconst wheelExtractor = makeExtractor(\n\t[...MOUSE_KEYS, \"deltaMode\", \"deltaX\", \"deltaY\", \"deltaZ\"] as const,\n\t{\n\t\trelatedTarget: mapRelated,\n\t},\n);\n\nconst animationExtractor = makeExtractor([\n\t...SYNTHETIC_KEYS,\n\t\"animationName\",\n\t\"elapsedTime\",\n\t\"pseudoElement\",\n] as const);\n\nconst toggleExtractor = makeExtractor([...SYNTHETIC_KEYS, \"oldState\", \"newState\"] as const);\n\nconst transitionExtractor = makeExtractor([\n\t...SYNTHETIC_KEYS,\n\t\"elapsedTime\",\n\t\"propertyName\",\n\t\"pseudoElement\",\n] as const);\n\nfunction mapTouchList(list: any): any[] {\n\treturn Array.from(list as ArrayLike<any>).map((touch: any) => ({\n\t\ttarget: extractElement(touch.target as Element),\n\t\tidentifier: touch.identifier,\n\t\tscreenX: touch.screenX,\n\t\tscreenY: touch.screenY,\n\t\tclientX: touch.clientX,\n\t\tclientY: touch.clientY,\n\t\tpageX: touch.pageX,\n\t\tpageY: touch.pageY,\n\t}));\n}\n\n// Helper function to extract DataTransfer properties\nfunction extractDataTransfer(dt: DataTransfer | null): object | null {\n\tif (!dt) {\n\t\treturn null;\n\t}\n\tconst items = [];\n\tif (dt.items) {\n\t\tfor (let i = 0; i < dt.items.length; i++) {\n\t\t\tconst item = dt.items[i]!;\n\t\t\titems.push({\n\t\t\t\tkind: item.kind,\n\t\t\t\ttype: item.type,\n\t\t\t});\n\t\t}\n\t}\n\treturn {\n\t\tdrop_effect: dt.dropEffect,\n\t\teffect_allowed: dt.effectAllowed,\n\t\titems: items,\n\t\ttypes: Array.from(dt.types || []),\n\t};\n}\n\nconst eventExtractorMap: { [key: string]: (evt: any) => object } = {};\n\nfunction add(map: Record<string, any>, names: readonly string[], fn: any) {\n\tfor (const n of names) map[n] = fn;\n}\n\nadd(\n\teventExtractorMap,\n\t[\n\t\t\"pointerdown\",\n\t\t\"pointermove\",\n\t\t\"pointerup\",\n\t\t\"pointercancel\",\n\t\t\"gotpointercapture\",\n\t\t\"lostpointercapture\",\n\t\t\"pointerenter\",\n\t\t\"pointerleave\",\n\t\t\"pointerover\",\n\t\t\"pointerout\",\n\t],\n\tpointerExtractor,\n);\n\nadd(\n\teventExtractorMap,\n\t[\n\t\t\"click\",\n\t\t\"contextmenu\",\n\t\t\"dblclick\",\n\t\t\"mousedown\",\n\t\t\"mouseenter\",\n\t\t\"mouseleave\",\n\t\t\"mousemove\",\n\t\t\"mouseout\",\n\t\t\"mouseover\",\n\t\t\"mouseup\",\n\t],\n\tmouseExtractor,\n);\n\nadd(\n\teventExtractorMap,\n\t[\"drag\", \"dragend\", \"dragenter\", \"dragexit\", \"dragleave\", \"dragover\", \"dragstart\", \"drop\"],\n\tdragExtractor,\n);\n\nadd(eventExtractorMap, [\"keydown\", \"keypress\", \"keyup\"], keyboardExtractor);\nadd(eventExtractorMap, [\"focus\", \"blur\"], focusExtractor);\nadd(eventExtractorMap, [\"change\", \"input\"], changeExtractor);\nadd(eventExtractorMap, [\"invalid\"], invalidExtractor);\nadd(eventExtractorMap, [\"reset\", \"submit\"], formExtractor);\nadd(eventExtractorMap, [\"copy\", \"cut\", \"paste\"], clipboardExtractor);\nadd(\n\teventExtractorMap,\n\t[\"compositionend\", \"compositionstart\", \"compositionupdate\"],\n\tcompositionExtractor,\n);\nadd(eventExtractorMap, [\"touchcancel\", \"touchend\", \"touchmove\", \"touchstart\"], touchExtractor);\nadd(eventExtractorMap, [\"scroll\"], uiExtractor);\nadd(eventExtractorMap, [\"wheel\"], wheelExtractor);\nadd(\n\teventExtractorMap,\n\t[\"animationstart\", \"animationend\", \"animationiteration\"],\n\tanimationExtractor,\n);\nadd(eventExtractorMap, [\"transitionend\"], transitionExtractor);\nadd(eventExtractorMap, [\"toggle\"], toggleExtractor);\n\nexport function extractEvent(value: any): any {\n\t// Duck-typing for React's SyntheticEvent.\n\t// We check for properties that are unique to synthetic events.\n\tif (\n\t\tvalue &&\n\t\ttypeof value === \"object\" &&\n\t\t\"nativeEvent\" in value &&\n\t\ttypeof value.isDefaultPrevented === \"function\"\n\t) {\n\t\tconst evt = value as SyntheticEvent;\n\t\t// The `type` property is crucial for the lookup.\n\t\tif (typeof evt.type !== \"string\") {\n\t\t\treturn value;\n\t\t}\n\n\t\tconst extractor = eventExtractorMap[evt.type.toLowerCase()];\n\t\tif (extractor) {\n\t\t\treturn extractor(evt);\n\t\t}\n\n\t\t// Fallback for unknown event types: minimal synthetic extractor\n\t\treturn syntheticExtractor(evt);\n\t}\n\n\t// If it's not a duck-typed event, return it as is.\n\treturn value;\n}\n","export type Primitive = number | string | boolean | null | undefined;\nexport type JSON<T> = T | Array<JSON<T>> | { [K: string]: JSON<T> };\nexport type PlainJSON = JSON<Primitive>;\nexport type Serializable = any;\n\nexport type Serialized = [[number[], number[], number[], number[]], PlainJSON];\n\nexport function serialize(data: Serializable): Serialized {\n\tconst seen = new Map<any, number>();\n\tconst refs: number[] = [];\n\tconst dates: number[] = [];\n\tconst sets: number[] = [];\n\tconst maps: number[] = [];\n\n\t// Single global counter - increments once per node visit\n\tlet globalIndex = 0;\n\n\tfunction process(value: Serializable, context?: string): PlainJSON {\n\t\tif (value == null || typeof value === \"string\" || typeof value === \"boolean\") {\n\t\t\treturn value;\n\t\t}\n\n\t\tif (typeof value === \"number\") {\n\t\t\tif (Number.isNaN(value)) {\n\t\t\t\tconst ctx = context ? ` in '${context}'` : \"\";\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot serialize NaN${ctx}. NaN and Infinity are not supported because they cannot be serialized to JSON.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tconst kind = value > 0 ? \"Infinity\" : \"-Infinity\";\n\t\t\t\tconst ctx = context ? ` in '${context}'` : \"\";\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot serialize ${kind}${ctx}. NaN and Infinity are not supported because they cannot be serialized to JSON.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\tconst idx = globalIndex++;\n\t\tconst prevRef = seen.get(value);\n\t\tif (prevRef !== undefined) {\n\t\t\t// Make sure to push the current index, but use the ref's index as the value!\n\t\t\trefs.push(idx);\n\t\t\treturn prevRef;\n\t\t}\n\n\t\tseen.set(value, idx);\n\n\t\tif (value instanceof Date) {\n\t\t\tdates.push(idx);\n\t\t\treturn value.getTime();\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tconst length = value.length;\n\t\t\tconst result = new Array(length);\n\t\t\tfor (let i = 0; i < length; i++) {\n\t\t\t\tresult[i] = process(value[i], context);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tif (value instanceof Map) {\n\t\t\tmaps.push(idx);\n\t\t\tconst rec: Record<string, any> = {};\n\t\t\tfor (const [key, entry] of value.entries()) {\n\t\t\t\trec[String(key)] = process(entry, String(key));\n\t\t\t}\n\t\t\treturn rec;\n\t\t}\n\n\t\tif (value instanceof Set) {\n\t\t\tsets.push(idx);\n\t\t\tconst size = value.size;\n\t\t\tconst result = new Array(size);\n\t\t\tlet i = 0;\n\t\t\tfor (const entry of value) {\n\t\t\t\tresult[i] = process(entry, context);\n\t\t\t\ti += 1;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tif (typeof value === \"object\") {\n\t\t\tconst rec: Record<string, any> = {};\n\t\t\tconst keys = Object.keys(value);\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\trec[key] = process(value[key], key);\n\t\t\t}\n\t\t\treturn rec;\n\t\t}\n\n\t\tthrow new Error(`Unsupported value in serialization: ${value}`);\n\t}\n\n\tconst payload = process(data);\n\treturn [[refs, dates, sets, maps], payload];\n}\n\nexport interface DeserializationOptions {\n\tcoerceNullsToUndefined?: boolean;\n}\n\nexport function deserialize<Data extends Serializable = Serializable>(\n\tpayload: Serialized,\n\toptions?: DeserializationOptions,\n): Data {\n\tconst [[refsA, datesA, setsA, mapsA], data] = payload;\n\n\tconst refs = new Set(refsA);\n\tconst dates = new Set(datesA);\n\tconst sets = new Set(setsA);\n\tconst maps = new Set(mapsA);\n\n\tconst objects: Array<any> = [];\n\n\tfunction reconstruct(value: PlainJSON): any {\n\t\tconst idx = objects.length;\n\t\tif (refs.has(idx)) {\n\t\t\t// We increment the counter on refs during serialization. We're never\n\t\t\t// going to use this entry, so we can just push null.\n\t\t\tobjects.push(null);\n\t\t\treturn objects[value as number];\n\t\t}\n\n\t\tif (dates.has(idx)) {\n\t\t\tconst dt = new Date(value as number);\n\t\t\tobjects.push(dt);\n\t\t\treturn dt;\n\t\t}\n\n\t\tif (\n\t\t\tvalue == null ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\ttypeof value === \"string\" ||\n\t\t\ttypeof value === \"boolean\"\n\t\t) {\n\t\t\tif (options?.coerceNullsToUndefined) {\n\t\t\t\treturn value ?? undefined;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tif (sets.has(idx)) {\n\t\t\t\tconst result = new Set();\n\t\t\t\tobjects.push(result);\n\t\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\t\tresult.add(reconstruct(value[i]));\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tconst length = value.length;\n\t\t\tconst arr = new Array(length);\n\t\t\tobjects.push(arr);\n\t\t\tfor (let i = 0; i < length; i++) {\n\t\t\t\tarr[i] = reconstruct(value[i]);\n\t\t\t}\n\t\t\treturn arr;\n\t\t}\n\n\t\tif (typeof value === \"object\") {\n\t\t\tif (maps.has(idx)) {\n\t\t\t\tconst result = new Map<string, any>();\n\t\t\t\tobjects.push(result);\n\t\t\t\tconst keys = Object.keys(value);\n\t\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\t\tconst key = keys[i];\n\t\t\t\t\tresult.set(key, reconstruct(value[key]));\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tconst result: Record<string, any> = {};\n\t\t\tobjects.push(result);\n\t\t\tconst keys = Object.keys(value);\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tresult[key] = reconstruct(value[key]);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tthrow new Error(`Unsupported value in deserialization: ${value}`);\n\t}\n\n\treturn reconstruct(data);\n}\n","import type { NavigateFunction } from \"react-router\";\nimport { io, type Socket } from \"socket.io-client\";\nimport { ChannelBridge, PulseChannelResetError } from \"./channel\";\nimport type { RouteInfo } from \"./helpers\";\nimport type {\n\tClientApiResultMessage,\n\tClientJsResultMessage,\n\tClientMessage,\n\tServerApiCallMessage,\n\tServerChannelMessage,\n\tServerErrorInfo,\n\tServerJsExecMessage,\n\tServerMessage,\n} from \"./messages\";\nimport type { PulsePrerenderView } from \"./pulse\";\nimport { extractEvent } from \"./serialize/events\";\nimport { deserialize, serialize } from \"./serialize/serializer\";\nimport type { VDOMUpdate } from \"./vdom\";\n\nexport interface SocketIODirectives {\n\theaders?: Record<string, string>;\n\tauth?: Record<string, string>;\n}\nexport interface Directives {\n\theaders?: Record<string, string>;\n\tsocketio?: SocketIODirectives;\n}\nexport interface MountedView {\n\trouteInfo: RouteInfo;\n\tonInit: (view: PulsePrerenderView) => void;\n\tonUpdate: (ops: VDOMUpdate[]) => void;\n\tonJsExec?: (msg: ServerJsExecMessage) => void;\n}\nexport type ConnectionStatus = \"ok\" | \"connecting\" | \"reconnecting\" | \"error\";\nexport type ConnectionStatusListener = (status: ConnectionStatus) => void;\nexport type ServerErrorListener = (path: string, error: ServerErrorInfo | null) => void;\n\nexport interface PulseClient {\n\t// Connection management\n\tconnect(): Promise<void>;\n\tdisconnect(): void;\n\tisConnected(): boolean;\n\tonConnectionChange(listener: ConnectionStatusListener): () => void;\n\t// Messages\n\tnavigate(path: string, routeInfo: RouteInfo): Promise<void>;\n\tleave(path: string): Promise<void>;\n\tinvokeCallback(path: string, callback: string, args: any[]): Promise<void>;\n\t// VDOM subscription\n\tmountView(path: string, view: MountedView): () => void;\n}\n\nexport class PulseSocketIOClient {\n\t#activeViews: Map<string, MountedView>;\n\t#socket: Socket | null = null;\n\t#messageQueue: ClientMessage[];\n\t#connectionListeners: Set<ConnectionStatusListener> = new Set();\n\t#serverErrors: Map<string, ServerErrorInfo> = new Map();\n\t#serverErrorListeners: Set<ServerErrorListener> = new Set();\n\t#channels: Map<string, { bridge: ChannelBridge; refCount: number }> = new Map();\n\t#url: string;\n\t#frameworkNavigate: NavigateFunction;\n\t#directives: Directives;\n\t#connectionStatusConfig: {\n\t\tinitialConnectingDelay: number;\n\t\tinitialErrorDelay: number;\n\t\treconnectErrorDelay: number;\n\t};\n\t#hasConnectedOnce: boolean = false;\n\t#connectingTimeout: ReturnType<typeof setTimeout> | null = null;\n\t#errorTimeout: ReturnType<typeof setTimeout> | null = null;\n\t#currentStatus: ConnectionStatus = \"ok\";\n\n\tconstructor(\n\t\turl: string,\n\t\tdirectives: Directives,\n\t\tframeworkNavigate: NavigateFunction,\n\t\tconnectionStatusConfig: {\n\t\t\tinitialConnectingDelay: number;\n\t\t\tinitialErrorDelay: number;\n\t\t\treconnectErrorDelay: number;\n\t\t},\n\t) {\n\t\tthis.#url = url;\n\t\tthis.#directives = directives;\n\t\tthis.#frameworkNavigate = frameworkNavigate;\n\t\tthis.#socket = null;\n\t\tthis.#activeViews = new Map();\n\t\tthis.#messageQueue = [];\n\t\tthis.#connectionStatusConfig = connectionStatusConfig;\n\t\t// Load directives from sessionStorage\n\t\tif (typeof window !== \"undefined\" && typeof sessionStorage !== \"undefined\") {\n\t\t\tconst stored = sessionStorage.getItem(\"__PULSE_DIRECTIVES\");\n\t\t\tif (stored) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.#directives = JSON.parse(stored);\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore parse errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tpublic setDirectives(directives: Directives) {\n\t\tthis.#directives = directives;\n\t}\n\tpublic isConnected(): boolean {\n\t\treturn this.#socket?.connected ?? false;\n\t}\n\n\t#clearTimeouts(): void {\n\t\tif (this.#connectingTimeout) {\n\t\t\tclearTimeout(this.#connectingTimeout);\n\t\t\tthis.#connectingTimeout = null;\n\t\t}\n\t\tif (this.#errorTimeout) {\n\t\t\tclearTimeout(this.#errorTimeout);\n\t\t\tthis.#errorTimeout = null;\n\t\t}\n\t}\n\n\t#setStatus(status: ConnectionStatus): void {\n\t\tthis.#clearTimeouts();\n\t\tthis.#currentStatus = status;\n\t\tthis.#notifyConnectionListeners(status);\n\t}\n\n\t#handleConnected(): void {\n\t\tthis.#hasConnectedOnce = true;\n\t\tthis.#setStatus(\"ok\");\n\t}\n\n\t#setInitialConnectionStatus(): void {\n\t\t// Initial connection attempt - start with no message, then show connecting after delay\n\t\tthis.#setStatus(\"ok\");\n\t\tthis.#connectingTimeout = setTimeout(() => {\n\t\t\tthis.#setStatus(\"connecting\");\n\t\t\tthis.#errorTimeout = setTimeout(() => {\n\t\t\t\tthis.#setStatus(\"error\");\n\t\t\t}, this.#connectionStatusConfig.initialErrorDelay);\n\t\t}, this.#connectionStatusConfig.initialConnectingDelay);\n\t}\n\n\t#handleDisconnected(): void {\n\t\t// Reconnection after losing connection - show reconnecting immediately\n\t\tthis.#setStatus(\"reconnecting\");\n\t\tthis.#errorTimeout = setTimeout(() => {\n\t\t\tthis.#setStatus(\"error\");\n\t\t}, this.#connectionStatusConfig.reconnectErrorDelay);\n\t}\n\n\tpublic async connect(): Promise<void> {\n\t\tif (this.#socket) {\n\t\t\treturn;\n\t\t}\n\t\t// Start timing logic for connection attempt\n\t\tif (!this.#hasConnectedOnce) {\n\t\t\tthis.#setInitialConnectionStatus();\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst socket = io(this.#url, {\n\t\t\t\ttransports: [\"websocket\", \"webtransport\"],\n\t\t\t\tauth: this.#directives.socketio?.auth,\n\t\t\t\textraHeaders: this.#directives.socketio?.headers,\n\t\t\t});\n\t\t\tthis.#socket = socket;\n\n\t\t\tsocket.on(\"connect\", () => {\n\t\t\t\tconsole.log(\"[SocketIOTransport] Connected:\", this.#socket?.id);\n\t\t\t\t// Make sure to send a navigate payload for all the routes\n\t\t\t\tfor (const [path, route] of this.#activeViews) {\n\t\t\t\t\tsocket.emit(\n\t\t\t\t\t\t\"message\",\n\t\t\t\t\t\tserialize({\n\t\t\t\t\t\t\ttype: \"mount\",\n\t\t\t\t\t\t\tpath: path,\n\t\t\t\t\t\t\trouteInfo: route.routeInfo,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tfor (const payload of this.#messageQueue) {\n\t\t\t\t\t// Already sent above\n\t\t\t\t\tif (payload.type === \"mount\" && this.#activeViews.has(payload.path)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// We're remounting all the routes, so no need to navigate\n\t\t\t\t\tif (payload.type === \"navigate\") {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tsocket.emit(\"message\", serialize(payload));\n\t\t\t\t}\n\t\t\t\tthis.#messageQueue = [];\n\n\t\t\t\tthis.#handleConnected();\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tsocket.on(\"connect_error\", (err) => {\n\t\t\t\tconsole.error(\"[SocketIOTransport] Connection failed:\", err);\n\t\t\t\tthis.#handleDisconnected();\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tsocket.on(\"disconnect\", () => {\n\t\t\t\tconsole.log(\"[SocketIOTransport] Disconnected\");\n\t\t\t\tthis.#handleTransportDisconnect();\n\t\t\t\tthis.#handleDisconnected();\n\t\t\t});\n\n\t\t\t// Wrap in an arrow function to avoid losing the `this` reference\n\t\t\tsocket.on(\"message\", (data) =>\n\t\t\t\tthis.#handleServerMessage(deserialize(data, { coerceNullsToUndefined: true })),\n\t\t\t);\n\t\t});\n\t}\n\n\tonConnectionChange(listener: ConnectionStatusListener): () => void {\n\t\tthis.#connectionListeners.add(listener);\n\t\t// Notify immediately with current status\n\t\tlistener(this.#currentStatus);\n\t\treturn () => {\n\t\t\tthis.#connectionListeners.delete(listener);\n\t\t};\n\t}\n\n\t#notifyConnectionListeners(status: ConnectionStatus): void {\n\t\tfor (const listener of this.#connectionListeners) {\n\t\t\tlistener(status);\n\t\t}\n\t}\n\n\tpublic onServerError(listener: ServerErrorListener): () => void {\n\t\tthis.#serverErrorListeners.add(listener);\n\t\t// Emit current errors to new listener\n\t\tfor (const [path, err] of this.#serverErrors) listener(path, err);\n\t\treturn () => {\n\t\t\tthis.#serverErrorListeners.delete(listener);\n\t\t};\n\t}\n\n\t#notifyServerError(path: string, error: ServerErrorInfo | null) {\n\t\tfor (const listener of this.#serverErrorListeners) listener(path, error);\n\t}\n\n\tpublic sendMessage(payload: ClientMessage) {\n\t\tif (this.isConnected()) {\n\t\t\t// console.log(\"[SocketIOTransport] Sending:\", payload);\n\t\t\tthis.#socket!.emit(\"message\", serialize(payload as any));\n\t\t} else {\n\t\t\t// console.log(\"[SocketIOTransport] Queuing message:\", payload);\n\t\t\tthis.#messageQueue.push(payload);\n\t\t}\n\t}\n\n\tpublic mountView(path: string, view: MountedView) {\n\t\tif (this.#activeViews.has(path)) {\n\t\t\tthrow new Error(`Path ${path} is already mounted`);\n\t\t}\n\t\tthis.#activeViews.set(path, view);\n\t\tvoid this.sendMessage({\n\t\t\ttype: \"mount\",\n\t\t\tpath,\n\t\t\trouteInfo: view.routeInfo,\n\t\t});\n\t}\n\n\tpublic navigate(path: string, routeInfo: RouteInfo) {\n\t\tthis.sendMessage({\n\t\t\ttype: \"navigate\",\n\t\t\tpath,\n\t\t\trouteInfo,\n\t\t});\n\t}\n\n\tpublic unmount(path: string) {\n\t\tvoid this.sendMessage({ type: \"unmount\", path });\n\t\tthis.#activeViews.delete(path);\n\t}\n\n\tpublic disconnect() {\n\t\tthis.#clearTimeouts();\n\t\tthis.#socket?.disconnect();\n\t\tthis.#socket = null;\n\t\tthis.#messageQueue = [];\n\t\tthis.#connectionListeners.clear();\n\t\tthis.#activeViews.clear();\n\t\tthis.#serverErrors.clear();\n\t\tthis.#serverErrorListeners.clear();\n\t\tfor (const { bridge } of this.#channels.values()) {\n\t\t\tbridge.dispose(new PulseChannelResetError(\"Client disconnected\"));\n\t\t}\n\t\tthis.#channels.clear();\n\t\tthis.#currentStatus = \"ok\";\n\t\tthis.#hasConnectedOnce = false;\n\t}\n\n\t#handleServerMessage(message: ServerMessage) {\n\t\t// console.log(\"[PulseClient] Received message:\", message);\n\t\tswitch (message.type) {\n\t\t\tcase \"vdom_init\": {\n\t\t\t\tconst route = this.#activeViews.get(message.path);\n\t\t\t\t// Ignore messages for paths that are not mounted\n\t\t\t\tif (!route) return;\n\t\t\t\tif (route) {\n\t\t\t\t\troute.onInit(message);\n\t\t\t\t}\n\t\t\t\t// Clear any prior error for this path on successful init\n\t\t\t\tif (this.#serverErrors.has(message.path)) {\n\t\t\t\t\tthis.#serverErrors.delete(message.path);\n\t\t\t\t\tthis.#notifyServerError(message.path, null);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"vdom_update\": {\n\t\t\t\tconst route = this.#activeViews.get(message.path);\n\t\t\t\tif (!route) return; // Not an active path; discard\n\t\t\t\troute.onUpdate(message.ops);\n\t\t\t\t// Clear any prior error for this path on successful update\n\t\t\t\tif (this.#serverErrors.has(message.path)) {\n\t\t\t\t\tthis.#serverErrors.delete(message.path);\n\t\t\t\t\tthis.#notifyServerError(message.path, null);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"server_error\": {\n\t\t\t\tif (!this.#activeViews.has(message.path)) return; // discard for inactive paths\n\t\t\t\tthis.#serverErrors.set(message.path, message.error);\n\t\t\t\tthis.#notifyServerError(message.path, message.error);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"api_call\": {\n\t\t\t\tvoid this.#performApiCall(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"navigate_to\": {\n\t\t\t\tconst replace = !!message.replace;\n\t\t\t\tlet dest = message.path || \"\";\n\t\t\t\tif (dest.startsWith(\"//\")) dest = `${window.location.protocol}${dest}`;\n\n\t\t\t\tconst hardNav = () =>\n\t\t\t\t\treplace ? window.location.replace(dest) : window.location.assign(dest);\n\n\t\t\t\tif (message.hard) {\n\t\t\t\t\thardNav();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// No scheme = relative path → SPA\n\t\t\t\tif (!/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(dest)) {\n\t\t\t\t\tthis.#frameworkNavigate(dest, { replace });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Same-origin http(s) → SPA\n\t\t\t\tif (/^https?:\\/\\//.test(dest)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst url = new URL(dest);\n\t\t\t\t\t\tif (url.origin === window.location.origin) {\n\t\t\t\t\t\t\tthis.#frameworkNavigate(`${url.pathname}${url.search}${url.hash}`, { replace });\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\n\t\t\t\t// External URL or other scheme (mailto:, tel:, etc.)\n\t\t\t\thardNav();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"channel_message\": {\n\t\t\t\tthis.#routeChannelMessage(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"js_exec\": {\n\t\t\t\tthis.#handleJsExec(message);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconsole.error(\"Unexpected message:\", message);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #performApiCall(msg: ServerApiCallMessage) {\n\t\ttry {\n\t\t\tconst res = await fetch(msg.url, {\n\t\t\t\tmethod: msg.method || \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\t...(msg.headers || {}),\n\t\t\t\t\t...(msg.body != null && !(\"content-type\" in (msg.headers || {}))\n\t\t\t\t\t\t? { \"content-type\": \"application/json\" }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t\tbody:\n\t\t\t\t\tmsg.body != null\n\t\t\t\t\t\t? typeof msg.body === \"string\"\n\t\t\t\t\t\t\t? msg.body\n\t\t\t\t\t\t\t: JSON.stringify(msg.body)\n\t\t\t\t\t\t: undefined,\n\t\t\t\tcredentials: msg.credentials || \"include\",\n\t\t\t});\n\t\t\tconst headersObj: Record<string, string> = {};\n\t\t\tres.headers.forEach((v, k) => {\n\t\t\t\theadersObj[k] = v;\n\t\t\t});\n\t\t\tlet body: any = null;\n\t\t\tconst ct = res.headers.get(\"content-type\") || \"\";\n\t\t\tif (ct.includes(\"application/json\")) {\n\t\t\t\tbody = await res.json().catch(() => null);\n\t\t\t} else {\n\t\t\t\tbody = await res.text().catch(() => null);\n\t\t\t}\n\t\t\tconst reply: ClientApiResultMessage = {\n\t\t\t\ttype: \"api_result\",\n\t\t\t\tid: msg.id,\n\t\t\t\tok: res.ok,\n\t\t\t\tstatus: res.status,\n\t\t\t\theaders: headersObj,\n\t\t\t\tbody,\n\t\t\t};\n\t\t\tthis.sendMessage(reply);\n\t\t} catch (err) {\n\t\t\tconst reply: ClientApiResultMessage = {\n\t\t\t\ttype: \"api_result\",\n\t\t\t\tid: msg.id,\n\t\t\t\tok: false,\n\t\t\t\tstatus: 0,\n\t\t\t\theaders: {},\n\t\t\t\tbody: { error: String(err) },\n\t\t\t};\n\t\t\tthis.sendMessage(reply);\n\t\t}\n\t}\n\n\tpublic invokeCallback(path: string, callback: string, args: any[]) {\n\t\tthis.sendMessage({\n\t\t\ttype: \"callback\",\n\t\t\tpath,\n\t\t\tcallback,\n\t\t\targs: args.map(extractEvent),\n\t\t});\n\t}\n\n\t#handleJsExec(message: ServerJsExecMessage) {\n\t\tconst view = this.#activeViews.get(message.path);\n\t\tif (!view?.onJsExec) {\n\t\t\t// No handler registered - execute anyway and send result back\n\t\t\t// This shouldn't happen in practice as views should register handlers\n\t\t\tconsole.warn(`[Pulse] No onJsExec handler for path: ${message.path}`);\n\t\t\tthis.#sendJsResult(message.id, undefined, \"No JS executor registered\");\n\t\t\treturn;\n\t\t}\n\t\tview.onJsExec(message);\n\t}\n\n\tpublic sendJsResult(id: string, result: any, error: string | null) {\n\t\tthis.#sendJsResult(id, result, error);\n\t}\n\n\t#sendJsResult(id: string, result: any, error: string | null) {\n\t\tconst msg: ClientJsResultMessage = {\n\t\t\ttype: \"js_result\",\n\t\t\tid,\n\t\t\tresult,\n\t\t\terror,\n\t\t};\n\t\tthis.sendMessage(msg);\n\t}\n\n\tpublic acquireChannel(id: string): ChannelBridge {\n\t\tconst entry = this.#ensureChannelEntry(id);\n\t\tentry.refCount += 1;\n\t\treturn entry.bridge;\n\t}\n\n\tpublic releaseChannel(id: string): void {\n\t\tconst entry = this.#channels.get(id);\n\t\tif (!entry) {\n\t\t\treturn;\n\t\t}\n\t\tentry.refCount = Math.max(0, entry.refCount - 1);\n\t\tif (entry.refCount === 0) {\n\t\t\tentry.bridge.dispose(new PulseChannelResetError(\"Channel released\"));\n\t\t\tthis.sendMessage({\n\t\t\t\ttype: \"channel_message\",\n\t\t\t\tchannel: id,\n\t\t\t\tevent: \"__close__\",\n\t\t\t\tpayload: { reason: \"refcount_zero\" },\n\t\t\t});\n\t\t\tthis.#channels.delete(id);\n\t\t}\n\t}\n\n\t#ensureChannelEntry(id: string): {\n\t\tbridge: ChannelBridge;\n\t\trefCount: number;\n\t} {\n\t\tlet entry = this.#channels.get(id);\n\t\tif (!entry) {\n\t\t\tentry = {\n\t\t\t\tbridge: new ChannelBridge(this, id),\n\t\t\t\trefCount: 0,\n\t\t\t};\n\t\t\tthis.#channels.set(id, entry);\n\t\t}\n\t\treturn entry;\n\t}\n\n\t#routeChannelMessage(message: ServerChannelMessage): void {\n\t\tconst entry = this.#ensureChannelEntry(message.channel);\n\t\tconst closed = entry.bridge.handleServerMessage(message);\n\t\tif (closed && entry.refCount === 0) {\n\t\t\tthis.#channels.delete(message.channel);\n\t\t}\n\t}\n\n\t#handleTransportDisconnect(): void {\n\t\tfor (const entry of this.#channels.values()) {\n\t\t\tentry.bridge.handleDisconnect(new PulseChannelResetError(\"Connection lost\"));\n\t\t}\n\t}\n}\n","import type { ComponentType } from \"react\";\n\n// Special prefixes for reserved node types\nexport const FRAGMENT_TAG = \"$$fragment\";\nexport const MOUNT_POINT_PREFIX = \"$$\";\n\n// export type LazyComponent = () => Promise<{ default: ComponentType<any> }>;\nexport type RegistryEntry = ComponentType<any>;\nexport type ComponentRegistry = Record<string, ComponentType<any>>;\n\nexport interface VDOMElement {\n\ttag: string;\n\tprops?: Record<string, any>;\n\tchildren?: VDOMNode[];\n\tkey?: string;\n\tlazy?: boolean;\n}\n\n// Primitive nodes that can be rendered\nexport type PrimitiveNode = string | number | boolean;\n\n// VDOMNode is either a primitive (string, number, boolean) or an element node.\n// Booleans are valid children in React but do not render anything.\n// Mount points are just UIElementNodes with tags starting with $$ComponentKey\nexport type VDOMNode = PrimitiveNode | VDOMElement;\n\nexport type VDOM = VDOMNode;\n\nexport interface VDOMUpdateBase {\n\ttype: string;\n\tpath: string; // Dot-separated path to the node\n}\n\nexport interface ReplaceUpdate extends VDOMUpdateBase {\n\ttype: \"replace\";\n\tdata: VDOMNode; // The new node\n}\n\nexport interface UpdatePropsUpdate extends VDOMUpdateBase {\n\ttype: \"update_props\";\n\tdata: {\n\t\tset?: Record<string, any>;\n\t\tremove?: string[];\n\t};\n}\n\nexport interface ReconciliationUpdate {\n\ttype: \"reconciliation\";\n\tpath: string;\n\tN: number;\n\tnew: [number[], VDOM[]];\n\treuse: [number[], number[]];\n}\n\nexport interface PathDelta {\n\tadd?: string[];\n\tremove?: string[];\n}\n\nexport interface UpdateCallbacksUpdate extends VDOMUpdateBase {\n\ttype: \"update_callbacks\";\n\tdata: PathDelta;\n}\n\nexport interface UpdateRenderPropsUpdate extends VDOMUpdateBase {\n\ttype: \"update_render_props\";\n\tdata: PathDelta;\n}\n\nexport interface UpdateJsExprPathsUpdate extends VDOMUpdateBase {\n\ttype: \"update_jsexpr_paths\";\n\tdata: PathDelta;\n}\n\nexport type VDOMUpdate =\n\t| ReplaceUpdate\n\t| UpdatePropsUpdate\n\t| ReconciliationUpdate\n\t| UpdateCallbacksUpdate\n\t| UpdateRenderPropsUpdate\n\t| UpdateJsExprPathsUpdate;\n\nexport type UpdateType = VDOMUpdate[\"type\"];\n\n// Utility functions for working with the UI tree structure\nexport function isElementNode(node: VDOMNode): node is VDOMElement {\n\t// Matches all non-text nodes\n\treturn typeof node === \"object\" && node !== null;\n}\n\nexport function isMountPointNode(node: VDOMNode): node is VDOMElement {\n\treturn (\n\t\ttypeof node === \"object\" &&\n\t\tnode !== null &&\n\t\tnode.tag.startsWith(MOUNT_POINT_PREFIX) &&\n\t\tnode.tag !== FRAGMENT_TAG\n\t);\n}\n\nexport function isTextNode(node: VDOMNode): node is string {\n\treturn typeof node === \"string\";\n}\n\nexport function isFragment(node: VDOMNode): boolean {\n\treturn typeof node === \"object\" && node !== null && node.tag === FRAGMENT_TAG;\n}\n","import {\n\ttype ComponentType,\n\tcloneElement,\n\tcreateElement,\n\ttype FC,\n\tFragment,\n\tisValidElement,\n\tlazy,\n\ttype PropsWithChildren,\n\ttype ReactElement,\n\ttype ReactNode,\n\tSuspense,\n} from \"react\";\nimport type { PulseSocketIOClient } from \"./client\";\nimport type { PulsePrerenderView } from \"./pulse\";\nimport type { ComponentRegistry, PathDelta, VDOMNode, VDOMUpdate } from \"./vdom\";\nimport { FRAGMENT_TAG, isElementNode, isMountPointNode, MOUNT_POINT_PREFIX } from \"./vdom\";\n\n// Prefix for JSExpr values - code is embedded after the colon\nconst JSEXPR_PREFIX = \"$js:\";\n\nexport class VDOMRenderer {\n\t#callbacks: Set<string>;\n\t#callbackCache: Map<string, (...args: any) => void>;\n\t#renderPropKeys: Set<string>;\n\t#jsexprPaths: Set<string>; // paths containing JS expressions\n\t#callbackList: string[];\n\t#client: PulseSocketIOClient;\n\t#path: string;\n\t#registry: Record<string, unknown>;\n\n\tconstructor(\n\t\tclient: PulseSocketIOClient,\n\t\tpath: string,\n\t\tinitialCallbacks: string[] = [],\n\t\tinitialRenderProps: string[] = [],\n\t\tregistry: Record<string, unknown> = {},\n\t\tinitialJsExprPaths: string[] = [],\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#path = path;\n\t\tthis.#registry = registry;\n\t\tthis.#callbacks = new Set(initialCallbacks);\n\t\tthis.#callbackCache = new Map();\n\t\tthis.#renderPropKeys = new Set(initialRenderProps);\n\t\tthis.#jsexprPaths = new Set(initialJsExprPaths);\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\t}\n\n\t/**\n\t * Get an object from the unified registry by its key (e.g., \"Button_1\").\n\t */\n\tgetObject(key: string): unknown {\n\t\tconst obj = this.#registry[key];\n\t\tif (obj === undefined) {\n\t\t\tthrow new Error(`[Pulse] Unknown registry key: ${key}`);\n\t\t}\n\t\treturn obj;\n\t}\n\n\t/**\n\t * Evaluate a JSExpr code string.\n\t * The code is expected to use get_object('key') calls to retrieve values from the registry.\n\t */\n\tevaluateJsExpr(code: string): unknown {\n\t\t// Create the get_object function that the code will call\n\t\tconst get_object = (key: string) => this.getObject(key);\n\t\t// Use Function constructor to avoid direct eval\n\t\t// The code is trusted (generated server-side) and uses get_object to access values\n\t\treturn new Function(\"get_object\", `return ${code}`)(get_object);\n\t}\n\n\t// Accessors used by update logic to determine which props need rebinding\n\thasCallbackPath(path: string) {\n\t\treturn this.#callbacks.has(path);\n\t}\n\n\thasRenderPropPath(path: string) {\n\t\treturn this.#renderPropKeys.has(path);\n\t}\n\n\thasAnyCallbackUnder(prefix: string): boolean {\n\t\tif (prefix === \"\") return this.#callbackList.length > 0;\n\t\tconst i = this.#lowerBound(this.#callbackList, prefix);\n\t\treturn i < this.#callbackList.length && this.#callbackList[i]!.startsWith(prefix);\n\t}\n\n\tapplyCallbackDelta(delta: PathDelta) {\n\t\t// Only update the internal callback path registry and cache. We rely on\n\t\t// accompanying update_props operations that contain the \"$cb\" placeholder\n\t\t// to trigger prop updates; transformValue will resolve to functions.\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#callbacks.delete(key);\n\t\t\t\tthis.#callbackCache.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#callbacks.add(key);\n\t\t\t}\n\t\t}\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\t}\n\n\tapplyRenderPropsDelta(delta: PathDelta) {\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#renderPropKeys.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#renderPropKeys.add(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tapplyJsExprPathsDelta(delta: PathDelta) {\n\t\tif (delta.remove) {\n\t\t\tfor (const key of delta.remove) {\n\t\t\t\tthis.#jsexprPaths.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (delta.add) {\n\t\t\tfor (const key of delta.add) {\n\t\t\t\tthis.#jsexprPaths.add(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCallback(path: string, prop: string) {\n\t\tconst key = this.#propPath(path, prop);\n\t\tlet fn = this.#callbackCache.get(key);\n\t\tif (!fn) {\n\t\t\tfn = (...args: any[]) => this.#client.invokeCallback(this.#path, key, args);\n\t\t\tthis.#callbackCache.set(key, fn);\n\t\t}\n\t\treturn fn;\n\t}\n\n\trenderNode(node: VDOMNode, currentPath = \"\"): ReactNode {\n\t\t// Handle primitives early\n\t\tif (\n\t\t\tnode == null || // catches both null and undefined\n\t\t\ttypeof node === \"boolean\" ||\n\t\t\ttypeof node === \"number\"\n\t\t) {\n\t\t\treturn node;\n\t\t}\n\n\t\t// Check for JSExpr - \"$js:code\" format has code embedded in the value\n\t\tif (typeof node === \"string\") {\n\t\t\tif (node.startsWith(JSEXPR_PREFIX)) {\n\t\t\t\tconst jsExprCode = node.slice(JSEXPR_PREFIX.length);\n\t\t\t\treturn this.evaluateJsExpr(jsExprCode) as ReactNode;\n\t\t\t}\n\t\t\treturn node;\n\t\t}\n\n\t\t// Element nodes\n\t\tif (isElementNode(node)) {\n\t\t\tconst { tag, props = {}, children = [] } = node;\n\n\t\t\tconst newProps: Record<string, any> = {};\n\t\t\tfor (const [propName, propValue] of Object.entries(props)) {\n\t\t\t\tnewProps[propName] = this.transformValue(currentPath, propName, propValue);\n\t\t\t}\n\n\t\t\tif (node.key) {\n\t\t\t\tnewProps.key = node.key;\n\t\t\t}\n\n\t\t\tconst renderedChildren = [];\n\t\t\tfor (let index = 0; index < children.length; index += 1) {\n\t\t\t\tconst child = children[index]!;\n\t\t\t\tconst childPath = currentPath ? `${currentPath}.${index}` : String(index);\n\t\t\t\trenderedChildren.push(this.renderNode(child, childPath));\n\t\t\t}\n\n\t\t\tif (isMountPointNode(node)) {\n\t\t\t\tconst componentKey = node.tag.slice(MOUNT_POINT_PREFIX.length);\n\t\t\t\tconst Component = this.#registry[componentKey] as ComponentRegistry[string];\n\t\t\t\tif (!Component) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Could not find component ${componentKey}. This is a Pulse internal error.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn createElement(Component, newProps, ...renderedChildren);\n\t\t\t}\n\n\t\t\treturn createElement(tag === FRAGMENT_TAG ? Fragment : tag, newProps, ...renderedChildren);\n\t\t}\n\n\t\t// Fallback for unknown node types\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.error(\"Unknown VDOM node type:\", node);\n\t\t}\n\t\treturn null;\n\t}\n\n\t#propPath(path: string, prop: string) {\n\t\treturn path ? `${path}.${prop}` : prop;\n\t}\n\n\ttransformValue(path: string, key: string, value: any) {\n\t\tconst propPath = this.#propPath(path, key);\n\t\tif (this.#callbacks.has(propPath)) {\n\t\t\treturn this.getCallback(path, key);\n\t\t}\n\t\tif (this.#renderPropKeys.has(propPath)) {\n\t\t\treturn this.renderNode(value, propPath);\n\t\t}\n\t\t// Check for JSExpr - \"$js:code\" format has code embedded in the value\n\t\tif (typeof value === \"string\" && value.startsWith(JSEXPR_PREFIX)) {\n\t\t\tconst jsExprCode = value.slice(JSEXPR_PREFIX.length);\n\t\t\treturn this.evaluateJsExpr(jsExprCode);\n\t\t}\n\t\treturn value;\n\t}\n\n\tinit(view: PulsePrerenderView): ReactNode {\n\t\t// Set callbacks\n\t\tthis.#callbacks = new Set(view.callbacks);\n\t\t// prune stale cached callbacks\n\t\tfor (const k of Array.from(this.#callbackCache.keys())) {\n\t\t\tif (!this.#callbacks.has(k)) this.#callbackCache.delete(k);\n\t\t}\n\t\tthis.#callbackList = [...this.#callbacks].sort();\n\n\t\t// Set render props\n\t\tthis.#renderPropKeys = new Set(view.render_props);\n\n\t\t// Set JSExpr paths\n\t\tthis.#jsexprPaths = new Set(view.jsexpr_paths);\n\n\t\treturn this.renderNode(view.vdom);\n\t}\n\n\t#ensureChildrenArray(el: ReactElement): ReactNode[] {\n\t\tconst children = (el.props as any)?.children as ReactNode | undefined;\n\t\tif (children == null) return [];\n\t\treturn Array.isArray(children) ? children.slice() : [children];\n\t}\n\n\tapplyUpdates(initialTree: ReactNode, updates: VDOMUpdate[]): ReactNode {\n\t\tlet newTree: ReactNode = initialTree;\n\t\tfor (const update of updates) {\n\t\t\tif (update.type === \"update_callbacks\") {\n\t\t\t\tthis.applyCallbackDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (update.type === \"update_render_props\") {\n\t\t\t\tthis.applyRenderPropsDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (update.type === \"update_jsexpr_paths\") {\n\t\t\t\tthis.applyJsExprPathsDelta(update.data);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst parts = update.path.split(\".\").filter((s) => s.length > 0);\n\n\t\t\tconst descend = (node: ReactNode, depth: number, path: string): ReactNode => {\n\t\t\t\tif (depth < parts.length) {\n\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\tconst element = node as ReactElement<Record<string, any> | null>;\n\t\t\t\t\tconst childKey = parts[depth]!;\n\t\t\t\t\tconst childIdx = +childKey;\n\t\t\t\t\tconst childPath = path ? `${path}.${childKey}` : childKey;\n\t\t\t\t\tif (!Number.isNaN(childIdx)) {\n\t\t\t\t\t\t// Regular child traversal\n\t\t\t\t\t\tconst childrenArr = this.#ensureChildrenArray(element);\n\t\t\t\t\t\tconst child = childrenArr[childIdx];\n\t\t\t\t\t\tchildrenArr[childIdx] = descend(child, depth + 1, childPath) as any;\n\t\t\t\t\t\treturn cloneElement(element, undefined, ...childrenArr);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Render prop traversal\n\t\t\t\t\t\tconst baseProps = (element.props ?? {}) as Record<string, any>;\n\t\t\t\t\t\tconst child = baseProps[childKey];\n\t\t\t\t\t\tconst props = {\n\t\t\t\t\t\t\t...baseProps,\n\t\t\t\t\t\t\t[childKey]: descend(child, depth + 1, childPath),\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn cloneElement(element, props);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tswitch (update.type) {\n\t\t\t\t\tcase \"replace\": {\n\t\t\t\t\t\treturn this.renderNode(update.data, update.path);\n\t\t\t\t\t}\n\t\t\t\t\tcase \"update_props\": {\n\t\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\t\tconst element = node as ReactElement;\n\t\t\t\t\t\tconst currentProps = (element.props ?? {}) as Record<string, any>;\n\t\t\t\t\t\tconst nextProps: Record<string, any> = { ...currentProps };\n\t\t\t\t\t\tconst delta = update.data;\n\t\t\t\t\t\tif (delta.remove && delta.remove.length > 0) {\n\t\t\t\t\t\t\tfor (const key of delta.remove) {\n\t\t\t\t\t\t\t\tif (key in nextProps) {\n\t\t\t\t\t\t\t\t\tdelete nextProps[key];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (delta.set) {\n\t\t\t\t\t\t\tfor (const [k, v] of Object.entries(delta.set)) {\n\t\t\t\t\t\t\t\tnextProps[k] = this.transformValue(path, k, v);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If some props were removed, use `createElement` to fully override\n\t\t\t\t\t\t// the props, as `cloneElement` shallowly merges the new props with\n\t\t\t\t\t\t// the old ones.\n\t\t\t\t\t\tconst removedSomething = (delta.remove?.length ?? 0) > 0;\n\t\t\t\t\t\tif (removedSomething) {\n\t\t\t\t\t\t\t// Preserve key + ref\n\t\t\t\t\t\t\tnextProps.key = element.key;\n\t\t\t\t\t\t\tnextProps.ref = (element as any).ref;\n\t\t\t\t\t\t\treturn createElement(element.type, nextProps, ...this.#ensureChildrenArray(element));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Don't touch children. Key and ref are transferred by cloneElement.\n\t\t\t\t\t\t\treturn cloneElement(element, nextProps);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase \"reconciliation\": {\n\t\t\t\t\t\tthis.#assertIsElement(node, parts, depth);\n\t\t\t\t\t\tconst element = node as ReactElement;\n\t\t\t\t\t\tconst prevChildren = this.#ensureChildrenArray(element);\n\t\t\t\t\t\tconst nextChildren = [];\n\n\t\t\t\t\t\tconst [newIndices, newContents] = update.new;\n\t\t\t\t\t\tconst [reuseIndices, reuseSources] = update.reuse;\n\n\t\t\t\t\t\tlet nextNew = -1,\n\t\t\t\t\t\t\tnextReuse = -1,\n\t\t\t\t\t\t\tnewIdx = -1,\n\t\t\t\t\t\t\treuseIdx = -1;\n\t\t\t\t\t\tif (newIndices.length > 0) {\n\t\t\t\t\t\t\tnextNew = newIndices[0];\n\t\t\t\t\t\t\tnewIdx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (reuseIndices.length > 0) {\n\t\t\t\t\t\t\tnextReuse = reuseIndices[0];\n\t\t\t\t\t\t\treuseIdx = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let i = 0; i < update.N; ++i) {\n\t\t\t\t\t\t\tif (i === nextNew) {\n\t\t\t\t\t\t\t\tconst contents = newContents[newIdx];\n\t\t\t\t\t\t\t\tconst childPath = path ? `${path}.${i}` : String(i);\n\t\t\t\t\t\t\t\tnextChildren.push(this.renderNode(contents, childPath));\n\t\t\t\t\t\t\t\tnextNew = newIdx < newIndices.length - 1 ? newIndices[++newIdx] : -1;\n\t\t\t\t\t\t\t} else if (i === nextReuse) {\n\t\t\t\t\t\t\t\tconst srcIdx = reuseSources[reuseIdx];\n\t\t\t\t\t\t\t\tlet src = prevChildren[srcIdx];\n\t\t\t\t\t\t\t\tconst childPath = path ? `${path}.${i}` : String(i);\n\t\t\t\t\t\t\t\t// The node may have callbacks that need to be updated for this new path\n\t\t\t\t\t\t\t\tif (this.hasAnyCallbackUnder(childPath)) {\n\t\t\t\t\t\t\t\t\tsrc = this.#rebindCallbacksInSubtree(src, childPath);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tnextChildren.push(src);\n\t\t\t\t\t\t\t\tnextReuse = reuseIdx < reuseIndices.length - 1 ? reuseIndices[++reuseIdx] : -1;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// No need to rebind callbacks, the node hasn't moved\n\t\t\t\t\t\t\t\tnextChildren.push(prevChildren[i]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Pass null to reuse previous props\n\t\t\t\t\t\treturn cloneElement(element, null!, ...nextChildren);\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(`[Pulse renderer] Unknown update type: ${(update as any)?.type}`);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tnewTree = descend(newTree, 0, \"\");\n\t\t}\n\t\treturn newTree;\n\t}\n\n\t#assertIsElement(node: ReactNode, parts: string[], depth: number): node is ReactElement {\n\t\tif (process.env.NODE_ENV !== \"production\" && !isValidElement(node)) {\n\t\t\tconsole.error(\"Invalid node:\", node);\n\t\t\tthrow new Error(`Invalid node at path ${parts.slice(0, depth).join(\".\")}`);\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Rebind callback function props within a subtree after a path-changing move\n\t#rebindCallbacksInSubtree(node: ReactNode, path: string): ReactNode {\n\t\tif (!isValidElement(node)) return node;\n\t\tconst element = node as ReactElement<Record<string, any> | null>;\n\t\tconst baseProps = (element.props ?? {}) as Record<string, any>;\n\t\tconst nextProps: Record<string, any> = { ...baseProps };\n\n\t\t// Rebind only callback props; CSS refs are path-agnostic and render-props\n\t\t// are handled by the server-side renderer via explicit updates\n\t\tfor (const key of Object.keys(baseProps)) {\n\t\t\tconst propPath = path ? `${path}.${key}` : key;\n\t\t\tif (this.hasCallbackPath(propPath)) {\n\t\t\t\tnextProps[key] = this.getCallback(path, key);\n\t\t\t}\n\t\t\tif (this.hasRenderPropPath(propPath) && this.hasAnyCallbackUnder(propPath)) {\n\t\t\t\tnextProps[key] = this.#rebindCallbacksInSubtree(baseProps[key], propPath);\n\t\t\t}\n\t\t}\n\n\t\tconst children = this.#ensureChildrenArray(element).map((child, idx) => {\n\t\t\tconst childPath = path ? `${path}.${idx}` : String(idx);\n\t\t\tif (this.hasAnyCallbackUnder(childPath)) {\n\t\t\t\treturn this.#rebindCallbacksInSubtree(child, childPath);\n\t\t\t} else {\n\t\t\t\treturn child;\n\t\t\t}\n\t\t});\n\n\t\treturn cloneElement(element, nextProps, ...children);\n\t}\n\n\t// Binary-search lower bound for prefix matching on sorted callback paths\n\t#lowerBound(arr: string[], target: string): number {\n\t\tlet lo = 0;\n\t\tlet hi = arr.length;\n\t\twhile (lo < hi) {\n\t\t\tconst mid = (lo + hi) >>> 1;\n\t\t\tif (arr[mid]! < target) {\n\t\t\t\tlo = mid + 1;\n\t\t\t} else {\n\t\t\t\thi = mid;\n\t\t\t}\n\t\t}\n\t\treturn lo;\n\t}\n}\n\n// The `component` prop should be something like `() =>\n// import('~/path/to/component') (we'll need to remap if we're importing a named export and not the default)\nexport function RenderLazy(\n\tcomponent: () => Promise<{ default: ComponentType<any> }>,\n\tfallback?: ReactNode,\n): FC<PropsWithChildren<unknown>> {\n\tconst Component = lazy(component);\n\treturn ({ children, ...props }: PropsWithChildren<unknown>) => {\n\t\treturn (\n\t\t\t<Suspense fallback={fallback}>\n\t\t\t\t<Component {...props}>{children}</Component>\n\t\t\t</Suspense>\n\t\t);\n\t};\n}\n","import {\n\tcreateContext,\n\ttype ReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { useLocation, useNavigate, useParams } from \"react-router\";\nimport { type ConnectionStatus, type Directives, PulseSocketIOClient } from \"./client\";\nimport type { RouteInfo } from \"./helpers\";\nimport type { ServerErrorInfo } from \"./messages\";\nimport { VDOMRenderer } from \"./renderer\";\nimport type { VDOM } from \"./vdom\";\n\n// =================================================================\n// Types\n// =================================================================\n\nexport interface ConnectionStatusConfig {\n\tinitialConnectingDelay: number;\n\tinitialErrorDelay: number;\n\treconnectErrorDelay: number;\n}\n\nexport interface PulseConfig {\n\tserverAddress: string;\n\tconnectionStatus: ConnectionStatusConfig;\n}\n\nexport type PulsePrerenderView = {\n\tvdom: VDOM;\n\tcallbacks: string[];\n\trender_props: string[];\n\tjsexpr_paths: string[]; // paths containing JS expressions\n};\n\nexport type PulsePrerender = {\n\tviews: Record<string, PulsePrerenderView>;\n\tdirectives: Directives;\n};\n// =================================================================\n// Context and Hooks\n// =================================================================\n\n// Context for the client, provided by PulseProvider\nconst PulseClientContext = createContext<PulseSocketIOClient | null>(null);\nconst PulsePrerenderContext = createContext<PulsePrerender | null>(null);\n\nexport const usePulseClient = () => {\n\tconst client = useContext(PulseClientContext);\n\tif (!client) {\n\t\tthrow new Error(\"usePulseClient must be used within a PulseProvider\");\n\t}\n\treturn client;\n};\n\nexport const usePulsePrerender = (path: string) => {\n\tconst ctx = useContext(PulsePrerenderContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"usePulsePrerender must be used within a PulseProvider\");\n\t}\n\tconst view = ctx.views[path];\n\tif (!view) {\n\t\tthrow new Error(`No prerender found for '${path}'`);\n\t}\n\treturn view;\n};\n\n// =================================================================\n// Provider\n// =================================================================\n\nexport interface PulseProviderProps {\n\tchildren: ReactNode;\n\tconfig: PulseConfig;\n\tprerender: PulsePrerender;\n}\n\nconst inBrowser = typeof window !== \"undefined\";\n\nexport function PulseProvider({ children, config, prerender }: PulseProviderProps) {\n\tconst [status, setStatus] = useState<ConnectionStatus>(\"ok\");\n\tconst rrNavigate = useNavigate();\n\tconst { directives } = prerender;\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: another useEffect syncs the directives without recreating the client\n\tconst client = useMemo(() => {\n\t\treturn new PulseSocketIOClient(\n\t\t\tconfig.serverAddress,\n\t\t\tdirectives,\n\t\t\trrNavigate,\n\t\t\tconfig.connectionStatus,\n\t\t);\n\t}, [config.serverAddress, rrNavigate, config.connectionStatus]);\n\tuseEffect(() => client.setDirectives(directives), [client, directives]);\n\n\tuseEffect(() => {\n\t\tif (!inBrowser) return;\n\n\t\tconst handleConnectionChange = (newStatus: ConnectionStatus) => {\n\t\t\tsetStatus(newStatus);\n\t\t};\n\n\t\tconst unsubscribe = client.onConnectionChange(handleConnectionChange);\n\n\t\t// Start connection attempt\n\t\tclient.connect();\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tclient.disconnect();\n\t\t};\n\t}, [client]);\n\n\tconst getStatusMessage = () => {\n\t\tswitch (status) {\n\t\t\tcase \"connecting\":\n\t\t\t\treturn \"Connecting...\";\n\t\t\tcase \"reconnecting\":\n\t\t\t\treturn \"Reconnecting...\";\n\t\t\tcase \"error\":\n\t\t\t\treturn \"Failed to connect to the server.\";\n\t\t\t// \"ok\" falls through to default\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t};\n\n\tconst statusMessage = getStatusMessage();\n\n\treturn (\n\t\t<PulseClientContext.Provider value={client}>\n\t\t\t<PulsePrerenderContext.Provider value={prerender}>\n\t\t\t\t{statusMessage && (\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tposition: \"fixed\",\n\t\t\t\t\t\t\tbottom: \"20px\",\n\t\t\t\t\t\t\tright: \"20px\",\n\t\t\t\t\t\t\tbackgroundColor: status === \"error\" ? \"red\" : \"#666\",\n\t\t\t\t\t\t\tcolor: \"white\",\n\t\t\t\t\t\t\tpadding: \"10px\",\n\t\t\t\t\t\t\tborderRadius: \"5px\",\n\t\t\t\t\t\t\tzIndex: 1000,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{statusMessage}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{children}\n\t\t\t</PulsePrerenderContext.Provider>\n\t\t</PulseClientContext.Provider>\n\t);\n}\n\n// =================================================================\n// View\n// =================================================================\n\nexport interface PulseViewProps {\n\tpath: string;\n\tregistry: Record<string, unknown>;\n}\n\nexport function PulseView({ path, registry }: PulseViewProps) {\n\tconst client = usePulseClient();\n\tconst initialView = usePulsePrerender(path);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: We only want to lose the renderer on unmount. initialView will change on every navigation with our current setup, so we hack around it with another useEffect below. This is not ideal and will be fixed in the future.\n\tconst renderer = useMemo(\n\t\t() =>\n\t\t\tnew VDOMRenderer(\n\t\t\t\tclient,\n\t\t\t\tpath,\n\t\t\t\tinitialView.callbacks,\n\t\t\t\tinitialView.render_props,\n\t\t\t\tregistry,\n\t\t\t\tinitialView.jsexpr_paths,\n\t\t\t),\n\t\t[client, path, registry],\n\t);\n\tconst [tree, setTree] = useState<ReactNode>(() => renderer.init(initialView));\n\tconst [serverError, setServerError] = useState<ServerErrorInfo | null>(null);\n\n\tconst location = useLocation();\n\tconst params = useParams();\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: using hacky deep equality for params\n\tconst routeInfo = useMemo(() => {\n\t\tconst { \"*\": catchall = \"\", ...pathParams } = params;\n\t\tconst queryParams = new URLSearchParams(location.search);\n\t\treturn {\n\t\t\thash: location.hash,\n\t\t\tpathname: location.pathname,\n\t\t\tquery: location.search,\n\t\t\tqueryParams: Object.fromEntries(queryParams.entries()),\n\t\t\tpathParams,\n\t\t\tcatchall: catchall.length > 0 ? catchall.split(\"/\") : [],\n\t\t} satisfies RouteInfo;\n\t}, [location.hash, location.pathname, location.search, JSON.stringify(params)]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: We don't want to unmount on navigation, so another useEffect sync the routeInfo on navigation.\n\tuseEffect(() => {\n\t\tif (inBrowser) {\n\t\t\tclient.mountView(path, {\n\t\t\t\trouteInfo,\n\t\t\t\tonInit: (view) => {\n\t\t\t\t\tsetTree(renderer.init(view));\n\t\t\t\t},\n\t\t\t\tonUpdate: (ops) => {\n\t\t\t\t\tsetTree((prev) => (prev == null ? prev : renderer.applyUpdates(prev, ops)));\n\t\t\t\t},\n\t\t\t\tonJsExec: (msg) => {\n\t\t\t\t\tlet result: any;\n\t\t\t\t\tlet error: string | null = null;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresult = renderer.evaluateJsExpr(msg.code);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\terror = e instanceof Error ? e.message : String(e);\n\t\t\t\t\t}\n\t\t\t\t\tclient.sendJsResult(msg.id, result, error);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst offErr = client.onServerError((p, err) => {\n\t\t\t\tif (p === path) setServerError(err);\n\t\t\t});\n\t\t\treturn () => {\n\t\t\t\toffErr();\n\t\t\t\tclient.unmount(path);\n\t\t\t};\n\t\t}\n\t\t// routeInfo is NOT included here on purpose\n\t}, [client, renderer, path]);\n\n\tuseEffect(() => {\n\t\tif (inBrowser) {\n\t\t\tclient.navigate(path, routeInfo);\n\t\t}\n\t}, [client, path, routeInfo]);\n\t// Hack for our current prerendering setup on client-side navigation. Will be improved soon\n\tconst hasRendered = useRef(false);\n\tuseEffect(() => {\n\t\t// First rendering pass, no need to update the tree\n\t\tif (!hasRendered.current) {\n\t\t\thasRendered.current = true;\n\t\t}\n\t\t// 2nd+ rendering pass. Happens when a route stays mounted on navigation.\n\t\telse {\n\t\t\tsetTree(renderer.init(initialView));\n\t\t}\n\t\treturn () => {\n\t\t\thasRendered.current = false;\n\t\t};\n\t}, [initialView, renderer]);\n\n\tif (serverError) {\n\t\treturn <ServerError error={serverError} />;\n\t}\n\n\treturn tree;\n}\n\nfunction ServerError({ error }: { error: ServerErrorInfo }) {\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tpadding: 16,\n\t\t\t\tborder: \"1px solid #e00\",\n\t\t\t\tbackground: \"#fff5f5\",\n\t\t\t\tcolor: \"#900\",\n\t\t\t\tfontFamily:\n\t\t\t\t\t'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n\t\t\t\twhiteSpace: \"pre-wrap\",\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ fontWeight: 700, marginBottom: 8 }}>Server Error during {error.phase}</div>\n\t\t\t{error.message && <div>{error.message}</div>}\n\t\t\t{error.stack && (\n\t\t\t\t<details open style={{ marginTop: 8 }}>\n\t\t\t\t\t<summary>Stack trace</summary>\n\t\t\t\t\t<pre style={{ margin: 0 }}>{error.stack}</pre>\n\t\t\t\t</details>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useEffect, useMemo } from \"react\";\nimport type { ChannelBridge } from \"./channel\";\nimport { usePulseClient } from \"./pulse\";\n\nexport function usePulseChannel(channelId: string): ChannelBridge {\n\tconst client = usePulseClient();\n\tconst bridge = useMemo(() => {\n\t\tif (!channelId) {\n\t\t\tthrow new Error(\"usePulseChannel requires a non-empty channelId\");\n\t\t}\n\t\treturn client.acquireChannel(channelId);\n\t}, [client, channelId]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tclient.releaseChannel(channelId);\n\t\t};\n\t}, [client, channelId]);\n\n\treturn bridge;\n}\n"],"mappings":"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,SACA,WACA,OACA,OACA,WACA,OACA,SACA,WACA,WACA,OACA,WACA,MACA,SACA,QACA,SACA,WACA,OACA,iBACA,CAC8D,CAwBzD,EAAiB,EAtBC,CACvB,WACA,WACA,cACA,aACA,cACA,eACA,sBACA,WACA,QACA,OACA,QACA,eACA,SACA,eACA,UACA,aACA,UACA,MACA,SACA,iBACA,CACiE,CAE5D,GAAkB,GAA0B,EAAe,EAAI,CAc/D,GAAkB,EAZC,CACxB,WACA,OACA,OACA,QACA,aACA,cACA,aACA,iBACA,aACA,sBACA,CACoE,CAG/D,GAAgB,EADC,CAAC,QAAQ,CAC+B,CAUzD,GAAiB,EARC,CACvB,SACA,MACA,OACA,QACA,QACA,OACA,CACiE,CAS5D,GAAoB,EAPC,CAC1B,WACA,OACA,OACA,oBACA,eACA,CAC0E,CAerEC,GAAgB,EAbC,CACtB,gBACA,SACA,eACA,WACA,UACA,SACA,SACA,OACA,aACA,SACA,MACA,CAC8D,CAmBzD,GAAkB,EAjBC,CACxB,QACA,kBACA,SACA,OACA,iBACA,MACA,SACA,QACA,QACA,cACA,WACA,eACA,cACA,YACA,UACA,CACoE,CA6B/D,GAAiB,EA3BC,CACvB,MACA,cACA,WACA,SACA,QACA,UACA,gBACA,eACA,iBACA,QACA,MACA,SACA,SACA,QACA,QACA,SACA,WACA,SACA,WACA,SACA,OACA,SACA,IACA,IACA,gBACA,CACiE,CA6C5D,GAAiB,EA3CC,8ZA0CvB,CACiE,CAG5D,GAAiB,EADC,CAAC,UAAU,CAC+B,CAG5D,GAAc,EADC,CAAC,QAAS,OAAO,CACmB,CAqBnD,GAAgB,EAnBC,CACtB,KACA,cACA,WACA,gBACA,OACA,WACA,aACA,cACA,YACA,QACA,iBACA,MACA,OACA,UACA,MACA,SACA,QACA,CAC8D,CAGzD,GAAe,EADC,CAAC,OAAO,CAC8B,CAUtD,GAAiB,EARC,CACvB,OACA,MACA,MACA,MACA,UACA,QACA,CACiE,CAG5D,EAAe,EADC,CAAC,OAAQ,WAAW,CACkB,CAQtD,GAAiB,EANF,CACpB,WACA,QACA,OACA,UACA,CAC8D,CAsBzD,GAAkB,EApBC,CACxB,OACA,SACA,OACA,OACA,SACA,QACA,oBACA,eACA,QACA,UACA,SACA,OACA,WACA,WACA,UACA,SACA,UACA,SACA,CACoE,CAM/D,GAAoB,EAJC,CAC1B,WACA,QACA,CAC0E,CAWrE,GAAkB,EATC,CACxB,kBACA,WACA,QACA,QACA,WACA,OACA,QACA,CACoE,CAW/D,GAAkB,EATC,CACxB,eACA,OACA,OACA,QACA,UACA,oBACA,eACA,CACoE,CAO/D,GAAoB,EALC,CAC1B,MACA,WACA,QACA,CAC0E,CAGrE,EAAiB,EADC,CAAC,OAAO,CACkC,CAE5D,GAAiB,GAAqB,EAAuB,EAAI,CAejE,GAAwB,GAAoC,CAbzC,CACxB,QACA,cACA,QACA,gBACA,YACA,WACA,iBACA,MACA,OACA,OACA,UACA,CACoF,CACpF,MAAQ,GAAO,EAAU,MACzB,QAAU,GAAO,EAAU,QAC3B,CAAC,CACI,GAAmB,IAA4B,CACpD,GAAG,EAAuB,EAAI,CAC9B,GAAG,GAAsB,EAAI,CAC7B,EAgBK,GAAkB,EAdC,CACxB,eACA,WACA,SACA,WACA,OACA,WACA,gBACA,OACA,OACA,QACA,oBACA,eACA,CACoE,CAG/D,GAAgB,EADC,CAAC,OAAO,CACgC,CAWzD,GAAkB,EATC,CACxB,SACA,QACA,QACA,MACA,SACA,OACA,QACA,CACoE,CAK/D,GAAwB,EAHE,CAC/B,QACA,CACuF,CAmBlF,EAAqB,EAjBE,CAC5B,OACA,YACA,UACA,UACA,UACA,QACA,QACA,OACA,UACA,KACA,QACA,SACA,SACA,SACA,QACA,CAC8E,CAUzE,EAAoB,EARE,CAC3B,OACA,QACA,KACA,QACA,SACA,QACA,CAC2E,CAatE,GAAiB,EAXC,CACvB,QACA,UACA,SACA,cACA,cACA,QACA,QACA,UACA,QACA,CACiE,CAW5D,GAAoB,EATL,CACpB,WACA,kBACA,QACA,UACA,KACA,QACA,SACA,CACoE,CAQ/D,EAAwB,EANH,CAC1B,QAC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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-ui-client",
3
- "version": "0.1.49",
3
+ "version": "0.1.51",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,