phlex-reactive 0.11.0 → 0.11.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b92414ce55aa10f4ac2fb223ba0cb689928ca773750dd14c7ef80284156f255
4
- data.tar.gz: bd12836456aa3f2010f8ea86c0f5c3a6a54f7dabfd04f0f5ceb28b6466fb28e6
3
+ metadata.gz: 4cfa5e7304bbb131fae2403858494732b6c560c305e920d76bfaa64deed8dca0
4
+ data.tar.gz: 8ba95cb7f00ce3d7b643a4385ddfceb69f992d6ce9b947e3eb31f4af9d3ab8e6
5
5
  SHA512:
6
- metadata.gz: 2608d8963434dd4d8a5e015f12e17d54ba7e3c62fdbfab0dca5ffb31c8fd75786eb6467dc864143a2635fa51e1ec574f1ad45a1d804800cb553dcce0fd82f18d
7
- data.tar.gz: e5ad1eeeaab37b4f69fe1ab5368fced9f427bbe56ead3ef24f63c950ded96d755d14a6f2dc9b6dd5f3a8af7fe3d96cef2eb6112eb623a5513ebba322df823cfd
6
+ metadata.gz: 0f8a010d359dba2455e83a1986749e3fe2c6107092246729d3fe68db56db056617df3fc0e521d112166733462f16e3890162a120a7c9662a05d8486488512975
7
+ data.tar.gz: 23206611a3db2be0ea53876d0600c34c89db673d0fc5bdf6f8908ac346ef04b3a92ab8538384fa9c587ab41cd81ae96dd7e2fa8acf095c941a6c1982f5574ac0
data/CHANGELOG.md CHANGED
@@ -8,6 +8,25 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
9
  ### Fixed
10
10
 
