phlex-reactive 0.12.3 → 0.12.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 +31 -0
- data/README.md +29 -6
- data/app/javascript/phlex/reactive/compute.js +7 -1
- data/app/javascript/phlex/reactive/compute.min.js.map +2 -2
- data/app/javascript/phlex/reactive/reactive_controller.js +105 -3
- 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/phlex/reactive/component/helpers.rb +5 -0
- data/lib/phlex/reactive/js.rb +29 -0
- data/lib/phlex/reactive/streamable.rb +31 -24
- data/lib/phlex/reactive/version.rb +1 -1
- metadata +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Controller as WX}from"@hotwired/stimulus";import{confirmResolver as I}from"phlex/reactive/confirm";import{computeReducer as JX}from"phlex/reactive/compute";import{confirmPredicate as LX}from"phlex/reactive/confirm_predicate";function VX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:visit"])return;X["reactive:visit"]=function(){let Z=this.getAttribute("data-url");if(Z)window.Turbo.visit(Z,{action:"advance"})}}function BX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:token"])return;X["reactive:token"]=function(){let Z=this.getAttribute("data-reactive-token-value"),$=this.getAttribute("target");if(!Z||!$)return;let Q=document.getElementById($);if(Q)Q.setAttribute("data-reactive-token-value",Z)}}function _X(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:js"])return;X["reactive:js"]=function(){let Z=UX(this.getAttribute("data-reactive-ops"));if(!Z.length)return;let $=this.getAttribute("target"),Q=$?document.getElementById($):null;if($&&!Q)return;N(Z,(j)=>qZ(j,Q))}}var _=new Map;function n(X,Z){let $=!_.has(X);if(_.set(X,Z),$)jX()}function R(X){if(_.delete(X))zX()}function UZ(){_.clear(),w=!1}function WZ(X){return _.get(X)?.via}var w=!1;function MX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:defer"])return;if(X["reactive:defer"]=function(){let Z=this.getAttribute("target");if(!Z)return;if(this.getAttribute("data-reactive-defer-via")==="stream"){xX(Z,this);return}let $=this.getAttribute("data-reactive-defer-token");if(!$)return;F(Z,$)},!w&&typeof document<"u"&&document.addEventListener)w=!0,document.addEventListener("turbo:before-stream-render",AX)}function AX(X){let $=X.target?.getAttribute?.("target");if(!$)return;let Q=$.startsWith("reactive-defer-src-")?$.slice(19):$;if(_.get(Q)?.via==="stream")R(Q)}function F(X,Z){let $=document.getElementById(X);if(!$){console.warn(`[phlex-reactive] reactive:defer target #${X} is not on the page — skipped`);return}r(X),t($);let Q={via:"fetch",abort:new AbortController,timedOut:!1};n(X,Q),PX(X,Q,Z)}function xX(X,Z){let $=document.getElementById(X);if(!$){console.warn(`[phlex-reactive] reactive:defer target #${X} is not on the page — skipped`);return}let Q=Z.getAttribute("data-reactive-defer-src");if(!Q)return;if(!globalThis.customElements?.get?.("pgbus-stream-source")){let z=Z.getAttribute("data-reactive-defer-token");if(z){F(X,z);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}r(X),t($);let j=document.createElement("pgbus-stream-source");j.id=a(X),j.setAttribute("src",Q),j.setAttribute("since-id",Z.getAttribute("data-reactive-defer-since-id")??"0"),j.setAttribute("hidden",""),document.body.appendChild(j),n(X,{via:"stream"})}function a(X){return`reactive-defer-src-${X}`}async function PX(X,Z,$){let Q=setTimeout(()=>{Z.timedOut=!0,Z.abort.abort()},DX()),j;try{j=await fetch(NX(),{method:"POST",headers:{Accept:"text/vnd.turbo-stream.html","Content-Type":"application/json","X-CSRF-Token":OX()},body:JSON.stringify({token:$}),credentials:"same-origin",signal:Z.abort.signal})}catch(q){if(clearTimeout(Q),_.get(X)!==Z)return;console.error("[phlex-reactive] deferred render failed",q),T(X,$);return}if(_.get(X)!==Z){clearTimeout(Q);return}if(j.status===204){clearTimeout(Q),c(X);return}if(!j.ok){clearTimeout(Q),console.error(`[phlex-reactive] deferred render failed: HTTP ${j.status}`),T(X,$,j.status);return}let z;try{z=await j.text()}catch(q){if(clearTimeout(Q),_.get(X)!==Z)return;console.error("[phlex-reactive] deferred render failed reading the body",q),T(X,$);return}if(clearTimeout(Q),_.get(X)!==Z)return;c(X),window.Turbo.renderStreamMessage(z)}function r(X){let Z=_.get(X);if(!Z)return;if(R(X),Z.via==="fetch")Z.abort.abort();else document.getElementById(a(X))?.remove?.()}function t(X){X.setAttribute("data-reactive-defer-pending","true"),X.setAttribute("aria-busy","true")}function e(X){X.removeAttribute("data-reactive-defer-pending"),X.removeAttribute("aria-busy")}function c(X){R(X);let Z=document.getElementById(X);if(!Z)return;e(Z),Z.removeAttribute("data-reactive-error")}function T(X,Z,$){R(X);let Q=document.getElementById(X);if(!Q)return;e(Q),Q.setAttribute("data-reactive-error","defer");let j=()=>{let z=document.getElementById(X);if(!z){console.warn("[phlex-reactive] defer retry() ignored — the target left the DOM");return}z.removeAttribute("data-reactive-error"),F(X,Z)};Q.dispatchEvent(new CustomEvent("reactive:error",{bubbles:!0,composed:!0,detail:{kind:"defer",target:X,status:$,retry:j}}))}function NX(){return document.querySelector('meta[name="phlex-reactive-defer-path"]')?.content||"/reactive/defer"}function OX(){return document.querySelector('meta[name="csrf-token"]')?.content??""}function DX(){let X=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Z=Number(X);return Number.isFinite(Z)&&Z>0?Z:30000}var h=!1;function RX(){if(h)return;if(typeof document>"u"||!document.addEventListener)return;h=!0,document.addEventListener("turbo:before-stream-render",FX)}function FX(X){let Z=X.detail,$=Z?.render;if(typeof $!=="function"||$.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(E);else setTimeout(E,0);return}let Q=async(j)=>{await $(j),E()};Q.__reactiveDismissWrapped=!0,Z.render=Q}function E(){let X=document.querySelectorAll("[data-reactive-dismiss-after]");for(let Z of X){if(Z.hasAttribute("data-reactive-dismiss-scheduled"))continue;let $=Number(Z.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite($)||$<=0)continue;Z.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>Z.remove(),$)}}function JZ(){h=!1}var CX=Object.freeze({append:"enter",prepend:"enter",replace:"update",update:"update",remove:"exit"}),k=Object.freeze(["fade","slide","scale","highlight","shake"]),y="data-reactive-fx-pending",XX=1000,v=!1;function IX(){if(v)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;v=!0,document.addEventListener("turbo:before-stream-render",TX)}function LZ(){v=!1}function TX(X){let Z=X.detail,$=Z?.render;if(typeof $!=="function"||$.__reactiveEffectsWrapped)return;let Q=Z?.newStream??X.target,j=CX[Q?.getAttribute?.("action")];if(!j||SX())return;let z=EX(Q,j);if(!z)return;let q=j==="exit"?async(G)=>{await hX(O(Q),z),await $(G)}:async(G)=>{let Y=j==="enter"?bX(Q):null;if(await $(G),j==="enter")wX(Y,z);else ZX(O(Q),z)};q.__reactiveEffectsWrapped=!0,Z.render=q}function EX(X,Z){let $=X.getAttribute?.("data-reactive-effect");if($==="off")return null;if($)return d($,Z);let j=(Z==="enter"?kX(X):O(X))?.getAttribute?.(`data-reactive-effect-${Z}`);return j?d(j,Z):null}function O(X){let Z=X.getAttribute?.("target");return Z?document.getElementById?.(Z)??null:null}function kX(X){return X.querySelector?.("template")?.content?.firstElementChild??null}function d(X,Z){if(X.startsWith("[")){let Q=null;try{let j=JSON.parse(X);if(Array.isArray(j)&&j.length===3)Q=j.map(String)}catch{}if(Q)return{legs:Q};return console.warn(`[phlex-reactive] malformed effect legs ${JSON.stringify(X)} — skipped`),null}let $=X==="random"?k[Math.floor(Math.random()*k.length)]:X;if(!k.includes($))return console.warn(`[phlex-reactive] unknown effect ${JSON.stringify(X)} — skipped`),null;return{className:`reactive-fx--${$}-${Z}`}}function SX(){try{return typeof matchMedia==="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches}catch{return!1}}function bX(X){let Z=X.querySelector?.("template")?.content;if(!Z)return null;for(let $ of Array.from(Z.children??[]))$.setAttribute?.(y,"");return O(X)}function wX(X,Z){if(typeof X?.querySelectorAll!=="function")return;for(let $ of Array.from(X.querySelectorAll(`[${y}]`)))$.removeAttribute(y),ZX($,Z)}async function hX(X,Z){if(!X?.classList)return;if(Z.legs){await $X(X,Z.legs);return}X.classList.add(Z.className);let $=p(X);if($<=0){X.classList.remove(Z.className);return}await u(X,$),X.classList.remove(Z.className)}function ZX(X,Z){if(!X?.classList)return;if(Z.legs){$X(X,Z.legs);return}if(X.classList.contains(Z.className))X.classList.remove(Z.className),X.offsetWidth;X.classList.add(Z.className);let $=p(X);if($<=0){X.classList.remove(Z.className);return}let Q=X.__reactiveFxToken=(X.__reactiveFxToken??0)+1;u(X,$).then(()=>{if(X.__reactiveFxToken===Q)X.classList.remove(Z.className)})}async function $X(X,Z){let[$,Q,j]=Z.map(yX),z=X.__reactiveFxToken=(X.__reactiveFxToken??0)+1;if(X.classList.remove(...$,...Q,...j),X.classList.add(...$,...Q),await vX(),X.__reactiveFxToken!==z)return;X.classList.remove(...Q),X.classList.add(...j);let q=p(X);if(q>0)await u(X,q);if(X.__reactiveFxToken!==z)return;X.classList.remove(...$,...j)}function yX(X){return String(X??"").split(/\s+/).filter(Boolean)}function p(X){if(typeof getComputedStyle!=="function")return 0;try{let Z=getComputedStyle(X),$=(z)=>String(z??"").split(",").reduce((q,G)=>Math.max(q,parseFloat(G)||0),0),Q=$(Z.animationDuration)+$(Z.animationDelay),j=$(Z.transitionDuration)+$(Z.transitionDelay);return Math.min(Math.max(Q,j)*1000,XX)}catch{return 0}}function u(X,Z){return new Promise(($)=>{let Q=!1,j=()=>{if(Q)return;Q=!0,$()};X.addEventListener?.("animationend",j,{once:!0}),X.addEventListener?.("transitionend",j,{once:!0}),setTimeout(j,Math.min(Z+50,XX))})}function vX(){return new Promise((X)=>{if(typeof requestAnimationFrame==="function")requestAnimationFrame(()=>X());else setTimeout(X,16)})}var f=!1;function fX(){if(f)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;f=!0;let X=()=>{let Z=document.documentElement;if(typeof Z?.toggleAttribute!=="function")return;Z.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};X(),window.addEventListener("online",X),window.addEventListener("offline",X)}function VZ(){f=!1}var m="phlex-reactive:latency",D=!1;function pX(X){if(typeof sessionStorage>"u")return;sessionStorage.setItem(m,String(X))}function uX(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(m),D=!1}function mX(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:pX,disableLatencySim:uX}}function BZ(){D=!1}var QX="data-reactive-active",M=0;function jX(){if(M++,M===1)qX("reactive:busy")}function zX(){if(M===0)return;if(M--,M===0)qX("reactive:idle")}function _Z(){return M}function MZ(){M=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(QX)}function qX(X){if(typeof document>"u")return;let Z=document.documentElement;if(typeof Z?.toggleAttribute==="function")Z.toggleAttribute(QX,M>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(X,{detail:{count:M}}))}function l(){VX(),BX(),_X(),MX(),RX(),IX(),fX(),mX()}function gX(X){return X.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)l();else document.addEventListener("turbo:load",l,{once:!0});var C=!1;function cX(){if(C)return;if(typeof document>"u")return;let X=document.querySelectorAll('[data-controller~="reactive"]');if(!X||X.length===0)return;console.warn("[phlex-reactive] found "+X.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 AZ(){C=!1}function xZ(){C=!0}if(typeof window<"u"&&typeof document<"u"){let X=()=>setTimeout(cX,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",X,{once:!0});else X()}var dX=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function lX(X){let Z=String(X).toLowerCase();return Z.startsWith("on")||dX.has(Z)}function iX(X,Z,$){let[Q,j,z]=Z;X.classList.add(Q,j),$(),requestAnimationFrame(()=>{X.classList.remove(j),X.classList.add(z)});let q=!1,G=()=>{if(q)return;q=!0,X.classList.remove(Q,z)};X.addEventListener("animationend",G,{once:!0}),setTimeout(G,350)}var i=Object.freeze({show:(X,Z)=>S(X,!1,Z),hide:(X,Z)=>S(X,!0,Z),toggle:(X,Z)=>S(X,!X.hidden,Z),add_class:(X,Z)=>X.classList.add(...Z.classes??[]),remove_class:(X,Z)=>X.classList.remove(...Z.classes??[]),toggle_class:(X,Z)=>(Z.classes??[]).forEach(($)=>X.classList.toggle($)),set_attr:(X,Z)=>{if(b(Z.name))X.setAttribute(Z.name,Z.value??"")},remove_attr:(X,Z)=>{if(b(Z.name))X.removeAttribute(Z.name)},toggle_attr:(X,Z)=>{if(!b(Z.name))return;if(X.hasAttribute(Z.name))X.removeAttribute(Z.name);else X.setAttribute(Z.name,"")},focus:(X)=>X.focus?.(),focus_first:(X)=>jZ(X)?.focus?.(),text:(X,Z)=>{let $=String(Z.value??"");if(X.textContent!==$)X.textContent=$},dispatch:(X,Z)=>{X.dispatchEvent(new CustomEvent(Z.name,{bubbles:!0,composed:!0,detail:Z.detail??{}}))},submit:(X)=>oX(X)?.requestSubmit?.()});function oX(X){if(X?.tagName==="FORM")return X;return X?.form??X?.closest?.("form")??null}function S(X,Z,$){if($?.transition)iX(X,$.transition,()=>X.hidden=Z);else X.hidden=Z}function b(X){if(!lX(X))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(X)} — skipped`),!1}var GX=/^#[A-Za-z_][\w-]*$/;function sX(X){if(typeof X==="string"&&GX.test(X))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(X)} — skipped`),!1}function nX(X,Z){let $=X.getAttribute("data-reactive-show-equals");if($!==null)return Z===$;let Q=X.getAttribute("data-reactive-show-not");if(Q!==null)return Z!==Q;let j=X.getAttribute("data-reactive-show-in");if(j!==null){try{let z=JSON.parse(j);if(Array.isArray(z))return z.includes(Z)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(j)} — skipped`),null}for(let z of YX){let q=X.getAttribute(`data-reactive-show-${z}`);if(q!==null)return KX(z,q,Z)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}var YX=["gte","gt","lte","lt"],aX=["len_eq","len_gte","len_gt","len_lte","len_lt"];function rX(X,Z,$){if(!Number.isInteger(Z))return console.warn(`[phlex-reactive] reactive_show ${X}: needs an integer literal, got ${JSON.stringify(Z)} — skipped`),null;let Q=[...String($??"")].length;switch(X){case"len_eq":return Q===Z;case"len_gte":return Q>=Z;case"len_gt":return Q>Z;case"len_lte":return Q<=Z;case"len_lt":return Q<Z;default:return null}}function KX(X,Z,$){let Q=Number(Z);if(Number.isNaN(Q))return console.warn(`[phlex-reactive] reactive_show ${X}: needs a numeric literal, got ${JSON.stringify(Z)} — skipped`),null;let j=$==null?"":String($).trim(),z=j===""?NaN:Number(j);if(Number.isNaN(z))return!1;switch(X){case"gte":return z>=Q;case"gt":return z>Q;case"lte":return z<=Q;case"lt":return z<Q;default:return null}}function HX(X,Z){if(!X||typeof X!=="object")return null;if(typeof X.equals==="string")return Z===X.equals;if(typeof X.not==="string")return Z!==X.not;if(Array.isArray(X.in))return X.in.includes(Z);for(let $ of YX)if($ in X)return KX($,X[$],Z);for(let $ of aX)if($ in X)return rX($,X[$],Z);return null}var o="[data-reactive-show-field], [data-reactive-show]";function tX(X){try{let Z=JSON.parse(X);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(X)} — skipped`),null}function eX(X){try{let Z=JSON.parse(X);if(Array.isArray(Z)&&Z.every(($)=>$&&typeof $==="object"&&Array.isArray($.any)&&Array.isArray($.ops)))return Z}catch{}return console.warn(`[phlex-reactive] malformed reactive_on_complete payload ${JSON.stringify(X)} — skipped`),[]}function g(X,Z){if(!X||typeof X!=="object"||typeof X.field!=="string")return!1;let $=Z(X.field)??"";return HX(X,$)===!0}function P(X,Z){if(!Array.isArray(X)||X.length===0)return null;return X.some(($)=>Array.isArray($)&&$.length>0&&$.every((Q)=>g(Q,Z)))}function XZ(X){if(!Array.isArray(X)||X.length===0)return null;let Z=new Set;for(let $ of X){if(!Array.isArray($))continue;for(let Q of $)if(Q&&typeof Q==="object"&&typeof Q.field==="string")Z.add(Q.field)}return Z.size>0?[...Z]:null}function ZZ(X,Z){if(!X||typeof X!=="object")return null;let $=X.any;if(Array.isArray($)&&($.length===0||Array.isArray($[0])))return P($,Z);return $Z(X,Z)}function $Z(X,Z){let $=Array.isArray(X.all)?"all":Array.isArray(X.any)?"any":null;if(!$)return null;let Q=X[$];if(Q.length===0)return null;let j=Q.map((z)=>g(z,Z));return $==="all"?j.every(Boolean):j.some(Boolean)}function s(X){if(typeof X==="string"&&GX.test(X))return!0;return console.warn(`[phlex-reactive] refused cross-root show target ${JSON.stringify(X)} — skipped`),!1}var QZ='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function jZ(X){return X.querySelectorAll?.(QZ)?.[0]??null}function UX(X){if(Array.isArray(X))return X;if(typeof X!=="string")return[];try{let Z=JSON.parse(X);return Array.isArray(Z)?Z:[]}catch{return[]}}function zZ(X){if(X==null)return null;let Z=Array.isArray(X)?X:X.ops;if(Array.isArray(Z))return Z.length>0?Z:null;return console.warn("[phlex-reactive] $ops must be an ops chain or a [[op, args], ...] list — skipped"),null}function N(X,Z){for(let $ of X){if(!Array.isArray($))continue;let[Q,j={}]=$;if(!Object.hasOwn(i,Q)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(Q)} — skipped`);continue}for(let z of Z(j))i[Q](z,j)}}function qZ(X,Z){let $=X.to;if(Z){if($==="@root")return[Z];if(typeof $!=="string"||$==="")return[];if(X.global)return[...document.querySelectorAll($)];return[...Z.querySelectorAll($)]}if(typeof $!=="string"||$===""||$==="@root")return[];return[...document.querySelectorAll($)]}class PZ extends WX{static values={token:String};#i;#x=new Map;#U=new Map;#RX;#E;#o;#k=0;#W=new Map;#S=new WeakMap;#P=new Map;#s=new WeakSet;#n=null;#J;#L;#V;#Z;#z;#b;#a;#w;#h;#Q;#B;#r=!1;#y=0;#t=!1;#j;#_;#M;#N;connect(){if(C=!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.#e(),this.#N=()=>this.#e(),this.element.addEventListener?.("turbo:morph-element",this.#N);if(this.#FX()){if(this.#J=()=>this.#u(),this.element.addEventListener?.("turbo:morph-element",this.#J),this.#u(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#tX()}if(this.#XZ())this.#Z=()=>this.#LX(),this.element.addEventListener?.("input",this.#Z),this.element.addEventListener?.("change",this.#Z),this.element.addEventListener?.("turbo:morph-element",this.#Z),this.#LX();if(this.#ZZ())this.#z=(X)=>this.#m(X),this.#b=()=>this.#m(null),this.element.addEventListener?.("input",this.#z),this.element.addEventListener?.("change",this.#z),this.element.addEventListener?.("turbo:morph-element",this.#b),this.#m(null);if(this.#C())this.#Q=(X)=>{if(X?.type==="input"&&!this.#KZ(X))return;this.#A()},this.element.addEventListener?.("input",this.#Q),this.element.addEventListener?.("turbo:morph-element",this.#Q),this.#A();if(this.#I())this.#B=()=>this.#d(),this.element.addEventListener?.("turbo:morph-element",this.#B),this.#d();if(this.#UZ())this.#j=(X)=>this.syncNestedJson(X),this.#_=()=>this.#D(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#_),this.#D();if(this.#YZ())this.#M=()=>this.recompute(),this.element.addEventListener?.("turbo:morph-element",this.#M),this.recompute()}#FX(){if((this.element.getAttribute?.("data-action")??"").includes("reactive#trackDirty"))return!0;let X=this.element.querySelectorAll?.('[data-action*="reactive#trackDirty"]')??[];for(let Z of X)if(this.#$(Z))return!0;return!1}disconnect(){if(this.#mX(),this.#cX(),this.#eX(),this.#GZ(),this.#QZ(),this.#HZ(),this.#MZ(),this.#AZ(),this.#xZ(),this.#N)this.element.removeEventListener?.("turbo:morph-element",this.#N)}#e(){let X=this.element;if(!X?.id)return;let Z=X.getAttribute?.("data-reactive-defer-token");if(!Z)return;if(X.getAttribute?.("data-reactive-defer-pending")!=="true")return;F(X.id,Z)}dispatch(X){let{action:Z,params:$,debounce:Q,throttle:j,confirm:z,confirmWhen:q,outside:G,window:Y,optimistic:K}=X.params;if(!Z)return;let U=X.params.busy??this.#EZ(X.params.loading);if(G&&this.element.contains(X.target))return;let B=X.currentTarget??X.target;if(!Y&&!this.#OZ(K,B))X.preventDefault();let W=this.#p(z,q);if(!W)return this.#GX(B,Z,$,Q,j,K,U);Promise.resolve().then(()=>I(W,{el:B})).catch(()=>!1).then((V)=>{if(V)this.#GX(B,Z,$,Q,j,K,U)})}runOps(X){let{ops:Z,confirm:$,confirmWhen:Q,outside:j,window:z}=X.params,q=X.currentTarget??X.target;if(j&&this.element.contains(X.target))return;if(!z)X.preventDefault();let G=this.#p($,Q);if(!G)return this.#PX(this.#xX(Z));Promise.resolve().then(()=>I(G,{el:q})).catch(()=>!1).then((Y)=>{if(Y)this.#PX(this.#xX(Z))})}trackDirty(){this.#u()}recompute(X){if(X&&this.#s.has(X))return;let Z=this.#wX(),$=Z.map(([H])=>H),Q=this.element.getAttribute?.("data-reactive-scope")||null,j=(H)=>Q&&!H.includes("[")?`${Q}[${H}]`:H,z=this.#X(),q=new Map,G=(H)=>{if(q.has(H))return q.get(H);let J=null;for(let L of this.element.querySelectorAll(`[name="${j(H)}"]`))if(z(L)){J=L;break}return q.set(H,J),J};for(let H of $)this.#zX(H,G(H)?.value??"");let Y=this.element.getAttribute("data-reactive-compute-reducer-param"),K=Y?JX(Y):null;if(!K){this.#qX({},G);return}let U=this.#bX("data-reactive-compute-outputs-param"),B={};for(let[H,J]of Z){let L=G(H);if(J==="string")B[H]=L?.value??"";else{let A=Number(L?.value);B[H]=Number.isFinite(A)?A:0}}let W=K(B,{changed:this.#hX(X,$,Q)})||{},V=zZ(W.$ops),x=[];for(let H of U){if(H==="$ops"||!(H in W))continue;let J=G(H);if(!J)continue;if(String(W[H])===J.value)continue;J.value=W[H],x.push(J)}for(let H of Object.keys(W)){if(H==="$ops")continue;let J=W[H];if(J===void 0||J===null)continue;this.#zX(H,J)}this.#qX(W,G);for(let H of x){let J=new Event("input",{bubbles:!0});this.#s.add(J),H.dispatchEvent(J)}this.#CX(V,Boolean(X))}#CX(X,Z){let $=X===null?null:JSON.stringify(X),Q=$!==null&&$!==this.#n&&Z;if(this.#n=$,!Q)return;N(X,(j)=>this.#T(j.to==null?{...j,to:"@root"}:j))}listnavNext(X){this.#XX(X,1)}listnavPrev(X){this.#XX(X,-1)}listnavPick(X){let Z=this.#O(X),$=Z.findIndex((Q)=>Q.hasAttribute("data-reactive-highlighted"));if($<0)return;X.preventDefault(),Z[$].click()}listnavClose(X){for(let Z of this.#O(X))Z.removeAttribute("data-reactive-highlighted")}#XX(X,Z){let $=this.#O(X);if(!$.length)return;X.preventDefault();let Q=$.findIndex((q)=>q.hasAttribute("data-reactive-highlighted")),j=Q<0?Z>0?0:$.length-1:(Q+Z+$.length)%$.length;for(let q of $)q.removeAttribute("data-reactive-highlighted");let z=$[j];z.setAttribute("data-reactive-highlighted","true"),z.scrollIntoView?.({block:"nearest"})}#O(X){let $=(X?.currentTarget??X?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!$)return[];let Q=this.#X();return Array.from(this.element.querySelectorAll($)).filter((j)=>!j.hidden&&Q(j))}tagsAdd(X){if(!this.#I())return;if(X?.defaultPrevented)return;if(this.#O(X).some((Q)=>Q.hasAttribute?.("data-reactive-highlighted")))return;X?.preventDefault?.();let Z=X?.currentTarget??X?.target;if(!Z)return;if(!this.#_X(String(Z.value??"").split(",")))return;if(Z.value="",this.#C())this.#A()}tagsPick(X){if(!this.#I())return;X?.preventDefault?.();let $=(X?.currentTarget??X?.target)?.getAttribute?.("data-reactive-tag-param");if(!$)return;if(!this.#_X([$]))return;let Q=this.#WZ();if(!Q)return;Q.value="",this.#A(),Q.focus?.()}tagsRemove(X){if(!this.#I())return;X?.preventDefault?.();let $=(X?.currentTarget??X?.target)?.getAttribute?.("data-reactive-tag-param");if(!$)return;let Q=this.#g();if(!Q)return;let j=this.#c(Q),z=j.filter((q)=>q.toLowerCase()!==$.toLowerCase());if(z.length===j.length)return;this.#MX(Q,z)}nestedAdd(X){X?.preventDefault?.();let Z=X?.currentTarget??X?.target,$=Z?.getAttribute?.("data-reactive-association-param");if(!$)return;if(typeof this.element?.querySelectorAll!=="function")return;let Q=this.#X(),j=[...this.element.querySelectorAll(`[data-reactive-nested-list="${$}"]`)].find(Q),q=[...this.element.querySelectorAll(`[data-reactive-nested-template="${$}"]`)].find(Q)?.content?.firstElementChild;if(!j||!q){this.#_Z($);return}let G=q.cloneNode(!0);this.#BZ(G,this.#VZ()),j.appendChild(G);let Y=Z?.getAttribute?.("data-reactive-nested-from-param"),K=Z?.getAttribute?.("data-reactive-nested-clear-param")==="true",U=this.#IX(G,Y,K);if(Y)U?.focus?.();else[...G.querySelectorAll?.("input, select, textarea")??[]][0]?.focus?.();if(j.getAttribute?.("data-reactive-nested-json")===$)this.#$X($)}#IX(X,Z,$){if(!Z)return null;let Q;try{Q=JSON.parse(Z)}catch{return null}if(!Q||typeof Q!=="object")return null;let j=this.#X(),z=[...X.querySelectorAll?.("input, select, textarea")??[]],q=[];for(let[G,Y]of Object.entries(Q)){let K=[...this.element.querySelectorAll?.(Y)??[]].find(j);if(!K)continue;let U=z.find((B)=>this.#jX(B.getAttribute?.("name"))===G);if(!U)continue;this.#TX(U,K),q.push(K)}if($)for(let G of q)this.#EX(G);return q[0]??null}#TX(X,Z){if(X.type==="checkbox")X.checked=Z.type==="checkbox"?!!Z.checked:this.#v(Z)!=="";else X.value=this.#v(Z);if(typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}))}#EX(X){if(X.type==="checkbox")X.checked=!1;else X.value="";if(typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}))}nestedRemove(X){X?.preventDefault?.();let Z=X?.currentTarget??X?.target,$=Z?.closest?.("[data-reactive-nested-row]");if(!$)return;if($.closest?.('[data-controller~="reactive"]')!==this.element)return;let Q=Z?.getAttribute?.("data-reactive-confirm-param"),j=Z?.getAttribute?.("data-reactive-confirm-when-param"),z=this.#p(Q,j);if(!z)return this.#ZX($);let q=this.#QX($),G=this.#kX(z,q);return Promise.resolve().then(()=>I(G,{el:Z,row:$,fields:q})).catch(()=>!1).then((Y)=>{if(Y)this.#ZX($)})}#kX(X,Z){if(!X.includes("%{"))return X;return X.replace(/%\{(\w+)\}/g,($,Q)=>Object.prototype.hasOwnProperty.call(Z,Q)?Z[Q]:$)}#ZX(X){let Z=[...X.querySelectorAll?.('input[name$="[_destroy]"]')??[]][0];if(Z){if(Z.value="1",typeof Z.dispatchEvent==="function")Z.dispatchEvent(new Event("input",{bubbles:!0}));X.hidden=!0}else X.parentNode?.removeChild?.(X);this.#D()}syncNestedJson(X){let Z=X?.target;if(!Z||!this.#$(Z))return;this.#D()}#D(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.#X();for(let Z of[...this.element.querySelectorAll("[data-reactive-nested-json]")].filter(X))this.#$X(Z.getAttribute("data-reactive-nested-json"))}#$X(X){let Z=this.#X(),$=[...this.element.querySelectorAll(`[data-reactive-nested-list="${X}"]`)].find(Z);if(!$)return;let Q=this.#SX($);if(!Q)return;let j=[];for(let q of[...$.querySelectorAll?.("[data-reactive-nested-row]")??[]]){if(!Z(q)||q.hidden)continue;j.push(this.#QX(q))}let z=JSON.stringify(j);if(Q.value===z)return;if(Q.value=z,typeof Q.dispatchEvent==="function")Q.dispatchEvent(new Event("input",{bubbles:!0}))}#SX(X){let Z=X.getAttribute?.("data-reactive-nested-json-field");if(!Z)return null;let $=this.#X();return[...this.element.querySelectorAll(Z)].find($)??null}#QX(X){let Z={};for(let $ of[...X.querySelectorAll?.("input, select, textarea")??[]]){let Q=this.#jX($.getAttribute?.("name"));if(Q===null||Q==="_destroy")continue;Z[Q]=this.#v($)}return Z}#jX(X){if(!X)return null;let Z=X.match(/\[([^\][]+)\]$/);return Z?Z[1]:X}#v(X){if(X.type==="checkbox")return X.checked?X.value||"on":"";return X.value??""}#bX(X){let Z=this.element.getAttribute(X);if(!Z)return[];try{let $=JSON.parse(Z);return Array.isArray($)?$:[]}catch{return[]}}#wX(){let X=this.element.getAttribute("data-reactive-compute-inputs-param");if(!X)return[];try{let Z=JSON.parse(X);if(Array.isArray(Z))return Z.map(($)=>[$,"number"]);if(Z&&typeof Z==="object")return Object.entries(Z);return[]}catch{return[]}}#hX(X,Z,$){let Q=X?.target;if(!Q?.name||typeof Q.closest!=="function")return null;let j=this.#yX(Q.name,$);if(!Z.includes(j))return null;return this.#$(Q)?j:null}#yX(X,Z){if(!Z)return X;let $=`${Z}[`;return X.startsWith($)&&X.endsWith("]")?X.slice($.length,-1):X}#zX(X,Z){let $=String(Z);for(let Q of this.#vX(X)){if(Q.textContent===$)continue;Q.textContent=$}}#vX(X){let Z=this.element.querySelectorAll(`[data-reactive-text="${X}"]`);return Array.from(Z).filter(($)=>this.#$($))}#qX(X,Z){let $=this.#fX();for(let[Q,j]of Object.entries($)){let z=Q in X?X[Q]:Z(Q)?.value;if(z===void 0||z===null)continue;let q=String(z);for(let G of Array.isArray(j)?j:[j]){if(!sX(G))continue;for(let Y of document.querySelectorAll(G)){if(Y.textContent===q)continue;Y.textContent=q}}}}#fX(){let X=this.element.getAttribute("data-reactive-compute-mirror-param");if(!X)return{};try{let Z=JSON.parse(X);return Z&&typeof Z==="object"&&!Array.isArray(Z)?Z:{}}catch{return{}}}#GX(X,Z,$,Q,j,z,q){if(this.#F("reactive:before-dispatch",{action:Z,params:this.#AX($),element:this.element},{cancelable:!0}).defaultPrevented)return;let Y=Number(Q)||0;if(Y>0)return this.#uX(X,Y,Z,$,z,q);let K=Number(j)||0;if(K>0)return this.#gX(X,K,Z,$,z,q);return this.#R(Z,$,z,X,q)}#R(X,Z,$,Q,j){let z=this.#DZ($,Q),q=this.#RZ(X,Q,j),G=this.#YX()?this.#pX($,Q):null;return this.queue=(this.queue??Promise.resolve()).then(()=>this.#nX(X,Z,z,q,G)),this.queue}#pX(X,Z){if(!X?.hide)return null;let $=this.#OX(X,Z);if(!$.length)return null;return()=>{let Q=$.filter((j)=>j.isConnected&&!j.hidden);if(!Q.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.",Q)}}#uX(X,Z,$,Q,j,z){this.#f(X);let q=()=>{this.#f(X),this.#R($,Q,j,X,z)},G=setTimeout(q,Z);X?.addEventListener?.("blur",q,{once:!0}),this.#x.set(X,{timer:G,flush:q})}#f(X){let Z=this.#x.get(X);if(!Z)return;clearTimeout(Z.timer),X?.removeEventListener?.("blur",Z.flush),this.#x.delete(X)}#mX(){for(let X of[...this.#x.keys()])this.#f(X)}#gX(X,Z,$,Q,j,z){let q=this.#U.get(X)??new Map;if(q.has($))return;let G=setTimeout(()=>{if(q.delete($),q.size===0)this.#U.delete(X)},Z);return q.set($,G),this.#U.set(X,q),this.#R($,Q,j,X,z)}#cX(){for(let X of this.#U.values())for(let Z of X.values())clearTimeout(Z);this.#U.clear()}#F(X,Z,{cancelable:$=!1}={}){let Q=new CustomEvent(X,{bubbles:!0,composed:!0,cancelable:$,detail:Z});return(this.element.isConnected?this.element:document).dispatchEvent(Q),Q}#q(X,Z,$,Q){let j=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#R(X,Z)};this.#F("reactive:error",{action:X,params:$,...Q,retry:j})}#G(X){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",X)}#dX(){this.element?.removeAttribute?.("data-reactive-error")}#lX(){let X=document.querySelector("[data-reactive-error-flash]");if(!X?.content)return;let Z=X.getAttribute("data-reactive-error-flash")||"flash",$=document.getElementById(Z);if(!$)return;$.appendChild(X.content.cloneNode(!0))}#iX(){if(typeof sessionStorage>"u")return Promise.resolve();let X=Number(sessionStorage.getItem(m));if(!Number.isFinite(X)||X<=0)return Promise.resolve();if(!D)D=!0,console.warn(`[phlex-reactive] latency simulator ACTIVE — every action is delayed by ${X}ms. Call PhlexReactive.disableLatencySim() (or clear sessionStorage) to turn it off.`);return new Promise((Z)=>setTimeout(Z,X))}#YX(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#KX(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#oX(X){if(!X)return[];let Z=[],$=/<turbo-stream\b([^>]*)>/g,Q;while((Q=$.exec(X))!==null){let j=Q[1],z=j.match(/\baction="([^"]*)"/)?.[1]??"?",q=j.match(/\btarget="([^"]*)"/)?.[1];Z.push(q?`${z} → #${q}`:z)}return Z}#sX(X){let{action:Z,status:$,ms:Q}=X,z=`reactive ${this.element?.id?`#${this.element.id} `:""}${Z} → ${$??"—"} (${Math.round(Q)}ms)`;if(console.groupCollapsed(z),console.log(`params: [${X.paramNames.join(", ")}] + collected: [${X.fieldNames.join(", ")}]`),console.log(`encoding: ${X.encoding}`),X.streams.length)console.log(`streams: ${X.streams.join(" ")}`);console.log(`token: ${X.tokenRefreshed?"refreshed ✓":"unchanged"}`),console.groupEnd()}async#nX(X,Z,$,Q,j){let{fields:z,files:q}=this.#WX(),G=this.#AX(Z),Y={...z,...G},K=this.#Y,U=q.length>0,B=U?this.#PZ(K,X,Y,q):JSON.stringify({token:K,act:X,params:Y}),W=this.#YX()?{action:X,paramNames:Object.keys(G),fieldNames:Object.keys(z),encoding:U?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#KX()}:null;await this.#iX();try{if(navigator.onLine===!1){this.#K($),this.#G("offline"),this.#q(X,Z,Y,{kind:"offline"});return}let V;try{let L={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#bZ()};if(!U)L["Content-Type"]="application/json";let A=this.#wZ();if(A)L["X-Pgbus-Connection"]=A;V=await fetch(this.#kZ(),{method:"POST",headers:L,body:B,credentials:"same-origin",signal:AbortSignal.timeout(this.#SZ())})}catch(L){if(console.error("[phlex-reactive] action error",L),this.#K($),L?.name==="TimeoutError"||L?.name==="AbortError"){this.#G("timeout"),this.#q(X,Z,Y,{kind:"timeout"});return}this.#lX(),this.#G("network"),this.#q(X,Z,Y,{kind:"network"});return}if(W)W.status=V.status;if(V.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#K($),this.#G("redirected"),this.#q(X,Z,Y,{kind:"redirected",status:V.status});return}if(!V.ok){let L=await V.text();if(console.error(`[phlex-reactive] action failed: HTTP ${V.status}`,L),this.#K($),(V.headers.get("Content-Type")||"").includes("turbo-stream")){let A=this.#UX(L);if(this.#Y=A??this.#Y,W)this.#HX(W,L,A);window.Turbo.renderStreamMessage(L)}this.#G("http"),this.#q(X,Z,Y,{kind:"http",status:V.status,body:L});return}let x=V.headers.get("Content-Type")||"";if(!x.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${x}" — no update applied`),this.#K($),this.#G("content-type"),this.#q(X,Z,Y,{kind:"content-type",status:V.status});return}let H=await V.text(),J=this.#UX(H);if(this.#Y=J??this.#Y,W)this.#HX(W,H,J);if(window.Turbo.renderStreamMessage(H),j)queueMicrotask(j);this.#dX(),this.#F("reactive:applied",{action:X,params:Y,html:H})}catch(V){console.error("[phlex-reactive] action error",V),this.#K($),this.#F("reactive:error",{action:X,params:Y,kind:"apply"})}finally{if(Q?.(),W)this.#sX({...W,ms:this.#KX()-W.started})}}#HX(X,Z,$){X.streams=this.#oX(Z),X.tokenRefreshed=$!=null}get#Y(){return this.#i??this.tokenValue}set#Y(X){this.#i=X}#UX(X){let Z=this.element.id;if(!Z)return X.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:$,self:Q}=this.#aX(Z),j=X.match($);if(j)return j[1];let z=X.match(Q);if(z)return z[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#aX(X){let Z=this.#o;if(Z&&Z.id===X)return Z;let $=gX(X);return this.#o={id:X,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${$}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${$}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#$(X){return X.closest('[data-controller~="reactive"]')===this.element}#X(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(Z)=>this.#$(Z)}#p(X,Z){if(X)return X;if(!Z)return null;let $=Z;if(typeof Z==="string")try{$=JSON.parse(Z)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(Z)} — skipped`),null}if(!$||typeof $!=="object")return null;let{fields:Q}=this.#WX(),j=(q)=>Q[q],z;if(typeof $.predicate==="string"){let q=LX($.predicate);if(!q)return console.warn(`[phlex-reactive] confirm predicate "${$.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;z=!!q(Q)}else z=P($.groups?.any,j)===!0;return z?$.message:null}#WX(){let X={},Z=[],$=this.#X();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Q)=>{if(!$(Q))return;if(Q.type==="file")for(let j of Q.files??[])Z.push({name:Q.name,file:j,multiple:Q.multiple});else if(Q.type==="checkbox")X[Q.name]=Q.checked;else if(Q.type==="radio"){if(Q.checked)X[Q.name]=Q.value}else X[Q.name]=Q.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((Q)=>{if(!$(Q))return;let j=Q.getAttribute("name");if(!j)return;let z=X[j];if(z==null||z==="")X[j]=Q.value??Q.textContent??Q.innerHTML??""}),{fields:X,files:Z}}#u(){if(typeof this.element?.querySelectorAll!=="function")return;let X=0;if(this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Z)=>{if(!this.#$(Z))return;if(Z.type==="file")return;if(this.#rX(Z))Z.setAttribute("data-reactive-dirty","true"),X++;else Z.removeAttribute("data-reactive-dirty")}),X>0)this.element.setAttribute("data-reactive-dirty",String(X));else this.element.removeAttribute("data-reactive-dirty")}#rX(X){if(X.type==="checkbox"||X.type==="radio")return X.checked!==X.defaultChecked;if(X.tag==="select"||X.options)return Array.from(X.options??[]).some((Z)=>Z.selected!==Z.defaultSelected);return X.value!==X.defaultValue}#JX(){let X=this.element.getAttribute?.("data-reactive-dirty"),Z=Number(X);return Number.isFinite(Z)&&Z>0?Z:0}#tX(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#L=(X)=>{if(this.#JX()===0)return;return X.preventDefault(),X.returnValue="You have unsaved changes.",X.returnValue},this.#V=(X)=>{if(this.#JX()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))X.preventDefault?.()},window.addEventListener("beforeunload",this.#L),window.addEventListener("turbo:before-visit",this.#V)}#eX(){if(this.#J)this.element.removeEventListener?.("turbo:morph-element",this.#J),this.#J=void 0;if(typeof window<"u"&&typeof window.removeEventListener==="function"){if(this.#L)window.removeEventListener("beforeunload",this.#L);if(this.#V)window.removeEventListener("turbo:before-visit",this.#V)}this.#L=void 0,this.#V=void 0}#XZ(){if(this.element.getAttribute?.("data-reactive-show-targets"))return!0;let X=this.element.querySelectorAll?.(o)??[];for(let Z of X)if(this.#$(Z))return!0;return!1}#ZZ(){return!!this.element.getAttribute?.("data-reactive-on-complete")}#$Z(){let X=this.element.getAttribute?.("data-reactive-on-complete")??null;if(X!==this.#a)this.#a=X,this.#w=X==null?[]:eX(X),this.#h=this.#w.map(()=>!1);return this.#w}#m(X){let Z=this.#$Z();if(!Z.length)return;let $=this.#X(),Q=this.element.getAttribute?.("data-reactive-scope")||null,j=new Map,z=(q)=>{if(!j.has(q))j.set(q,this.#BX(q,$,Q));return j.get(q)};Z.forEach((q,G)=>{let Y=P(q.any,z);if(Y===null)return;let K=Y&&!this.#h[G]&&Boolean(X);if(this.#h[G]=Y,K)N(q.ops,(U)=>this.#T(U.to==null?{...U,to:"@root"}:U))})}#QZ(){if(!this.#z)return;this.element.removeEventListener?.("input",this.#z),this.element.removeEventListener?.("change",this.#z),this.element.removeEventListener?.("turbo:morph-element",this.#b)}#LX(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.#X(),Z=this.element.getAttribute?.("data-reactive-scope")||null,$=new Map,Q=(j)=>{if(!$.has(j))$.set(j,this.#BX(j,X,Z));return $.get(j)};for(let j of this.element.querySelectorAll(o)){if(!X(j))continue;let z=j.getAttribute("data-reactive-show");if(z!==null){let K=ZZ(tX(z),Q);if(K!==null)this.#VX(j,K,X,Z);continue}let q=j.getAttribute("data-reactive-show-field");if(!q)continue;let G=Q(q);if(G===null)continue;let Y=nX(j,G);if(Y===null)continue;this.#VX(j,Y,X,Z)}this.#jZ(Q)}#VX(X,Z,$,Q){if(X.hidden=!Z,X.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof X.querySelectorAll!=="function")return;for(let j of X.querySelectorAll("input[name], select[name], textarea[name]"))if($(j))j.disabled=!Z;if(X.name&&$(X))X.disabled=!Z}#jZ(X){let Z=this.#qZ();for(let[$,Q]of Object.entries(Z)){if($.startsWith("#")){this.#zZ($,Q,X);continue}if(!Q||typeof Q!=="object"||Array.isArray(Q))continue;let j=X($);if(j===null)continue;let z=()=>j;for(let[q,G]of Object.entries(Q)){if(!s(q))continue;let Y;if(Array.isArray(G)){if(G.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${q} — skipped`);continue}Y=G.every((K)=>g(K,z))}else{let K=HX(G,j);if(K===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${q} — skipped`);continue}Y=K}for(let K of document.querySelectorAll(q))K.hidden=!Y}}}#zZ(X,Z,$){if(!s(X))return;let Q=Z&&typeof Z==="object"&&!Array.isArray(Z)?Z.any:null,j=XZ(Q);if(j===null){console.warn(`[phlex-reactive] malformed reactive_show_targets conditions for ${X} — skipped`);return}if(j.every((q)=>$(q)===null))return;let z=P(Q,$);if(z===null)return;for(let q of document.querySelectorAll(X))q.hidden=!z}#qZ(){let X=this.element.getAttribute?.("data-reactive-show-targets");if(!X)return{};try{let Z=JSON.parse(X);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}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: { ... })"),{}}#BX(X,Z,$){let Q=$&&!X.includes("[")?`${$}[${X}]`:X,j=!1,z=null;for(let q of this.element.querySelectorAll(`[name="${Q}"]`)){if(!Z(q))continue;if(q.type==="checkbox")return q.checked?"true":"false";if(q.type==="radio"){if(q.checked)return q.value??"";j=!0;continue}z??=q}if(z)return z.value??"";return j?"":null}#GZ(){if(!this.#Z)return;this.element.removeEventListener?.("input",this.#Z),this.element.removeEventListener?.("change",this.#Z),this.element.removeEventListener?.("turbo:morph-element",this.#Z),this.#Z=void 0}#C(){return!!(this.element.getAttribute?.("data-reactive-filter-input")&&this.element.getAttribute?.("data-reactive-filter-option"))}#YZ(){return this.element.getAttribute?.("data-reactive-compute-seed")==="true"}#KZ(X){let Z=this.element.getAttribute("data-reactive-filter-input");return!!Z&&typeof X.target?.matches==="function"&&X.target.matches(Z)}#A(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.element.getAttribute("data-reactive-filter-input"),Z=this.element.getAttribute("data-reactive-filter-option");if(!X||!Z)return;let $=this.#X(),Q=[...this.element.querySelectorAll(X)].find($);if(!Q)return;let j=(Q.value??"").trim().toLowerCase(),z=0;for(let Y of this.element.querySelectorAll(Z)){if(!$(Y))continue;let K=(Y.getAttribute("data-reactive-filter-text")??Y.textContent??"").toLowerCase(),U=Y.hasAttribute?.("data-reactive-tags-selected")||j!==""&&!K.includes(j);if(Y.hidden=U,U)Y.removeAttribute("data-reactive-highlighted");else z++}let q=this.element.getAttribute("data-reactive-filter-group");if(q)for(let Y of this.element.querySelectorAll(q)){if(!$(Y))continue;let K=[...Y.querySelectorAll(Z)].filter($);if(K.length===0)continue;Y.hidden=K.every((U)=>U.hidden)}let G=this.element.getAttribute("data-reactive-filter-empty");if(G){for(let Y of this.element.querySelectorAll(G))if($(Y))Y.hidden=z>0}}#HZ(){if(!this.#Q)return;this.element.removeEventListener?.("input",this.#Q),this.element.removeEventListener?.("turbo:morph-element",this.#Q),this.#Q=void 0}#I(){return!!this.element.getAttribute?.("data-reactive-tags-field")}#UZ(){if(typeof this.element?.querySelector!=="function")return!1;return!!this.element.querySelector("[data-reactive-nested-json]")}#g(){if(typeof this.element?.querySelectorAll!=="function")return null;let X=this.element.getAttribute("data-reactive-tags-field");if(!X)return null;let Z=this.#X();return[...this.element.querySelectorAll(X)].find(Z)??null}#c(X){let Z=new Set,$=[];for(let Q of String(X.value??"").split(",")){let j=Q.trim();if(j===""||Z.has(j.toLowerCase()))continue;Z.add(j.toLowerCase()),$.push(j)}return $}#_X(X){let Z=this.#g();if(!Z)return!1;let $=this.#c(Z),Q=new Set($.map((z)=>z.toLowerCase())),j=!1;for(let z of X){let q=String(z??"").trim();if(q===""||Q.has(q.toLowerCase()))continue;Q.add(q.toLowerCase()),$.push(q),j=!0}if(j)this.#MX(Z,$);return j}#MX(X,Z){if(X.value=Z.join(","),typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}));this.#d()}#WZ(){if(typeof this.element?.querySelectorAll!=="function")return null;let X=this.element.getAttribute("data-reactive-filter-input");if(!X)return null;let Z=this.#X();return[...this.element.querySelectorAll(X)].find(Z)??null}#d(){let X=this.#g();if(!X)return;let Z=this.#c(X),$=this.#X();this.#JZ(Z,$),this.#LZ(Z,$)}#JZ(X,Z){let $=[...this.element.querySelectorAll("[data-reactive-tags-list]")].find(Z);if(!$)return;let j=[...this.element.querySelectorAll("[data-reactive-tags-template]")].find(Z)?.content?.firstElementChild;if(!j){if(!this.#r)console.warn("[phlex-reactive] reactive_tags: no chip <template data-reactive-tags-template> found in this root — "+"chips will not render (the hidden field still updates). Add a template with a [data-reactive-tag-text] node and a reactive_tags_remove button."),this.#r=!0;return}while($.firstChild)$.removeChild($.firstChild);for(let z of X){let q=j.cloneNode(!0);q.setAttribute?.("data-reactive-tag",z);let G=q.matches?.("[data-reactive-tag-text]")?q:(q.querySelectorAll?.("[data-reactive-tag-text]")??[])[0];if(G)G.textContent=z;let Y=[...q.querySelectorAll?.('[data-action*="reactive#tagsRemove"]')??[]];if(q.matches?.('[data-action*="reactive#tagsRemove"]'))Y.push(q);for(let K of Y)K.setAttribute?.("data-reactive-tag-param",z);$.appendChild(q)}}#LZ(X,Z){let $=new Set(X.map((Q)=>Q.toLowerCase()));for(let Q of this.element.querySelectorAll("[role=option]")){if(!Z(Q))continue;let j=Q.getAttribute?.("data-reactive-tag-param");if(!j)continue;if($.has(j.toLowerCase()))Q.setAttribute("data-reactive-tags-selected","true"),Q.hidden=!0,Q.removeAttribute?.("data-reactive-highlighted");else if(Q.hasAttribute?.("data-reactive-tags-selected")){if(Q.removeAttribute("data-reactive-tags-selected"),!this.#C())Q.hidden=!1}}if(this.#C())this.#A()}#VZ(){return this.#y=Math.max(this.#y+1,Date.now()),this.#y}#BZ(X,Z){let $=[X,...X.querySelectorAll?.("*")??[]];for(let Q of $)for(let j of["name","id","for"]){let z=Q.getAttribute?.(j);if(z&&z.includes("NEW_ROW"))Q.setAttribute?.(j,z.replaceAll("NEW_ROW",String(Z)))}}#_Z(X){if(this.#t)return;console.warn(`[phlex-reactive] nested rows: no owned [data-reactive-nested-list="${X}"] container + <template data-reactive-nested-template="${X}"> pair found in this root — the add `+"trigger did nothing. Render both inside the same reactive root (reactive_nested_list / reactive_nested_template)."),this.#t=!0}#MZ(){if(!this.#B)return;this.element.removeEventListener?.("turbo:morph-element",this.#B),this.#B=void 0}#AZ(){if(this.#j)this.element.removeEventListener?.("input",this.#j),this.element.removeEventListener?.("change",this.#j),this.#j=void 0;if(this.#_)this.element.removeEventListener?.("turbo:morph-element",this.#_),this.#_=void 0}#xZ(){if(!this.#M)return;this.element.removeEventListener?.("turbo:morph-element",this.#M),this.#M=void 0}#PZ(X,Z,$,Q){let j=new FormData;j.append("token",X),j.append("act",Z);for(let[q,G]of Object.entries($))this.#l(j,`params[${q}]`,G);let z=this.#NZ(Q);for(let{name:q,file:G,multiple:Y}of Q){let U=Y||z.has(q)?`params[${q}][]`:`params[${q}]`;j.append(U,G,G.name)}return j}#l(X,Z,$){if($==null)X.append(Z,"");else if(Array.isArray($))$.forEach((Q,j)=>this.#l(X,`${Z}[${j}]`,Q));else if(typeof $==="object")for(let[Q,j]of Object.entries($))this.#l(X,`${Z}[${Q}]`,j);else X.append(Z,String($))}#NZ(X){let Z=new Map;for(let{name:$}of X)Z.set($,(Z.get($)??0)+1);return new Set([...Z].filter(([,$])=>$>1).map(([$])=>$))}#AX(X){if(!X)return{};try{return typeof X==="string"?JSON.parse(X):X}catch{return{}}}#xX(X){return UX(X)}#PX(X){N(X,(Z)=>this.#T(Z))}#T(X){let Z=X.to;if(Z==="@root")return[this.element];if(typeof Z!=="string"||Z==="")return[];if(X.global)return[...document.querySelectorAll(Z)];return[...this.element.querySelectorAll(Z)].filter(($)=>this.#$($))}#OZ(X,Z){if(X?.checked!=="keep")return!1;let $=Z?.type;return $==="checkbox"||$==="radio"}#DZ(X,Z){if(!X)return null;let $=this.#NX(X,Z,!0);return $.length?$:null}#K(X){if(!X)return;if(!this.element.isConnected)return;for(let Z of X)Z()}#RZ(X,Z,$){this.#CZ(X,Z);let Q=$?this.#NX($,Z,!1):[];jX();let j=!1;return()=>{if(j)return;j=!0,this.#IZ(X,Z),zX();for(let z of Q)z()}}#NX(X,Z,$){let Q=[];for(let j of this.#OX(X,Z)){if(X.add_class){let z=X.add_class.filter((q)=>!j.classList.contains(q));if(j.classList.add(...z),z.length)Q.push(()=>j.classList.remove(...z))}if(X.remove_class){let z=X.remove_class.filter((q)=>j.classList.contains(q));if(j.classList.remove(...z),z.length)Q.push(()=>j.classList.add(...z))}if(X.toggle_class)X.toggle_class.forEach((z)=>j.classList.toggle(z)),Q.push(()=>X.toggle_class.forEach((z)=>j.classList.toggle(z)));if(X.hide)j.hidden=!0,Q.push(()=>j.hidden=!1);if(X.show)j.hidden=!1,Q.push(()=>j.hidden=!0)}if(Z&&(X.disable||X.text!=null))Q.push(this.#FZ(X,Z));if($&&X.checked==="keep"&&Z&&"checked"in Z){let j=Z.checked;Q.push(()=>Z.checked=!j)}return Q}#OX(X,Z){if(X.to==null)return Z?[Z]:[];return this.#T({to:X.to})}#FZ(X,Z){let $=this.#P.get(Z);if($)$.count++;else this.#P.set(Z,{count:1,disabled:Z.disabled,html:Z.innerHTML,hadText:X.text!=null,swappedTo:X.text});if(X.disable)Z.disabled=!0;if(X.text!=null)Z.innerHTML=X.text;return()=>this.#TZ(Z,X)}#CZ(X,Z){if(this.#H(Z,X,1),this.#H(this.element,X,1),this.#W.set(X,(this.#W.get(X)??0)+1),this.#k++===0)this.element.setAttribute("aria-busy","true");for(let $ of this.#DX(X))this.#H($,X,1)}#IZ(X,Z){this.#H(Z,X,-1),this.#H(this.element,X,-1);let $=(this.#W.get(X)??1)-1;if($<=0)this.#W.delete(X);else this.#W.set(X,$);if(--this.#k<=0)this.#k=0,this.element.removeAttribute("aria-busy");for(let Q of this.#DX(X))this.#H(Q,X,-1)}#H(X,Z,$){if(!X||typeof X.getAttribute!=="function")return;let Q=this.#S.get(X)??new Map,j=(Q.get(Z)??0)+$;if(j<=0)Q.delete(Z);else Q.set(Z,j);if(Q.size===0){this.#S.delete(X),X.removeAttribute("data-reactive-busy");return}this.#S.set(X,Q),X.setAttribute("data-reactive-busy",[...Q.keys()].join(" "))}#DX(X){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter(($)=>$.getAttribute("data-reactive-busy-on")===X&&this.#$($))}#TZ(X,Z){let $=this.#P.get(X);if(!$)return;if(--$.count>0)return;if(this.#P.delete(X),!X.isConnected)return;if(Z.disable)X.disabled=$.disabled;if($.hadText&&X.innerHTML===$.swappedTo)X.innerHTML=$.html}#EZ(X){if(!X||typeof X!=="object")return null;let{class:Z,...$}=X;return Z==null?X:{...$,add_class:Z}}#kZ(){return this.#RX??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#SZ(){if(this.#E!=null)return this.#E;let X=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Z=Number(X);return this.#E=Number.isFinite(Z)&&Z>0?Z:30000}#bZ(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#wZ(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{UZ as resetReactiveDefers,MZ as resetReactiveActivity,VX as registerReactiveVisit,BX as registerReactiveToken,fX as registerReactiveOffline,_X as registerReactiveJs,IX as registerReactiveEffects,RX as registerReactiveDismiss,MX as registerReactiveDefer,l as registerReactiveActions,_Z as reactiveActivityCount,WZ as pendingDeferVia,zX as exitReactiveActivity,gX as escapeRegExp,jX as enterReactiveActivity,pX as enableLatencySim,uX as disableLatencySim,PZ as default,cX as checkReactiveRegistration,AZ as __resetReactiveRegistrationForTest,VZ as __resetReactiveOfflineForTest,BZ as __resetReactiveLatencyForTest,LZ as __resetReactiveEffectsForTest,JZ as __resetReactiveDismissForTest,xZ as __markReactiveConnectedForTest,m as LATENCY_KEY,QX as ACTIVE_ATTR};
|
|
1
|
+
import{Controller as WX}from"@hotwired/stimulus";import{confirmResolver as C}from"phlex/reactive/confirm";import{computeReducer as JX}from"phlex/reactive/compute";import{confirmPredicate as LX}from"phlex/reactive/confirm_predicate";function VX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:visit"])return;X["reactive:visit"]=function(){let Z=this.getAttribute("data-url");if(Z)window.Turbo.visit(Z,{action:"advance"})}}function BX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:token"])return;X["reactive:token"]=function(){let Z=this.getAttribute("data-reactive-token-value"),$=this.getAttribute("target");if(!Z||!$)return;let Q=document.getElementById($);if(Q)Q.setAttribute("data-reactive-token-value",Z)}}function _X(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:js"])return;X["reactive:js"]=function(){let Z=UX(this.getAttribute("data-reactive-ops"));if(!Z.length)return;let $=this.getAttribute("target"),Q=$?document.getElementById($):null;if($&&!Q)return;N(Z,(j)=>YZ(j,Q))}}var _=new Map;function n(X,Z){let $=!_.has(X);if(_.set(X,Z),$)jX()}function R(X){if(_.delete(X))zX()}function WZ(){_.clear(),w=!1}function JZ(X){return _.get(X)?.via}var w=!1;function MX(){let X=window.Turbo?.StreamActions;if(!X||X["reactive:defer"])return;if(X["reactive:defer"]=function(){let Z=this.getAttribute("target");if(!Z)return;if(this.getAttribute("data-reactive-defer-via")==="stream"){xX(Z,this);return}let $=this.getAttribute("data-reactive-defer-token");if(!$)return;F(Z,$)},!w&&typeof document<"u"&&document.addEventListener)w=!0,document.addEventListener("turbo:before-stream-render",AX)}function AX(X){let $=X.target?.getAttribute?.("target");if(!$)return;let Q=$.startsWith("reactive-defer-src-")?$.slice(19):$;if(_.get(Q)?.via==="stream")R(Q)}function F(X,Z){let $=document.getElementById(X);if(!$){console.warn(`[phlex-reactive] reactive:defer target #${X} is not on the page — skipped`);return}r(X),t($);let Q={via:"fetch",abort:new AbortController,timedOut:!1};n(X,Q),PX(X,Q,Z)}function xX(X,Z){let $=document.getElementById(X);if(!$){console.warn(`[phlex-reactive] reactive:defer target #${X} is not on the page — skipped`);return}let Q=Z.getAttribute("data-reactive-defer-src");if(!Q)return;if(!globalThis.customElements?.get?.("pgbus-stream-source")){let z=Z.getAttribute("data-reactive-defer-token");if(z){F(X,z);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}r(X),t($);let j=document.createElement("pgbus-stream-source");j.id=a(X),j.setAttribute("src",Q),j.setAttribute("since-id",Z.getAttribute("data-reactive-defer-since-id")??"0"),j.setAttribute("hidden",""),document.body.appendChild(j),n(X,{via:"stream"})}function a(X){return`reactive-defer-src-${X}`}async function PX(X,Z,$){let Q=setTimeout(()=>{Z.timedOut=!0,Z.abort.abort()},DX()),j;try{j=await fetch(NX(),{method:"POST",headers:{Accept:"text/vnd.turbo-stream.html","Content-Type":"application/json","X-CSRF-Token":OX()},body:JSON.stringify({token:$}),credentials:"same-origin",signal:Z.abort.signal})}catch(q){if(clearTimeout(Q),_.get(X)!==Z)return;console.error("[phlex-reactive] deferred render failed",q),E(X,$);return}if(_.get(X)!==Z){clearTimeout(Q);return}if(j.status===204){clearTimeout(Q),c(X);return}if(!j.ok){clearTimeout(Q),console.error(`[phlex-reactive] deferred render failed: HTTP ${j.status}`),E(X,$,j.status);return}let z;try{z=await j.text()}catch(q){if(clearTimeout(Q),_.get(X)!==Z)return;console.error("[phlex-reactive] deferred render failed reading the body",q),E(X,$);return}if(clearTimeout(Q),_.get(X)!==Z)return;c(X),window.Turbo.renderStreamMessage(z)}function r(X){let Z=_.get(X);if(!Z)return;if(R(X),Z.via==="fetch")Z.abort.abort();else document.getElementById(a(X))?.remove?.()}function t(X){X.setAttribute("data-reactive-defer-pending","true"),X.setAttribute("aria-busy","true")}function e(X){X.removeAttribute("data-reactive-defer-pending"),X.removeAttribute("aria-busy")}function c(X){R(X);let Z=document.getElementById(X);if(!Z)return;e(Z),Z.removeAttribute("data-reactive-error")}function E(X,Z,$){R(X);let Q=document.getElementById(X);if(!Q)return;e(Q),Q.setAttribute("data-reactive-error","defer");let j=()=>{let z=document.getElementById(X);if(!z){console.warn("[phlex-reactive] defer retry() ignored — the target left the DOM");return}z.removeAttribute("data-reactive-error"),F(X,Z)};Q.dispatchEvent(new CustomEvent("reactive:error",{bubbles:!0,composed:!0,detail:{kind:"defer",target:X,status:$,retry:j}}))}function NX(){return document.querySelector('meta[name="phlex-reactive-defer-path"]')?.content||"/reactive/defer"}function OX(){return document.querySelector('meta[name="csrf-token"]')?.content??""}function DX(){let X=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Z=Number(X);return Number.isFinite(Z)&&Z>0?Z:30000}var h=!1;function RX(){if(h)return;if(typeof document>"u"||!document.addEventListener)return;h=!0,document.addEventListener("turbo:before-stream-render",FX)}function FX(X){let Z=X.detail,$=Z?.render;if(typeof $!=="function"||$.__reactiveDismissWrapped){if(typeof requestAnimationFrame==="function")requestAnimationFrame(T);else setTimeout(T,0);return}let Q=async(j)=>{await $(j),T()};Q.__reactiveDismissWrapped=!0,Z.render=Q}function T(){let X=document.querySelectorAll("[data-reactive-dismiss-after]");for(let Z of X){if(Z.hasAttribute("data-reactive-dismiss-scheduled"))continue;let $=Number(Z.getAttribute("data-reactive-dismiss-after"));if(!Number.isFinite($)||$<=0)continue;Z.setAttribute("data-reactive-dismiss-scheduled",""),setTimeout(()=>Z.remove(),$)}}function LZ(){h=!1}var IX=Object.freeze({append:"enter",prepend:"enter",replace:"update",update:"update",remove:"exit"}),k=Object.freeze(["fade","slide","scale","highlight","shake"]),y="data-reactive-fx-pending",XX=1000,v=!1;function CX(){if(v)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;v=!0,document.addEventListener("turbo:before-stream-render",EX)}function VZ(){v=!1}function EX(X){let Z=X.detail,$=Z?.render;if(typeof $!=="function"||$.__reactiveEffectsWrapped)return;let Q=Z?.newStream??X.target,j=IX[Q?.getAttribute?.("action")];if(!j||SX())return;let z=TX(Q,j);if(!z)return;let q=j==="exit"?async(Y)=>{await hX(O(Q),z),await $(Y)}:async(Y)=>{let G=j==="enter"?bX(Q):null;if(await $(Y),j==="enter")wX(G,z);else ZX(O(Q),z)};q.__reactiveEffectsWrapped=!0,Z.render=q}function TX(X,Z){let $=X.getAttribute?.("data-reactive-effect");if($==="off")return null;if($)return d($,Z);let j=(Z==="enter"?kX(X):O(X))?.getAttribute?.(`data-reactive-effect-${Z}`);return j?d(j,Z):null}function O(X){let Z=X.getAttribute?.("target");return Z?document.getElementById?.(Z)??null:null}function kX(X){return X.querySelector?.("template")?.content?.firstElementChild??null}function d(X,Z){if(X.startsWith("[")){let Q=null;try{let j=JSON.parse(X);if(Array.isArray(j)&&j.length===3)Q=j.map(String)}catch{}if(Q)return{legs:Q};return console.warn(`[phlex-reactive] malformed effect legs ${JSON.stringify(X)} — skipped`),null}let $=X==="random"?k[Math.floor(Math.random()*k.length)]:X;if(!k.includes($))return console.warn(`[phlex-reactive] unknown effect ${JSON.stringify(X)} — skipped`),null;return{className:`reactive-fx--${$}-${Z}`}}function SX(){try{return typeof matchMedia==="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches}catch{return!1}}function bX(X){let Z=X.querySelector?.("template")?.content;if(!Z)return null;for(let $ of Array.from(Z.children??[]))$.setAttribute?.(y,"");return O(X)}function wX(X,Z){if(typeof X?.querySelectorAll!=="function")return;for(let $ of Array.from(X.querySelectorAll(`[${y}]`)))$.removeAttribute(y),ZX($,Z)}async function hX(X,Z){if(!X?.classList)return;if(Z.legs){await $X(X,Z.legs);return}X.classList.add(Z.className);let $=p(X);if($<=0){X.classList.remove(Z.className);return}await u(X,$),X.classList.remove(Z.className)}function ZX(X,Z){if(!X?.classList)return;if(Z.legs){$X(X,Z.legs);return}if(X.classList.contains(Z.className))X.classList.remove(Z.className),X.offsetWidth;X.classList.add(Z.className);let $=p(X);if($<=0){X.classList.remove(Z.className);return}let Q=X.__reactiveFxToken=(X.__reactiveFxToken??0)+1;u(X,$).then(()=>{if(X.__reactiveFxToken===Q)X.classList.remove(Z.className)})}async function $X(X,Z){let[$,Q,j]=Z.map(yX),z=X.__reactiveFxToken=(X.__reactiveFxToken??0)+1;if(X.classList.remove(...$,...Q,...j),X.classList.add(...$,...Q),await vX(),X.__reactiveFxToken!==z)return;X.classList.remove(...Q),X.classList.add(...j);let q=p(X);if(q>0)await u(X,q);if(X.__reactiveFxToken!==z)return;X.classList.remove(...$,...j)}function yX(X){return String(X??"").split(/\s+/).filter(Boolean)}function p(X){if(typeof getComputedStyle!=="function")return 0;try{let Z=getComputedStyle(X),$=(z)=>String(z??"").split(",").reduce((q,Y)=>Math.max(q,parseFloat(Y)||0),0),Q=$(Z.animationDuration)+$(Z.animationDelay),j=$(Z.transitionDuration)+$(Z.transitionDelay);return Math.min(Math.max(Q,j)*1000,XX)}catch{return 0}}function u(X,Z){return new Promise(($)=>{let Q=!1,j=()=>{if(Q)return;Q=!0,$()};X.addEventListener?.("animationend",j,{once:!0}),X.addEventListener?.("transitionend",j,{once:!0}),setTimeout(j,Math.min(Z+50,XX))})}function vX(){return new Promise((X)=>{if(typeof requestAnimationFrame==="function")requestAnimationFrame(()=>X());else setTimeout(X,16)})}var f=!1;function fX(){if(f)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;f=!0;let X=()=>{let Z=document.documentElement;if(typeof Z?.toggleAttribute!=="function")return;Z.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};X(),window.addEventListener("online",X),window.addEventListener("offline",X)}function BZ(){f=!1}var m="phlex-reactive:latency",D=!1;function pX(X){if(typeof sessionStorage>"u")return;sessionStorage.setItem(m,String(X))}function uX(){if(typeof sessionStorage>"u")return;sessionStorage.removeItem(m),D=!1}function mX(){if(typeof window>"u"||typeof document>"u")return;if(document.querySelector?.('meta[name="phlex-reactive-env"]')?.content!=="development")return;window.PhlexReactive={enableLatencySim:pX,disableLatencySim:uX}}function _Z(){D=!1}var QX="data-reactive-active",M=0;function jX(){if(M++,M===1)qX("reactive:busy")}function zX(){if(M===0)return;if(M--,M===0)qX("reactive:idle")}function MZ(){return M}function AZ(){M=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(QX)}function qX(X){if(typeof document>"u")return;let Z=document.documentElement;if(typeof Z?.toggleAttribute==="function")Z.toggleAttribute(QX,M>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(X,{detail:{count:M}}))}function l(){VX(),BX(),_X(),MX(),RX(),CX(),fX(),mX()}function gX(X){return X.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}if(typeof window<"u")if(window.Turbo)l();else document.addEventListener("turbo:load",l,{once:!0});var I=!1;function cX(){if(I)return;if(typeof document>"u")return;let X=document.querySelectorAll('[data-controller~="reactive"]');if(!X||X.length===0)return;console.warn("[phlex-reactive] found "+X.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 xZ(){I=!1}function PZ(){I=!0}if(typeof window<"u"&&typeof document<"u"){let X=()=>setTimeout(cX,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",X,{once:!0});else X()}var dX=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function lX(X){let Z=String(X).toLowerCase();return Z.startsWith("on")||dX.has(Z)}function iX(X,Z,$){let[Q,j,z]=Z;X.classList.add(Q,j),$(),requestAnimationFrame(()=>{X.classList.remove(j),X.classList.add(z)});let q=!1,Y=()=>{if(q)return;q=!0,X.classList.remove(Q,z)};X.addEventListener("animationend",Y,{once:!0}),setTimeout(Y,350)}var i=Object.freeze({show:(X,Z)=>S(X,!1,Z),hide:(X,Z)=>S(X,!0,Z),toggle:(X,Z)=>S(X,!X.hidden,Z),add_class:(X,Z)=>X.classList.add(...Z.classes??[]),remove_class:(X,Z)=>X.classList.remove(...Z.classes??[]),toggle_class:(X,Z)=>(Z.classes??[]).forEach(($)=>X.classList.toggle($)),set_attr:(X,Z)=>{if(b(Z.name))X.setAttribute(Z.name,Z.value??"")},remove_attr:(X,Z)=>{if(b(Z.name))X.removeAttribute(Z.name)},toggle_attr:(X,Z)=>{if(!b(Z.name))return;if(X.hasAttribute(Z.name))X.removeAttribute(Z.name);else X.setAttribute(Z.name,"")},focus:(X)=>X.focus?.(),focus_first:(X)=>zZ(X)?.focus?.(),text:(X,Z)=>{let $=String(Z.value??"");if(X.textContent!==$)X.textContent=$},dispatch:(X,Z)=>{X.dispatchEvent(new CustomEvent(Z.name,{bubbles:!0,composed:!0,detail:Z.detail??{}}))},submit:(X)=>oX(X)?.requestSubmit?.(),paste_into:(X)=>sX(X)});function oX(X){if(X?.tagName==="FORM")return X;return X?.form??X?.closest?.("form")??null}function sX(X){let Z=globalThis.navigator?.clipboard;if(typeof Z?.readText!=="function")return;Z.readText().then(($)=>{if(!$)return;if(X.value=$,typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}));X.focus?.()}).catch(()=>{})}function S(X,Z,$){if($?.transition)iX(X,$.transition,()=>X.hidden=Z);else X.hidden=Z}function b(X){if(!lX(X))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(X)} — skipped`),!1}var YX=/^#[A-Za-z_][\w-]*$/;function nX(X){if(typeof X==="string"&&YX.test(X))return!0;return console.warn(`[phlex-reactive] refused cross-root mirror target ${JSON.stringify(X)} — skipped`),!1}function aX(X,Z){let $=X.getAttribute("data-reactive-show-equals");if($!==null)return Z===$;let Q=X.getAttribute("data-reactive-show-not");if(Q!==null)return Z!==Q;let j=X.getAttribute("data-reactive-show-in");if(j!==null){try{let z=JSON.parse(j);if(Array.isArray(z))return z.includes(Z)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(j)} — skipped`),null}for(let z of GX){let q=X.getAttribute(`data-reactive-show-${z}`);if(q!==null)return KX(z,q,Z)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}var GX=["gte","gt","lte","lt"],rX=["len_eq","len_gte","len_gt","len_lte","len_lt"];function tX(X,Z,$){if(!Number.isInteger(Z))return console.warn(`[phlex-reactive] reactive_show ${X}: needs an integer literal, got ${JSON.stringify(Z)} — skipped`),null;let Q=[...String($??"")].length;switch(X){case"len_eq":return Q===Z;case"len_gte":return Q>=Z;case"len_gt":return Q>Z;case"len_lte":return Q<=Z;case"len_lt":return Q<Z;default:return null}}function KX(X,Z,$){let Q=Number(Z);if(Number.isNaN(Q))return console.warn(`[phlex-reactive] reactive_show ${X}: needs a numeric literal, got ${JSON.stringify(Z)} — skipped`),null;let j=$==null?"":String($).trim(),z=j===""?NaN:Number(j);if(Number.isNaN(z))return!1;switch(X){case"gte":return z>=Q;case"gt":return z>Q;case"lte":return z<=Q;case"lt":return z<Q;default:return null}}function HX(X,Z){if(!X||typeof X!=="object")return null;if(typeof X.equals==="string")return Z===X.equals;if(typeof X.not==="string")return Z!==X.not;if(Array.isArray(X.in))return X.in.includes(Z);for(let $ of GX)if($ in X)return KX($,X[$],Z);for(let $ of rX)if($ in X)return tX($,X[$],Z);return null}var o="[data-reactive-show-field], [data-reactive-show]";function eX(X){try{let Z=JSON.parse(X);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(X)} — skipped`),null}function XZ(X){try{let Z=JSON.parse(X);if(Array.isArray(Z)&&Z.every(($)=>$&&typeof $==="object"&&Array.isArray($.any)&&Array.isArray($.ops)))return Z}catch{}return console.warn(`[phlex-reactive] malformed reactive_on_complete payload ${JSON.stringify(X)} — skipped`),[]}function g(X,Z){if(!X||typeof X!=="object"||typeof X.field!=="string")return!1;let $=Z(X.field)??"";return HX(X,$)===!0}function P(X,Z){if(!Array.isArray(X)||X.length===0)return null;return X.some(($)=>Array.isArray($)&&$.length>0&&$.every((Q)=>g(Q,Z)))}function ZZ(X){if(!Array.isArray(X)||X.length===0)return null;let Z=new Set;for(let $ of X){if(!Array.isArray($))continue;for(let Q of $)if(Q&&typeof Q==="object"&&typeof Q.field==="string")Z.add(Q.field)}return Z.size>0?[...Z]:null}function $Z(X,Z){if(!X||typeof X!=="object")return null;let $=X.any;if(Array.isArray($)&&($.length===0||Array.isArray($[0])))return P($,Z);return QZ(X,Z)}function QZ(X,Z){let $=Array.isArray(X.all)?"all":Array.isArray(X.any)?"any":null;if(!$)return null;let Q=X[$];if(Q.length===0)return null;let j=Q.map((z)=>g(z,Z));return $==="all"?j.every(Boolean):j.some(Boolean)}function s(X){if(typeof X==="string"&&YX.test(X))return!0;return console.warn(`[phlex-reactive] refused cross-root show target ${JSON.stringify(X)} — skipped`),!1}var jZ='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function zZ(X){return X.querySelectorAll?.(jZ)?.[0]??null}function UX(X){if(Array.isArray(X))return X;if(typeof X!=="string")return[];try{let Z=JSON.parse(X);return Array.isArray(Z)?Z:[]}catch{return[]}}function qZ(X){if(X==null)return null;let Z=Array.isArray(X)?X:X.ops;if(Array.isArray(Z))return Z.length>0?Z:null;return console.warn("[phlex-reactive] $ops must be an ops chain or a [[op, args], ...] list — skipped"),null}function N(X,Z){for(let $ of X){if(!Array.isArray($))continue;let[Q,j={}]=$;if(!Object.hasOwn(i,Q)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(Q)} — skipped`);continue}for(let z of Z(j))i[Q](z,j)}}function YZ(X,Z){let $=X.to;if(Z){if($==="@root")return[Z];if(typeof $!=="string"||$==="")return[];if(X.global)return[...document.querySelectorAll($)];return[...Z.querySelectorAll($)]}if(typeof $!=="string"||$===""||$==="@root")return[];return[...document.querySelectorAll($)]}class NZ extends WX{static values={token:String};#o;#P=new Map;#U=new Map;#IX;#k;#s;#S=0;#W=new Map;#b=new WeakMap;#N=new Map;#n=new WeakSet;#a=null;#J;#L;#V;#$;#z;#w;#r;#h;#y;#Q;#B;#t=!1;#v=0;#e=!1;#j;#_;#M;#O;#A;connect(){if(I=!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.#XX(),this.#O=()=>this.#XX(),this.element.addEventListener?.("turbo:morph-element",this.#O);if(this.#CX()){if(this.#J=()=>this.#m(),this.element.addEventListener?.("turbo:morph-element",this.#J),this.#m(),this.element.getAttribute?.("data-reactive-warn-unsaved")==="true")this.#XZ()}if(this.#$Z())this.#$=()=>this.#BX(),this.element.addEventListener?.("input",this.#$),this.element.addEventListener?.("change",this.#$),this.element.addEventListener?.("turbo:morph-element",this.#$),this.#BX();if(this.#QZ())this.#z=(X)=>this.#g(X),this.#w=()=>this.#g(null),this.element.addEventListener?.("input",this.#z),this.element.addEventListener?.("change",this.#z),this.element.addEventListener?.("turbo:morph-element",this.#w),this.#g(null);if(this.#C())this.#Q=(X)=>{if(X?.type==="input"&&!this.#JZ(X))return;this.#x()},this.element.addEventListener?.("input",this.#Q),this.element.addEventListener?.("turbo:morph-element",this.#Q),this.#x();if(this.#E())this.#B=()=>this.#l(),this.element.addEventListener?.("turbo:morph-element",this.#B),this.#l();if(this.#VZ())this.#j=(X)=>this.syncNestedJson(X),this.#_=()=>this.#R(),this.element.addEventListener?.("input",this.#j),this.element.addEventListener?.("change",this.#j),this.element.addEventListener?.("turbo:morph-element",this.#_),this.#R();if(this.#WZ())this.#M=()=>this.recompute(),this.element.addEventListener?.("turbo:morph-element",this.#M),this.recompute();if(this.#jZ())this.#A=()=>this.#VX(),this.element.addEventListener?.("turbo:morph-element",this.#A),this.#VX()}#CX(){if((this.element.getAttribute?.("data-action")??"").includes("reactive#trackDirty"))return!0;let X=this.element.querySelectorAll?.('[data-action*="reactive#trackDirty"]')??[];for(let Z of X)if(this.#Z(Z))return!0;return!1}disconnect(){if(this.#cX(),this.#lX(),this.#ZZ(),this.#UZ(),this.#YZ(),this.#LZ(),this.#NZ(),this.#OZ(),this.#DZ(),this.#zZ(),this.#O)this.element.removeEventListener?.("turbo:morph-element",this.#O)}#XX(){let X=this.element;if(!X?.id)return;let Z=X.getAttribute?.("data-reactive-defer-token");if(!Z)return;if(X.getAttribute?.("data-reactive-defer-pending")!=="true")return;F(X.id,Z)}dispatch(X){let{action:Z,params:$,debounce:Q,throttle:j,confirm:z,confirmWhen:q,outside:Y,window:G,optimistic:K}=X.params;if(!Z)return;let U=X.params.busy??this.#wZ(X.params.loading);if(Y&&this.element.contains(X.target))return;let B=X.currentTarget??X.target;if(!G&&!this.#IZ(K,B))X.preventDefault();let W=this.#u(z,q);if(!W)return this.#GX(B,Z,$,Q,j,K,U);Promise.resolve().then(()=>C(W,{el:B})).catch(()=>!1).then((V)=>{if(V)this.#GX(B,Z,$,Q,j,K,U)})}runOps(X){let{ops:Z,confirm:$,confirmWhen:Q,outside:j,window:z}=X.params,q=X.currentTarget??X.target;if(j&&this.element.contains(X.target))return;if(!z)X.preventDefault();let Y=this.#u($,Q);if(!Y)return this.#OX(this.#NX(Z));Promise.resolve().then(()=>C(Y,{el:q})).catch(()=>!1).then((G)=>{if(G)this.#OX(this.#NX(Z))})}trackDirty(){this.#m()}recompute(X){if(X&&this.#n.has(X))return;let Z=this.#yX(),$=Z.map(([H])=>H),Q=this.element.getAttribute?.("data-reactive-scope")||null,j=(H)=>Q&&!H.includes("[")?`${Q}[${H}]`:H,z=this.#X(),q=new Map,Y=(H)=>{if(q.has(H))return q.get(H);let J=null;for(let L of this.element.querySelectorAll(`[name="${j(H)}"]`))if(z(L)){J=L;break}return q.set(H,J),J};for(let H of $)this.#qX(H,Y(H)?.value??"");let G=this.element.getAttribute("data-reactive-compute-reducer-param"),K=G?JX(G):null;if(!K){this.#YX({},Y);return}let U=this.#hX("data-reactive-compute-outputs-param"),B={};for(let[H,J]of Z){let L=Y(H);if(J==="string")B[H]=L?.value??"";else{let A=Number(L?.value);B[H]=Number.isFinite(A)?A:0}}let W=K(B,{changed:this.#vX(X,$,Q)})||{},V=qZ(W.$ops),x=[];for(let H of U){if(H==="$ops"||!(H in W))continue;let J=Y(H);if(!J)continue;if(String(W[H])===J.value)continue;J.value=W[H],x.push(J)}for(let H of Object.keys(W)){if(H==="$ops")continue;let J=W[H];if(J===void 0||J===null)continue;this.#qX(H,J)}this.#YX(W,Y);for(let H of x){let J=new Event("input",{bubbles:!0});this.#n.add(J),H.dispatchEvent(J)}this.#EX(V,Boolean(X))}#EX(X,Z){let $=X===null?null:JSON.stringify(X),Q=$!==null&&$!==this.#a&&Z;if(this.#a=$,!Q)return;N(X,(j)=>this.#T(j.to==null?{...j,to:"@root"}:j))}listnavNext(X){this.#ZX(X,1)}listnavPrev(X){this.#ZX(X,-1)}listnavPick(X){let Z=this.#D(X),$=Z.findIndex((Q)=>Q.hasAttribute("data-reactive-highlighted"));if($<0)return;X.preventDefault(),Z[$].click()}listnavClose(X){for(let Z of this.#D(X))Z.removeAttribute("data-reactive-highlighted")}#ZX(X,Z){let $=this.#D(X);if(!$.length)return;X.preventDefault();let Q=$.findIndex((q)=>q.hasAttribute("data-reactive-highlighted")),j=Q<0?Z>0?0:$.length-1:(Q+Z+$.length)%$.length;for(let q of $)q.removeAttribute("data-reactive-highlighted");let z=$[j];z.setAttribute("data-reactive-highlighted","true"),z.scrollIntoView?.({block:"nearest"})}#D(X){let $=(X?.currentTarget??X?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!$)return[];let Q=this.#X();return Array.from(this.element.querySelectorAll($)).filter((j)=>!j.hidden&&Q(j))}tagsAdd(X){if(!this.#E())return;if(X?.defaultPrevented)return;if(this.#D(X).some((Q)=>Q.hasAttribute?.("data-reactive-highlighted")))return;X?.preventDefault?.();let Z=X?.currentTarget??X?.target;if(!Z)return;if(!this.#AX(String(Z.value??"").split(",")))return;if(Z.value="",this.#C())this.#x()}tagsPick(X){if(!this.#E())return;X?.preventDefault?.();let $=(X?.currentTarget??X?.target)?.getAttribute?.("data-reactive-tag-param");if(!$)return;if(!this.#AX([$]))return;let Q=this.#BZ();if(!Q)return;Q.value="",this.#x(),Q.focus?.()}tagsRemove(X){if(!this.#E())return;X?.preventDefault?.();let $=(X?.currentTarget??X?.target)?.getAttribute?.("data-reactive-tag-param");if(!$)return;let Q=this.#c();if(!Q)return;let j=this.#d(Q),z=j.filter((q)=>q.toLowerCase()!==$.toLowerCase());if(z.length===j.length)return;this.#xX(Q,z)}nestedAdd(X){X?.preventDefault?.();let Z=X?.currentTarget??X?.target,$=Z?.getAttribute?.("data-reactive-association-param");if(!$)return;if(typeof this.element?.querySelectorAll!=="function")return;let Q=this.#X(),j=[...this.element.querySelectorAll(`[data-reactive-nested-list="${$}"]`)].find(Q),q=[...this.element.querySelectorAll(`[data-reactive-nested-template="${$}"]`)].find(Q)?.content?.firstElementChild;if(!j||!q){this.#PZ($);return}let Y=q.cloneNode(!0);this.#xZ(Y,this.#AZ()),j.appendChild(Y);let G=Z?.getAttribute?.("data-reactive-nested-from-param"),K=Z?.getAttribute?.("data-reactive-nested-clear-param")==="true",U=this.#TX(Y,G,K);if(G)U?.focus?.();else[...Y.querySelectorAll?.("input, select, textarea")??[]][0]?.focus?.();if(j.getAttribute?.("data-reactive-nested-json")===$)this.#QX($)}#TX(X,Z,$){if(!Z)return null;let Q;try{Q=JSON.parse(Z)}catch{return null}if(!Q||typeof Q!=="object")return null;let j=this.#X(),z=[...X.querySelectorAll?.("input, select, textarea")??[]],q=[];for(let[Y,G]of Object.entries(Q)){let K=[...this.element.querySelectorAll?.(G)??[]].find(j);if(!K)continue;let U=z.find((B)=>this.#zX(B.getAttribute?.("name"))===Y);if(!U)continue;this.#kX(U,K),q.push(K)}if($)for(let Y of q)this.#SX(Y);return q[0]??null}#kX(X,Z){if(X.type==="checkbox")X.checked=Z.type==="checkbox"?!!Z.checked:this.#f(Z)!=="";else X.value=this.#f(Z);if(typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}))}#SX(X){if(X.type==="checkbox")X.checked=!1;else X.value="";if(typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}))}nestedRemove(X){X?.preventDefault?.();let Z=X?.currentTarget??X?.target,$=Z?.closest?.("[data-reactive-nested-row]");if(!$)return;if($.closest?.('[data-controller~="reactive"]')!==this.element)return;let Q=Z?.getAttribute?.("data-reactive-confirm-param"),j=Z?.getAttribute?.("data-reactive-confirm-when-param"),z=this.#u(Q,j);if(!z)return this.#$X($);let q=this.#jX($),Y=this.#bX(z,q);return Promise.resolve().then(()=>C(Y,{el:Z,row:$,fields:q})).catch(()=>!1).then((G)=>{if(G)this.#$X($)})}#bX(X,Z){if(!X.includes("%{"))return X;return X.replace(/%\{(\w+)\}/g,($,Q)=>Object.prototype.hasOwnProperty.call(Z,Q)?Z[Q]:$)}#$X(X){let Z=[...X.querySelectorAll?.('input[name$="[_destroy]"]')??[]][0];if(Z){if(Z.value="1",typeof Z.dispatchEvent==="function")Z.dispatchEvent(new Event("input",{bubbles:!0}));X.hidden=!0}else X.parentNode?.removeChild?.(X);this.#R()}syncNestedJson(X){let Z=X?.target;if(!Z||!this.#Z(Z))return;this.#R()}#R(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.#X();for(let Z of[...this.element.querySelectorAll("[data-reactive-nested-json]")].filter(X))this.#QX(Z.getAttribute("data-reactive-nested-json"))}#QX(X){let Z=this.#X(),$=[...this.element.querySelectorAll(`[data-reactive-nested-list="${X}"]`)].find(Z);if(!$)return;let Q=this.#wX($);if(!Q)return;let j=[];for(let q of[...$.querySelectorAll?.("[data-reactive-nested-row]")??[]]){if(!Z(q)||q.hidden)continue;j.push(this.#jX(q))}let z=JSON.stringify(j);if(Q.value===z)return;if(Q.value=z,typeof Q.dispatchEvent==="function")Q.dispatchEvent(new Event("input",{bubbles:!0}))}#wX(X){let Z=X.getAttribute?.("data-reactive-nested-json-field");if(!Z)return null;let $=this.#X();return[...this.element.querySelectorAll(Z)].find($)??null}#jX(X){let Z={};for(let $ of[...X.querySelectorAll?.("input, select, textarea")??[]]){let Q=this.#zX($.getAttribute?.("name"));if(Q===null||Q==="_destroy")continue;Z[Q]=this.#f($)}return Z}#zX(X){if(!X)return null;let Z=X.match(/\[([^\][]+)\]$/);return Z?Z[1]:X}#f(X){if(X.type==="checkbox")return X.checked?X.value||"on":"";return X.value??""}#hX(X){let Z=this.element.getAttribute(X);if(!Z)return[];try{let $=JSON.parse(Z);return Array.isArray($)?$:[]}catch{return[]}}#yX(){let X=this.element.getAttribute("data-reactive-compute-inputs-param");if(!X)return[];try{let Z=JSON.parse(X);if(Array.isArray(Z))return Z.map(($)=>[$,"number"]);if(Z&&typeof Z==="object")return Object.entries(Z);return[]}catch{return[]}}#vX(X,Z,$){let Q=X?.target;if(!Q?.name||typeof Q.closest!=="function")return null;let j=this.#fX(Q.name,$);if(!Z.includes(j))return null;return this.#Z(Q)?j:null}#fX(X,Z){if(!Z)return X;let $=`${Z}[`;return X.startsWith($)&&X.endsWith("]")?X.slice($.length,-1):X}#qX(X,Z){let $=String(Z);for(let Q of this.#pX(X)){if(Q.textContent===$)continue;Q.textContent=$}}#pX(X){let Z=this.element.querySelectorAll(`[data-reactive-text="${X}"]`);return Array.from(Z).filter(($)=>this.#Z($))}#YX(X,Z){let $=this.#uX();for(let[Q,j]of Object.entries($)){let z=Q in X?X[Q]:Z(Q)?.value;if(z===void 0||z===null)continue;let q=String(z);for(let Y of Array.isArray(j)?j:[j]){if(!nX(Y))continue;for(let G of document.querySelectorAll(Y)){if(G.textContent===q)continue;G.textContent=q}}}}#uX(){let X=this.element.getAttribute("data-reactive-compute-mirror-param");if(!X)return{};try{let Z=JSON.parse(X);return Z&&typeof Z==="object"&&!Array.isArray(Z)?Z:{}}catch{return{}}}#GX(X,Z,$,Q,j,z,q){if(this.#I("reactive:before-dispatch",{action:Z,params:this.#PX($),element:this.element},{cancelable:!0}).defaultPrevented)return;let G=Number(Q)||0;if(G>0)return this.#gX(X,G,Z,$,z,q);let K=Number(j)||0;if(K>0)return this.#dX(X,K,Z,$,z,q);return this.#F(Z,$,z,X,q)}#F(X,Z,$,Q,j){let z=this.#CZ($,Q),q=this.#EZ(X,Q,j),Y=this.#KX()?this.#mX($,Q):null;return this.queue=(this.queue??Promise.resolve()).then(()=>this.#rX(X,Z,z,q,Y)),this.queue}#mX(X,Z){if(!X?.hide)return null;let $=this.#RX(X,Z);if(!$.length)return null;return()=>{let Q=$.filter((j)=>j.isConnected&&!j.hidden);if(!Q.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.",Q)}}#gX(X,Z,$,Q,j,z){this.#p(X);let q=()=>{this.#p(X),this.#F($,Q,j,X,z)},Y=setTimeout(q,Z);X?.addEventListener?.("blur",q,{once:!0}),this.#P.set(X,{timer:Y,flush:q})}#p(X){let Z=this.#P.get(X);if(!Z)return;clearTimeout(Z.timer),X?.removeEventListener?.("blur",Z.flush),this.#P.delete(X)}#cX(){for(let X of[...this.#P.keys()])this.#p(X)}#dX(X,Z,$,Q,j,z){let q=this.#U.get(X)??new Map;if(q.has($))return;let Y=setTimeout(()=>{if(q.delete($),q.size===0)this.#U.delete(X)},Z);return q.set($,Y),this.#U.set(X,q),this.#F($,Q,j,X,z)}#lX(){for(let X of this.#U.values())for(let Z of X.values())clearTimeout(Z);this.#U.clear()}#I(X,Z,{cancelable:$=!1}={}){let Q=new CustomEvent(X,{bubbles:!0,composed:!0,cancelable:$,detail:Z});return(this.element.isConnected?this.element:document).dispatchEvent(Q),Q}#q(X,Z,$,Q){let j=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#F(X,Z)};this.#I("reactive:error",{action:X,params:$,...Q,retry:j})}#Y(X){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",X)}#iX(){this.element?.removeAttribute?.("data-reactive-error")}#oX(){let X=document.querySelector("[data-reactive-error-flash]");if(!X?.content)return;let Z=X.getAttribute("data-reactive-error-flash")||"flash",$=document.getElementById(Z);if(!$)return;$.appendChild(X.content.cloneNode(!0))}#sX(){if(typeof sessionStorage>"u")return Promise.resolve();let X=Number(sessionStorage.getItem(m));if(!Number.isFinite(X)||X<=0)return Promise.resolve();if(!D)D=!0,console.warn(`[phlex-reactive] latency simulator ACTIVE — every action is delayed by ${X}ms. Call PhlexReactive.disableLatencySim() (or clear sessionStorage) to turn it off.`);return new Promise((Z)=>setTimeout(Z,X))}#KX(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#HX(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}#nX(X){if(!X)return[];let Z=[],$=/<turbo-stream\b([^>]*)>/g,Q;while((Q=$.exec(X))!==null){let j=Q[1],z=j.match(/\baction="([^"]*)"/)?.[1]??"?",q=j.match(/\btarget="([^"]*)"/)?.[1];Z.push(q?`${z} → #${q}`:z)}return Z}#aX(X){let{action:Z,status:$,ms:Q}=X,z=`reactive ${this.element?.id?`#${this.element.id} `:""}${Z} → ${$??"—"} (${Math.round(Q)}ms)`;if(console.groupCollapsed(z),console.log(`params: [${X.paramNames.join(", ")}] + collected: [${X.fieldNames.join(", ")}]`),console.log(`encoding: ${X.encoding}`),X.streams.length)console.log(`streams: ${X.streams.join(" ")}`);console.log(`token: ${X.tokenRefreshed?"refreshed ✓":"unchanged"}`),console.groupEnd()}async#rX(X,Z,$,Q,j){let{fields:z,files:q}=this.#JX(),Y=this.#PX(Z),G={...z,...Y},K=this.#G,U=q.length>0,B=U?this.#RZ(K,X,G,q):JSON.stringify({token:K,act:X,params:G}),W=this.#KX()?{action:X,paramNames:Object.keys(Y),fieldNames:Object.keys(z),encoding:U?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#HX()}:null;await this.#sX();try{if(navigator.onLine===!1){this.#K($),this.#Y("offline"),this.#q(X,Z,G,{kind:"offline"});return}let V;try{let L={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#vZ()};if(!U)L["Content-Type"]="application/json";let A=this.#fZ();if(A)L["X-Pgbus-Connection"]=A;V=await fetch(this.#hZ(),{method:"POST",headers:L,body:B,credentials:"same-origin",signal:AbortSignal.timeout(this.#yZ())})}catch(L){if(console.error("[phlex-reactive] action error",L),this.#K($),L?.name==="TimeoutError"||L?.name==="AbortError"){this.#Y("timeout"),this.#q(X,Z,G,{kind:"timeout"});return}this.#oX(),this.#Y("network"),this.#q(X,Z,G,{kind:"network"});return}if(W)W.status=V.status;if(V.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#K($),this.#Y("redirected"),this.#q(X,Z,G,{kind:"redirected",status:V.status});return}if(!V.ok){let L=await V.text();if(console.error(`[phlex-reactive] action failed: HTTP ${V.status}`,L),this.#K($),(V.headers.get("Content-Type")||"").includes("turbo-stream")){let A=this.#WX(L);if(this.#G=A??this.#G,W)this.#UX(W,L,A);window.Turbo.renderStreamMessage(L)}this.#Y("http"),this.#q(X,Z,G,{kind:"http",status:V.status,body:L});return}let x=V.headers.get("Content-Type")||"";if(!x.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${x}" — no update applied`),this.#K($),this.#Y("content-type"),this.#q(X,Z,G,{kind:"content-type",status:V.status});return}let H=await V.text(),J=this.#WX(H);if(this.#G=J??this.#G,W)this.#UX(W,H,J);if(window.Turbo.renderStreamMessage(H),j)queueMicrotask(j);this.#iX(),this.#I("reactive:applied",{action:X,params:G,html:H})}catch(V){console.error("[phlex-reactive] action error",V),this.#K($),this.#I("reactive:error",{action:X,params:G,kind:"apply"})}finally{if(Q?.(),W)this.#aX({...W,ms:this.#HX()-W.started})}}#UX(X,Z,$){X.streams=this.#nX(Z),X.tokenRefreshed=$!=null}get#G(){return this.#o??this.tokenValue}set#G(X){this.#o=X}#WX(X){let Z=this.element.id;if(!Z)return X.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:$,self:Q}=this.#tX(Z),j=X.match($);if(j)return j[1];let z=X.match(Q);if(z)return z[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#tX(X){let Z=this.#s;if(Z&&Z.id===X)return Z;let $=gX(X);return this.#s={id:X,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${$}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${$}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#Z(X){return X.closest('[data-controller~="reactive"]')===this.element}#X(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(Z)=>this.#Z(Z)}#u(X,Z){if(X)return X;if(!Z)return null;let $=Z;if(typeof Z==="string")try{$=JSON.parse(Z)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(Z)} — skipped`),null}if(!$||typeof $!=="object")return null;let{fields:Q}=this.#JX(),j=(q)=>Q[q],z;if(typeof $.predicate==="string"){let q=LX($.predicate);if(!q)return console.warn(`[phlex-reactive] confirm predicate "${$.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;z=!!q(Q)}else z=P($.groups?.any,j)===!0;return z?$.message:null}#JX(){let X={},Z=[],$=this.#X();return this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((Q)=>{if(!$(Q))return;if(Q.type==="file")for(let j of Q.files??[])Z.push({name:Q.name,file:j,multiple:Q.multiple});else if(Q.type==="checkbox")X[Q.name]=Q.checked;else if(Q.type==="radio"){if(Q.checked)X[Q.name]=Q.value}else X[Q.name]=Q.value}),this.element.querySelectorAll("[name]:is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])").forEach((Q)=>{if(!$(Q))return;let j=Q.getAttribute("name");if(!j)return;let z=X[j];if(z==null||z==="")X[j]=Q.value??Q.textContent??Q.innerHTML??""}),{fields:X,files:Z}}#m(){if(typeof this.element?.querySelectorAll!=="function")return;let X=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.#eX(Z))Z.setAttribute("data-reactive-dirty","true"),X++;else Z.removeAttribute("data-reactive-dirty")}),X>0)this.element.setAttribute("data-reactive-dirty",String(X));else this.element.removeAttribute("data-reactive-dirty")}#eX(X){if(X.type==="checkbox"||X.type==="radio")return X.checked!==X.defaultChecked;if(X.tag==="select"||X.options)return Array.from(X.options??[]).some((Z)=>Z.selected!==Z.defaultSelected);return X.value!==X.defaultValue}#LX(){let X=this.element.getAttribute?.("data-reactive-dirty"),Z=Number(X);return Number.isFinite(Z)&&Z>0?Z:0}#XZ(){if(typeof window>"u"||typeof window.addEventListener!=="function")return;this.#L=(X)=>{if(this.#LX()===0)return;return X.preventDefault(),X.returnValue="You have unsaved changes.",X.returnValue},this.#V=(X)=>{if(this.#LX()===0)return;if(!(typeof window.confirm==="function"?window.confirm("You have unsaved changes. Leave anyway?"):!0))X.preventDefault?.()},window.addEventListener("beforeunload",this.#L),window.addEventListener("turbo:before-visit",this.#V)}#ZZ(){if(this.#J)this.element.removeEventListener?.("turbo:morph-element",this.#J),this.#J=void 0;if(typeof window<"u"&&typeof window.removeEventListener==="function"){if(this.#L)window.removeEventListener("beforeunload",this.#L);if(this.#V)window.removeEventListener("turbo:before-visit",this.#V)}this.#L=void 0,this.#V=void 0}#$Z(){if(this.element.getAttribute?.("data-reactive-show-targets"))return!0;let X=this.element.querySelectorAll?.(o)??[];for(let Z of X)if(this.#Z(Z))return!0;return!1}#QZ(){return!!this.element.getAttribute?.("data-reactive-on-complete")}#jZ(){if(this.element.getAttribute?.("data-reactive-clipboard"))return!0;let X=this.element.querySelectorAll?.("[data-reactive-clipboard]")??[];for(let Z of X)if(this.#Z(Z))return!0;return!1}#VX(){let X=typeof globalThis.navigator?.clipboard?.readText==="function";if(this.element.getAttribute?.("data-reactive-clipboard"))this.element.hidden=!X;for(let Z of this.element.querySelectorAll?.("[data-reactive-clipboard]")??[])if(this.#Z(Z))Z.hidden=!X}#zZ(){if(!this.#A)return;this.element.removeEventListener?.("turbo:morph-element",this.#A),this.#A=void 0}#qZ(){let X=this.element.getAttribute?.("data-reactive-on-complete")??null;if(X!==this.#r)this.#r=X,this.#h=X==null?[]:XZ(X),this.#y=this.#h.map(()=>!1);return this.#h}#g(X){let Z=this.#qZ();if(!Z.length)return;let $=this.#X(),Q=this.element.getAttribute?.("data-reactive-scope")||null,j=new Map,z=(q)=>{if(!j.has(q))j.set(q,this.#MX(q,$,Q));return j.get(q)};Z.forEach((q,Y)=>{let G=P(q.any,z);if(G===null)return;let K=G&&!this.#y[Y]&&Boolean(X);if(this.#y[Y]=G,K)N(q.ops,(U)=>this.#T(U.to==null?{...U,to:"@root"}:U))})}#YZ(){if(!this.#z)return;this.element.removeEventListener?.("input",this.#z),this.element.removeEventListener?.("change",this.#z),this.element.removeEventListener?.("turbo:morph-element",this.#w)}#BX(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.#X(),Z=this.element.getAttribute?.("data-reactive-scope")||null,$=new Map,Q=(j)=>{if(!$.has(j))$.set(j,this.#MX(j,X,Z));return $.get(j)};for(let j of this.element.querySelectorAll(o)){if(!X(j))continue;let z=j.getAttribute("data-reactive-show");if(z!==null){let K=$Z(eX(z),Q);if(K!==null)this.#_X(j,K,X,Z);continue}let q=j.getAttribute("data-reactive-show-field");if(!q)continue;let Y=Q(q);if(Y===null)continue;let G=aX(j,Y);if(G===null)continue;this.#_X(j,G,X,Z)}this.#GZ(Q)}#_X(X,Z,$,Q){if(X.hidden=!Z,X.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof X.querySelectorAll!=="function")return;for(let j of X.querySelectorAll("input[name], select[name], textarea[name]"))if($(j))j.disabled=!Z;if(X.name&&$(X))X.disabled=!Z}#GZ(X){let Z=this.#HZ();for(let[$,Q]of Object.entries(Z)){if($.startsWith("#")){this.#KZ($,Q,X);continue}if(!Q||typeof Q!=="object"||Array.isArray(Q))continue;let j=X($);if(j===null)continue;let z=()=>j;for(let[q,Y]of Object.entries(Q)){if(!s(q))continue;let G;if(Array.isArray(Y)){if(Y.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${q} — skipped`);continue}G=Y.every((K)=>g(K,z))}else{let K=HX(Y,j);if(K===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${q} — skipped`);continue}G=K}for(let K of document.querySelectorAll(q))K.hidden=!G}}}#KZ(X,Z,$){if(!s(X))return;let Q=Z&&typeof Z==="object"&&!Array.isArray(Z)?Z.any:null,j=ZZ(Q);if(j===null){console.warn(`[phlex-reactive] malformed reactive_show_targets conditions for ${X} — skipped`);return}if(j.every((q)=>$(q)===null))return;let z=P(Q,$);if(z===null)return;for(let q of document.querySelectorAll(X))q.hidden=!z}#HZ(){let X=this.element.getAttribute?.("data-reactive-show-targets");if(!X)return{};try{let Z=JSON.parse(X);if(Z&&typeof Z==="object"&&!Array.isArray(Z))return Z}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: { ... })"),{}}#MX(X,Z,$){let Q=$&&!X.includes("[")?`${$}[${X}]`:X,j=!1,z=null;for(let q of this.element.querySelectorAll(`[name="${Q}"]`)){if(!Z(q))continue;if(q.type==="checkbox")return q.checked?"true":"false";if(q.type==="radio"){if(q.checked)return q.value??"";j=!0;continue}z??=q}if(z)return z.value??"";return j?"":null}#UZ(){if(!this.#$)return;this.element.removeEventListener?.("input",this.#$),this.element.removeEventListener?.("change",this.#$),this.element.removeEventListener?.("turbo:morph-element",this.#$),this.#$=void 0}#C(){return!!(this.element.getAttribute?.("data-reactive-filter-input")&&this.element.getAttribute?.("data-reactive-filter-option"))}#WZ(){return this.element.getAttribute?.("data-reactive-compute-seed")==="true"}#JZ(X){let Z=this.element.getAttribute("data-reactive-filter-input");return!!Z&&typeof X.target?.matches==="function"&&X.target.matches(Z)}#x(){if(typeof this.element?.querySelectorAll!=="function")return;let X=this.element.getAttribute("data-reactive-filter-input"),Z=this.element.getAttribute("data-reactive-filter-option");if(!X||!Z)return;let $=this.#X(),Q=[...this.element.querySelectorAll(X)].find($);if(!Q)return;let j=(Q.value??"").trim().toLowerCase(),z=0;for(let G of this.element.querySelectorAll(Z)){if(!$(G))continue;let K=(G.getAttribute("data-reactive-filter-text")??G.textContent??"").toLowerCase(),U=G.hasAttribute?.("data-reactive-tags-selected")||j!==""&&!K.includes(j);if(G.hidden=U,U)G.removeAttribute("data-reactive-highlighted");else z++}let q=this.element.getAttribute("data-reactive-filter-group");if(q)for(let G of this.element.querySelectorAll(q)){if(!$(G))continue;let K=[...G.querySelectorAll(Z)].filter($);if(K.length===0)continue;G.hidden=K.every((U)=>U.hidden)}let Y=this.element.getAttribute("data-reactive-filter-empty");if(Y){for(let G of this.element.querySelectorAll(Y))if($(G))G.hidden=z>0}}#LZ(){if(!this.#Q)return;this.element.removeEventListener?.("input",this.#Q),this.element.removeEventListener?.("turbo:morph-element",this.#Q),this.#Q=void 0}#E(){return!!this.element.getAttribute?.("data-reactive-tags-field")}#VZ(){if(typeof this.element?.querySelector!=="function")return!1;return!!this.element.querySelector("[data-reactive-nested-json]")}#c(){if(typeof this.element?.querySelectorAll!=="function")return null;let X=this.element.getAttribute("data-reactive-tags-field");if(!X)return null;let Z=this.#X();return[...this.element.querySelectorAll(X)].find(Z)??null}#d(X){let Z=new Set,$=[];for(let Q of String(X.value??"").split(",")){let j=Q.trim();if(j===""||Z.has(j.toLowerCase()))continue;Z.add(j.toLowerCase()),$.push(j)}return $}#AX(X){let Z=this.#c();if(!Z)return!1;let $=this.#d(Z),Q=new Set($.map((z)=>z.toLowerCase())),j=!1;for(let z of X){let q=String(z??"").trim();if(q===""||Q.has(q.toLowerCase()))continue;Q.add(q.toLowerCase()),$.push(q),j=!0}if(j)this.#xX(Z,$);return j}#xX(X,Z){if(X.value=Z.join(","),typeof X.dispatchEvent==="function")X.dispatchEvent(new Event("input",{bubbles:!0}));this.#l()}#BZ(){if(typeof this.element?.querySelectorAll!=="function")return null;let X=this.element.getAttribute("data-reactive-filter-input");if(!X)return null;let Z=this.#X();return[...this.element.querySelectorAll(X)].find(Z)??null}#l(){let X=this.#c();if(!X)return;let Z=this.#d(X),$=this.#X();this.#_Z(Z,$),this.#MZ(Z,$)}#_Z(X,Z){let $=[...this.element.querySelectorAll("[data-reactive-tags-list]")].find(Z);if(!$)return;let j=[...this.element.querySelectorAll("[data-reactive-tags-template]")].find(Z)?.content?.firstElementChild;if(!j){if(!this.#t)console.warn("[phlex-reactive] reactive_tags: no chip <template data-reactive-tags-template> found in this root — "+"chips will not render (the hidden field still updates). Add a template with a [data-reactive-tag-text] node and a reactive_tags_remove button."),this.#t=!0;return}while($.firstChild)$.removeChild($.firstChild);for(let z of X){let q=j.cloneNode(!0);q.setAttribute?.("data-reactive-tag",z);let Y=q.matches?.("[data-reactive-tag-text]")?q:(q.querySelectorAll?.("[data-reactive-tag-text]")??[])[0];if(Y)Y.textContent=z;let G=[...q.querySelectorAll?.('[data-action*="reactive#tagsRemove"]')??[]];if(q.matches?.('[data-action*="reactive#tagsRemove"]'))G.push(q);for(let K of G)K.setAttribute?.("data-reactive-tag-param",z);$.appendChild(q)}}#MZ(X,Z){let $=new Set(X.map((Q)=>Q.toLowerCase()));for(let Q of this.element.querySelectorAll("[role=option]")){if(!Z(Q))continue;let j=Q.getAttribute?.("data-reactive-tag-param");if(!j)continue;if($.has(j.toLowerCase()))Q.setAttribute("data-reactive-tags-selected","true"),Q.hidden=!0,Q.removeAttribute?.("data-reactive-highlighted");else if(Q.hasAttribute?.("data-reactive-tags-selected")){if(Q.removeAttribute("data-reactive-tags-selected"),!this.#C())Q.hidden=!1}}if(this.#C())this.#x()}#AZ(){return this.#v=Math.max(this.#v+1,Date.now()),this.#v}#xZ(X,Z){let $=[X,...X.querySelectorAll?.("*")??[]];for(let Q of $)for(let j of["name","id","for"]){let z=Q.getAttribute?.(j);if(z&&z.includes("NEW_ROW"))Q.setAttribute?.(j,z.replaceAll("NEW_ROW",String(Z)))}}#PZ(X){if(this.#e)return;console.warn(`[phlex-reactive] nested rows: no owned [data-reactive-nested-list="${X}"] container + <template data-reactive-nested-template="${X}"> pair found in this root — the add `+"trigger did nothing. Render both inside the same reactive root (reactive_nested_list / reactive_nested_template)."),this.#e=!0}#NZ(){if(!this.#B)return;this.element.removeEventListener?.("turbo:morph-element",this.#B),this.#B=void 0}#OZ(){if(this.#j)this.element.removeEventListener?.("input",this.#j),this.element.removeEventListener?.("change",this.#j),this.#j=void 0;if(this.#_)this.element.removeEventListener?.("turbo:morph-element",this.#_),this.#_=void 0}#DZ(){if(!this.#M)return;this.element.removeEventListener?.("turbo:morph-element",this.#M),this.#M=void 0}#RZ(X,Z,$,Q){let j=new FormData;j.append("token",X),j.append("act",Z);for(let[q,Y]of Object.entries($))this.#i(j,`params[${q}]`,Y);let z=this.#FZ(Q);for(let{name:q,file:Y,multiple:G}of Q){let U=G||z.has(q)?`params[${q}][]`:`params[${q}]`;j.append(U,Y,Y.name)}return j}#i(X,Z,$){if($==null)X.append(Z,"");else if(Array.isArray($))$.forEach((Q,j)=>this.#i(X,`${Z}[${j}]`,Q));else if(typeof $==="object")for(let[Q,j]of Object.entries($))this.#i(X,`${Z}[${Q}]`,j);else X.append(Z,String($))}#FZ(X){let Z=new Map;for(let{name:$}of X)Z.set($,(Z.get($)??0)+1);return new Set([...Z].filter(([,$])=>$>1).map(([$])=>$))}#PX(X){if(!X)return{};try{return typeof X==="string"?JSON.parse(X):X}catch{return{}}}#NX(X){return UX(X)}#OX(X){N(X,(Z)=>this.#T(Z))}#T(X){let Z=X.to;if(Z==="@root")return[this.element];if(typeof Z!=="string"||Z==="")return[];if(X.global)return[...document.querySelectorAll(Z)];return[...this.element.querySelectorAll(Z)].filter(($)=>this.#Z($))}#IZ(X,Z){if(X?.checked!=="keep")return!1;let $=Z?.type;return $==="checkbox"||$==="radio"}#CZ(X,Z){if(!X)return null;let $=this.#DX(X,Z,!0);return $.length?$:null}#K(X){if(!X)return;if(!this.element.isConnected)return;for(let Z of X)Z()}#EZ(X,Z,$){this.#kZ(X,Z);let Q=$?this.#DX($,Z,!1):[];jX();let j=!1;return()=>{if(j)return;j=!0,this.#SZ(X,Z),zX();for(let z of Q)z()}}#DX(X,Z,$){let Q=[];for(let j of this.#RX(X,Z)){if(X.add_class){let z=X.add_class.filter((q)=>!j.classList.contains(q));if(j.classList.add(...z),z.length)Q.push(()=>j.classList.remove(...z))}if(X.remove_class){let z=X.remove_class.filter((q)=>j.classList.contains(q));if(j.classList.remove(...z),z.length)Q.push(()=>j.classList.add(...z))}if(X.toggle_class)X.toggle_class.forEach((z)=>j.classList.toggle(z)),Q.push(()=>X.toggle_class.forEach((z)=>j.classList.toggle(z)));if(X.hide)j.hidden=!0,Q.push(()=>j.hidden=!1);if(X.show)j.hidden=!1,Q.push(()=>j.hidden=!0)}if(Z&&(X.disable||X.text!=null))Q.push(this.#TZ(X,Z));if($&&X.checked==="keep"&&Z&&"checked"in Z){let j=Z.checked;Q.push(()=>Z.checked=!j)}return Q}#RX(X,Z){if(X.to==null)return Z?[Z]:[];return this.#T({to:X.to})}#TZ(X,Z){let $=this.#N.get(Z);if($)$.count++;else this.#N.set(Z,{count:1,disabled:Z.disabled,html:Z.innerHTML,hadText:X.text!=null,swappedTo:X.text});if(X.disable)Z.disabled=!0;if(X.text!=null)Z.innerHTML=X.text;return()=>this.#bZ(Z,X)}#kZ(X,Z){if(this.#H(Z,X,1),this.#H(this.element,X,1),this.#W.set(X,(this.#W.get(X)??0)+1),this.#S++===0)this.element.setAttribute("aria-busy","true");for(let $ of this.#FX(X))this.#H($,X,1)}#SZ(X,Z){this.#H(Z,X,-1),this.#H(this.element,X,-1);let $=(this.#W.get(X)??1)-1;if($<=0)this.#W.delete(X);else this.#W.set(X,$);if(--this.#S<=0)this.#S=0,this.element.removeAttribute("aria-busy");for(let Q of this.#FX(X))this.#H(Q,X,-1)}#H(X,Z,$){if(!X||typeof X.getAttribute!=="function")return;let Q=this.#b.get(X)??new Map,j=(Q.get(Z)??0)+$;if(j<=0)Q.delete(Z);else Q.set(Z,j);if(Q.size===0){this.#b.delete(X),X.removeAttribute("data-reactive-busy");return}this.#b.set(X,Q),X.setAttribute("data-reactive-busy",[...Q.keys()].join(" "))}#FX(X){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter(($)=>$.getAttribute("data-reactive-busy-on")===X&&this.#Z($))}#bZ(X,Z){let $=this.#N.get(X);if(!$)return;if(--$.count>0)return;if(this.#N.delete(X),!X.isConnected)return;if(Z.disable)X.disabled=$.disabled;if($.hadText&&X.innerHTML===$.swappedTo)X.innerHTML=$.html}#wZ(X){if(!X||typeof X!=="object")return null;let{class:Z,...$}=X;return Z==null?X:{...$,add_class:Z}}#hZ(){return this.#IX??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#yZ(){if(this.#k!=null)return this.#k;let X=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,Z=Number(X);return this.#k=Number.isFinite(Z)&&Z>0?Z:30000}#vZ(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#fZ(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}export{WZ as resetReactiveDefers,AZ as resetReactiveActivity,VX as registerReactiveVisit,BX as registerReactiveToken,fX as registerReactiveOffline,_X as registerReactiveJs,CX as registerReactiveEffects,RX as registerReactiveDismiss,MX as registerReactiveDefer,l as registerReactiveActions,MZ as reactiveActivityCount,JZ as pendingDeferVia,zX as exitReactiveActivity,gX as escapeRegExp,jX as enterReactiveActivity,pX as enableLatencySim,uX as disableLatencySim,NZ as default,cX as checkReactiveRegistration,xZ as __resetReactiveRegistrationForTest,BZ as __resetReactiveOfflineForTest,_Z as __resetReactiveLatencyForTest,VZ as __resetReactiveEffectsForTest,LZ as __resetReactiveDismissForTest,PZ as __markReactiveConnectedForTest,m as LATENCY_KEY,QX as ACTIVE_ATTR};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=5DD971D088374C7264756E2164756E21
|
|
4
4
|
//# sourceMappingURL=reactive_controller.min.js.map
|