phlex-reactive 0.9.3 → 0.9.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +197 -0
- data/README.md +282 -2
- data/app/controllers/phlex/reactive/actions_controller.rb +120 -10
- data/app/javascript/phlex/reactive/inspect.js +225 -0
- data/app/javascript/phlex/reactive/inspect.min.js +4 -0
- data/app/javascript/phlex/reactive/inspect.min.js.map +10 -0
- data/app/javascript/phlex/reactive/reactive_controller.js +534 -6
- data/app/javascript/phlex/reactive/reactive_controller.min.js +2 -2
- data/app/javascript/phlex/reactive/reactive_controller.min.js.map +3 -3
- data/lib/generators/phlex/reactive/claude/USAGE +15 -0
- data/lib/generators/phlex/reactive/claude/claude_generator.rb +86 -0
- data/lib/generators/phlex/reactive/install/install_generator.rb +3 -0
- data/lib/generators/phlex/reactive/install/templates/phlex_reactive.rb.erb +56 -0
- data/lib/phlex/reactive/authorization.rb +118 -0
- data/lib/phlex/reactive/claude/skills/phlex-reactive-debugging/SKILL.md +105 -0
- data/lib/phlex/reactive/component/dsl.rb +70 -0
- data/lib/phlex/reactive/component/helpers.rb +193 -8
- data/lib/phlex/reactive/component/identity.rb +10 -1
- data/lib/phlex/reactive/component/lazy.rb +79 -0
- data/lib/phlex/reactive/component/registry.rb +7 -1
- data/lib/phlex/reactive/component.rb +1 -0
- data/lib/phlex/reactive/defer.rb +363 -0
- data/lib/phlex/reactive/deferred_render_job.rb +116 -0
- data/lib/phlex/reactive/doctor.rb +79 -11
- data/lib/phlex/reactive/engine.rb +16 -2
- data/lib/phlex/reactive/inspector/report.rb +140 -0
- data/lib/phlex/reactive/inspector.rb +253 -0
- data/lib/phlex/reactive/log_subscriber.rb +10 -0
- data/lib/phlex/reactive/mcp/base_tool.rb +57 -0
- data/lib/phlex/reactive/mcp/runner.rb +24 -0
- data/lib/phlex/reactive/mcp/server.rb +47 -0
- data/lib/phlex/reactive/mcp/tools/actions_tool.rb +43 -0
- data/lib/phlex/reactive/mcp/tools/components_tool.rb +39 -0
- data/lib/phlex/reactive/mcp/tools/config_tool.rb +74 -0
- data/lib/phlex/reactive/mcp/tools/doctor_tool.rb +36 -0
- data/lib/phlex/reactive/mcp/tools/find_tool.rb +66 -0
- data/lib/phlex/reactive/mcp.rb +58 -0
- data/lib/phlex/reactive/reply.rb +18 -0
- data/lib/phlex/reactive/response.rb +47 -2
- data/lib/phlex/reactive/streamable.rb +5 -1
- data/lib/phlex/reactive/version.rb +1 -1
- data/lib/phlex/reactive.rb +253 -3
- data/lib/tasks/phlex_reactive.rake +28 -0
- metadata +22 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Controller as S}from"@hotwired/stimulus";import{confirmResolver as T}from"phlex/reactive/confirm";import{computeReducer as k}from"phlex/reactive/compute";function b(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:visit"])return;j["reactive:visit"]=function(){let z=this.getAttribute("data-url");if(z)window.Turbo.visit(z,{action:"advance"})}}function w(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:token"])return;j["reactive:token"]=function(){let z=this.getAttribute("data-reactive-token-value"),Q=this.getAttribute("target");if(!z||!Q)return;let W=document.getElementById(Q);if(W)W.setAttribute("data-reactive-token-value",z)}}function y(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:js"])return;j["reactive:js"]=function(){let z=B(this.getAttribute("data-reactive-ops"));if(!z.length)return;let Q=this.getAttribute("target"),W=Q?document.getElementById(Q):null;if(Q&&!W)return;R(z,(X)=>t(X,W))}}var O=!1;function h(){if(O)return;if(typeof document>"u"||!document.addEventListener)return;O=!0,document.addEventListener("turbo:before-stream-render",v)}function v(j){let z=j.detail,Q=z?.render;if(typeof Q!=="function"||Q.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(L);else setTimeout(L,0);return}let W=async(X)=>{await Q(X),L()};W.__reactiveDismissWrapped=!0,z.render=W}function L(){let j=document.querySelectorAll("[data-reactive-dismiss-after]");for(let z of j){if(z.hasAttribute("data-reactive-dismiss-scheduled"))continue;let Q=Number(z.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite(Q)||Q<=0)continue;z.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>z.remove(),Q)}}function Qj(){O=!1}var x=!1;function f(){if(x)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;x=!0;let j=()=>{let z=document.documentElement;if(typeof z?.toggleAttribute!=="function")return;z.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};j(),window.addEventListener("online",j),window.addEventListener("offline",j)}function Wj(){x=!1}var P="phlex-reactive:latency",M=!1;function u(j){if(typeof sessionStorage>"u")return;sessionStorage.setItem(P,String(j))}function p(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(P),M=!1}function m(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:u,disableLatencySim:p}}function Xj(){M=!1}function F(){b(),w(),y(),h(),f(),m()}function c(j){return j.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)F();else document.addEventListener("turbo:load",F,{once:!0});var N=!1;function g(){if(N)return;if(typeof document>"u")return;let j=document.querySelectorAll('[data-controller~="reactive"]');if(!j||j.length===0)return;console.warn("[phlex-reactive] found "+j.length+' element(s) with data-controller="reactive" '+"but the reactive controller never connected. It is loaded but not registered — "+'add `application.register("reactive", ReactiveController)` (importmap) or import it into app/javascript/controllers/ for lazyLoadControllersFrom apps. See the README.')}function Zj(){N=!1}function $j(){N=!0}if(typeof window<"u"&&typeof document<"u"){let j=()=>setTimeout(g,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",j,{once:!0});else j()}var d=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function l(j){let z=String(j).toLowerCase();return z.startsWith("on")||d.has(z)}function s(j,z,Q){let[W,X,Z]=z;j.classList.add(W,X),Q(),requestAnimationFrame(()=>{j.classList.remove(X),j.classList.add(Z)});let $=!1,G=()=>{if($)return;$=!0,j.classList.remove(W,Z)};j.addEventListener("animationend",G,{once:!0}),setTimeout(G,350)}var C=Object.freeze({show:(j,z)=>A(j,!1,z),hide:(j,z)=>A(j,!0,z),toggle:(j,z)=>A(j,!j.hidden,z),add_class:(j,z)=>j.classList.add(...z.classes??[]),remove_class:(j,z)=>j.classList.remove(...z.classes??[]),toggle_class:(j,z)=>(z.classes??[]).forEach((Q)=>j.classList.toggle(Q)),set_attr:(j,z)=>{if(D(z.name))j.setAttribute(z.name,z.value??"")},remove_attr:(j,z)=>{if(D(z.name))j.removeAttribute(z.name)},toggle_attr:(j,z)=>{if(!D(z.name))return;if(j.hasAttribute(z.name))j.removeAttribute(z.name);else j.setAttribute(z.name,"")},focus:(j)=>j.focus?.(),focus_first:(j)=>i(j)?.focus?.(),text:(j,z)=>{let Q=String(z.value??"");if(j.textContent!==Q)j.textContent=Q},dispatch:(j,z)=>{j.dispatchEvent(new CustomEvent(z.name,{bubbles:!0,composed:!0,detail:z.detail??{}}))}});function A(j,z,Q){if(Q?.transition)s(j,Q.transition,()=>j.hidden=z);else j.hidden=z}function D(j){if(!l(j))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(j)} — skipped`),!1}var o=/^#[A-Za-z_][\w-]*$/;function n(j){if(typeof j==="string"&&o.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(j)} — skipped`),!1}function r(j,z){let Q=j.getAttribute("data-reactive-show-equals");if(Q!==null)return z===Q;let W=j.getAttribute("data-reactive-show-not");if(W!==null)return z!==W;let X=j.getAttribute("data-reactive-show-in");if(X!==null){try{let Z=JSON.parse(X);if(Array.isArray(Z))return Z.includes(z)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(X)} — skipped`),null}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}var a='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function i(j){return j.querySelectorAll?.(a)?.[0]??null}function B(j){if(Array.isArray(j))return j;if(typeof j!=="string")return[];try{let z=JSON.parse(j);return Array.isArray(z)?z:[]}catch{return[]}}function R(j,z){for(let Q of j){if(!Array.isArray(Q))continue;let[W,X={}]=Q;if(!Object.hasOwn(C,W)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(W)} — skipped`);continue}for(let Z of z(X))C[W](Z,X)}}function t(j,z){let Q=j.to;if(z){if(Q==="@root")return[z];if(typeof Q!=="string"||Q==="")return[];if(j.global)return[...document.querySelectorAll(Q)];return[...z.querySelectorAll(Q)]}if(typeof Q!=="string"||Q===""||Q==="@root")return[];return[...document.querySelectorAll(Q)]}class Gj extends S{static values={token:String};#E;#H=new Map;#G=new Map;#f;#M;#F;#N=0;#J=new Map;#L=new WeakMap;#V=new Map;#K;#q;#Y;#j;connect(){if(N=!0,this.element.id==="")console.warn("[phlex-reactive] a reactive root has no id; its next-action token can't self-match "+"and may fall back to the first token in the response → a silent HTTP 403 on the NEXT action. "+"Put id: on the SAME element as reactive_attrs — use div(**reactive_root) (emits id + token together), "+"or div(id:, **reactive_attrs). The id: must NOT be on a child. See the README.");if(this.#u()){if(this.#K=()=>this.#O(),this.element.addEventListener?.("turbo:morph-element",this.#K),this.#O(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#Zj()}if(this.#Gj())this.#j=()=>this.#y(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#j),this.#y()}#u(){if((this.element.getAttribute?.("data-action")??"").includes("reactive#trackDirty"))return!0;let j=this.element.querySelectorAll?.('[data-action*="reactive#trackDirty"]')??[];for(let z of j)if(this.#z(z))return!0;return!1}disconnect(){this.#s(),this.#n(),this.#$j(),this.#Kj()}dispatch(j){let{action:z,params:Q,debounce:W,throttle:X,confirm:Z,outside:$,window:G,optimistic:q,loading:Y}=j.params;if(!z)return;if($&&this.element.contains(j.target))return;let H=j.currentTarget??j.target;if(!G&&!this.#Uj(q,H))j.preventDefault();if(!Z)return this.#S(H,z,Q,W,X,q,Y);Promise.resolve().then(()=>T(Z)).catch(()=>!1).then((J)=>{if(J)this.#S(H,z,Q,W,X,q,Y)})}runOps(j){let{ops:z,outside:Q,window:W}=j.params;if(Q&&this.element.contains(j.target))return;if(!W)j.preventDefault();this.#Vj(this.#Hj(z))}trackDirty(){this.#O()}recompute(j){let z=this.#m(),Q=z.map(([J])=>J),W=this.#I(),X=new Map,Z=(J)=>{if(X.has(J))return X.get(J);let K=null;for(let U of this.element.querySelectorAll(`[name="${J}"]`))if(W(U)){K=U;break}return X.set(J,K),K};for(let J of Q)this.#B(J,Z(J)?.value??"");let $=this.element.getAttribute("data-reactive-compute-reducer-param"),G=$?k($):null;if(!G){this.#R({},Z);return}let q=this.#p("data-reactive-compute-outputs-param"),Y={};for(let[J,K]of z){let U=Z(J);if(K==="string")Y[J]=U?.value??"";else{let _=Number(U?.value);Y[J]=Number.isFinite(_)?_:0}}let H=G(Y,{changed:this.#c(j,Q)})||{};for(let J of q){if(!(J in H))continue;let K=Z(J);if(K){if(String(H[J])===K.value)continue;K.value=H[J],K.dispatchEvent(new Event("input",{bubbles:!0}))}else this.#B(J,H[J])}this.#R(H,Z)}listnavNext(j){this.#C(j,1)}listnavPrev(j){this.#C(j,-1)}listnavPick(j){let z=this.#A(j),Q=z.findIndex((W)=>W.hasAttribute("data-reactive-highlighted"));if(Q<0)return;j.preventDefault(),z[Q].click()}listnavClose(j){for(let z of this.#A(j))z.removeAttribute("data-reactive-highlighted")}#C(j,z){let Q=this.#A(j);if(!Q.length)return;j.preventDefault();let W=Q.findIndex(($)=>$.hasAttribute("data-reactive-highlighted")),X=W<0?z>0?0:Q.length-1:(W+z+Q.length)%Q.length;for(let $ of Q)$.removeAttribute("data-reactive-highlighted");let Z=Q[X];Z.setAttribute("data-reactive-highlighted","true"),Z.scrollIntoView?.({block:"nearest"})}#A(j){let Q=(j?.currentTarget??j?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!Q)return[];let W=this.#I();return Array.from(this.element.querySelectorAll(Q)).filter(W)}#p(j){let z=this.element.getAttribute(j);if(!z)return[];try{let Q=JSON.parse(z);return Array.isArray(Q)?Q:[]}catch{return[]}}#m(){let j=this.element.getAttribute("data-reactive-compute-inputs-param");if(!j)return[];try{let z=JSON.parse(j);if(Array.isArray(z))return z.map((Q)=>[Q,"number"]);if(z&&typeof z==="object")return Object.entries(z);return[]}catch{return[]}}#c(j,z){let Q=j?.target;if(!Q?.name||typeof Q.closest!=="function")return null;if(!z.includes(Q.name))return null;return this.#z(Q)?Q.name:null}#B(j,z){let Q=String(z);for(let W of this.#g(j)){if(W.textContent===Q)continue;W.textContent=Q}}#g(j){let z=this.element.querySelectorAll(`[data-reactive-text="${j}"]`);return Array.from(z).filter((Q)=>this.#z(Q))}#R(j,z){let Q=this.#d();for(let[W,X]of Object.entries(Q)){let Z=W in j?j[W]:z(W)?.value;if(Z===void 0||Z===null)continue;let $=String(Z);for(let G of Array.isArray(X)?X:[X]){if(!n(G))continue;for(let q of document.querySelectorAll(G)){if(q.textContent===$)continue;q.textContent=$}}}}#d(){let j=this.element.getAttribute("data-reactive-compute-mirror-param");if(!j)return{};try{let z=JSON.parse(j);return z&&typeof z==="object"&&!Array.isArray(z)?z:{}}catch{return{}}}#S(j,z,Q,W,X,Z,$){if(this.#_("reactive:before-dispatch",{action:z,params:this.#h(Q),element:this.element},{cancelable:!0}).defaultPrevented)return;let q=Number(W)||0;if(q>0)return this.#l(j,q,z,Q,Z,$);let Y=Number(X)||0;if(Y>0)return this.#o(j,Y,z,Q,Z,$);return this.#U(z,Q,Z,j,$)}#U(j,z,Q,W,X){let Z=this.#_j(Q,W),$=this.#Mj(j,W,X);return this.queue=(this.queue??Promise.resolve()).then(()=>this.#zj(j,z,Z,$)),this.queue}#l(j,z,Q,W,X,Z){this.#D(j);let $=()=>{this.#D(j),this.#U(Q,W,X,j,Z)},G=setTimeout($,z);j?.addEventListener?.("blur",$,{once:!0}),this.#H.set(j,{timer:G,flush:$})}#D(j){let z=this.#H.get(j);if(!z)return;clearTimeout(z.timer),j?.removeEventListener?.("blur",z.flush),this.#H.delete(j)}#s(){for(let j of[...this.#H.keys()])this.#D(j)}#o(j,z,Q,W,X,Z){let $=this.#G.get(j)??new Map;if($.has(Q))return;let G=setTimeout(()=>{if($.delete(Q),$.size===0)this.#G.delete(j)},z);return $.set(Q,G),this.#G.set(j,$),this.#U(Q,W,X,j,Z)}#n(){for(let j of this.#G.values())for(let z of j.values())clearTimeout(z);this.#G.clear()}#_(j,z,{cancelable:Q=!1}={}){let W=new CustomEvent(j,{bubbles:!0,composed:!0,cancelable:Q,detail:z});return(this.element.isConnected?this.element:document).dispatchEvent(W),W}#Q(j,z,Q,W){let X=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#U(j,z)};this.#_("reactive:error",{action:j,params:Q,...W,retry:X})}#W(j){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",j)}#r(){this.element?.removeAttribute?.("data-reactive-error")}#a(){let j=document.querySelector("[data-reactive-error-flash]");if(!j?.content)return;let z=j.getAttribute("data-reactive-error-flash")||"flash",Q=document.getElementById(z);if(!Q)return;Q.appendChild(j.content.cloneNode(!0))}#i(){if(typeof sessionStorage>"u")return Promise.resolve();let j=Number(sessionStorage.getItem(P));if(!Number.isFinite(j)||j<=0)return Promise.resolve();if(!M)M=!0,console.warn(`[phlex-reactive] latency simulator ACTIVE — every action is delayed by ${j}ms. Call PhlexReactive.disableLatencySim() (or clear sessionStorage) to turn it off.`);return new Promise((z)=>setTimeout(z,j))}#t(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#T(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#e(j){if(!j)return[];let z=[],Q=/<turbo-stream\b([^>]*)>/g,W;while((W=Q.exec(j))!==null){let X=W[1],Z=X.match(/\baction="([^"]*)"/)?.[1]??"?",$=X.match(/\btarget="([^"]*)"/)?.[1];z.push($?`${Z} → #${$}`:Z)}return z}#jj(j){let{action:z,status:Q,ms:W}=j,Z=`reactive ${this.element?.id?`#${this.element.id} `:""}${z} → ${Q??"—"} (${Math.round(W)}ms)`;if(console.groupCollapsed(Z),console.log(`params: [${j.paramNames.join(", ")}] + collected: [${j.fieldNames.join(", ")}]`),console.log(`encoding: ${j.encoding}`),j.streams.length)console.log(`streams: ${j.streams.join(" ")}`);console.log(`token: ${j.tokenRefreshed?"refreshed ✓":"unchanged"}`),console.groupEnd()}async#zj(j,z,Q,W){let{fields:X,files:Z}=this.#Wj(),$=this.#h(z),G={...X,...$},q=this.#X,Y=Z.length>0,H=Y?this.#qj(q,j,G,Z):JSON.stringify({token:q,act:j,params:G}),J=this.#t()?{action:j,paramNames:Object.keys($),fieldNames:Object.keys(X),encoding:Y?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#T()}:null;await this.#i();try{if(navigator.onLine===!1){this.#Z(Q),this.#W("offline"),this.#Q(j,z,G,{kind:"offline"});return}let K;try{let V={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#Ej()};if(!Y)V["Content-Type"]="application/json";let I=this.#Fj();if(I)V["X-Pgbus-Connection"]=I;K=await fetch(this.#xj(),{method:"POST",headers:V,body:H,credentials:"same-origin",signal:AbortSignal.timeout(this.#Pj())})}catch(V){if(console.error("[phlex-reactive] action error",V),this.#Z(Q),V?.name==="TimeoutError"||V?.name==="AbortError"){this.#W("timeout"),this.#Q(j,z,G,{kind:"timeout"});return}this.#a(),this.#W("network"),this.#Q(j,z,G,{kind:"network"});return}if(J)J.status=K.status;if(K.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#Z(Q),this.#W("redirected"),this.#Q(j,z,G,{kind:"redirected",status:K.status});return}if(!K.ok){let V=await K.text();if(console.error(`[phlex-reactive] action failed: HTTP ${K.status}`,V),this.#Z(Q),(K.headers.get("Content-Type")||"").includes("turbo-stream")){let I=this.#b(V);if(this.#X=I??this.#X,J)this.#k(J,V,I);window.Turbo.renderStreamMessage(V)}this.#W("http"),this.#Q(j,z,G,{kind:"http",status:K.status,body:V});return}let U=K.headers.get("Content-Type")||"";if(!U.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${U}" — no update applied`),this.#Z(Q),this.#W("content-type"),this.#Q(j,z,G,{kind:"content-type",status:K.status});return}let _=await K.text(),E=this.#b(_);if(this.#X=E??this.#X,J)this.#k(J,_,E);window.Turbo.renderStreamMessage(_),this.#r(),this.#_("reactive:applied",{action:j,params:G,html:_})}catch(K){console.error("[phlex-reactive] action error",K),this.#Z(Q),this.#_("reactive:error",{action:j,params:G,kind:"apply"})}finally{if(W?.(),J)this.#jj({...J,ms:this.#T()-J.started})}}#k(j,z,Q){j.streams=this.#e(z),j.tokenRefreshed=Q!=null}get#X(){return this.#E??this.tokenValue}set#X(j){this.#E=j}#b(j){let z=this.element.id;if(!z)return j.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:Q,self:W}=this.#Qj(z),X=j.match(Q);if(X)return X[1];let Z=j.match(W);if(Z)return Z[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#Qj(j){let z=this.#F;if(z&&z.id===j)return z;let Q=c(j);return this.#F={id:j,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${Q}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${Q}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#z(j){return j.closest('[data-controller~="reactive"]')===this.element}#I(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(z)=>this.#z(z)}#Wj(){let j={},z=[],Q=this.#I();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((W)=>{if(!Q(W))return;if(W.type==="file")for(let X of W.files??[])z.push({name:W.name,file:X,multiple:W.multiple});else if(W.type==="checkbox")j[W.name]=W.checked;else if(W.type==="radio"){if(W.checked)j[W.name]=W.value}else j[W.name]=W.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((W)=>{if(!Q(W))return;let X=W.getAttribute("name");if(!X)return;let Z=j[X];if(Z==null||Z==="")j[X]=W.value??W.textContent??W.innerHTML??""}),{fields:j,files:z}}#O(){if(typeof this.element?.querySelectorAll!=="function")return;let j=0;if(this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((z)=>{if(!this.#z(z))return;if(z.type==="file")return;if(this.#Xj(z))z.setAttribute("data-reactive-dirty","true"),j++;else z.removeAttribute("data-reactive-dirty")}),j>0)this.element.setAttribute("data-reactive-dirty",String(j));else this.element.removeAttribute("data-reactive-dirty")}#Xj(j){if(j.type==="checkbox"||j.type==="radio")return j.checked!==j.defaultChecked;if(j.tag==="select"||j.options)return Array.from(j.options??[]).some((z)=>z.selected!==z.defaultSelected);return j.value!==j.defaultValue}#w(){let j=this.element.getAttribute?.("data-reactive-dirty"),z=Number(j);return Number.isFinite(z)&&z>0?z:0}#Zj(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#q=(j)=>{if(this.#w()===0)return;return j.preventDefault(),j.returnValue="You have unsaved changes.",j.returnValue},this.#Y=(j)=>{if(this.#w()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))j.preventDefault?.()},window.addEventListener("beforeunload",this.#q),window.addEventListener("turbo:before-visit",this.#Y)}#$j(){if(this.#K)this.element.removeEventListener?.("turbo:morph-element",this.#K),this.#K=void 0;if(typeof window<"u"&&typeof window.removeEventListener==="function"){if(this.#q)window.removeEventListener("beforeunload",this.#q);if(this.#Y)window.removeEventListener("turbo:before-visit",this.#Y)}this.#q=void 0,this.#Y=void 0}#Gj(){let j=this.element.querySelectorAll?.("[data-reactive-show-field]")??[];for(let z of j)if(this.#z(z))return!0;return!1}#y(){if(typeof this.element?.querySelectorAll!=="function")return;let j=this.#I(),z=new Map;for(let Q of this.element.querySelectorAll("[data-reactive-show-field]")){if(!j(Q))continue;let W=Q.getAttribute("data-reactive-show-field");if(!W)continue;if(!z.has(W))z.set(W,this.#Jj(W,j));let X=z.get(W);if(X===null)continue;let Z=r(Q,X);if(Z===null)continue;Q.hidden=!Z}}#Jj(j,z){let Q=!1,W=null;for(let X of this.element.querySelectorAll(`[name="${j}"]`)){if(!z(X))continue;if(X.type==="checkbox")return X.checked?"true":"false";if(X.type==="radio"){if(X.checked)return X.value??"";Q=!0;continue}W??=X}if(W)return W.value??"";return Q?"":null}#Kj(){if(!this.#j)return;this.element.removeEventListener?.("input",this.#j),this.element.removeEventListener?.("change",this.#j),this.element.removeEventListener?.("turbo:morph-element",this.#j),this.#j=void 0}#qj(j,z,Q,W){let X=new FormData;X.append("token",j),X.append("act",z);for(let[$,G]of Object.entries(Q))this.#x(X,`params[${$}]`,G);let Z=this.#Yj(W);for(let{name:$,file:G,multiple:q}of W){let H=q||Z.has($)?`params[${$}][]`:`params[${$}]`;X.append(H,G,G.name)}return X}#x(j,z,Q){if(Q==null)j.append(z,"");else if(Array.isArray(Q))Q.forEach((W,X)=>this.#x(j,`${z}[${X}]`,W));else if(typeof Q==="object")for(let[W,X]of Object.entries(Q))this.#x(j,`${z}[${W}]`,X);else j.append(z,String(Q))}#Yj(j){let z=new Map;for(let{name:Q}of j)z.set(Q,(z.get(Q)??0)+1);return new Set([...z].filter(([,Q])=>Q>1).map(([Q])=>Q))}#h(j){if(!j)return{};try{return typeof j==="string"?JSON.parse(j):j}catch{return{}}}#Hj(j){return B(j)}#Vj(j){R(j,(z)=>this.#P(z))}#P(j){let z=j.to;if(z==="@root")return[this.element];if(typeof z!=="string"||z==="")return[];if(j.global)return[...document.querySelectorAll(z)];return[...this.element.querySelectorAll(z)].filter((Q)=>this.#z(Q))}#Uj(j,z){if(j?.checked!=="keep")return!1;let Q=z?.type;return Q==="checkbox"||Q==="radio"}#_j(j,z){if(!j)return null;let Q=this.#Ij(j,z),W=[];for(let X of Q){if(j.add_class){let Z=j.add_class.filter(($)=>!X.classList.contains($));if(X.classList.add(...Z),Z.length)W.push(()=>X.classList.remove(...Z))}if(j.remove_class){let Z=j.remove_class.filter(($)=>X.classList.contains($));if(X.classList.remove(...Z),Z.length)W.push(()=>X.classList.add(...Z))}if(j.toggle_class)j.toggle_class.forEach((Z)=>X.classList.toggle(Z)),W.push(()=>j.toggle_class.forEach((Z)=>X.classList.toggle(Z)));if(j.hide)X.hidden=!0,W.push(()=>X.hidden=!1)}if(j.checked==="keep"&&z&&"checked"in z){let X=z.checked;W.push(()=>z.checked=!X)}return W.length?W:null}#Z(j){if(!j)return;if(!this.element.isConnected)return;for(let z of j)z()}#Ij(j,z){if(j.to==null)return z?[z]:[];return this.#P({to:j.to})}#Mj(j,z,Q){this.#Nj(j,z);let W=this.#Aj(j,z,Q),X=!1;return()=>{if(X)return;X=!0,this.#Lj(j,z),W()}}#Nj(j,z){if(this.#$(z,j,1),this.#$(this.element,j,1),this.#J.set(j,(this.#J.get(j)??0)+1),this.#N++===0)this.element.setAttribute("aria-busy","true");for(let Q of this.#v(j))this.#$(Q,j,1)}#Lj(j,z){this.#$(z,j,-1),this.#$(this.element,j,-1);let Q=(this.#J.get(j)??1)-1;if(Q<=0)this.#J.delete(j);else this.#J.set(j,Q);if(--this.#N<=0)this.#N=0,this.element.removeAttribute("aria-busy");for(let W of this.#v(j))this.#$(W,j,-1)}#$(j,z,Q){if(!j||typeof j.getAttribute!=="function")return;let W=this.#L.get(j)??new Map,X=(W.get(z)??0)+Q;if(X<=0)W.delete(z);else W.set(z,X);if(W.size===0){this.#L.delete(j),j.removeAttribute("data-reactive-busy");return}this.#L.set(j,W),j.setAttribute("data-reactive-busy",[...W.keys()].join(" "))}#v(j){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((Q)=>Q.getAttribute("data-reactive-busy-on")===j&&this.#z(Q))}#Aj(j,z,Q){if(!Q||!z)return()=>{};let W=this.#Oj(Q,z),X=Array.isArray(Q.class)?Q.class:[],Z=[];for(let G of W){let q=X.filter((Y)=>!G.classList.contains(Y));if(G.classList.add(...q),q.length)Z.push([G,q])}let $=this.#V.get(z);if($)$.count++;else if(Q.disable||Q.text!=null)this.#V.set(z,{count:1,disabled:z.disabled,text:z.textContent,hadText:Q.text!=null});if(Q.disable)z.disabled=!0;if(Q.text!=null)z.textContent=Q.text;return()=>{for(let[G,q]of Z)if(G.isConnected)G.classList.remove(...q);this.#Dj(z,Q)}}#Dj(j,z){let Q=this.#V.get(j);if(!Q)return;if(--Q.count>0)return;if(this.#V.delete(j),!j.isConnected)return;if(z.disable)j.disabled=Q.disabled;if(Q.hadText&&j.textContent===z.text)j.textContent=Q.text}#Oj(j,z){if(j.to==null)return z?[z]:[];return this.#P({to:j.to})}#xj(){return this.#f??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#Pj(){if(this.#M!=null)return this.#M;let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,z=Number(j);return this.#M=Number.isFinite(z)&&z>0?z:30000}#Ej(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#Fj(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{b as registerReactiveVisit,w as registerReactiveToken,f as registerReactiveOffline,y as registerReactiveJs,h as registerReactiveDismiss,F as registerReactiveActions,c as escapeRegExp,u as enableLatencySim,p as disableLatencySim,Gj as default,g as checkReactiveRegistration,Zj as __resetReactiveRegistrationForTest,Wj as __resetReactiveOfflineForTest,Xj as __resetReactiveLatencyForTest,Qj as __resetReactiveDismissForTest,$j as __markReactiveConnectedForTest,P as LATENCY_KEY};
|
|
1
|
+
import{Controller as p}from"@hotwired/stimulus";import{confirmResolver as m}from"phlex/reactive/confirm";import{computeReducer as c}from"phlex/reactive/compute";function g(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:visit"])return;j["reactive:visit"]=function(){let Q=this.getAttribute("data-url");if(Q)window.Turbo.visit(Q,{action:"advance"})}}function d(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:token"])return;j["reactive:token"]=function(){let Q=this.getAttribute("data-reactive-token-value"),W=this.getAttribute("target");if(!Q||!W)return;let X=document.getElementById(W);if(X)X.setAttribute("data-reactive-token-value",Q)}}function l(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:js"])return;j["reactive:js"]=function(){let Q=f(this.getAttribute("data-reactive-ops"));if(!Q.length)return;let W=this.getAttribute("target"),X=W?document.getElementById(W):null;if(W&&!X)return;u(Q,(Z)=>Mj(Z,X))}}var U=new Map;function Oj(){U.clear(),P=!1}function xj(j){return U.get(j)?.via}var P=!1;function s(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:defer"])return;if(j["reactive:defer"]=function(){let Q=this.getAttribute("target");if(!Q)return;if(this.getAttribute("data-reactive-defer-via")==="stream"){n(Q,this);return}let W=this.getAttribute("data-reactive-defer-token");if(!W)return;L(Q,W)},!P&&typeof document<"u"&&document.addEventListener)P=!0,document.addEventListener("turbo:before-stream-render",o)}function o(j){let W=j.target?.getAttribute?.("target");if(!W)return;let X=W.startsWith("reactive-defer-src-")?W.slice(19):W;if(U.get(X)?.via==="stream")U.delete(X)}function L(j,Q){let W=document.getElementById(j);if(!W){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}b(j),h(W);let X={via:"fetch",abort:new AbortController,timedOut:!1};U.set(j,X),i(j,X,Q)}function n(j,Q){let W=document.getElementById(j);if(!W){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}let X=Q.getAttribute("data-reactive-defer-src");if(!X)return;if(!globalThis.customElements?.get?.("pgbus-stream-source")){let $=Q.getAttribute("data-reactive-defer-token");if($){L(j,$);return}console.error("[phlex-reactive] reactive:defer via=stream but <pgbus-stream-source> is not registered "+"and no fallback token was provided — is the pgbus client loaded on this page?");return}b(j),h(W);let Z=document.createElement("pgbus-stream-source");Z.id=w(j),Z.setAttribute("src",X),Z.setAttribute("since-id",Q.getAttribute("data-reactive-defer-since-id")??"0"),Z.setAttribute("hidden",""),document.body.appendChild(Z),U.set(j,{via:"stream"})}function w(j){return`reactive-defer-src-${j}`}async function i(j,Q,W){let X=setTimeout(()=>{Q.timedOut=!0,Q.abort.abort()},t()),Z;try{Z=await fetch(a(),{method:"POST",headers:{Accept:"text/vnd.turbo-stream.html","Content-Type":"application/json","X-CSRF-Token":r()},body:JSON.stringify({token:W}),credentials:"same-origin",signal:Q.abort.signal})}catch(G){if(clearTimeout(X),U.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed",G),x(j,W);return}if(U.get(j)!==Q){clearTimeout(X);return}if(Z.status===204){clearTimeout(X),I(j);return}if(!Z.ok){clearTimeout(X),console.error(`[phlex-reactive] deferred render failed: HTTP ${Z.status}`),x(j,W,Z.status);return}let $;try{$=await Z.text()}catch(G){if(clearTimeout(X),U.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed reading the body",G),x(j,W);return}if(clearTimeout(X),U.get(j)!==Q)return;I(j),window.Turbo.renderStreamMessage($)}function b(j){let Q=U.get(j);if(!Q)return;if(U.delete(j),Q.via==="fetch")Q.abort.abort();else document.getElementById(w(j))?.remove?.()}function h(j){j.setAttribute("data-reactive-defer-pending","true"),j.setAttribute("aria-busy","true")}function y(j){j.removeAttribute("data-reactive-defer-pending"),j.removeAttribute("aria-busy")}function I(j){U.delete(j);let Q=document.getElementById(j);if(!Q)return;y(Q),Q.removeAttribute("data-reactive-error")}function x(j,Q,W){U.delete(j);let X=document.getElementById(j);if(!X)return;y(X),X.setAttribute("data-reactive-error","defer");let Z=()=>{let $=document.getElementById(j);if(!$){console.warn("[phlex-reactive] defer retry() ignored — the target left the DOM");return}$.removeAttribute("data-reactive-error"),L(j,Q)};X.dispatchEvent(new CustomEvent("reactive:error",{bubbles:!0,composed:!0,detail:{kind:"defer",target:j,status:W,retry:Z}}))}function a(){return document.querySelector('meta[name="phlex-reactive-defer-path"]')?.content||"/reactive/defer"}function r(){return document.querySelector('meta[name="csrf-token"]')?.content??""}function t(){let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:30000}var F=!1;function e(){if(F)return;if(typeof document>"u"||!document.addEventListener)return;F=!0,document.addEventListener("turbo:before-stream-render",jj)}function jj(j){let Q=j.detail,W=Q?.render;if(typeof W!=="function"||W.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(B);else setTimeout(B,0);return}let X=async(Z)=>{await W(Z),B()};X.__reactiveDismissWrapped=!0,Q.render=X}function B(){let j=document.querySelectorAll("[data-reactive-dismiss-after]");for(let Q of j){if(Q.hasAttribute("data-reactive-dismiss-scheduled"))continue;let W=Number(Q.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite(W)||W<=0)continue;Q.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>Q.remove(),W)}}function Bj(){F=!1}var R=!1;function Qj(){if(R)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;R=!0;let j=()=>{let Q=document.documentElement;if(typeof Q?.toggleAttribute!=="function")return;Q.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};j(),window.addEventListener("online",j),window.addEventListener("offline",j)}function Cj(){R=!1}var D="phlex-reactive:latency",A=!1;function Wj(j){if(typeof sessionStorage>"u")return;sessionStorage.setItem(D,String(j))}function Xj(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(D),A=!1}function Zj(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:Wj,disableLatencySim:Xj}}function Ej(){A=!1}function S(){g(),d(),l(),s(),e(),Qj(),Zj()}function $j(j){return j.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)S();else document.addEventListener("turbo:load",S,{once:!0});var O=!1;function Gj(){if(O)return;if(typeof document>"u")return;let j=document.querySelectorAll('[data-controller~="reactive"]');if(!j||j.length===0)return;console.warn("[phlex-reactive] found "+j.length+' element(s) with data-controller="reactive" '+"but the reactive controller never connected. It is loaded but not registered — "+'add `application.register("reactive", ReactiveController)` (importmap) or import it into app/javascript/controllers/ for lazyLoadControllersFrom apps. See the README.')}function Pj(){O=!1}function Fj(){O=!0}if(typeof window<"u"&&typeof document<"u"){let j=()=>setTimeout(Gj,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",j,{once:!0});else j()}var Jj=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function Kj(j){let Q=String(j).toLowerCase();return Q.startsWith("on")||Jj.has(Q)}function zj(j,Q,W){let[X,Z,$]=Q;j.classList.add(X,Z),W(),requestAnimationFrame(()=>{j.classList.remove(Z),j.classList.add($)});let G=!1,J=()=>{if(G)return;G=!0,j.classList.remove(X,$)};j.addEventListener("animationend",J,{once:!0}),setTimeout(J,350)}var k=Object.freeze({show:(j,Q)=>C(j,!1,Q),hide:(j,Q)=>C(j,!0,Q),toggle:(j,Q)=>C(j,!j.hidden,Q),add_class:(j,Q)=>j.classList.add(...Q.classes??[]),remove_class:(j,Q)=>j.classList.remove(...Q.classes??[]),toggle_class:(j,Q)=>(Q.classes??[]).forEach((W)=>j.classList.toggle(W)),set_attr:(j,Q)=>{if(E(Q.name))j.setAttribute(Q.name,Q.value??"")},remove_attr:(j,Q)=>{if(E(Q.name))j.removeAttribute(Q.name)},toggle_attr:(j,Q)=>{if(!E(Q.name))return;if(j.hasAttribute(Q.name))j.removeAttribute(Q.name);else j.setAttribute(Q.name,"")},focus:(j)=>j.focus?.(),focus_first:(j)=>_j(j)?.focus?.(),text:(j,Q)=>{let W=String(Q.value??"");if(j.textContent!==W)j.textContent=W},dispatch:(j,Q)=>{j.dispatchEvent(new CustomEvent(Q.name,{bubbles:!0,composed:!0,detail:Q.detail??{}}))}});function C(j,Q,W){if(W?.transition)zj(j,W.transition,()=>j.hidden=Q);else j.hidden=Q}function E(j){if(!Kj(j))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(j)} — skipped`),!1}var v=/^#[A-Za-z_][\w-]*$/;function Yj(j){if(typeof j==="string"&&v.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(j)} — skipped`),!1}function qj(j,Q){let W=j.getAttribute("data-reactive-show-equals");if(W!==null)return Q===W;let X=j.getAttribute("data-reactive-show-not");if(X!==null)return Q!==X;let Z=j.getAttribute("data-reactive-show-in");if(Z!==null){try{let $=JSON.parse(Z);if(Array.isArray($))return $.includes(Q)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(Z)} — skipped`),null}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}function Hj(j,Q){if(!j||typeof j!=="object")return null;if(typeof j.equals==="string")return Q===j.equals;if(typeof j.not==="string")return Q!==j.not;if(Array.isArray(j.in))return j.in.includes(Q);return null}function Uj(j){if(typeof j==="string"&&v.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root show target ${JSON.stringify(j)} — skipped`),!1}var Vj='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function _j(j){return j.querySelectorAll?.(Vj)?.[0]??null}function f(j){if(Array.isArray(j))return j;if(typeof j!=="string")return[];try{let Q=JSON.parse(j);return Array.isArray(Q)?Q:[]}catch{return[]}}function u(j,Q){for(let W of j){if(!Array.isArray(W))continue;let[X,Z={}]=W;if(!Object.hasOwn(k,X)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(X)} — skipped`);continue}for(let $ of Q(Z))k[X]($,Z)}}function Mj(j,Q){let W=j.to;if(Q){if(W==="@root")return[Q];if(typeof W!=="string"||W==="")return[];if(j.global)return[...document.querySelectorAll(W)];return[...Q.querySelectorAll(W)]}if(typeof W!=="string"||W===""||W==="@root")return[];return[...document.querySelectorAll(W)]}class Rj extends p{static values={token:String};#R;#V=new Map;#K=new Map;#g;#L;#D;#O=0;#z=new Map;#x=new WeakMap;#_=new Map;#Y;#q;#H;#j;#W;#M;connect(){if(O=!0,this.element.id==="")console.warn("[phlex-reactive] a reactive root has no id; its next-action token can't self-match "+"and may fall back to the first token in the response → a silent HTTP 403 on the NEXT action. "+"Put id: on the SAME element as reactive_attrs — use div(**reactive_root) (emits id + token together), "+"or div(id:, **reactive_attrs). The id: must NOT be on a child. See the README.");if(this.element.getAttribute?.("data-reactive-defer-token"))this.#T(),this.#M=()=>this.#T(),this.element.addEventListener?.("turbo:morph-element",this.#M);if(this.#d()){if(this.#Y=()=>this.#E(),this.element.addEventListener?.("turbo:morph-element",this.#Y),this.#E(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#Yj()}if(this.#Hj())this.#j=()=>this.#f(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#j),this.#f();if(this.#Mj())this.#W=(j)=>{if(j?.type==="input"&&!this.#Nj(j))return;this.#p()},this.element.addEventListener?.("input",this.#W),this.element.addEventListener?.("turbo:morph-element",this.#W),this.#p()}#d(){if((this.element.getAttribute?.("data-action")??"").includes("reactive#trackDirty"))return!0;let j=this.element.querySelectorAll?.('[data-action*="reactive#trackDirty"]')??[];for(let Q of j)if(this.#Q(Q))return!0;return!1}disconnect(){if(this.#r(),this.#e(),this.#qj(),this.#_j(),this.#Aj(),this.#M)this.element.removeEventListener?.("turbo:morph-element",this.#M)}#T(){let j=this.element;if(!j?.id)return;let Q=j.getAttribute?.("data-reactive-defer-token");if(!Q)return;if(j.getAttribute?.("data-reactive-defer-pending")!=="true")return;L(j.id,Q)}dispatch(j){let{action:Q,params:W,debounce:X,throttle:Z,confirm:$,outside:G,window:J,optimistic:K,loading:q}=j.params;if(!Q)return;if(G&&this.element.contains(j.target))return;let H=j.currentTarget??j.target;if(!J&&!this.#Cj(K,H))j.preventDefault();if(!$)return this.#w(H,Q,W,X,Z,K,q);Promise.resolve().then(()=>m($)).catch(()=>!1).then((z)=>{if(z)this.#w(H,Q,W,X,Z,K,q)})}runOps(j){let{ops:Q,outside:W,window:X}=j.params;if(W&&this.element.contains(j.target))return;if(!X)j.preventDefault();this.#Bj(this.#xj(Q))}trackDirty(){this.#E()}recompute(j){let Q=this.#s(),W=Q.map(([z])=>z),X=this.#U(),Z=new Map,$=(z)=>{if(Z.has(z))return Z.get(z);let Y=null;for(let _ of this.element.querySelectorAll(`[name="${z}"]`))if(X(_)){Y=_;break}return Z.set(z,Y),Y};for(let z of W)this.#S(z,$(z)?.value??"");let G=this.element.getAttribute("data-reactive-compute-reducer-param"),J=G?c(G):null;if(!J){this.#k({},$);return}let K=this.#l("data-reactive-compute-outputs-param"),q={};for(let[z,Y]of Q){let _=$(z);if(Y==="string")q[z]=_?.value??"";else{let M=Number(_?.value);q[z]=Number.isFinite(M)?M:0}}let H=J(q,{changed:this.#o(j,W)})||{};for(let z of K){if(!(z in H))continue;let Y=$(z);if(Y){if(String(H[z])===Y.value)continue;Y.value=H[z],Y.dispatchEvent(new Event("input",{bubbles:!0}))}else this.#S(z,H[z])}this.#k(H,$)}listnavNext(j){this.#I(j,1)}listnavPrev(j){this.#I(j,-1)}listnavPick(j){let Q=this.#B(j),W=Q.findIndex((X)=>X.hasAttribute("data-reactive-highlighted"));if(W<0)return;j.preventDefault(),Q[W].click()}listnavClose(j){for(let Q of this.#B(j))Q.removeAttribute("data-reactive-highlighted")}#I(j,Q){let W=this.#B(j);if(!W.length)return;j.preventDefault();let X=W.findIndex((G)=>G.hasAttribute("data-reactive-highlighted")),Z=X<0?Q>0?0:W.length-1:(X+Q+W.length)%W.length;for(let G of W)G.removeAttribute("data-reactive-highlighted");let $=W[Z];$.setAttribute("data-reactive-highlighted","true"),$.scrollIntoView?.({block:"nearest"})}#B(j){let W=(j?.currentTarget??j?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!W)return[];let X=this.#U();return Array.from(this.element.querySelectorAll(W)).filter((Z)=>!Z.hidden&&X(Z))}#l(j){let Q=this.element.getAttribute(j);if(!Q)return[];try{let W=JSON.parse(Q);return Array.isArray(W)?W:[]}catch{return[]}}#s(){let j=this.element.getAttribute("data-reactive-compute-inputs-param");if(!j)return[];try{let Q=JSON.parse(j);if(Array.isArray(Q))return Q.map((W)=>[W,"number"]);if(Q&&typeof Q==="object")return Object.entries(Q);return[]}catch{return[]}}#o(j,Q){let W=j?.target;if(!W?.name||typeof W.closest!=="function")return null;if(!Q.includes(W.name))return null;return this.#Q(W)?W.name:null}#S(j,Q){let W=String(Q);for(let X of this.#n(j)){if(X.textContent===W)continue;X.textContent=W}}#n(j){let Q=this.element.querySelectorAll(`[data-reactive-text="${j}"]`);return Array.from(Q).filter((W)=>this.#Q(W))}#k(j,Q){let W=this.#i();for(let[X,Z]of Object.entries(W)){let $=X in j?j[X]:Q(X)?.value;if($===void 0||$===null)continue;let G=String($);for(let J of Array.isArray(Z)?Z:[Z]){if(!Yj(J))continue;for(let K of document.querySelectorAll(J)){if(K.textContent===G)continue;K.textContent=G}}}}#i(){let j=this.element.getAttribute("data-reactive-compute-mirror-param");if(!j)return{};try{let Q=JSON.parse(j);return Q&&typeof Q==="object"&&!Array.isArray(Q)?Q:{}}catch{return{}}}#w(j,Q,W,X,Z,$,G){if(this.#A("reactive:before-dispatch",{action:Q,params:this.#m(W),element:this.element},{cancelable:!0}).defaultPrevented)return;let K=Number(X)||0;if(K>0)return this.#a(j,K,Q,W,$,G);let q=Number(Z)||0;if(q>0)return this.#t(j,q,Q,W,$,G);return this.#N(Q,W,$,j,G)}#N(j,Q,W,X,Z){let $=this.#Ej(W,X),G=this.#Fj(j,X,Z);return this.queue=(this.queue??Promise.resolve()).then(()=>this.#Gj(j,Q,$,G)),this.queue}#a(j,Q,W,X,Z,$){this.#C(j);let G=()=>{this.#C(j),this.#N(W,X,Z,j,$)},J=setTimeout(G,Q);j?.addEventListener?.("blur",G,{once:!0}),this.#V.set(j,{timer:J,flush:G})}#C(j){let Q=this.#V.get(j);if(!Q)return;clearTimeout(Q.timer),j?.removeEventListener?.("blur",Q.flush),this.#V.delete(j)}#r(){for(let j of[...this.#V.keys()])this.#C(j)}#t(j,Q,W,X,Z,$){let G=this.#K.get(j)??new Map;if(G.has(W))return;let J=setTimeout(()=>{if(G.delete(W),G.size===0)this.#K.delete(j)},Q);return G.set(W,J),this.#K.set(j,G),this.#N(W,X,Z,j,$)}#e(){for(let j of this.#K.values())for(let Q of j.values())clearTimeout(Q);this.#K.clear()}#A(j,Q,{cancelable:W=!1}={}){let X=new CustomEvent(j,{bubbles:!0,composed:!0,cancelable:W,detail:Q});return(this.element.isConnected?this.element:document).dispatchEvent(X),X}#X(j,Q,W,X){let Z=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#N(j,Q)};this.#A("reactive:error",{action:j,params:W,...X,retry:Z})}#Z(j){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",j)}#jj(){this.element?.removeAttribute?.("data-reactive-error")}#Qj(){let j=document.querySelector("[data-reactive-error-flash]");if(!j?.content)return;let Q=j.getAttribute("data-reactive-error-flash")||"flash",W=document.getElementById(Q);if(!W)return;W.appendChild(j.content.cloneNode(!0))}#Wj(){if(typeof sessionStorage>"u")return Promise.resolve();let j=Number(sessionStorage.getItem(D));if(!Number.isFinite(j)||j<=0)return Promise.resolve();if(!A)A=!0,console.warn(`[phlex-reactive] latency simulator ACTIVE — every action is delayed by ${j}ms. Call PhlexReactive.disableLatencySim() (or clear sessionStorage) to turn it off.`);return new Promise((Q)=>setTimeout(Q,j))}#Xj(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#b(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#Zj(j){if(!j)return[];let Q=[],W=/<turbo-stream\b([^>]*)>/g,X;while((X=W.exec(j))!==null){let Z=X[1],$=Z.match(/\baction="([^"]*)"/)?.[1]??"?",G=Z.match(/\btarget="([^"]*)"/)?.[1];Q.push(G?`${$} → #${G}`:$)}return Q}#$j(j){let{action:Q,status:W,ms:X}=j,$=`reactive ${this.element?.id?`#${this.element.id} `:""}${Q} → ${W??"—"} (${Math.round(X)}ms)`;if(console.groupCollapsed($),console.log(`params: [${j.paramNames.join(", ")}] + collected: [${j.fieldNames.join(", ")}]`),console.log(`encoding: ${j.encoding}`),j.streams.length)console.log(`streams: ${j.streams.join(" ")}`);console.log(`token: ${j.tokenRefreshed?"refreshed ✓":"unchanged"}`),console.groupEnd()}async#Gj(j,Q,W,X){let{fields:Z,files:$}=this.#Kj(),G=this.#m(Q),J={...Z,...G},K=this.#$,q=$.length>0,H=q?this.#Lj(K,j,J,$):JSON.stringify({token:K,act:j,params:J}),z=this.#Xj()?{action:j,paramNames:Object.keys(G),fieldNames:Object.keys(Z),encoding:q?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#b()}:null;await this.#Wj();try{if(navigator.onLine===!1){this.#G(W),this.#Z("offline"),this.#X(j,Q,J,{kind:"offline"});return}let Y;try{let V={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#bj()};if(!q)V["Content-Type"]="application/json";let N=this.#hj();if(N)V["X-Pgbus-Connection"]=N;Y=await fetch(this.#kj(),{method:"POST",headers:V,body:H,credentials:"same-origin",signal:AbortSignal.timeout(this.#wj())})}catch(V){if(console.error("[phlex-reactive] action error",V),this.#G(W),V?.name==="TimeoutError"||V?.name==="AbortError"){this.#Z("timeout"),this.#X(j,Q,J,{kind:"timeout"});return}this.#Qj(),this.#Z("network"),this.#X(j,Q,J,{kind:"network"});return}if(z)z.status=Y.status;if(Y.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#G(W),this.#Z("redirected"),this.#X(j,Q,J,{kind:"redirected",status:Y.status});return}if(!Y.ok){let V=await Y.text();if(console.error(`[phlex-reactive] action failed: HTTP ${Y.status}`,V),this.#G(W),(Y.headers.get("Content-Type")||"").includes("turbo-stream")){let N=this.#y(V);if(this.#$=N??this.#$,z)this.#h(z,V,N);window.Turbo.renderStreamMessage(V)}this.#Z("http"),this.#X(j,Q,J,{kind:"http",status:Y.status,body:V});return}let _=Y.headers.get("Content-Type")||"";if(!_.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${_}" — no update applied`),this.#G(W),this.#Z("content-type"),this.#X(j,Q,J,{kind:"content-type",status:Y.status});return}let M=await Y.text(),T=this.#y(M);if(this.#$=T??this.#$,z)this.#h(z,M,T);window.Turbo.renderStreamMessage(M),this.#jj(),this.#A("reactive:applied",{action:j,params:J,html:M})}catch(Y){console.error("[phlex-reactive] action error",Y),this.#G(W),this.#A("reactive:error",{action:j,params:J,kind:"apply"})}finally{if(X?.(),z)this.#$j({...z,ms:this.#b()-z.started})}}#h(j,Q,W){j.streams=this.#Zj(Q),j.tokenRefreshed=W!=null}get#$(){return this.#R??this.tokenValue}set#$(j){this.#R=j}#y(j){let Q=this.element.id;if(!Q)return j.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:W,self:X}=this.#Jj(Q),Z=j.match(W);if(Z)return Z[1];let $=j.match(X);if($)return $[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#Jj(j){let Q=this.#D;if(Q&&Q.id===j)return Q;let W=$j(j);return this.#D={id:j,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${W}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${W}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#Q(j){return j.closest('[data-controller~="reactive"]')===this.element}#U(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(Q)=>this.#Q(Q)}#Kj(){let j={},Q=[],W=this.#U();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((X)=>{if(!W(X))return;if(X.type==="file")for(let Z of X.files??[])Q.push({name:X.name,file:Z,multiple:X.multiple});else if(X.type==="checkbox")j[X.name]=X.checked;else if(X.type==="radio"){if(X.checked)j[X.name]=X.value}else j[X.name]=X.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((X)=>{if(!W(X))return;let Z=X.getAttribute("name");if(!Z)return;let $=j[Z];if($==null||$==="")j[Z]=X.value??X.textContent??X.innerHTML??""}),{fields:j,files:Q}}#E(){if(typeof this.element?.querySelectorAll!=="function")return;let j=0;if(this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Q)=>{if(!this.#Q(Q))return;if(Q.type==="file")return;if(this.#zj(Q))Q.setAttribute("data-reactive-dirty","true"),j++;else Q.removeAttribute("data-reactive-dirty")}),j>0)this.element.setAttribute("data-reactive-dirty",String(j));else this.element.removeAttribute("data-reactive-dirty")}#zj(j){if(j.type==="checkbox"||j.type==="radio")return j.checked!==j.defaultChecked;if(j.tag==="select"||j.options)return Array.from(j.options??[]).some((Q)=>Q.selected!==Q.defaultSelected);return j.value!==j.defaultValue}#v(){let j=this.element.getAttribute?.("data-reactive-dirty"),Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:0}#Yj(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#q=(j)=>{if(this.#v()===0)return;return j.preventDefault(),j.returnValue="You have unsaved changes.",j.returnValue},this.#H=(j)=>{if(this.#v()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))j.preventDefault?.()},window.addEventListener("beforeunload",this.#q),window.addEventListener("turbo:before-visit",this.#H)}#qj(){if(this.#Y)this.element.removeEventListener?.("turbo:morph-element",this.#Y),this.#Y=void 0;if(typeof window<"u"&&typeof window.removeEventListener==="function"){if(this.#q)window.removeEventListener("beforeunload",this.#q);if(this.#H)window.removeEventListener("turbo:before-visit",this.#H)}this.#q=void 0,this.#H=void 0}#Hj(){if(this.element.getAttribute?.("data-reactive-show-targets"))return!0;let j=this.element.querySelectorAll?.("[data-reactive-show-field]")??[];for(let Q of j)if(this.#Q(Q))return!0;return!1}#f(){if(typeof this.element?.querySelectorAll!=="function")return;let j=this.#U(),Q=new Map;for(let W of this.element.querySelectorAll("[data-reactive-show-field]")){if(!j(W))continue;let X=W.getAttribute("data-reactive-show-field");if(!X)continue;if(!Q.has(X))Q.set(X,this.#u(X,j));let Z=Q.get(X);if(Z===null)continue;let $=qj(W,Z);if($===null)continue;W.hidden=!$}this.#Uj(j,Q)}#Uj(j,Q){let W=this.#Vj();for(let[X,Z]of Object.entries(W)){if(!Z||typeof Z!=="object"||Array.isArray(Z))continue;if(!Q.has(X))Q.set(X,this.#u(X,j));let $=Q.get(X);if($===null)continue;for(let[G,J]of Object.entries(Z)){if(!Uj(G))continue;let K=Hj(J,$);if(K===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${G} — skipped`);continue}for(let q of document.querySelectorAll(G))q.hidden=!K}}}#Vj(){let j=this.element.getAttribute?.("data-reactive-show-targets");if(!j)return{};try{let Q=JSON.parse(j);if(Q&&typeof Q==="object"&&!Array.isArray(Q))return Q}catch{}return console.warn("[phlex-reactive] malformed data-reactive-show-targets — ignored. "+"Did two reactive_show_targets calls collide on one root? Declare every field in ONE call: reactive_show_targets(mode: { ... }, kind: { ... })"),{}}#u(j,Q){let W=!1,X=null;for(let Z of this.element.querySelectorAll(`[name="${j}"]`)){if(!Q(Z))continue;if(Z.type==="checkbox")return Z.checked?"true":"false";if(Z.type==="radio"){if(Z.checked)return Z.value??"";W=!0;continue}X??=Z}if(X)return X.value??"";return W?"":null}#_j(){if(!this.#j)return;this.element.removeEventListener?.("input",this.#j),this.element.removeEventListener?.("change",this.#j),this.element.removeEventListener?.("turbo:morph-element",this.#j),this.#j=void 0}#Mj(){return!!(this.element.getAttribute?.("data-reactive-filter-input")&&this.element.getAttribute?.("data-reactive-filter-option"))}#Nj(j){let Q=this.element.getAttribute("data-reactive-filter-input");return!!Q&&typeof j.target?.matches==="function"&&j.target.matches(Q)}#p(){if(typeof this.element?.querySelectorAll!=="function")return;let j=this.element.getAttribute("data-reactive-filter-input"),Q=this.element.getAttribute("data-reactive-filter-option");if(!j||!Q)return;let W=this.#U(),X=[...this.element.querySelectorAll(j)].find(W);if(!X)return;let Z=(X.value??"").trim().toLowerCase(),$=0;for(let K of this.element.querySelectorAll(Q)){if(!W(K))continue;let q=(K.getAttribute("data-reactive-filter-text")??K.textContent??"").toLowerCase(),H=Z!==""&&!q.includes(Z);if(K.hidden=H,H)K.removeAttribute("data-reactive-highlighted");else $++}let G=this.element.getAttribute("data-reactive-filter-group");if(G)for(let K of this.element.querySelectorAll(G)){if(!W(K))continue;let q=[...K.querySelectorAll(Q)].filter(W);if(q.length===0)continue;K.hidden=q.every((H)=>H.hidden)}let J=this.element.getAttribute("data-reactive-filter-empty");if(J){for(let K of this.element.querySelectorAll(J))if(W(K))K.hidden=$>0}}#Aj(){if(!this.#W)return;this.element.removeEventListener?.("input",this.#W),this.element.removeEventListener?.("turbo:morph-element",this.#W),this.#W=void 0}#Lj(j,Q,W,X){let Z=new FormData;Z.append("token",j),Z.append("act",Q);for(let[G,J]of Object.entries(W))this.#P(Z,`params[${G}]`,J);let $=this.#Oj(X);for(let{name:G,file:J,multiple:K}of X){let H=K||$.has(G)?`params[${G}][]`:`params[${G}]`;Z.append(H,J,J.name)}return Z}#P(j,Q,W){if(W==null)j.append(Q,"");else if(Array.isArray(W))W.forEach((X,Z)=>this.#P(j,`${Q}[${Z}]`,X));else if(typeof W==="object")for(let[X,Z]of Object.entries(W))this.#P(j,`${Q}[${X}]`,Z);else j.append(Q,String(W))}#Oj(j){let Q=new Map;for(let{name:W}of j)Q.set(W,(Q.get(W)??0)+1);return new Set([...Q].filter(([,W])=>W>1).map(([W])=>W))}#m(j){if(!j)return{};try{return typeof j==="string"?JSON.parse(j):j}catch{return{}}}#xj(j){return f(j)}#Bj(j){u(j,(Q)=>this.#F(Q))}#F(j){let Q=j.to;if(Q==="@root")return[this.element];if(typeof Q!=="string"||Q==="")return[];if(j.global)return[...document.querySelectorAll(Q)];return[...this.element.querySelectorAll(Q)].filter((W)=>this.#Q(W))}#Cj(j,Q){if(j?.checked!=="keep")return!1;let W=Q?.type;return W==="checkbox"||W==="radio"}#Ej(j,Q){if(!j)return null;let W=this.#Pj(j,Q),X=[];for(let Z of W){if(j.add_class){let $=j.add_class.filter((G)=>!Z.classList.contains(G));if(Z.classList.add(...$),$.length)X.push(()=>Z.classList.remove(...$))}if(j.remove_class){let $=j.remove_class.filter((G)=>Z.classList.contains(G));if(Z.classList.remove(...$),$.length)X.push(()=>Z.classList.add(...$))}if(j.toggle_class)j.toggle_class.forEach(($)=>Z.classList.toggle($)),X.push(()=>j.toggle_class.forEach(($)=>Z.classList.toggle($)));if(j.hide)Z.hidden=!0,X.push(()=>Z.hidden=!1)}if(j.checked==="keep"&&Q&&"checked"in Q){let Z=Q.checked;X.push(()=>Q.checked=!Z)}return X.length?X:null}#G(j){if(!j)return;if(!this.element.isConnected)return;for(let Q of j)Q()}#Pj(j,Q){if(j.to==null)return Q?[Q]:[];return this.#F({to:j.to})}#Fj(j,Q,W){this.#Rj(j,Q);let X=this.#Tj(j,Q,W),Z=!1;return()=>{if(Z)return;Z=!0,this.#Dj(j,Q),X()}}#Rj(j,Q){if(this.#J(Q,j,1),this.#J(this.element,j,1),this.#z.set(j,(this.#z.get(j)??0)+1),this.#O++===0)this.element.setAttribute("aria-busy","true");for(let W of this.#c(j))this.#J(W,j,1)}#Dj(j,Q){this.#J(Q,j,-1),this.#J(this.element,j,-1);let W=(this.#z.get(j)??1)-1;if(W<=0)this.#z.delete(j);else this.#z.set(j,W);if(--this.#O<=0)this.#O=0,this.element.removeAttribute("aria-busy");for(let X of this.#c(j))this.#J(X,j,-1)}#J(j,Q,W){if(!j||typeof j.getAttribute!=="function")return;let X=this.#x.get(j)??new Map,Z=(X.get(Q)??0)+W;if(Z<=0)X.delete(Q);else X.set(Q,Z);if(X.size===0){this.#x.delete(j),j.removeAttribute("data-reactive-busy");return}this.#x.set(j,X),j.setAttribute("data-reactive-busy",[...X.keys()].join(" "))}#c(j){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((W)=>W.getAttribute("data-reactive-busy-on")===j&&this.#Q(W))}#Tj(j,Q,W){if(!W||!Q)return()=>{};let X=this.#Sj(W,Q),Z=Array.isArray(W.class)?W.class:[],$=[];for(let J of X){let K=Z.filter((q)=>!J.classList.contains(q));if(J.classList.add(...K),K.length)$.push([J,K])}let G=this.#_.get(Q);if(G)G.count++;else if(W.disable||W.text!=null)this.#_.set(Q,{count:1,disabled:Q.disabled,text:Q.textContent,hadText:W.text!=null});if(W.disable)Q.disabled=!0;if(W.text!=null)Q.textContent=W.text;return()=>{for(let[J,K]of $)if(J.isConnected)J.classList.remove(...K);this.#Ij(Q,W)}}#Ij(j,Q){let W=this.#_.get(j);if(!W)return;if(--W.count>0)return;if(this.#_.delete(j),!j.isConnected)return;if(Q.disable)j.disabled=W.disabled;if(W.hadText&&j.textContent===Q.text)j.textContent=W.text}#Sj(j,Q){if(j.to==null)return Q?[Q]:[];return this.#F({to:j.to})}#kj(){return this.#g??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#wj(){if(this.#L!=null)return this.#L;let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return this.#L=Number.isFinite(Q)&&Q>0?Q:30000}#bj(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#hj(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{Oj as resetReactiveDefers,g as registerReactiveVisit,d as registerReactiveToken,Qj as registerReactiveOffline,l as registerReactiveJs,e as registerReactiveDismiss,s as registerReactiveDefer,S as registerReactiveActions,xj as pendingDeferVia,$j as escapeRegExp,Wj as enableLatencySim,Xj as disableLatencySim,Rj as default,Gj as checkReactiveRegistration,Pj as __resetReactiveRegistrationForTest,Cj as __resetReactiveOfflineForTest,Ej as __resetReactiveLatencyForTest,Bj as __resetReactiveDismissForTest,Fj as __markReactiveConnectedForTest,D as LATENCY_KEY};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=40909AB57A30FB9064756E2164756E21
|
|
4
4
|
//# sourceMappingURL=reactive_controller.min.js.map
|