11
+ - **A freshly-rendered `reactive_compute` root now self-seeds its derived fields on connect (#199).**
12
+ Before, a compute root computed nothing until the first user `input` — a fresh render
13
+ (or a server validation-error re-render that replaced the body) left every derived
14
+ output and cross-root `mirror:` node blank until you typed. Apps worked around it by
15
+ dispatching a synthetic seed `input` on connect, but the compute root is a distinct
16
+ Stimulus controller that may connect a frame later, so the seed raced its own wiring —
17
+ the reported symptom being a PARTIAL apply (an early output painted; a later output
18
+ and the mirror stayed blank). Now `connect()` runs ONE full `recompute()` after the
19
+ controller is fully connected, so the whole single-pass write set (batch outputs →
20
+ paint text sinks + cross-root mirrors → dispatch) runs synchronously and every
21
+ declared output, text sink, and mirror paints from a single reducer result — no user
22
+ interaction, no round trip. It re-seeds on `turbo:morph-element` (the show/filter/dirty
23
+ precedent) and is idempotent (change-guarded writes make a re-seed a no-op, so an app
24
+ still dispatching a synthetic input is harmless). The seed is gated on a new
25
+ `data-reactive-compute-seed` marker emitted by `reactive_root(compute:)`; a non-compute
26
+ root pays one attribute read and never seeds. The seed passes no event, so
27
+ `meta.changed` is `null` — the correct "no field edited yet" semantics, so a convergent
28
+ reducer's default branch computes the full settled set.
29
+
11
30
  - **Scoped form fields no longer silently drop their params — the #67 footgun is fixed (#184).**
12
31
  Under `reactive_scope`, `reactive_field(:date)` now emits the scoped wire name
13
32
  (`name="invoice[date]"`), so the POST arrives bracketed — and the endpoint unwraps
@@ -1031,6 +1031,9 @@ export default class extends Controller {
1031
1031
  // Option filtering (issue #163): the ONE delegated sync handler shared by the
1032
1032
  // root's input/turbo:morph-element listeners, held for teardown.
1033
1033
  #boundSyncFilter
1034
+ // Connect-time compute seed (issue #199): the bound re-seed attached to
1035
+ // turbo:morph-element so an in-place morph re-runs the compute, held for teardown.
1036
+ #boundSeedCompute
1034
1037
  // Lazy initial mount (issue #165): the bound re-probe attached to
1035
1038
  // turbo:morph-element so a Turbo page-refresh morph re-fires the defer fetch.
1036
1039
  #boundProbeLazyDefer
@@ -1136,6 +1139,32 @@ export default class extends Controller {
1136
1139
  this.element.addEventListener?.("turbo:morph-element", this.#boundSyncFilter)
1137
1140
  this.#syncFilter()
1138
1141
  }
1142
+
1143
+ // Connect-time compute seed (issue #199) — ONLY when the root carries a
1144
+ // reactive_compute binding that opts in (data-reactive-compute-seed). A
1145
+ // freshly-rendered compute root (a first paint, or a server validation-error
1146
+ // re-render that replaced the body) computed NOTHING until the first user
1147
+ // `input`; apps worked around it by dispatching a synthetic seed `input` on
1148
+ // connect, but the compute root is a distinct Stimulus controller that may
1149
+ // connect a frame later, so the seed raced its own wiring — the reported
1150
+ // symptom being a PARTIAL apply (an early output paints; a later output + the
1151
+ // mirror stay blank). Running ONE recompute() HERE — after Stimulus has fully
1152
+ // connected the controller and wired the input->recompute delegation — runs
1153
+ // the whole single-pass write set (issue #183) synchronously, so every
1154
+ // declared output, text sink, and cross-root mirror paints from one reducer
1155
+ // result. It is client-only (recompute never enqueues a round trip) and
1156
+ // idempotent (change-guarded writes make a re-seed a no-op — an app still
1157
+ // dispatching a synthetic input is harmless). A plain replace re-connects and
1158
+ // re-seeds; an in-place morph keeps the element CONNECTED and fires no
1159
+ // Stimulus lifecycle, so ALSO re-seed on turbo:morph-element (the show/filter/
1160
+ // dirty precedent). No event is passed, so meta.changed is null — the correct
1161
+ // "no field edited yet" seed semantics; a convergent reducer's default branch
1162
+ // computes the full settled set (see compute.js CONVERGENCE REQUIREMENT).
1163
+ if (this.#computeSeedEnabled()) {
1164
+ this.#boundSeedCompute = () => this.recompute()
1165
+ this.element.addEventListener?.("turbo:morph-element", this.#boundSeedCompute)
1166
+ this.recompute()
1167
+ }
1139
1168
  }
1140
1169
 
1141
1170
  // Whether this root opts into dirty tracking (issue #103): track_dirty: puts the
@@ -1162,6 +1191,7 @@ export default class extends Controller {
1162
1191
  this.#teardownDirtyTracking()
1163
1192
  this.#teardownShowSync()
1164
1193
  this.#teardownFilterSync()
1194
+ this.#teardownComputeSeed()
1165
1195
  if (this.#boundProbeLazyDefer) {
1166
1196
  this.element.removeEventListener?.("turbo:morph-element", this.#boundProbeLazyDefer)
1167
1197
  }
@@ -2720,6 +2750,14 @@ export default class extends Controller {
2720
2750
  )
2721
2751
  }
2722
2752
 
2753
+ // Whether this root opts into the connect-time compute seed (issue #199).
2754
+ // reactive_compute's root binding emits data-reactive-compute-seed="true"; a
2755
+ // root without a compute binding (or with the seed opted out) pays one
2756
+ // attribute read and never seeds. A quick read, evaluated once per connect.
2757
+ #computeSeedEnabled() {
2758
+ return this.element.getAttribute?.("data-reactive-compute-seed") === "true"
2759
+ }
2760
+
2723
2761
  // Whether a delegated input event came from the NAMED filter input (issue
2724
2762
  // #163). Anything else — another field's keystroke, a target without
2725
2763
  // matches() — skips the filter pass (the morph re-sync path bypasses this).
@@ -2788,6 +2826,15 @@ export default class extends Controller {
2788
2826
  this.#boundSyncFilter = undefined
2789
2827
  }
2790
2828
 
2829
+ // Remove the compute seed morph listener on disconnect (issue #199), so a
2830
+ // stray turbo:morph-element after the element leaves the DOM never re-seeds
2831
+ // against a detached root.
2832
+ #teardownComputeSeed() {
2833
+ if (!this.#boundSeedCompute) return
2834
+ this.element.removeEventListener?.("turbo:morph-element", this.#boundSeedCompute)
2835
+ this.#boundSeedCompute = undefined
2836
+ }
2837
+
2791
2838
  // Build the multipart body (issue #34). `token`/`act` are flat fields the
2792
2839
  // endpoint reads from params[:token]/params[:act]; scalar params nest under
2793
2840
  // params[<key>] (Rails parses the bracket into params[:params]); each file is
@@ -1,4 +1,4 @@
1
- import{Controller as i}from"@hotwired/stimulus";import{confirmResolver as k}from"phlex/reactive/confirm";import{computeReducer as n}from"phlex/reactive/compute";import{confirmPredicate as a}from"phlex/reactive/confirm_predicate";function r(){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 t(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:token"])return;j["reactive:token"]=function(){let Q=this.getAttribute("data-reactive-token-value"),X=this.getAttribute("target");if(!Q||!X)return;let Z=document.getElementById(X);if(Z)Z.setAttribute("data-reactive-token-value",Q)}}function e(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:js"])return;j["reactive:js"]=function(){let Q=o(this.getAttribute("data-reactive-ops"));if(!Q.length)return;let X=this.getAttribute("target"),Z=X?document.getElementById(X):null;if(X&&!Z)return;s(Q,($)=>Fj($,Z))}}var N=new Map;function Sj(){N.clear(),R=!1}function kj(j){return N.get(j)?.via}var R=!1;function jj(){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"){Xj(Q,this);return}let X=this.getAttribute("data-reactive-defer-token");if(!X)return;B(Q,X)},!R&&typeof document<"u"&&document.addEventListener)R=!0,document.addEventListener("turbo:before-stream-render",Qj)}function Qj(j){let X=j.target?.getAttribute?.("target");if(!X)return;let Z=X.startsWith("reactive-defer-src-")?X.slice(19):X;if(N.get(Z)?.via==="stream")N.delete(Z)}function B(j,Q){let X=document.getElementById(j);if(!X){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}f(j),u(X);let Z={via:"fetch",abort:new AbortController,timedOut:!1};N.set(j,Z),Zj(j,Z,Q)}function Xj(j,Q){let X=document.getElementById(j);if(!X){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}let Z=Q.getAttribute("data-reactive-defer-src");if(!Z)return;if(!globalThis.customElements?.get?.("pgbus-stream-source")){let J=Q.getAttribute("data-reactive-defer-token");if(J){B(j,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}f(j),u(X);let $=document.createElement("pgbus-stream-source");$.id=h(j),$.setAttribute("src",Z),$.setAttribute("since-id",Q.getAttribute("data-reactive-defer-since-id")??"0"),$.setAttribute("hidden",""),document.body.appendChild($),N.set(j,{via:"stream"})}function h(j){return`reactive-defer-src-${j}`}async function Zj(j,Q,X){let Z=setTimeout(()=>{Q.timedOut=!0,Q.abort.abort()},Gj()),$;try{$=await fetch($j(),{method:"POST",headers:{Accept:"text/vnd.turbo-stream.html","Content-Type":"application/json","X-CSRF-Token":Jj()},body:JSON.stringify({token:X}),credentials:"same-origin",signal:Q.abort.signal})}catch(G){if(clearTimeout(Z),N.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed",G),P(j,X);return}if(N.get(j)!==Q){clearTimeout(Z);return}if($.status===204){clearTimeout(Z),w(j);return}if(!$.ok){clearTimeout(Z),console.error(`[phlex-reactive] deferred render failed: HTTP ${$.status}`),P(j,X,$.status);return}let J;try{J=await $.text()}catch(G){if(clearTimeout(Z),N.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed reading the body",G),P(j,X);return}if(clearTimeout(Z),N.get(j)!==Q)return;w(j),window.Turbo.renderStreamMessage(J)}function f(j){let Q=N.get(j);if(!Q)return;if(N.delete(j),Q.via==="fetch")Q.abort.abort();else document.getElementById(h(j))?.remove?.()}function u(j){j.setAttribute("data-reactive-defer-pending","true"),j.setAttribute("aria-busy","true")}function p(j){j.removeAttribute("data-reactive-defer-pending"),j.removeAttribute("aria-busy")}function w(j){N.delete(j);let Q=document.getElementById(j);if(!Q)return;p(Q),Q.removeAttribute("data-reactive-error")}function P(j,Q,X){N.delete(j);let Z=document.getElementById(j);if(!Z)return;p(Z),Z.setAttribute("data-reactive-error","defer");let $=()=>{let J=document.getElementById(j);if(!J){console.warn("[phlex-reactive] defer retry() ignored — the target left the DOM");return}J.removeAttribute("data-reactive-error"),B(j,Q)};Z.dispatchEvent(new CustomEvent("reactive:error",{bubbles:!0,composed:!0,detail:{kind:"defer",target:j,status:X,retry:$}}))}function $j(){return document.querySelector('meta[name="phlex-reactive-defer-path"]')?.content||"/reactive/defer"}function Jj(){return document.querySelector('meta[name="csrf-token"]')?.content??""}function Gj(){let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:30000}var T=!1;function zj(){if(T)return;if(typeof document>"u"||!document.addEventListener)return;T=!0,document.addEventListener("turbo:before-stream-render",Kj)}function Kj(j){let Q=j.detail,X=Q?.render;if(typeof X!=="function"||X.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(C);else setTimeout(C,0);return}let Z=async($)=>{await X($),C()};Z.__reactiveDismissWrapped=!0,Q.render=Z}function C(){let j=document.querySelectorAll("[data-reactive-dismiss-after]");for(let Q of j){if(Q.hasAttribute("data-reactive-dismiss-scheduled"))continue;let X=Number(Q.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite(X)||X<=0)continue;Q.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>Q.remove(),X)}}function wj(){T=!1}var D=!1;function qj(){if(D)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;D=!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 bj(){D=!1}var I="phlex-reactive:latency",x=!1;function Yj(j){if(typeof sessionStorage>"u")return;sessionStorage.setItem(I,String(j))}function Uj(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(I),x=!1}function Hj(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:Yj,disableLatencySim:Uj}}function vj(){x=!1}function b(){r(),t(),e(),jj(),zj(),qj(),Hj()}function Wj(j){return j.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)b();else document.addEventListener("turbo:load",b,{once:!0});var O=!1;function Aj(){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 yj(){O=!1}function hj(){O=!0}if(typeof window<"u"&&typeof document<"u"){let j=()=>setTimeout(Aj,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",j,{once:!0});else j()}var _j=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function Lj(j){let Q=String(j).toLowerCase();return Q.startsWith("on")||_j.has(Q)}function Nj(j,Q,X){let[Z,$,J]=Q;j.classList.add(Z,$),X(),requestAnimationFrame(()=>{j.classList.remove($),j.classList.add(J)});let G=!1,K=()=>{if(G)return;G=!0,j.classList.remove(Z,J)};j.addEventListener("animationend",K,{once:!0}),setTimeout(K,350)}var v=Object.freeze({show:(j,Q)=>E(j,!1,Q),hide:(j,Q)=>E(j,!0,Q),toggle:(j,Q)=>E(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((X)=>j.classList.toggle(X)),set_attr:(j,Q)=>{if(F(Q.name))j.setAttribute(Q.name,Q.value??"")},remove_attr:(j,Q)=>{if(F(Q.name))j.removeAttribute(Q.name)},toggle_attr:(j,Q)=>{if(!F(Q.name))return;if(j.hasAttribute(Q.name))j.removeAttribute(Q.name);else j.setAttribute(Q.name,"")},focus:(j)=>j.focus?.(),focus_first:(j)=>Ej(j)?.focus?.(),text:(j,Q)=>{let X=String(Q.value??"");if(j.textContent!==X)j.textContent=X},dispatch:(j,Q)=>{j.dispatchEvent(new CustomEvent(Q.name,{bubbles:!0,composed:!0,detail:Q.detail??{}}))}});function E(j,Q,X){if(X?.transition)Nj(j,X.transition,()=>j.hidden=Q);else j.hidden=Q}function F(j){if(!Lj(j))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(j)} — skipped`),!1}var m=/^#[A-Za-z_][\w-]*$/;function Vj(j){if(typeof j==="string"&&m.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(j)} — skipped`),!1}function Mj(j,Q){let X=j.getAttribute("data-reactive-show-equals");if(X!==null)return Q===X;let Z=j.getAttribute("data-reactive-show-not");if(Z!==null)return Q!==Z;let $=j.getAttribute("data-reactive-show-in");if($!==null){try{let J=JSON.parse($);if(Array.isArray(J))return J.includes(Q)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify($)} — skipped`),null}for(let J of g){let G=j.getAttribute(`data-reactive-show-${J}`);if(G!==null)return c(J,G,Q)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}var g=["gte","gt","lte","lt"];function c(j,Q,X){let Z=Number(Q);if(Number.isNaN(Z))return console.warn(`[phlex-reactive] reactive_show ${j}: needs a numeric literal, got ${JSON.stringify(Q)} — skipped`),null;let $=X==null?"":String(X).trim(),J=$===""?NaN:Number($);if(Number.isNaN(J))return!1;switch(j){case"gte":return J>=Z;case"gt":return J>Z;case"lte":return J<=Z;case"lt":return J<Z;default:return null}}function d(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);for(let X of g)if(X in j)return c(X,j[X],Q);return null}var y="[data-reactive-show-field], [data-reactive-show]";function xj(j){try{let Q=JSON.parse(j);if(Q&&typeof Q==="object"&&!Array.isArray(Q))return Q}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(j)} — skipped`),null}function S(j,Q){if(!j||typeof j!=="object"||typeof j.field!=="string")return!1;let X=Q(j.field)??"";return d(j,X)===!0}function l(j,Q){if(!Array.isArray(j)||j.length===0)return null;return j.some((X)=>Array.isArray(X)&&X.length>0&&X.every((Z)=>S(Z,Q)))}function Bj(j,Q){if(!j||typeof j!=="object")return null;let X=j.any;if(Array.isArray(X)&&(X.length===0||Array.isArray(X[0])))return l(X,Q);return Oj(j,Q)}function Oj(j,Q){let X=Array.isArray(j.all)?"all":Array.isArray(j.any)?"any":null;if(!X)return null;let Z=j[X];if(Z.length===0)return null;let $=Z.map((J)=>S(J,Q));return X==="all"?$.every(Boolean):$.some(Boolean)}function Pj(j){if(typeof j==="string"&&m.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root show target ${JSON.stringify(j)} — skipped`),!1}var Cj='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Ej(j){return j.querySelectorAll?.(Cj)?.[0]??null}function o(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 s(j,Q){for(let X of j){if(!Array.isArray(X))continue;let[Z,$={}]=X;if(!Object.hasOwn(v,Z)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(Z)} — skipped`);continue}for(let J of Q($))v[Z](J,$)}}function Fj(j,Q){let X=j.to;if(Q){if(X==="@root")return[Q];if(typeof X!=="string"||X==="")return[];if(j.global)return[...document.querySelectorAll(X)];return[...Q.querySelectorAll(X)]}if(typeof X!=="string"||X===""||X==="@root")return[];return[...document.querySelectorAll(X)]}class fj extends i{static values={token:String};#F;#A=new Map;#K=new Map;#t;#M;#R;#x=0;#q=new Map;#B=new WeakMap;#_=new Map;#T=new WeakSet;#Y;#U;#H;#j;#X;#L;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.#D(),this.#L=()=>this.#D(),this.element.addEventListener?.("turbo:morph-element",this.#L);if(this.#e()){if(this.#Y=()=>this.#C(),this.element.addEventListener?.("turbo:morph-element",this.#Y),this.#C(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#Mj()}if(this.#Bj())this.#j=()=>this.#m(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#j),this.#m();if(this.#Ej())this.#X=(j)=>{if(j?.type==="input"&&!this.#Fj(j))return;this.#d()},this.element.addEventListener?.("input",this.#X),this.element.addEventListener?.("turbo:morph-element",this.#X),this.#d()}#e(){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.#Kj(),this.#Yj(),this.#xj(),this.#Cj(),this.#Rj(),this.#L)this.element.removeEventListener?.("turbo:morph-element",this.#L)}#D(){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;B(j.id,Q)}dispatch(j){let{action:Q,params:X,debounce:Z,throttle:$,confirm:J,confirmWhen:G,outside:K,window:z,optimistic:Y}=j.params;if(!Q)return;let H=j.params.busy??this.#hj(j.params.loading);if(K&&this.element.contains(j.target))return;let _=j.currentTarget??j.target;if(!z&&!this.#Ij(Y,_))j.preventDefault();let W=this.#f(J,G);if(!W)return this.#w(_,Q,X,Z,$,Y,H);Promise.resolve().then(()=>k(W)).catch(()=>!1).then((A)=>{if(A)this.#w(_,Q,X,Z,$,Y,H)})}runOps(j){let{ops:Q,confirm:X,confirmWhen:Z,outside:$,window:J}=j.params;if($&&this.element.contains(j.target))return;if(!J)j.preventDefault();let G=this.#f(X,Z);if(!G)return this.#s(this.#o(Q));Promise.resolve().then(()=>k(G)).catch(()=>!1).then((K)=>{if(K)this.#s(this.#o(Q))})}trackDirty(){this.#C()}recompute(j){if(j&&this.#T.has(j))return;let Q=this.#Qj(),X=Q.map(([q])=>q),Z=this.element.getAttribute?.("data-reactive-scope")||null,$=(q)=>Z&&!q.includes("[")?`${Z}[${q}]`:q,J=this.#W(),G=new Map,K=(q)=>{if(G.has(q))return G.get(q);let U=null;for(let V of this.element.querySelectorAll(`[name="${$(q)}"]`))if(J(V)){U=V;break}return G.set(q,U),U};for(let q of X)this.#S(q,K(q)?.value??"");let z=this.element.getAttribute("data-reactive-compute-reducer-param"),Y=z?n(z):null;if(!Y){this.#k({},K);return}let H=this.#jj("data-reactive-compute-outputs-param"),_={};for(let[q,U]of Q){let V=K(q);if(U==="string")_[q]=V?.value??"";else{let L=Number(V?.value);_[q]=Number.isFinite(L)?L:0}}let W=Y(_,{changed:this.#Xj(j,X,Z)})||{},A=[];for(let q of H){if(!(q in W))continue;let U=K(q);if(!U)continue;if(String(W[q])===U.value)continue;U.value=W[q],A.push(U)}for(let q of Object.keys(W)){let U=W[q];if(U===void 0||U===null)continue;this.#S(q,U)}this.#k(W,K);for(let q of A){let U=new Event("input",{bubbles:!0});this.#T.add(U),q.dispatchEvent(U)}}listnavNext(j){this.#I(j,1)}listnavPrev(j){this.#I(j,-1)}listnavPick(j){let Q=this.#O(j),X=Q.findIndex((Z)=>Z.hasAttribute("data-reactive-highlighted"));if(X<0)return;j.preventDefault(),Q[X].click()}listnavClose(j){for(let Q of this.#O(j))Q.removeAttribute("data-reactive-highlighted")}#I(j,Q){let X=this.#O(j);if(!X.length)return;j.preventDefault();let Z=X.findIndex((G)=>G.hasAttribute("data-reactive-highlighted")),$=Z<0?Q>0?0:X.length-1:(Z+Q+X.length)%X.length;for(let G of X)G.removeAttribute("data-reactive-highlighted");let J=X[$];J.setAttribute("data-reactive-highlighted","true"),J.scrollIntoView?.({block:"nearest"})}#O(j){let X=(j?.currentTarget??j?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!X)return[];let Z=this.#W();return Array.from(this.element.querySelectorAll(X)).filter(($)=>!$.hidden&&Z($))}#jj(j){let Q=this.element.getAttribute(j);if(!Q)return[];try{let X=JSON.parse(Q);return Array.isArray(X)?X:[]}catch{return[]}}#Qj(){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((X)=>[X,"number"]);if(Q&&typeof Q==="object")return Object.entries(Q);return[]}catch{return[]}}#Xj(j,Q,X){let Z=j?.target;if(!Z?.name||typeof Z.closest!=="function")return null;let $=this.#Zj(Z.name,X);if(!Q.includes($))return null;return this.#Q(Z)?$:null}#Zj(j,Q){if(!Q)return j;let X=`${Q}[`;return j.startsWith(X)&&j.endsWith("]")?j.slice(X.length,-1):j}#S(j,Q){let X=String(Q);for(let Z of this.#$j(j)){if(Z.textContent===X)continue;Z.textContent=X}}#$j(j){let Q=this.element.querySelectorAll(`[data-reactive-text="${j}"]`);return Array.from(Q).filter((X)=>this.#Q(X))}#k(j,Q){let X=this.#Jj();for(let[Z,$]of Object.entries(X)){let J=Z in j?j[Z]:Q(Z)?.value;if(J===void 0||J===null)continue;let G=String(J);for(let K of Array.isArray($)?$:[$]){if(!Vj(K))continue;for(let z of document.querySelectorAll(K)){if(z.textContent===G)continue;z.textContent=G}}}}#Jj(){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,X,Z,$,J,G){if(this.#V("reactive:before-dispatch",{action:Q,params:this.#l(X),element:this.element},{cancelable:!0}).defaultPrevented)return;let z=Number(Z)||0;if(z>0)return this.#zj(j,z,Q,X,J,G);let Y=Number($)||0;if(Y>0)return this.#qj(j,Y,Q,X,J,G);return this.#N(Q,X,J,j,G)}#N(j,Q,X,Z,$){let J=this.#Sj(X,Z),G=this.#kj(j,Z,$),K=this.#b()?this.#Gj(X,Z):null;return this.queue=(this.queue??Promise.resolve()).then(()=>this.#Lj(j,Q,J,G,K)),this.queue}#Gj(j,Q){if(!j?.hide)return null;let X=this.#a(j,Q);if(!X.length)return null;return()=>{let Z=X.filter(($)=>$.isConnected&&!$.hidden);if(!Z.length)return;console.warn("[phlex-reactive] optimistic: { hide: true } was undone by the reply's re-render — "+"the element is visible again. For an instant delete, return reply.remove so the server removes it; otherwise the hide only flashes.",Z)}}#zj(j,Q,X,Z,$,J){this.#P(j);let G=()=>{this.#P(j),this.#N(X,Z,$,j,J)},K=setTimeout(G,Q);j?.addEventListener?.("blur",G,{once:!0}),this.#A.set(j,{timer:K,flush:G})}#P(j){let Q=this.#A.get(j);if(!Q)return;clearTimeout(Q.timer),j?.removeEventListener?.("blur",Q.flush),this.#A.delete(j)}#Kj(){for(let j of[...this.#A.keys()])this.#P(j)}#qj(j,Q,X,Z,$,J){let G=this.#K.get(j)??new Map;if(G.has(X))return;let K=setTimeout(()=>{if(G.delete(X),G.size===0)this.#K.delete(j)},Q);return G.set(X,K),this.#K.set(j,G),this.#N(X,Z,$,j,J)}#Yj(){for(let j of this.#K.values())for(let Q of j.values())clearTimeout(Q);this.#K.clear()}#V(j,Q,{cancelable:X=!1}={}){let Z=new CustomEvent(j,{bubbles:!0,composed:!0,cancelable:X,detail:Q});return(this.element.isConnected?this.element:document).dispatchEvent(Z),Z}#Z(j,Q,X,Z){let $=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#N(j,Q)};this.#V("reactive:error",{action:j,params:X,...Z,retry:$})}#$(j){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",j)}#Uj(){this.element?.removeAttribute?.("data-reactive-error")}#Hj(){let j=document.querySelector("[data-reactive-error-flash]");if(!j?.content)return;let Q=j.getAttribute("data-reactive-error-flash")||"flash",X=document.getElementById(Q);if(!X)return;X.appendChild(j.content.cloneNode(!0))}#Wj(){if(typeof sessionStorage>"u")return Promise.resolve();let j=Number(sessionStorage.getItem(I));if(!Number.isFinite(j)||j<=0)return Promise.resolve();if(!x)x=!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))}#b(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#v(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#Aj(j){if(!j)return[];let Q=[],X=/<turbo-stream\b([^>]*)>/g,Z;while((Z=X.exec(j))!==null){let $=Z[1],J=$.match(/\baction="([^"]*)"/)?.[1]??"?",G=$.match(/\btarget="([^"]*)"/)?.[1];Q.push(G?`${J} → #${G}`:J)}return Q}#_j(j){let{action:Q,status:X,ms:Z}=j,J=`reactive ${this.element?.id?`#${this.element.id} `:""}${Q} → ${X??"—"} (${Math.round(Z)}ms)`;if(console.groupCollapsed(J),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#Lj(j,Q,X,Z,$){let{fields:J,files:G}=this.#u(),K=this.#l(Q),z={...J,...K},Y=this.#J,H=G.length>0,_=H?this.#Tj(Y,j,z,G):JSON.stringify({token:Y,act:j,params:z}),W=this.#b()?{action:j,paramNames:Object.keys(K),fieldNames:Object.keys(J),encoding:H?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#v()}:null;await this.#Wj();try{if(navigator.onLine===!1){this.#G(X),this.#$("offline"),this.#Z(j,Q,z,{kind:"offline"});return}let A;try{let L={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#pj()};if(!H)L["Content-Type"]="application/json";let M=this.#mj();if(M)L["X-Pgbus-Connection"]=M;A=await fetch(this.#fj(),{method:"POST",headers:L,body:_,credentials:"same-origin",signal:AbortSignal.timeout(this.#uj())})}catch(L){if(console.error("[phlex-reactive] action error",L),this.#G(X),L?.name==="TimeoutError"||L?.name==="AbortError"){this.#$("timeout"),this.#Z(j,Q,z,{kind:"timeout"});return}this.#Hj(),this.#$("network"),this.#Z(j,Q,z,{kind:"network"});return}if(W)W.status=A.status;if(A.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#G(X),this.#$("redirected"),this.#Z(j,Q,z,{kind:"redirected",status:A.status});return}if(!A.ok){let L=await A.text();if(console.error(`[phlex-reactive] action failed: HTTP ${A.status}`,L),this.#G(X),(A.headers.get("Content-Type")||"").includes("turbo-stream")){let M=this.#h(L);if(this.#J=M??this.#J,W)this.#y(W,L,M);window.Turbo.renderStreamMessage(L)}this.#$("http"),this.#Z(j,Q,z,{kind:"http",status:A.status,body:L});return}let q=A.headers.get("Content-Type")||"";if(!q.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${q}" — no update applied`),this.#G(X),this.#$("content-type"),this.#Z(j,Q,z,{kind:"content-type",status:A.status});return}let U=await A.text(),V=this.#h(U);if(this.#J=V??this.#J,W)this.#y(W,U,V);if(window.Turbo.renderStreamMessage(U),$)queueMicrotask($);this.#Uj(),this.#V("reactive:applied",{action:j,params:z,html:U})}catch(A){console.error("[phlex-reactive] action error",A),this.#G(X),this.#V("reactive:error",{action:j,params:z,kind:"apply"})}finally{if(Z?.(),W)this.#_j({...W,ms:this.#v()-W.started})}}#y(j,Q,X){j.streams=this.#Aj(Q),j.tokenRefreshed=X!=null}get#J(){return this.#F??this.tokenValue}set#J(j){this.#F=j}#h(j){let Q=this.element.id;if(!Q)return j.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:X,self:Z}=this.#Nj(Q),$=j.match(X);if($)return $[1];let J=j.match(Z);if(J)return J[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#Nj(j){let Q=this.#R;if(Q&&Q.id===j)return Q;let X=Wj(j);return this.#R={id:j,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${X}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${X}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#Q(j){return j.closest('[data-controller~="reactive"]')===this.element}#W(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(Q)=>this.#Q(Q)}#f(j,Q){if(j)return j;if(!Q)return null;let X=Q;if(typeof Q==="string")try{X=JSON.parse(Q)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(Q)} — skipped`),null}if(!X||typeof X!=="object")return null;let{fields:Z}=this.#u(),$=(G)=>Z[G],J;if(typeof X.predicate==="string"){let G=a(X.predicate);if(!G)return console.warn(`[phlex-reactive] confirm predicate "${X.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;J=!!G(Z)}else J=l(X.groups?.any,$)===!0;return J?X.message:null}#u(){let j={},Q=[],X=this.#W();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Z)=>{if(!X(Z))return;if(Z.type==="file")for(let $ of Z.files??[])Q.push({name:Z.name,file:$,multiple:Z.multiple});else if(Z.type==="checkbox")j[Z.name]=Z.checked;else if(Z.type==="radio"){if(Z.checked)j[Z.name]=Z.value}else j[Z.name]=Z.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((Z)=>{if(!X(Z))return;let $=Z.getAttribute("name");if(!$)return;let J=j[$];if(J==null||J==="")j[$]=Z.value??Z.textContent??Z.innerHTML??""}),{fields:j,files:Q}}#C(){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.#Vj(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")}#Vj(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}#p(){let j=this.element.getAttribute?.("data-reactive-dirty"),Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:0}#Mj(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#U=(j)=>{if(this.#p()===0)return;return j.preventDefault(),j.returnValue="You have unsaved changes.",j.returnValue},this.#H=(j)=>{if(this.#p()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))j.preventDefault?.()},window.addEventListener("beforeunload",this.#U),window.addEventListener("turbo:before-visit",this.#H)}#xj(){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.#U)window.removeEventListener("beforeunload",this.#U);if(this.#H)window.removeEventListener("turbo:before-visit",this.#H)}this.#U=void 0,this.#H=void 0}#Bj(){if(this.element.getAttribute?.("data-reactive-show-targets"))return!0;let j=this.element.querySelectorAll?.(y)??[];for(let Q of j)if(this.#Q(Q))return!0;return!1}#m(){if(typeof this.element?.querySelectorAll!=="function")return;let j=this.#W(),Q=this.element.getAttribute?.("data-reactive-scope")||null,X=new Map,Z=($)=>{if(!X.has($))X.set($,this.#c($,j,Q));return X.get($)};for(let $ of this.element.querySelectorAll(y)){if(!j($))continue;let J=$.getAttribute("data-reactive-show");if(J!==null){let Y=Bj(xj(J),Z);if(Y!==null)this.#g($,Y,j,Q);continue}let G=$.getAttribute("data-reactive-show-field");if(!G)continue;let K=Z(G);if(K===null)continue;let z=Mj($,K);if(z===null)continue;this.#g($,z,j,Q)}this.#Oj(j,X,Q)}#g(j,Q,X,Z){if(j.hidden=!Q,j.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof j.querySelectorAll!=="function")return;for(let $ of j.querySelectorAll("input[name], select[name], textarea[name]"))if(X($))$.disabled=!Q;if(j.name&&X(j))j.disabled=!Q}#Oj(j,Q,X){let Z=this.#Pj();for(let[$,J]of Object.entries(Z)){if(!J||typeof J!=="object"||Array.isArray(J))continue;if(!Q.has($))Q.set($,this.#c($,j,X));let G=Q.get($);if(G===null)continue;let K=()=>G;for(let[z,Y]of Object.entries(J)){if(!Pj(z))continue;let H;if(Array.isArray(Y)){if(Y.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${z} — skipped`);continue}H=Y.every((_)=>S(_,K))}else{let _=d(Y,G);if(_===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${z} — skipped`);continue}H=_}for(let _ of document.querySelectorAll(z))_.hidden=!H}}}#Pj(){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: { ... })"),{}}#c(j,Q,X){let Z=X&&!j.includes("[")?`${X}[${j}]`:j,$=!1,J=null;for(let G of this.element.querySelectorAll(`[name="${Z}"]`)){if(!Q(G))continue;if(G.type==="checkbox")return G.checked?"true":"false";if(G.type==="radio"){if(G.checked)return G.value??"";$=!0;continue}J??=G}if(J)return J.value??"";return $?"":null}#Cj(){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}#Ej(){return!!(this.element.getAttribute?.("data-reactive-filter-input")&&this.element.getAttribute?.("data-reactive-filter-option"))}#Fj(j){let Q=this.element.getAttribute("data-reactive-filter-input");return!!Q&&typeof j.target?.matches==="function"&&j.target.matches(Q)}#d(){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 X=this.#W(),Z=[...this.element.querySelectorAll(j)].find(X);if(!Z)return;let $=(Z.value??"").trim().toLowerCase(),J=0;for(let z of this.element.querySelectorAll(Q)){if(!X(z))continue;let Y=(z.getAttribute("data-reactive-filter-text")??z.textContent??"").toLowerCase(),H=$!==""&&!Y.includes($);if(z.hidden=H,H)z.removeAttribute("data-reactive-highlighted");else J++}let G=this.element.getAttribute("data-reactive-filter-group");if(G)for(let z of this.element.querySelectorAll(G)){if(!X(z))continue;let Y=[...z.querySelectorAll(Q)].filter(X);if(Y.length===0)continue;z.hidden=Y.every((H)=>H.hidden)}let K=this.element.getAttribute("data-reactive-filter-empty");if(K){for(let z of this.element.querySelectorAll(K))if(X(z))z.hidden=J>0}}#Rj(){if(!this.#X)return;this.element.removeEventListener?.("input",this.#X),this.element.removeEventListener?.("turbo:morph-element",this.#X),this.#X=void 0}#Tj(j,Q,X,Z){let $=new FormData;$.append("token",j),$.append("act",Q);for(let[G,K]of Object.entries(X))this.#E($,`params[${G}]`,K);let J=this.#Dj(Z);for(let{name:G,file:K,multiple:z}of Z){let H=z||J.has(G)?`params[${G}][]`:`params[${G}]`;$.append(H,K,K.name)}return $}#E(j,Q,X){if(X==null)j.append(Q,"");else if(Array.isArray(X))X.forEach((Z,$)=>this.#E(j,`${Q}[${$}]`,Z));else if(typeof X==="object")for(let[Z,$]of Object.entries(X))this.#E(j,`${Q}[${Z}]`,$);else j.append(Q,String(X))}#Dj(j){let Q=new Map;for(let{name:X}of j)Q.set(X,(Q.get(X)??0)+1);return new Set([...Q].filter(([,X])=>X>1).map(([X])=>X))}#l(j){if(!j)return{};try{return typeof j==="string"?JSON.parse(j):j}catch{return{}}}#o(j){return o(j)}#s(j){s(j,(Q)=>this.#i(Q))}#i(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((X)=>this.#Q(X))}#Ij(j,Q){if(j?.checked!=="keep")return!1;let X=Q?.type;return X==="checkbox"||X==="radio"}#Sj(j,Q){if(!j)return null;let X=this.#n(j,Q,!0);return X.length?X:null}#G(j){if(!j)return;if(!this.element.isConnected)return;for(let Q of j)Q()}#kj(j,Q,X){this.#bj(j,Q);let Z=X?this.#n(X,Q,!1):[],$=!1;return()=>{if($)return;$=!0,this.#vj(j,Q);for(let J of Z)J()}}#n(j,Q,X){let Z=[];for(let $ of this.#a(j,Q)){if(j.add_class){let J=j.add_class.filter((G)=>!$.classList.contains(G));if($.classList.add(...J),J.length)Z.push(()=>$.classList.remove(...J))}if(j.remove_class){let J=j.remove_class.filter((G)=>$.classList.contains(G));if($.classList.remove(...J),J.length)Z.push(()=>$.classList.add(...J))}if(j.toggle_class)j.toggle_class.forEach((J)=>$.classList.toggle(J)),Z.push(()=>j.toggle_class.forEach((J)=>$.classList.toggle(J)));if(j.hide)$.hidden=!0,Z.push(()=>$.hidden=!1);if(j.show)$.hidden=!1,Z.push(()=>$.hidden=!0)}if(Q&&(j.disable||j.text!=null))Z.push(this.#wj(j,Q));if(X&&j.checked==="keep"&&Q&&"checked"in Q){let $=Q.checked;Z.push(()=>Q.checked=!$)}return Z}#a(j,Q){if(j.to==null)return Q?[Q]:[];return this.#i({to:j.to})}#wj(j,Q){let X=this.#_.get(Q);if(X)X.count++;else this.#_.set(Q,{count:1,disabled:Q.disabled,html:Q.innerHTML,hadText:j.text!=null,swappedTo:j.text});if(j.disable)Q.disabled=!0;if(j.text!=null)Q.innerHTML=j.text;return()=>this.#yj(Q,j)}#bj(j,Q){if(this.#z(Q,j,1),this.#z(this.element,j,1),this.#q.set(j,(this.#q.get(j)??0)+1),this.#x++===0)this.element.setAttribute("aria-busy","true");for(let X of this.#r(j))this.#z(X,j,1)}#vj(j,Q){this.#z(Q,j,-1),this.#z(this.element,j,-1);let X=(this.#q.get(j)??1)-1;if(X<=0)this.#q.delete(j);else this.#q.set(j,X);if(--this.#x<=0)this.#x=0,this.element.removeAttribute("aria-busy");for(let Z of this.#r(j))this.#z(Z,j,-1)}#z(j,Q,X){if(!j||typeof j.getAttribute!=="function")return;let Z=this.#B.get(j)??new Map,$=(Z.get(Q)??0)+X;if($<=0)Z.delete(Q);else Z.set(Q,$);if(Z.size===0){this.#B.delete(j),j.removeAttribute("data-reactive-busy");return}this.#B.set(j,Z),j.setAttribute("data-reactive-busy",[...Z.keys()].join(" "))}#r(j){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((X)=>X.getAttribute("data-reactive-busy-on")===j&&this.#Q(X))}#yj(j,Q){let X=this.#_.get(j);if(!X)return;if(--X.count>0)return;if(this.#_.delete(j),!j.isConnected)return;if(Q.disable)j.disabled=X.disabled;if(X.hadText&&j.innerHTML===X.swappedTo)j.innerHTML=X.html}#hj(j){if(!j||typeof j!=="object")return null;let{class:Q,...X}=j;return Q==null?j:{...X,add_class:Q}}#fj(){return this.#t??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#uj(){if(this.#M!=null)return this.#M;let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return this.#M=Number.isFinite(Q)&&Q>0?Q:30000}#pj(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#mj(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{Sj as resetReactiveDefers,r as registerReactiveVisit,t as registerReactiveToken,qj as registerReactiveOffline,e as registerReactiveJs,zj as registerReactiveDismiss,jj as registerReactiveDefer,b as registerReactiveActions,kj as pendingDeferVia,Wj as escapeRegExp,Yj as enableLatencySim,Uj as disableLatencySim,fj as default,Aj as checkReactiveRegistration,yj as __resetReactiveRegistrationForTest,bj as __resetReactiveOfflineForTest,vj as __resetReactiveLatencyForTest,wj as __resetReactiveDismissForTest,hj as __markReactiveConnectedForTest,I as LATENCY_KEY};
1
+ import{Controller as i}from"@hotwired/stimulus";import{confirmResolver as k}from"phlex/reactive/confirm";import{computeReducer as n}from"phlex/reactive/compute";import{confirmPredicate as a}from"phlex/reactive/confirm_predicate";function r(){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 t(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:token"])return;j["reactive:token"]=function(){let Q=this.getAttribute("data-reactive-token-value"),X=this.getAttribute("target");if(!Q||!X)return;let Z=document.getElementById(X);if(Z)Z.setAttribute("data-reactive-token-value",Q)}}function e(){let j=window.Turbo?.StreamActions;if(!j||j["reactive:js"])return;j["reactive:js"]=function(){let Q=o(this.getAttribute("data-reactive-ops"));if(!Q.length)return;let X=this.getAttribute("target"),Z=X?document.getElementById(X):null;if(X&&!Z)return;s(Q,($)=>Fj($,Z))}}var N=new Map;function Sj(){N.clear(),R=!1}function kj(j){return N.get(j)?.via}var R=!1;function jj(){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"){Xj(Q,this);return}let X=this.getAttribute("data-reactive-defer-token");if(!X)return;B(Q,X)},!R&&typeof document<"u"&&document.addEventListener)R=!0,document.addEventListener("turbo:before-stream-render",Qj)}function Qj(j){let X=j.target?.getAttribute?.("target");if(!X)return;let Z=X.startsWith("reactive-defer-src-")?X.slice(19):X;if(N.get(Z)?.via==="stream")N.delete(Z)}function B(j,Q){let X=document.getElementById(j);if(!X){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}f(j),p(X);let Z={via:"fetch",abort:new AbortController,timedOut:!1};N.set(j,Z),Zj(j,Z,Q)}function Xj(j,Q){let X=document.getElementById(j);if(!X){console.warn(`[phlex-reactive] reactive:defer target #${j} is not on the page — skipped`);return}let Z=Q.getAttribute("data-reactive-defer-src");if(!Z)return;if(!globalThis.customElements?.get?.("pgbus-stream-source")){let J=Q.getAttribute("data-reactive-defer-token");if(J){B(j,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}f(j),p(X);let $=document.createElement("pgbus-stream-source");$.id=h(j),$.setAttribute("src",Z),$.setAttribute("since-id",Q.getAttribute("data-reactive-defer-since-id")??"0"),$.setAttribute("hidden",""),document.body.appendChild($),N.set(j,{via:"stream"})}function h(j){return`reactive-defer-src-${j}`}async function Zj(j,Q,X){let Z=setTimeout(()=>{Q.timedOut=!0,Q.abort.abort()},Gj()),$;try{$=await fetch($j(),{method:"POST",headers:{Accept:"text/vnd.turbo-stream.html","Content-Type":"application/json","X-CSRF-Token":Jj()},body:JSON.stringify({token:X}),credentials:"same-origin",signal:Q.abort.signal})}catch(G){if(clearTimeout(Z),N.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed",G),P(j,X);return}if(N.get(j)!==Q){clearTimeout(Z);return}if($.status===204){clearTimeout(Z),w(j);return}if(!$.ok){clearTimeout(Z),console.error(`[phlex-reactive] deferred render failed: HTTP ${$.status}`),P(j,X,$.status);return}let J;try{J=await $.text()}catch(G){if(clearTimeout(Z),N.get(j)!==Q)return;console.error("[phlex-reactive] deferred render failed reading the body",G),P(j,X);return}if(clearTimeout(Z),N.get(j)!==Q)return;w(j),window.Turbo.renderStreamMessage(J)}function f(j){let Q=N.get(j);if(!Q)return;if(N.delete(j),Q.via==="fetch")Q.abort.abort();else document.getElementById(h(j))?.remove?.()}function p(j){j.setAttribute("data-reactive-defer-pending","true"),j.setAttribute("aria-busy","true")}function u(j){j.removeAttribute("data-reactive-defer-pending"),j.removeAttribute("aria-busy")}function w(j){N.delete(j);let Q=document.getElementById(j);if(!Q)return;u(Q),Q.removeAttribute("data-reactive-error")}function P(j,Q,X){N.delete(j);let Z=document.getElementById(j);if(!Z)return;u(Z),Z.setAttribute("data-reactive-error","defer");let $=()=>{let J=document.getElementById(j);if(!J){console.warn("[phlex-reactive] defer retry() ignored — the target left the DOM");return}J.removeAttribute("data-reactive-error"),B(j,Q)};Z.dispatchEvent(new CustomEvent("reactive:error",{bubbles:!0,composed:!0,detail:{kind:"defer",target:j,status:X,retry:$}}))}function $j(){return document.querySelector('meta[name="phlex-reactive-defer-path"]')?.content||"/reactive/defer"}function Jj(){return document.querySelector('meta[name="csrf-token"]')?.content??""}function Gj(){let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:30000}var T=!1;function zj(){if(T)return;if(typeof document>"u"||!document.addEventListener)return;T=!0,document.addEventListener("turbo:before-stream-render",Kj)}function Kj(j){let Q=j.detail,X=Q?.render;if(typeof X!=="function"||X.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(E);else setTimeout(E,0);return}let Z=async($)=>{await X($),E()};Z.__reactiveDismissWrapped=!0,Q.render=Z}function E(){let j=document.querySelectorAll("[data-reactive-dismiss-after]");for(let Q of j){if(Q.hasAttribute("data-reactive-dismiss-scheduled"))continue;let X=Number(Q.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite(X)||X<=0)continue;Q.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>Q.remove(),X)}}function wj(){T=!1}var D=!1;function qj(){if(D)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;D=!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 bj(){D=!1}var I="phlex-reactive:latency",x=!1;function Yj(j){if(typeof sessionStorage>"u")return;sessionStorage.setItem(I,String(j))}function Uj(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(I),x=!1}function Hj(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:Yj,disableLatencySim:Uj}}function vj(){x=!1}function b(){r(),t(),e(),jj(),zj(),qj(),Hj()}function Wj(j){return j.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)b();else document.addEventListener("turbo:load",b,{once:!0});var O=!1;function Aj(){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 yj(){O=!1}function hj(){O=!0}if(typeof window<"u"&&typeof document<"u"){let j=()=>setTimeout(Aj,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",j,{once:!0});else j()}var _j=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function Lj(j){let Q=String(j).toLowerCase();return Q.startsWith("on")||_j.has(Q)}function Nj(j,Q,X){let[Z,$,J]=Q;j.classList.add(Z,$),X(),requestAnimationFrame(()=>{j.classList.remove($),j.classList.add(J)});let G=!1,K=()=>{if(G)return;G=!0,j.classList.remove(Z,J)};j.addEventListener("animationend",K,{once:!0}),setTimeout(K,350)}var v=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((X)=>j.classList.toggle(X)),set_attr:(j,Q)=>{if(F(Q.name))j.setAttribute(Q.name,Q.value??"")},remove_attr:(j,Q)=>{if(F(Q.name))j.removeAttribute(Q.name)},toggle_attr:(j,Q)=>{if(!F(Q.name))return;if(j.hasAttribute(Q.name))j.removeAttribute(Q.name);else j.setAttribute(Q.name,"")},focus:(j)=>j.focus?.(),focus_first:(j)=>Cj(j)?.focus?.(),text:(j,Q)=>{let X=String(Q.value??"");if(j.textContent!==X)j.textContent=X},dispatch:(j,Q)=>{j.dispatchEvent(new CustomEvent(Q.name,{bubbles:!0,composed:!0,detail:Q.detail??{}}))}});function C(j,Q,X){if(X?.transition)Nj(j,X.transition,()=>j.hidden=Q);else j.hidden=Q}function F(j){if(!Lj(j))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(j)} — skipped`),!1}var m=/^#[A-Za-z_][\w-]*$/;function Vj(j){if(typeof j==="string"&&m.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(j)} — skipped`),!1}function Mj(j,Q){let X=j.getAttribute("data-reactive-show-equals");if(X!==null)return Q===X;let Z=j.getAttribute("data-reactive-show-not");if(Z!==null)return Q!==Z;let $=j.getAttribute("data-reactive-show-in");if($!==null){try{let J=JSON.parse($);if(Array.isArray(J))return J.includes(Q)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify($)} — skipped`),null}for(let J of g){let G=j.getAttribute(`data-reactive-show-${J}`);if(G!==null)return c(J,G,Q)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}var g=["gte","gt","lte","lt"];function c(j,Q,X){let Z=Number(Q);if(Number.isNaN(Z))return console.warn(`[phlex-reactive] reactive_show ${j}: needs a numeric literal, got ${JSON.stringify(Q)} — skipped`),null;let $=X==null?"":String(X).trim(),J=$===""?NaN:Number($);if(Number.isNaN(J))return!1;switch(j){case"gte":return J>=Z;case"gt":return J>Z;case"lte":return J<=Z;case"lt":return J<Z;default:return null}}function d(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);for(let X of g)if(X in j)return c(X,j[X],Q);return null}var y="[data-reactive-show-field], [data-reactive-show]";function xj(j){try{let Q=JSON.parse(j);if(Q&&typeof Q==="object"&&!Array.isArray(Q))return Q}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(j)} — skipped`),null}function S(j,Q){if(!j||typeof j!=="object"||typeof j.field!=="string")return!1;let X=Q(j.field)??"";return d(j,X)===!0}function l(j,Q){if(!Array.isArray(j)||j.length===0)return null;return j.some((X)=>Array.isArray(X)&&X.length>0&&X.every((Z)=>S(Z,Q)))}function Bj(j,Q){if(!j||typeof j!=="object")return null;let X=j.any;if(Array.isArray(X)&&(X.length===0||Array.isArray(X[0])))return l(X,Q);return Oj(j,Q)}function Oj(j,Q){let X=Array.isArray(j.all)?"all":Array.isArray(j.any)?"any":null;if(!X)return null;let Z=j[X];if(Z.length===0)return null;let $=Z.map((J)=>S(J,Q));return X==="all"?$.every(Boolean):$.some(Boolean)}function Pj(j){if(typeof j==="string"&&m.test(j))return!0;return console.warn(`[phlex-reactive] refused cross-root show target ${JSON.stringify(j)} — skipped`),!1}var Ej='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Cj(j){return j.querySelectorAll?.(Ej)?.[0]??null}function o(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 s(j,Q){for(let X of j){if(!Array.isArray(X))continue;let[Z,$={}]=X;if(!Object.hasOwn(v,Z)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(Z)} — skipped`);continue}for(let J of Q($))v[Z](J,$)}}function Fj(j,Q){let X=j.to;if(Q){if(X==="@root")return[Q];if(typeof X!=="string"||X==="")return[];if(j.global)return[...document.querySelectorAll(X)];return[...Q.querySelectorAll(X)]}if(typeof X!=="string"||X===""||X==="@root")return[];return[...document.querySelectorAll(X)]}class fj extends i{static values={token:String};#R;#_=new Map;#K=new Map;#e;#x;#T;#B=0;#q=new Map;#O=new WeakMap;#L=new Map;#D=new WeakSet;#Y;#U;#H;#j;#X;#W;#N;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.#I(),this.#N=()=>this.#I(),this.element.addEventListener?.("turbo:morph-element",this.#N);if(this.#jj()){if(this.#Y=()=>this.#C(),this.element.addEventListener?.("turbo:morph-element",this.#Y),this.#C(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#xj()}if(this.#Oj())this.#j=()=>this.#g(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#j),this.#g();if(this.#Fj())this.#X=(j)=>{if(j?.type==="input"&&!this.#Tj(j))return;this.#l()},this.element.addEventListener?.("input",this.#X),this.element.addEventListener?.("turbo:morph-element",this.#X),this.#l();if(this.#Rj())this.#W=()=>this.recompute(),this.element.addEventListener?.("turbo:morph-element",this.#W),this.recompute()}#jj(){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.#qj(),this.#Uj(),this.#Bj(),this.#Cj(),this.#Dj(),this.#Ij(),this.#N)this.element.removeEventListener?.("turbo:morph-element",this.#N)}#I(){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;B(j.id,Q)}dispatch(j){let{action:Q,params:X,debounce:Z,throttle:$,confirm:J,confirmWhen:G,outside:K,window:z,optimistic:Y}=j.params;if(!Q)return;let H=j.params.busy??this.#uj(j.params.loading);if(K&&this.element.contains(j.target))return;let _=j.currentTarget??j.target;if(!z&&!this.#wj(Y,_))j.preventDefault();let W=this.#p(J,G);if(!W)return this.#b(_,Q,X,Z,$,Y,H);Promise.resolve().then(()=>k(W)).catch(()=>!1).then((A)=>{if(A)this.#b(_,Q,X,Z,$,Y,H)})}runOps(j){let{ops:Q,confirm:X,confirmWhen:Z,outside:$,window:J}=j.params;if($&&this.element.contains(j.target))return;if(!J)j.preventDefault();let G=this.#p(X,Z);if(!G)return this.#i(this.#s(Q));Promise.resolve().then(()=>k(G)).catch(()=>!1).then((K)=>{if(K)this.#i(this.#s(Q))})}trackDirty(){this.#C()}recompute(j){if(j&&this.#D.has(j))return;let Q=this.#Xj(),X=Q.map(([q])=>q),Z=this.element.getAttribute?.("data-reactive-scope")||null,$=(q)=>Z&&!q.includes("[")?`${Z}[${q}]`:q,J=this.#A(),G=new Map,K=(q)=>{if(G.has(q))return G.get(q);let U=null;for(let V of this.element.querySelectorAll(`[name="${$(q)}"]`))if(J(V)){U=V;break}return G.set(q,U),U};for(let q of X)this.#k(q,K(q)?.value??"");let z=this.element.getAttribute("data-reactive-compute-reducer-param"),Y=z?n(z):null;if(!Y){this.#w({},K);return}let H=this.#Qj("data-reactive-compute-outputs-param"),_={};for(let[q,U]of Q){let V=K(q);if(U==="string")_[q]=V?.value??"";else{let L=Number(V?.value);_[q]=Number.isFinite(L)?L:0}}let W=Y(_,{changed:this.#Zj(j,X,Z)})||{},A=[];for(let q of H){if(!(q in W))continue;let U=K(q);if(!U)continue;if(String(W[q])===U.value)continue;U.value=W[q],A.push(U)}for(let q of Object.keys(W)){let U=W[q];if(U===void 0||U===null)continue;this.#k(q,U)}this.#w(W,K);for(let q of A){let U=new Event("input",{bubbles:!0});this.#D.add(U),q.dispatchEvent(U)}}listnavNext(j){this.#S(j,1)}listnavPrev(j){this.#S(j,-1)}listnavPick(j){let Q=this.#P(j),X=Q.findIndex((Z)=>Z.hasAttribute("data-reactive-highlighted"));if(X<0)return;j.preventDefault(),Q[X].click()}listnavClose(j){for(let Q of this.#P(j))Q.removeAttribute("data-reactive-highlighted")}#S(j,Q){let X=this.#P(j);if(!X.length)return;j.preventDefault();let Z=X.findIndex((G)=>G.hasAttribute("data-reactive-highlighted")),$=Z<0?Q>0?0:X.length-1:(Z+Q+X.length)%X.length;for(let G of X)G.removeAttribute("data-reactive-highlighted");let J=X[$];J.setAttribute("data-reactive-highlighted","true"),J.scrollIntoView?.({block:"nearest"})}#P(j){let X=(j?.currentTarget??j?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!X)return[];let Z=this.#A();return Array.from(this.element.querySelectorAll(X)).filter(($)=>!$.hidden&&Z($))}#Qj(j){let Q=this.element.getAttribute(j);if(!Q)return[];try{let X=JSON.parse(Q);return Array.isArray(X)?X:[]}catch{return[]}}#Xj(){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((X)=>[X,"number"]);if(Q&&typeof Q==="object")return Object.entries(Q);return[]}catch{return[]}}#Zj(j,Q,X){let Z=j?.target;if(!Z?.name||typeof Z.closest!=="function")return null;let $=this.#$j(Z.name,X);if(!Q.includes($))return null;return this.#Q(Z)?$:null}#$j(j,Q){if(!Q)return j;let X=`${Q}[`;return j.startsWith(X)&&j.endsWith("]")?j.slice(X.length,-1):j}#k(j,Q){let X=String(Q);for(let Z of this.#Jj(j)){if(Z.textContent===X)continue;Z.textContent=X}}#Jj(j){let Q=this.element.querySelectorAll(`[data-reactive-text="${j}"]`);return Array.from(Q).filter((X)=>this.#Q(X))}#w(j,Q){let X=this.#Gj();for(let[Z,$]of Object.entries(X)){let J=Z in j?j[Z]:Q(Z)?.value;if(J===void 0||J===null)continue;let G=String(J);for(let K of Array.isArray($)?$:[$]){if(!Vj(K))continue;for(let z of document.querySelectorAll(K)){if(z.textContent===G)continue;z.textContent=G}}}}#Gj(){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{}}}#b(j,Q,X,Z,$,J,G){if(this.#M("reactive:before-dispatch",{action:Q,params:this.#o(X),element:this.element},{cancelable:!0}).defaultPrevented)return;let z=Number(Z)||0;if(z>0)return this.#Kj(j,z,Q,X,J,G);let Y=Number($)||0;if(Y>0)return this.#Yj(j,Y,Q,X,J,G);return this.#V(Q,X,J,j,G)}#V(j,Q,X,Z,$){let J=this.#bj(X,Z),G=this.#vj(j,Z,$),K=this.#v()?this.#zj(X,Z):null;return this.queue=(this.queue??Promise.resolve()).then(()=>this.#Nj(j,Q,J,G,K)),this.queue}#zj(j,Q){if(!j?.hide)return null;let X=this.#r(j,Q);if(!X.length)return null;return()=>{let Z=X.filter(($)=>$.isConnected&&!$.hidden);if(!Z.length)return;console.warn("[phlex-reactive] optimistic: { hide: true } was undone by the reply's re-render — "+"the element is visible again. For an instant delete, return reply.remove so the server removes it; otherwise the hide only flashes.",Z)}}#Kj(j,Q,X,Z,$,J){this.#E(j);let G=()=>{this.#E(j),this.#V(X,Z,$,j,J)},K=setTimeout(G,Q);j?.addEventListener?.("blur",G,{once:!0}),this.#_.set(j,{timer:K,flush:G})}#E(j){let Q=this.#_.get(j);if(!Q)return;clearTimeout(Q.timer),j?.removeEventListener?.("blur",Q.flush),this.#_.delete(j)}#qj(){for(let j of[...this.#_.keys()])this.#E(j)}#Yj(j,Q,X,Z,$,J){let G=this.#K.get(j)??new Map;if(G.has(X))return;let K=setTimeout(()=>{if(G.delete(X),G.size===0)this.#K.delete(j)},Q);return G.set(X,K),this.#K.set(j,G),this.#V(X,Z,$,j,J)}#Uj(){for(let j of this.#K.values())for(let Q of j.values())clearTimeout(Q);this.#K.clear()}#M(j,Q,{cancelable:X=!1}={}){let Z=new CustomEvent(j,{bubbles:!0,composed:!0,cancelable:X,detail:Q});return(this.element.isConnected?this.element:document).dispatchEvent(Z),Z}#Z(j,Q,X,Z){let $=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#V(j,Q)};this.#M("reactive:error",{action:j,params:X,...Z,retry:$})}#$(j){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",j)}#Hj(){this.element?.removeAttribute?.("data-reactive-error")}#Wj(){let j=document.querySelector("[data-reactive-error-flash]");if(!j?.content)return;let Q=j.getAttribute("data-reactive-error-flash")||"flash",X=document.getElementById(Q);if(!X)return;X.appendChild(j.content.cloneNode(!0))}#Aj(){if(typeof sessionStorage>"u")return Promise.resolve();let j=Number(sessionStorage.getItem(I));if(!Number.isFinite(j)||j<=0)return Promise.resolve();if(!x)x=!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))}#v(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#y(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#_j(j){if(!j)return[];let Q=[],X=/<turbo-stream\b([^>]*)>/g,Z;while((Z=X.exec(j))!==null){let $=Z[1],J=$.match(/\baction="([^"]*)"/)?.[1]??"?",G=$.match(/\btarget="([^"]*)"/)?.[1];Q.push(G?`${J} → #${G}`:J)}return Q}#Lj(j){let{action:Q,status:X,ms:Z}=j,J=`reactive ${this.element?.id?`#${this.element.id} `:""}${Q} → ${X??"—"} (${Math.round(Z)}ms)`;if(console.groupCollapsed(J),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#Nj(j,Q,X,Z,$){let{fields:J,files:G}=this.#u(),K=this.#o(Q),z={...J,...K},Y=this.#J,H=G.length>0,_=H?this.#Sj(Y,j,z,G):JSON.stringify({token:Y,act:j,params:z}),W=this.#v()?{action:j,paramNames:Object.keys(K),fieldNames:Object.keys(J),encoding:H?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#y()}:null;await this.#Aj();try{if(navigator.onLine===!1){this.#G(X),this.#$("offline"),this.#Z(j,Q,z,{kind:"offline"});return}let A;try{let L={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#cj()};if(!H)L["Content-Type"]="application/json";let M=this.#dj();if(M)L["X-Pgbus-Connection"]=M;A=await fetch(this.#mj(),{method:"POST",headers:L,body:_,credentials:"same-origin",signal:AbortSignal.timeout(this.#gj())})}catch(L){if(console.error("[phlex-reactive] action error",L),this.#G(X),L?.name==="TimeoutError"||L?.name==="AbortError"){this.#$("timeout"),this.#Z(j,Q,z,{kind:"timeout"});return}this.#Wj(),this.#$("network"),this.#Z(j,Q,z,{kind:"network"});return}if(W)W.status=A.status;if(A.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#G(X),this.#$("redirected"),this.#Z(j,Q,z,{kind:"redirected",status:A.status});return}if(!A.ok){let L=await A.text();if(console.error(`[phlex-reactive] action failed: HTTP ${A.status}`,L),this.#G(X),(A.headers.get("Content-Type")||"").includes("turbo-stream")){let M=this.#f(L);if(this.#J=M??this.#J,W)this.#h(W,L,M);window.Turbo.renderStreamMessage(L)}this.#$("http"),this.#Z(j,Q,z,{kind:"http",status:A.status,body:L});return}let q=A.headers.get("Content-Type")||"";if(!q.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${q}" — no update applied`),this.#G(X),this.#$("content-type"),this.#Z(j,Q,z,{kind:"content-type",status:A.status});return}let U=await A.text(),V=this.#f(U);if(this.#J=V??this.#J,W)this.#h(W,U,V);if(window.Turbo.renderStreamMessage(U),$)queueMicrotask($);this.#Hj(),this.#M("reactive:applied",{action:j,params:z,html:U})}catch(A){console.error("[phlex-reactive] action error",A),this.#G(X),this.#M("reactive:error",{action:j,params:z,kind:"apply"})}finally{if(Z?.(),W)this.#Lj({...W,ms:this.#y()-W.started})}}#h(j,Q,X){j.streams=this.#_j(Q),j.tokenRefreshed=X!=null}get#J(){return this.#R??this.tokenValue}set#J(j){this.#R=j}#f(j){let Q=this.element.id;if(!Q)return j.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:X,self:Z}=this.#Vj(Q),$=j.match(X);if($)return $[1];let J=j.match(Z);if(J)return J[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#Vj(j){let Q=this.#T;if(Q&&Q.id===j)return Q;let X=Wj(j);return this.#T={id:j,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${X}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${X}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#Q(j){return j.closest('[data-controller~="reactive"]')===this.element}#A(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(Q)=>this.#Q(Q)}#p(j,Q){if(j)return j;if(!Q)return null;let X=Q;if(typeof Q==="string")try{X=JSON.parse(Q)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(Q)} — skipped`),null}if(!X||typeof X!=="object")return null;let{fields:Z}=this.#u(),$=(G)=>Z[G],J;if(typeof X.predicate==="string"){let G=a(X.predicate);if(!G)return console.warn(`[phlex-reactive] confirm predicate "${X.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;J=!!G(Z)}else J=l(X.groups?.any,$)===!0;return J?X.message:null}#u(){let j={},Q=[],X=this.#A();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Z)=>{if(!X(Z))return;if(Z.type==="file")for(let $ of Z.files??[])Q.push({name:Z.name,file:$,multiple:Z.multiple});else if(Z.type==="checkbox")j[Z.name]=Z.checked;else if(Z.type==="radio"){if(Z.checked)j[Z.name]=Z.value}else j[Z.name]=Z.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((Z)=>{if(!X(Z))return;let $=Z.getAttribute("name");if(!$)return;let J=j[$];if(J==null||J==="")j[$]=Z.value??Z.textContent??Z.innerHTML??""}),{fields:j,files:Q}}#C(){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.#Mj(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")}#Mj(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}#m(){let j=this.element.getAttribute?.("data-reactive-dirty"),Q=Number(j);return Number.isFinite(Q)&&Q>0?Q:0}#xj(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#U=(j)=>{if(this.#m()===0)return;return j.preventDefault(),j.returnValue="You have unsaved changes.",j.returnValue},this.#H=(j)=>{if(this.#m()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))j.preventDefault?.()},window.addEventListener("beforeunload",this.#U),window.addEventListener("turbo:before-visit",this.#H)}#Bj(){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.#U)window.removeEventListener("beforeunload",this.#U);if(this.#H)window.removeEventListener("turbo:before-visit",this.#H)}this.#U=void 0,this.#H=void 0}#Oj(){if(this.element.getAttribute?.("data-reactive-show-targets"))return!0;let j=this.element.querySelectorAll?.(y)??[];for(let Q of j)if(this.#Q(Q))return!0;return!1}#g(){if(typeof this.element?.querySelectorAll!=="function")return;let j=this.#A(),Q=this.element.getAttribute?.("data-reactive-scope")||null,X=new Map,Z=($)=>{if(!X.has($))X.set($,this.#d($,j,Q));return X.get($)};for(let $ of this.element.querySelectorAll(y)){if(!j($))continue;let J=$.getAttribute("data-reactive-show");if(J!==null){let Y=Bj(xj(J),Z);if(Y!==null)this.#c($,Y,j,Q);continue}let G=$.getAttribute("data-reactive-show-field");if(!G)continue;let K=Z(G);if(K===null)continue;let z=Mj($,K);if(z===null)continue;this.#c($,z,j,Q)}this.#Pj(j,X,Q)}#c(j,Q,X,Z){if(j.hidden=!Q,j.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof j.querySelectorAll!=="function")return;for(let $ of j.querySelectorAll("input[name], select[name], textarea[name]"))if(X($))$.disabled=!Q;if(j.name&&X(j))j.disabled=!Q}#Pj(j,Q,X){let Z=this.#Ej();for(let[$,J]of Object.entries(Z)){if(!J||typeof J!=="object"||Array.isArray(J))continue;if(!Q.has($))Q.set($,this.#d($,j,X));let G=Q.get($);if(G===null)continue;let K=()=>G;for(let[z,Y]of Object.entries(J)){if(!Pj(z))continue;let H;if(Array.isArray(Y)){if(Y.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${z} — skipped`);continue}H=Y.every((_)=>S(_,K))}else{let _=d(Y,G);if(_===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${z} — skipped`);continue}H=_}for(let _ of document.querySelectorAll(z))_.hidden=!H}}}#Ej(){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: { ... })"),{}}#d(j,Q,X){let Z=X&&!j.includes("[")?`${X}[${j}]`:j,$=!1,J=null;for(let G of this.element.querySelectorAll(`[name="${Z}"]`)){if(!Q(G))continue;if(G.type==="checkbox")return G.checked?"true":"false";if(G.type==="radio"){if(G.checked)return G.value??"";$=!0;continue}J??=G}if(J)return J.value??"";return $?"":null}#Cj(){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}#Fj(){return!!(this.element.getAttribute?.("data-reactive-filter-input")&&this.element.getAttribute?.("data-reactive-filter-option"))}#Rj(){return this.element.getAttribute?.("data-reactive-compute-seed")==="true"}#Tj(j){let Q=this.element.getAttribute("data-reactive-filter-input");return!!Q&&typeof j.target?.matches==="function"&&j.target.matches(Q)}#l(){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 X=this.#A(),Z=[...this.element.querySelectorAll(j)].find(X);if(!Z)return;let $=(Z.value??"").trim().toLowerCase(),J=0;for(let z of this.element.querySelectorAll(Q)){if(!X(z))continue;let Y=(z.getAttribute("data-reactive-filter-text")??z.textContent??"").toLowerCase(),H=$!==""&&!Y.includes($);if(z.hidden=H,H)z.removeAttribute("data-reactive-highlighted");else J++}let G=this.element.getAttribute("data-reactive-filter-group");if(G)for(let z of this.element.querySelectorAll(G)){if(!X(z))continue;let Y=[...z.querySelectorAll(Q)].filter(X);if(Y.length===0)continue;z.hidden=Y.every((H)=>H.hidden)}let K=this.element.getAttribute("data-reactive-filter-empty");if(K){for(let z of this.element.querySelectorAll(K))if(X(z))z.hidden=J>0}}#Dj(){if(!this.#X)return;this.element.removeEventListener?.("input",this.#X),this.element.removeEventListener?.("turbo:morph-element",this.#X),this.#X=void 0}#Ij(){if(!this.#W)return;this.element.removeEventListener?.("turbo:morph-element",this.#W),this.#W=void 0}#Sj(j,Q,X,Z){let $=new FormData;$.append("token",j),$.append("act",Q);for(let[G,K]of Object.entries(X))this.#F($,`params[${G}]`,K);let J=this.#kj(Z);for(let{name:G,file:K,multiple:z}of Z){let H=z||J.has(G)?`params[${G}][]`:`params[${G}]`;$.append(H,K,K.name)}return $}#F(j,Q,X){if(X==null)j.append(Q,"");else if(Array.isArray(X))X.forEach((Z,$)=>this.#F(j,`${Q}[${$}]`,Z));else if(typeof X==="object")for(let[Z,$]of Object.entries(X))this.#F(j,`${Q}[${Z}]`,$);else j.append(Q,String(X))}#kj(j){let Q=new Map;for(let{name:X}of j)Q.set(X,(Q.get(X)??0)+1);return new Set([...Q].filter(([,X])=>X>1).map(([X])=>X))}#o(j){if(!j)return{};try{return typeof j==="string"?JSON.parse(j):j}catch{return{}}}#s(j){return o(j)}#i(j){s(j,(Q)=>this.#n(Q))}#n(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((X)=>this.#Q(X))}#wj(j,Q){if(j?.checked!=="keep")return!1;let X=Q?.type;return X==="checkbox"||X==="radio"}#bj(j,Q){if(!j)return null;let X=this.#a(j,Q,!0);return X.length?X:null}#G(j){if(!j)return;if(!this.element.isConnected)return;for(let Q of j)Q()}#vj(j,Q,X){this.#hj(j,Q);let Z=X?this.#a(X,Q,!1):[],$=!1;return()=>{if($)return;$=!0,this.#fj(j,Q);for(let J of Z)J()}}#a(j,Q,X){let Z=[];for(let $ of this.#r(j,Q)){if(j.add_class){let J=j.add_class.filter((G)=>!$.classList.contains(G));if($.classList.add(...J),J.length)Z.push(()=>$.classList.remove(...J))}if(j.remove_class){let J=j.remove_class.filter((G)=>$.classList.contains(G));if($.classList.remove(...J),J.length)Z.push(()=>$.classList.add(...J))}if(j.toggle_class)j.toggle_class.forEach((J)=>$.classList.toggle(J)),Z.push(()=>j.toggle_class.forEach((J)=>$.classList.toggle(J)));if(j.hide)$.hidden=!0,Z.push(()=>$.hidden=!1);if(j.show)$.hidden=!1,Z.push(()=>$.hidden=!0)}if(Q&&(j.disable||j.text!=null))Z.push(this.#yj(j,Q));if(X&&j.checked==="keep"&&Q&&"checked"in Q){let $=Q.checked;Z.push(()=>Q.checked=!$)}return Z}#r(j,Q){if(j.to==null)return Q?[Q]:[];return this.#n({to:j.to})}#yj(j,Q){let X=this.#L.get(Q);if(X)X.count++;else this.#L.set(Q,{count:1,disabled:Q.disabled,html:Q.innerHTML,hadText:j.text!=null,swappedTo:j.text});if(j.disable)Q.disabled=!0;if(j.text!=null)Q.innerHTML=j.text;return()=>this.#pj(Q,j)}#hj(j,Q){if(this.#z(Q,j,1),this.#z(this.element,j,1),this.#q.set(j,(this.#q.get(j)??0)+1),this.#B++===0)this.element.setAttribute("aria-busy","true");for(let X of this.#t(j))this.#z(X,j,1)}#fj(j,Q){this.#z(Q,j,-1),this.#z(this.element,j,-1);let X=(this.#q.get(j)??1)-1;if(X<=0)this.#q.delete(j);else this.#q.set(j,X);if(--this.#B<=0)this.#B=0,this.element.removeAttribute("aria-busy");for(let Z of this.#t(j))this.#z(Z,j,-1)}#z(j,Q,X){if(!j||typeof j.getAttribute!=="function")return;let Z=this.#O.get(j)??new Map,$=(Z.get(Q)??0)+X;if($<=0)Z.delete(Q);else Z.set(Q,$);if(Z.size===0){this.#O.delete(j),j.removeAttribute("data-reactive-busy");return}this.#O.set(j,Z),j.setAttribute("data-reactive-busy",[...Z.keys()].join(" "))}#t(j){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((X)=>X.getAttribute("data-reactive-busy-on")===j&&this.#Q(X))}#pj(j,Q){let X=this.#L.get(j);if(!X)return;if(--X.count>0)return;if(this.#L.delete(j),!j.isConnected)return;if(Q.disable)j.disabled=X.disabled;if(X.hadText&&j.innerHTML===X.swappedTo)j.innerHTML=X.html}#uj(j){if(!j||typeof j!=="object")return null;let{class:Q,...X}=j;return Q==null?j:{...X,add_class:Q}}#mj(){return this.#e??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#gj(){if(this.#x!=null)return this.#x;let j=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Q=Number(j);return this.#x=Number.isFinite(Q)&&Q>0?Q:30000}#cj(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#dj(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{Sj as resetReactiveDefers,r as registerReactiveVisit,t as registerReactiveToken,qj as registerReactiveOffline,e as registerReactiveJs,zj as registerReactiveDismiss,jj as registerReactiveDefer,b as registerReactiveActions,kj as pendingDeferVia,Wj as escapeRegExp,Yj as enableLatencySim,Uj as disableLatencySim,fj as default,Aj as checkReactiveRegistration,yj as __resetReactiveRegistrationForTest,bj as __resetReactiveOfflineForTest,vj as __resetReactiveLatencyForTest,wj as __resetReactiveDismissForTest,hj as __markReactiveConnectedForTest,I as LATENCY_KEY};
2
2
 
3
- //# debugId=A6849C22D6EE177E64756E2164756E21
3
+ //# debugId=568EBF006DE0FA4E64756E2164756E21
4
4
  //# sourceMappingURL=reactive_controller.min.js.map