phlex-reactive 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eeebc2783f571e3e3fcc0847318ebef76050954e0e56a99f627e8e5654467133
4
- data.tar.gz: 974cc0de7e79babb8834bf41a10001e69a087bda3daf6a87122cae7654e128cb
3
+ metadata.gz: 3b268544642595b7c8912db0dcbee175ed751fb73290d1bfcfec0c4c9627583b
4
+ data.tar.gz: 459a72f7b048c8db6010213e252d09c552eefb3296eb838bc36973d9ded2a48d
5
5
  SHA512:
6
- metadata.gz: f95657cd231a4e711d6300fae52cbefacb42f34d5803f98073366710855a7c5906e795844800c55e8a6ee2b089224809bacb739c0c90f1a89c97c23851c2c7e7
7
- data.tar.gz: 0b47dacc177e41d086e045ec842879358c68d4ec298615c1fcb6e23fc8cdb8b53ce5db96fa4fe2424b1fdaa381870fd29ce6f50b1ac70b7375790590e1eae793
6
+ metadata.gz: dfcf217a1d1dd7fae8a79c5a4d146409a5528a13a0a7f6cadfa757ba2728c740e90fb3e95ed6957740b4219c9ea7ac5ad0bf3c5c719442671662a1f803b6a6e8
7
+ data.tar.gz: 6636ad3074cd8cba009c507730d901c38afc343b228e0780c4cf50b7404a6b0f1c8f61e75c3b5edeeb5f0fa1a56f5966ea15ed53a8db5ee4987fe320fde85dc5
data/CHANGELOG.md CHANGED
@@ -8,6 +8,31 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
9
  ### Added
10
10
 
11
+ - **Modal dialogs — `js.show_modal` / `js.close_dialog` and
12
+ `data-reactive-modal` (#365).** `js.show_modal("#picker")` calls
13
+ `HTMLDialogElement#showModal()`, so an `on_client` dialog gets the browser's
14
+ top layer, focus trap, `::backdrop`, Escape and focus restored to the opener;
15
+ `js.close_dialog("#picker")` calls `close()`. A dialog already open
16
+ non-modally is reopened as a modal; a non-dialog target is skipped. A
17
+ `dialog(open: true, data: { reactive_modal: true })` the server renders (a
18
+ full page, a reply, a broadcast) is made modal at connect, after a morph and
19
+ after a stream that brings a dialog; a morph that renders it without `open`
20
+ closes it with `close()`, so the page behind is interactive again. Both ops
21
+ are actor-only, refused by `broadcast_to(js:)` like `focus`. Client: +499 B
22
+ gzipped in the default bundle, +425 B in the split core. Docs: "Modal
23
+ dialogs" on the client-ops example.
24
+
25
+ - **`shortcut: "delete"` / `"backspace"` (#366).** `on(:remove_selected,
26
+ shortcut: "delete")`, `"backspace"` and `"mod+backspace"` are accepted, on
27
+ `on(...)` and `on_client(:keydown, ...)`. Stimulus's default key map lacks
28
+ these keys (a `keydown.delete` filter throws "unknown key filter" at
29
+ keypress), so such a shortcut renders a bare `keydown@window` descriptor and
30
+ the client matches the chord itself, with the usual rules: prevented, this
31
+ platform's `mod`, skipped while typing unless `in_editable: true`.
32
+ `phlex/reactive/early` queues and prevents the chord before connect and leaves
33
+ every other key alone (+134 B gzipped). `once:` raises on these keys. Existing
34
+ chords render unchanged.
35
+
11
36
  - **Presence — `reactive_presence`, `presence`, `js.presence` (#358).** A
12
37
  roster component declares the presence stream it shows
13
38
  (`reactive_presence :viewers, state: { selected: :integer }, ttl: 45`) and
data/README.md CHANGED
@@ -684,7 +684,7 @@ Use in controllers: `render turbo_stream: Counter.replace(counter)`.
684
684
  | `busy_on(:save)` | Mark any element so it carries `data-reactive-busy` **only while `save` is in flight** — a spinner styled with pure CSS, zero Ruby. See [Loading states](#declarative-loading-states-loading--disable_with). |
685
685
  | `on(:action, once: true)` | Fire at most once, then unbind (Stimulus's native `:once`). |
686
686
  | `on_client(:click, js.toggle("#menu"))` | **Client-only** trigger: applies declared DOM ops with ZERO round trip — no token, no POST, ever. Takes the same `window:`/`once:`/`outside:` modifiers, plus `detail:` (run only when `event.detail` carries the listed values). See [Client-only ops](#client-only-ops-on_client--js--zero-round-trips). |
687
- | `js` | The immutable op builder behind `on_client`: `show`/`hide`/`toggle` (the `hidden` attribute, with an optional `transition:` and `expanded:`), `add_class`/`remove_class`/`toggle_class`, `set_attr`/`remove_attr`/`toggle_attr` (allowlisted names; `toggle_attr` also flips between two values), `focus`/`focus_first`, `text` (set `textContent` — XSS-safe), `dispatch`, `submit` (requestSubmit the target's own form, optionally through a `submitter:`), `paste_into` (read the clipboard into a field, gesture-gated), `check_group` (tick or untick a checkbox group, then re-sync its bindings), and `persist_state`/`persist_clear` (the `reactive_persist` draft) — chainable. |
687
+ | `js` | The immutable op builder behind `on_client`: `show`/`hide`/`toggle` (the `hidden` attribute, with an optional `transition:` and `expanded:`), `add_class`/`remove_class`/`toggle_class`, `set_attr`/`remove_attr`/`toggle_attr` (allowlisted names; `toggle_attr` also flips between two values), `focus`/`focus_first`, `show_modal`/`close_dialog` (a real modal `<dialog>`), `text` (set `textContent` — XSS-safe), `dispatch`, `submit` (requestSubmit the target's own form, optionally through a `submitter:`), `paste_into` (read the clipboard into a field, gesture-gated), `check_group` (tick or untick a checkbox group, then re-sync its bindings), and `persist_state`/`persist_clear` (the `reactive_persist` draft) — chainable. |
688
688
  | `reactive_field(:param, **attrs)` | The attribute hash that binds a control to an action param (no magic `name:`) — spread onto any control: `input(**reactive_field(:value, value: @record.name))`, `select(**reactive_field(:status)) { … }`. |
689
689
  | `reactive_editable(:name, multiline: false, placeholder: nil, on_enter: nil, on_escape: :revert, spellcheck: true)` | A plain-text **editable element** as a field (issue #351): `h3(**reactive_editable(:title)) { @card.title }`. Its text travels under the scope-aware `name`: with `multiline: true` its line breaks are sent as `\n`; a single-line field (the default) folds them to spaces; a morph keeps the focused element's text and caret (attributes still morph); paste is plain text; Enter runs `on_enter:` (a single-line field swallows it); Escape reverts. `reactive_dirty` and `reactive_persist` treat it like an input. See the [Editable text](https://phlex-reactive.zoolutions.llc/docs/editable-text) page. |
690
690
  | `reactive_text(:name, initial)` | Mirror a compute output (or a declared input) into a **text node** — a live preview heading, a character counter, `"Hello, {name}"` — via `textContent` (XSS-safe). The text sibling of `reactive_field`; carries no `name`, so it's never POSTed. See [Client-side computes](#client-side-computes-reactive_compute--reactive_text). |
@@ -972,7 +972,15 @@ A shortcut is a window `keydown` binding with three rules a plain
972
972
  `event:`, `window:` or `outside:` raises `ArgumentError`, as does a key outside
973
973
  Stimulus's default key map (a letter, a digit, `enter`, `tab`, `esc`, `space`,
974
974
  the arrows, `home`, `end`, `page_up`, `page_down`; bind a custom `keyMappings`
975
- key with `event:` and `window:`). On `on_client` the event must be `:keydown`.
975
+ key with `event:` and `window:`) other than `delete` and `backspace`. On
976
+ `on_client` the event must be bare `:keydown` or `"keydown"`.
977
+
978
+ `delete` and `backspace` are matched by the library rather than Stimulus (its
979
+ default key map lacks them, and a `keydown.delete` filter makes Stimulus throw
980
+ at keypress): the shortcut binds a bare `keydown@window` and the client matches
981
+ the chord, with every rule above — `on(:remove_selected, shortcut: "delete")`
982
+ never fires while typing in a field. They cannot take `once:` (the first key
983
+ pressed of any kind would spend the bare binding).
976
984
  `shortcut` is now a **reserved keyword** on `on(...)`.
977
985
 
978
986
  `once: true` on a shortcut unbinds the Stimulus descriptor after its first
@@ -1257,6 +1265,15 @@ button(**on_client(:click, js
1257
1265
  - **`focus(to)`** focuses the first match; **`focus_first(to)`** focuses the first
1258
1266
  focusable descendant of the match (e.g. the first menuitem inside an opened
1259
1267
  menu).
1268
+ - **`show_modal(to)`** / **`close_dialog(to)`** (#365) call
1269
+ `HTMLDialogElement#showModal()` / `#close()`: the top layer, a focus trap,
1270
+ `::backdrop`, Escape to close and focus back on the opener — all the
1271
+ browser's own. A dialog already open non-modally is reopened as a modal; a
1272
+ target that is not a `<dialog>` is skipped. A dialog the server renders open
1273
+ with `data: { reactive_modal: true }` (a full page, a reply, a broadcast) is
1274
+ made modal as soon as the client sees it, and closed with `close()` when a
1275
+ morph renders it without `open`. **Actor-only like focus**: refused in
1276
+ `broadcast_to(js:)` — render the dialog open or closed, with the marker, instead.
1260
1277
  - **`text(to, value)`** sets the target's `textContent` (stringified; `nil`
1261
1278
  clears) — **XSS-safe by construction**, never `innerHTML`, strictly less
1262
1279
  powerful than `set_attr`. With `global: true` it is the **cross-root text
@@ -3048,8 +3065,8 @@ Notifications::Badge.broadcast_to(user, :alerts,
3048
3065
  ```
3049
3066
 
3050
3067
  `broadcast_to` with `js:` **refuses the actor-only ops** (`focus`/`focus_first`/
3051
- `submit`/`paste_into`/`persist_state`/`persist_clear`/`check_group` raise
3052
- `ArgumentError`): broadcasting focus would steal it in every subscriber's tab, a
3068
+ `show_modal`/`close_dialog`/`submit`/`paste_into`/`persist_state`/`persist_clear`/`check_group` raise
3069
+ `ArgumentError`): broadcasting focus (or a modal) would steal it in every subscriber's tab, a
3053
3070
  broadcast submit would force-submit every subscriber's form, and a broadcast
3054
3071
  clipboard read, draft write or selection change would be hostile — these
3055
3072
  belong to the actor's own reply or gesture. Everything else is a fair broadcast
@@ -1,8 +1,8 @@
1
- import{Controller as Ce}from"@hotwired/stimulus";import{confirmResolver as Z}from"phlex/reactive/confirm";function De(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:visit"])return;e["reactive:visit"]=function(){let t=this.getAttribute("data-url");if(t)window.Turbo.visit(t,{action:"advance"})}}function qe(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:token"])return;e["reactive:token"]=function(){let t=this.getAttribute("data-reactive-token-value"),r=this.getAttribute("target");if(!t||!r)return;let n=document.getElementById(r);if(n)n.setAttribute("data-reactive-token-value",t)}}function $e(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=X(this.getAttribute("data-reactive-ops"));if(!t.length)return;let r=this.getAttribute("target"),n=this.getAttribute("data-reactive-verbose")==="true",i=r?document.getElementById(r):null;if(r&&!i){if(n)b("devtools",(o)=>o.missingRoot(r));return}V(t,(o)=>pt(o,i),n?(o,a)=>b("devtools",(s)=>s.diagnoseStream(o,a,i)):void 0)}}function Be(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){b("defer",(t)=>t.streamAction(this))}}var Q=!1,H=null;function We(){if(Q)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Q=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(je(e),H)H(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var P="reactive:streamed";function je(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target,i=n?.getAttribute?.("action"),o=/^(append|prepend|update)$/.test(i);if(typeof r!=="function"||!(o||/^(before|after|replace)$/.test(i)))return;let a=n.getAttribute("target"),s=n.getAttribute("targets"),c=new Set;for(let l of a?[document.getElementById(a)]:s?document.querySelectorAll(s):[]){let d=(o?l:l?.parentElement)?.closest?.('[data-controller~="reactive"]');if(d)c.add(d)}if(c.size===0)return;t.render=async(l)=>{await r(l);for(let d of c)if(d.isConnected)d.dispatchEvent(new Event(P))}}function ge(e){H=e}var R,B=null,ee="[data-reactive-editable][contenteditable=plaintext-only]";function be(){if(R===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",R=e.contentEditable==="plaintext-only"}catch{R=!1}return R}function I(e){if(e.matches?.(ee))e.setAttribute("contenteditable","true");e.querySelectorAll?.(ee).forEach(I)}function Ue(){if(B||typeof document>"u"||typeof document.createElement!=="function")return;if(be())return;I(document),B=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")I(t.target);else t.addedNodes.forEach(I)}),B.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var te=!1;function W(e){return e===document.activeElement&&(e.localName==="input"||e.localName==="textarea"||e.hasAttribute("data-reactive-editable"))&&!e.hasAttribute("data-reactive-morph-value")&&!!e.closest('[data-controller~="reactive"]')}function Je(){if(te)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;te=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;if(t.hasAttribute?.("data-reactive-editable")){if(O.set(t,F(r)),!W(t))return;for(let{name:i}of[...t.attributes])if(!r.hasAttribute(i)&&i!=="contenteditable")t.removeAttribute(i);for(let{name:i,value:o}of r.attributes)if(i!=="contenteditable"&&t.getAttribute(i)!==o)t.setAttribute(i,o);return e.preventDefault()}if(t.localName!=="input"||!W(t))return;let n=r.getAttribute("value");if(n==null)t.removeAttribute("value");else if(t.getAttribute("value")!==n)t.setAttribute("value",n)}),document.addEventListener("focusin",(e)=>Y(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{if(e.detail?.attributeName==="value"&&W(e.target))e.preventDefault()})}var Ke="__materialize",re=!1;function ze(){if(re)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;re=!0;let e=()=>{let t=document.documentElement;if(typeof t?.toggleAttribute!=="function")return;t.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};e(),window.addEventListener("online",e),window.addEventListener("offline",e)}var He="phlex-reactive:latency";function ye(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(He))}function G(){if(typeof document>"u")return;if(!p.has("devtools")&&!_.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||ye())b("devtools",(t)=>e&&t.attach())}var ve="data-reactive-active",S=0;function _e(){if(S++,S===1)we("reactive:busy")}function Se(){if(S===0)return;if(S--,S===0)we("reactive:idle")}function jt(){return S}function Ut(){S=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(ve)}function we(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(ve,S>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:S}}))}var Ae="data-reactive-requests";function Te(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Ve(t))return;let r=Ge(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(Ae,JSON.stringify(r))}function Ve(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Ge(e){try{let t=JSON.parse(e.getAttribute(Ae));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function ne(){De(),qe(),$e(),Be(),We(),Je(),Ue(),ze(),G()}function Ye(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Ee=Symbol.for("phlex-reactive.core");if(globalThis[Ee])console.error("[phlex-reactive] the client was loaded twice. Import EITHER phlex/reactive/reactive_controller (the default, "+"everything in one file) OR phlex/reactive/core (features on demand), not both — each carries its own state.");globalThis[Ee]=!0;var Fe=!1;function Xe(){if(Fe)return;if(typeof document>"u")return;let e=document.querySelectorAll('[data-controller~="reactive"]');if(!e||e.length===0)return;console.warn("[phlex-reactive] found "+e.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.')}if(typeof window<"u"&&typeof document<"u"){let e=()=>setTimeout(Xe,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var Ze=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function Qe(e){let t=String(e).toLowerCase();return t.startsWith("on")||Ze.has(t)}var j=new WeakMap;function et(e,t,r){let[n,i,o]=t;j.get(e)?.(),e.classList.add(n,i),r();let a=!1,s=requestAnimationFrame(()=>{if(a)return;e.classList.remove(i),e.classList.add(o)}),c=(d)=>{if(a||d&&d.target!==e)return;a=!0,j.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(s),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,o)};j.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,tt(e))}function tt(e){let t=0;try{let r=getComputedStyle(e);for(let n of["transition","animation"]){let[i,o]=["Duration","Delay"].map((s)=>String(r[n+s]).split(",").map((c)=>parseFloat(c)*(/ms/.test(c)?1:1000)||0)),a=String(r[n+"IterationCount"]).split(",").map((s)=>/inf/.test(s)?1/0:parseFloat(s)>=0?parseFloat(s):1);for(let s=0;s<i.length||s<o.length||s<a.length;s++){let c=i[s%i.length]*a[s%a.length]||0;t=Math.max(t,c+o[s%o.length])}}}catch{}return Math.min(Math.max(t+50,350),5000)}var rt=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",nt=new Set(["lexxy-editor","trix-editor"]);function F(e){let t="",r=!1,n=(o)=>{if(r&&t&&!t.endsWith(`
1
+ import{Controller as We}from"@hotwired/stimulus";import{confirmResolver as re}from"phlex/reactive/confirm";function je(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:visit"])return;e["reactive:visit"]=function(){let t=this.getAttribute("data-url");if(t)window.Turbo.visit(t,{action:"advance"})}}function Ue(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:token"])return;e["reactive:token"]=function(){let t=this.getAttribute("data-reactive-token-value"),r=this.getAttribute("target");if(!t||!r)return;let n=document.getElementById(r);if(n)n.setAttribute("data-reactive-token-value",t)}}function Je(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=te(this.getAttribute("data-reactive-ops"));if(!t.length)return;let r=this.getAttribute("target"),n=this.getAttribute("data-reactive-verbose")==="true",i=r?document.getElementById(r):null;if(r&&!i){if(n)b("devtools",(o)=>o.missingRoot(r));return}Y(t,(o)=>At(o,i),n?(o,a)=>b("devtools",(s)=>s.diagnoseStream(o,a,i)):void 0)}}function Ke(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){b("defer",(t)=>t.streamAction(this))}}var ne=!1,V=null;function ze(){if(ne)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;ne=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(He(e),Ve(e),V)V(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var P="reactive:streamed";function He(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target,i=n?.getAttribute?.("action"),o=/^(append|prepend|update)$/.test(i);if(typeof r!=="function"||!(o||/^(before|after|replace)$/.test(i)))return;let a=n.getAttribute("target"),s=n.getAttribute("targets"),c=new Set;for(let l of a?[document.getElementById(a)]:s?document.querySelectorAll(s):[]){let d=(o?l:l?.parentElement)?.closest?.('[data-controller~="reactive"]');if(d)c.add(d)}if(c.size===0)return;t.render=async(l)=>{await r(l);for(let d of c)if(d.isConnected)d.dispatchEvent(new Event(P))}}function X(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function Z(e){try{return e.matches(":modal")}catch{return!1}}function _e(e){if(!X(e)){if(e?.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))console.warn(`[phlex-reactive] show_modal targets a <dialog>, not <${e.localName}> — skipped`);return}if(!e.isConnected||Z(e))return;if(e.open)e.close();e.showModal()}function Ge(e){if(X(e)&&e.open)e.close()}function O(e){let r=[...e?.querySelectorAll?.("dialog[data-reactive-modal]")??[]];if(e?.matches?.("dialog[data-reactive-modal]"))r.push(e);for(let n of r)if(n.open&&!Z(n))_e(n)}function Ve(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target;if(typeof r!=="function"||!n?.querySelector?.("template")?.content?.querySelector?.("dialog"))return;t.render=async(i)=>{await r(i),O(document)}}var ie=!1;function Ye(){if(ie)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;ie=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))O(t.target)}),document.addEventListener("turbo:morph",()=>O(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!X(r)||!n)return;if(n.hasAttribute?.("open"))e.delete(r);else e.add(r)}),document.addEventListener("turbo:before-morph-attribute",(t)=>{let{target:r,detail:n}=t;if(n?.attributeName!=="open"||n.mutationType!=="remove")return;if(!e.has(r)||!r.open||!Z(r))return;e.delete(r),t.preventDefault(),r.close()})}function we(e){V=e}var R,W=null,se="[data-reactive-editable][contenteditable=plaintext-only]";function Se(){if(R===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",R=e.contentEditable==="plaintext-only"}catch{R=!1}return R}function N(e){if(e.matches?.(se))e.setAttribute("contenteditable","true");e.querySelectorAll?.(se).forEach(N)}function Xe(){if(W||typeof document>"u"||typeof document.createElement!=="function")return;if(Se())return;N(document),W=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")N(t.target);else t.addedNodes.forEach(N)}),W.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var oe=!1;function j(e){return e===document.activeElement&&(e.localName==="input"||e.localName==="textarea"||e.hasAttribute("data-reactive-editable"))&&!e.hasAttribute("data-reactive-morph-value")&&!!e.closest('[data-controller~="reactive"]')}function Ze(){if(oe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;oe=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;if(t.hasAttribute?.("data-reactive-editable")){if(M.set(t,F(r)),!j(t))return;for(let{name:i}of[...t.attributes])if(!r.hasAttribute(i)&&i!=="contenteditable")t.removeAttribute(i);for(let{name:i,value:o}of r.attributes)if(i!=="contenteditable"&&t.getAttribute(i)!==o)t.setAttribute(i,o);return e.preventDefault()}if(t.localName!=="input"||!j(t))return;let n=r.getAttribute("value");if(n==null)t.removeAttribute("value");else if(t.getAttribute("value")!==n)t.setAttribute("value",n)}),document.addEventListener("focusin",(e)=>ee(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{if(e.detail?.attributeName==="value"&&j(e.target))e.preventDefault()})}var Qe="__materialize",ae=!1;function et(){if(ae)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;ae=!0;let e=()=>{let t=document.documentElement;if(typeof t?.toggleAttribute!=="function")return;t.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};e(),window.addEventListener("online",e),window.addEventListener("offline",e)}var tt="phlex-reactive:latency";function Ae(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(tt))}function Q(){if(typeof document>"u")return;if(!p.has("devtools")&&!_.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||Ae())b("devtools",(t)=>e&&t.attach())}var Ee="data-reactive-active",w=0;function Te(){if(w++,w===1)Le("reactive:busy")}function Fe(){if(w===0)return;if(w--,w===0)Le("reactive:idle")}function Yt(){return w}function Xt(){w=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(Ee)}function Le(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(Ee,w>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:w}}))}var ke="data-reactive-requests";function xe(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!rt(t))return;let r=nt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(ke,JSON.stringify(r))}function rt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function nt(e){try{let t=JSON.parse(e.getAttribute(ke));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function ce(){je(),Ue(),Je(),Ke(),ze(),Ze(),Ye(),Xe(),et(),Q()}function it(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Re=Symbol.for("phlex-reactive.core");if(globalThis[Re])console.error("[phlex-reactive] the client was loaded twice. Import EITHER phlex/reactive/reactive_controller (the default, "+"everything in one file) OR phlex/reactive/core (features on demand), not both — each carries its own state.");globalThis[Re]=!0;var Pe=!1;function st(){if(Pe)return;if(typeof document>"u")return;let e=document.querySelectorAll('[data-controller~="reactive"]');if(!e||e.length===0)return;console.warn("[phlex-reactive] found "+e.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.')}if(typeof window<"u"&&typeof document<"u"){let e=()=>setTimeout(st,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var ot=new Set(["href","src","srcdoc","action","formaction","xlink:href","style"]);function at(e){let t=String(e).toLowerCase();return t.startsWith("on")||ot.has(t)}var U=new WeakMap;function ct(e,t,r){let[n,i,o]=t;U.get(e)?.(),e.classList.add(n,i),r();let a=!1,s=requestAnimationFrame(()=>{if(a)return;e.classList.remove(i),e.classList.add(o)}),c=(d)=>{if(a||d&&d.target!==e)return;a=!0,U.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(s),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,o)};U.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,ut(e))}function ut(e){let t=0;try{let r=getComputedStyle(e);for(let n of["transition","animation"]){let[i,o]=["Duration","Delay"].map((s)=>String(r[n+s]).split(",").map((c)=>parseFloat(c)*(/ms/.test(c)?1:1000)||0)),a=String(r[n+"IterationCount"]).split(",").map((s)=>/inf/.test(s)?1/0:parseFloat(s)>=0?parseFloat(s):1);for(let s=0;s<i.length||s<o.length||s<a.length;s++){let c=i[s%i.length]*a[s%a.length]||0;t=Math.max(t,c+o[s%o.length])}}}catch{}return Math.min(Math.max(t+50,350),5000)}var lt=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",dt=new Set(["lexxy-editor","trix-editor"]);function F(e){let t="",r=!1,n=(o)=>{if(r&&t&&!t.endsWith(`
2
2
  `))t+=`
3
3
  `;r=!1,t+=o},i=(o)=>{for(let a of o.childNodes){let s=/^(div|p|li)$/.test(a.localName);if(s)r=!0;if(a.nodeType===3)a.data&&n(a.data);else if(a.localName==="br")n(`
4
4
  `);else if(a.nodeType===1)i(a);if(s)r=!0}};return i(e),t=t.replace(/\r\n?/g,`
5
- `).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var O=new WeakMap;function Y(e){if(e?.hasAttribute?.("data-reactive-editable")&&!O.has(e))O.set(e,F(e))}function Le(e){return Y(e),O.get(e)}function it(e){return nt.has(e.localName)?typeof e.value==="string":!0}var ie=Object.freeze({show:(e,t,r)=>U(e,!1,t,r),hide:(e,t,r)=>U(e,!0,t,r),toggle:(e,t,r)=>U(e,!e.hidden,t,r),add_class:(e,t)=>e.classList.add(...t.classes??[]),remove_class:(e,t)=>e.classList.remove(...t.classes??[]),toggle_class:(e,t)=>(t.classes??[]).forEach((r)=>e.classList.toggle(r)),set_attr:(e,t)=>{if(J(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(J(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!J(t.name))return;if(Array.isArray(t.values)){let[r,n]=t.values;e.setAttribute(t.name,e.getAttribute(t.name)===r?n:r)}else if(e.hasAttribute(t.name))e.removeAttribute(t.name);else e.setAttribute(t.name,"")},focus:(e)=>e.focus?.(),focus_first:(e)=>ut(e)?.focus?.(),text:(e,t)=>{let r=String(t.value??"");if(e.textContent!==r)e.textContent=r},check_group:(e,t)=>{let r=t.global?document.querySelectorAll('[data-controller~="reactive"]'):[e];for(let n of r)b("bindings",(i)=>i.checkGroup(n,t.group,t.checked))},presence:(e,t)=>b("presence",(r)=>r.set(e,t.state)),dispatch:(e,t)=>{e.dispatchEvent(new CustomEvent(t.name,{bubbles:!0,composed:!0,detail:t.detail??{}}))},submit:(e,t,r)=>{let n=st(e);if(!n)return;let i=null;if(t?.submitter!=null&&typeof r==="function"){if(i=r({...t,to:t.submitter})[0]??null,!(i?.form===n&&(i.type==="submit"||i.type==="image")))console.warn(`[phlex-reactive] submitter ${t.submitter} is not a submit control of the form — ignored`),i=null}i?n.requestSubmit?.(i):n.requestSubmit?.()},paste_into:(e)=>ot(e),persist_state:(e,t)=>b("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>b("persist",(t)=>t.clearRoot(e))});function st(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function ot(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;if(e.value=r,typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}));e.focus?.()}).catch(()=>{})}function at(e,t,r){if(r?.transition)et(e,r.transition,()=>e.hidden=t);else e.hidden=t}function U(e,t,r,n){if(at(e,t,r),r?.expanded==null||typeof n!=="function")return;for(let i of n({...r,to:r.expanded}))i.setAttribute?.("aria-expanded",String(!t))}function J(e){if(!Qe(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}var ct='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function ut(e){return e.querySelectorAll?.(ct)?.[0]??null}function X(e){if(Array.isArray(e))return e;if(typeof e!=="string")return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}var se=Object.freeze({enter:"Enter",tab:"Tab",esc:"Escape",space:" ",up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight",home:"Home",end:"End",page_up:"PageUp",page_down:"PageDown"}),oe=Object.freeze(["meta","ctrl","alt","shift"]);function D(e,t,r){let n=e.split("+");for(let a of oe)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!oe.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let o=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(se,i)?se[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof o==="string"&&o.toLowerCase()===t.key.toLowerCase()}var lt=(e)=>e&&typeof e==="object"?e.keys:String(e);function ae(e,t,r){let n=t.target;if(e?.inEditable!==!0&&(n?.isContentEditable||/^(input|textarea|select)$/.test(n?.localName)))return!1;let i=/[Mm]ac|iP/.test(navigator.userAgentData?.platform??navigator.platform)?"meta":"ctrl";return D(lt(e).replace(/^mod\+/,`${i}+`),t,r)}function dt(e){if(Array.isArray(e))return[{ops:e,legacy:!0}];if(e&&typeof e==="object")return[e];if(typeof e!=="string")return[];let t=e.trim();if(t.startsWith("["))return[{ops:X(t),legacy:!0}];let r=[];for(let n of t.split(" ")){if(n==="")continue;let i=null;try{i=JSON.parse(n)}catch{i=null}if(i&&typeof i==="object"&&!Array.isArray(i))r.push(i);else console.warn(`[phlex-reactive] malformed on_client binding record ${JSON.stringify(n)} — skipped`)}return r}function ce(e,t,r){if(e.legacy)return!0;let n=e.on;if(typeof n!=="string"||n==="")return!1;let i=n.indexOf(".");if(t.type!==(i<0?n:n.slice(0,i)))return!1;if(Boolean(e.window)!==Ne(t.currentTarget))return!1;return i<0||r===null||D(n.slice(i+1),t,r)}function ft(e,t){let r=e.detail;if(r===void 0)return!0;if(r===null||typeof r!=="object"||Array.isArray(r))return!1;let n=t.detail;if(n===null||typeof n!=="object")return!1;return Object.keys(r).every((i)=>n[i]===r[i])}var ue=new WeakMap;function ht(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=ue.get(e);if(!i)i=new WeakMap,ue.set(e,i);let o=i.get(n);if(!o)o=new Set,i.set(n,o);let a=t.params?.ops,c=(n===globalThis.window?`${typeof a==="string"?a:JSON.stringify(a??null)}|`:"")+JSON.stringify(r);if(o.has(c))return!0;return o.add(c),!1}var le=new WeakMap;function mt(e,t){if(e===null||typeof e!=="object")return!1;let r=e.params?.ops,n=typeof r==="string"?r:JSON.stringify(r??null),i=le.get(e);if(!i)i=new WeakMap,le.set(e,i);let o=i.get(t);if(!o)o=new Map,i.set(t,o);let a=o.get(e.currentTarget);if(!a)a=new Set,o.set(e.currentTarget,a);if(a.has(n))return!0;return a.add(n),!1}function V(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,o={}]=n;if(!Object.hasOwn(ie,i)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(i)} — skipped`);continue}let a=t(o);if(a.length===0&&r)r(i,o);for(let s of a)ie[i](s,o,t)}}function pt(e,t){let r=e.to;if(t){if(r==="@root")return[t];if(typeof r!=="string"||r==="")return[];if(e.global)return[...document.querySelectorAll(r)];return[...t.querySelectorAll(r)]}if(typeof r!=="string"||r===""||r==="@root")return[];return[...document.querySelectorAll(r)]}function gt(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function ke(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}function bt(e){return(e.getAttribute?.("data-action")??"").includes("reactive#trackDirty")||e.getAttribute?.("data-reactive-clipboard")!=null||e.querySelector?.('[data-action*="reactive#trackDirty"],[data-reactive-clipboard]')!=null}function yt(e){return["show-targets","group-targets","on-complete","filter-input","tags-field"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)||(e.querySelectorAll?.("[data-reactive-show-field], [data-reactive-show]")??[]).length>0||e.querySelector?.("[data-reactive-nested-json], [data-reactive-nested-list], [data-reactive-confirm-when-param], [data-reactive-enable], [data-reactive-select-all], [data-reactive-count], [data-reactive-editable]")!=null}function vt(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function _t(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function xe(e){return e.getAttribute?.("data-reactive-presence")!=null}var St=[["persist",[gt,null,null,!0]],["defer",[ke,null]],["form",[bt,null]],["bindings",[yt,null,null,!0]],["compute",[vt,null,null,!0]],["sortable",[_t,null]],["presence",[xe,null]],["effects",[(e)=>["enter","update","exit"].some((t)=>e.getAttribute?.(`data-reactive-effect-${t}`)!=null),null]],["hints",[(e)=>e.querySelector?.("[data-reactive-optimistic-param], [data-reactive-busy-param], [data-reactive-loading-param]")!=null,null]],["devtools",[(e)=>e.getAttribute?.("data-reactive-debug")==="true",null]]],_=new Map(St),de=new Map,p=new Map,wt=new Map;function y(e,t,r){Re.set(e,[t,r]),At(e)}var Re=new Map;function At(e){let t=_.get(e),[r,n]=Re.get(e);t[1]=r,t[2]=n}function Jt(e,t){t.install?.(L),p.set(e,t),wt.set(e,t)}function Pe(e){let t=[];for(let[r,[n]]of _){if(!n||p.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function Ie(e){return E(e).catch((t)=>M(e,"load",t))}function E(e){let t=de.get(e);if(!t)t=(_.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(L),p.set(e,n),n)),de.set(e,t);return t}var fe=new Set;function M(e,t,r){let n=e+t;if(fe.has(n))return;fe.add(n),console.error(`[phlex-reactive] the "${e}" feature module (phlex/reactive/features/${e}) is unavailable: ${t}. If you bundle or vendor the client, alias or pin phlex/reactive/features/* (README: esbuild / webpack / bun).`,r)}function b(e,t){let r=p.get(e);if(r)return t(r);E(e).then(t,(n)=>M(e,"load",n))}var Tt=1e4;function K(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:Tt}function Kt(){return[..._.keys()]}var he=Promise.resolve();function me(e,t,r){let n=L.waiting.get(e);if(n&&n[t]===r)delete n[t]}var L={enter:_e,exit:Se,count:Te,text:F,served:Le,waiting:new WeakMap};var k=Symbol.for("phlex-reactive.early"),Et=1e4,Ft=1500,Ne=(e)=>e!=null&&(e===globalThis.window||e.window===e);function z(){return globalThis[k]??={queue:[],connected:new WeakSet},globalThis[k]}function Lt(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:Et}function kt(e){let t={};for(let{name:r,value:n}of Array.from(e.attributes??[])){let i=/^data-reactive-(.+)-param$/i.exec(r);if(!i)continue;let o;try{o=JSON.parse(n)}catch{o=n}t[i[1].replace(/[-_]([a-z0-9])/g,(a,s)=>s.toUpperCase())]=o}return t}function xt(e,t,r){return{[k]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:kt(t),key:e.key,code:e.code,metaKey:e.metaKey,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,button:e.button,submitter:e.submitter,bubbles:e.bubbles,timeStamp:e.timeStamp,defaultPrevented:e.defaultPrevented,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var C=new WeakMap;function Rt(e,{token:t,type:r,method:n,filter:i,win:o},a){let s=C.get(e);if(!s)C.set(e,s=new Map);let c=o?`${t} ${a}`:t;if(s.has(c))return!1;return s.set(c,{type:r,method:n,filter:i,win:o,params:a,armed:!0}),!0}function pe(e,t,r,n){if(e?.[k])return!1;let i=Ne(e?.currentTarget),o=i?n:e?.currentTarget,a=It(e,o,i?`@${t}`:t),s=C.get(o),c=i&&JSON.stringify(e.params);for(let l of s?.values()??[]){if(!l.armed||l.method!==t||l.type!==e.type||Boolean(l.win)!==i)continue;if(i&&l.params!==c)continue;if(l.filter&&!D(l.filter,e,r))continue;return l.armed=!1,!0}return a}var N=new WeakMap;function Pt(e,t,r){let n=N.get(e);if(!n)N.set(e,n=new Map),setTimeout(()=>N.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function It(e,t,r){let n=e&&N.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Oe extends Ce{static values={token:String};#_;#S=new Map;#l=new Map;#ee;#k;#j;#x=0;#d=new Map;#R=new WeakMap;#t;featuresReady=he;#r=new Map;#P=new Set;#f=!1;#n=null;#h=new Map;#w=new Map;#m=new Map;#p=0;#U;#Ne=0;#Oe=0;connect(){if(Fe=!0,z().connected.add(this.element),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-token-value")!=null||ke(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===P)this.#z();this.#J(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(P,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(Y),this.#p++,this.featuresReady=he,this.#J(),this.#ie()}#Me(e){}#Ce(e,t,r,n){}#De(){}#qe(e,t){}#J(e){{let t=this.#p,r=[];for(let[o,[a]]of _){if(!a||this.#P.has(o))continue;let s=p.get(o);if(s&&!s.connect)continue;try{if(a(this.element))r.push(o)}catch(c){this.#g(o,"detect",c)}}if(r.length===0)return;for(let o of r)this.#P.add(o);if(!this.#f&&r.every((o)=>p.has(o))){for(let o of r)this.#I(t,o,p.get(o),e);return}for(let o of r){let a=this.#te(t,o),s=[];for(let l of _.keys()){if(l===o)break;if(this.#m.has(l))s.push(this.#m.get(l))}let c=Promise.all(s).then(()=>a).then((l)=>l&&this.#I(t,o,l,e));if(this.#m.set(o,c),_.get(o)[3])this.#n=c}let n=this.#n;n?.then(()=>{if(this.#n===n)this.#n=null}),this.#f=!0;let i=Promise.all(this.#m.values()).then(()=>{if(this.featuresReady===i)this.#f=!1});this.featuresReady=i}}#te(e,t){{let r=()=>e===this.#p;return this.#re(t),new Promise((n)=>{let i=!1,o=setTimeout(()=>{if(this.#h.delete(o),i=!0,r())this.#g(t,"timeout",Error(`not loaded after ${K()} ms`));n(null)},K());this.#h.set(o,n);let a=()=>{clearTimeout(o),this.#h.delete(o)};E(t).then((s)=>{if(a(),i)queueMicrotask(()=>this.#I(e,t,s));else n(s)},(s)=>{if(a(),r())this.#g(t,"load",s);n(null)})})}}#re(e){{let t=_.get(e)[2];if(!t)return;let r={};try{this.#w.set(e,[t(this.element,r),r]),L.waiting.set(this.element,{...L.waiting.get(this.element),[e]:r})}catch(n){this.#g(e,"detect",n)}}}#K(e,t){{let[r,n]=this.#w.get(e)??[];if(this.#w.delete(e),!t)me(this.element,e,n);try{r?.()}catch(i){console.error(`[phlex-reactive] the "${e}" feature module failed to stop waiting`,i)}return n}}#I(e,t,r,n){{if(e!==this.#p)return;let i=this.#K(t);try{r.connect?.(this,this.#e(),n,i),this.#r.set(t,r)}catch(o){this.#g(t,"connect",o)}}}#e(){return this.#U??={emit:(e,t,r)=>this.#s(e,t,r),reseed:()=>this.#z(),proceed:(e,t,r,n)=>this.#O(e,t,r,0,0,null,n),forgetToken:()=>{this.#_=void 0},owns:(e)=>this.#F(e),ownership:()=>this.#D(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#B(e,t),applyOps:(e,t)=>V(e,(r)=>this.#W(t!=null&&r.to==null?{...r,to:t}:r),(r,n)=>this.#B(`client op "${r}"`,n)),listnavOptions:(e)=>this.#y(e),collectFields:()=>this.#X(),plain:be,text:F,served:Le,confirm:(e,t)=>Promise.resolve().then(()=>Z(e,t)).catch(()=>!1)},this.#U}#z(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#g(e,t,r){if(M(e,t,r),this.#i("feature"),t==="load"&&this.element.getAttribute?.("data-reactive-defer-pending"))this.element.removeAttribute("data-reactive-defer-pending"),this.element.removeAttribute("aria-busy");this.#s("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#ne(){{this.#p++;for(let[t,r]of this.#h)clearTimeout(t),r(null);this.#h.clear();for(let t of[...this.#w.keys()]){let r=this.#K(t,!0),n=this.element;b(t,(i)=>{i.abandon?.(n,r),me(n,t,r)})}this.#P.clear(),this.#m.clear(),this.#f=!1,this.#n=null;let e=[...this.#r];this.#r.clear();for(let[t,r]of e)try{r.disconnect?.(this,this.#e())}catch(n){console.error(`[phlex-reactive] the "${t}" feature module failed to disconnect`,n)}}}#ie(){if(this.element.setAttribute?.("data-reactive-connected",""),this.element.isConnected)this.element.dispatchEvent?.(new CustomEvent("reactive:connect",{bubbles:!0,composed:!0,detail:{id:this.element.id}}));this.#se()}#N=new Set;#se(){let{queue:e}=z();if(e.length===0)return;let t=[];for(let i=e.length-1;i>=0;i--){let{root:o}=e[i];if(o===this.element||!o.isConnected)t.unshift(...e.splice(i,1))}let r=Lt(),n=new Map;for(let i of t){let o=n.get(i.event)??[new Set,new Set];n.set(i.event,o);let a=o[+!!i.win];if(a.has(i.el))continue;a.add(i.el);let s=i.win?Math.min(Ft,r):r,c=i.root!==this.element?"its root left the page before a controller connected":performance.now()-i.at>s?`it is older than the ${s} ms ${i.win?"window-trigger":"early-event"} TTL`:i.el.isConnected&&this.element.contains(i.el)?null:"its element left the root before the controller connected";if(c){if(this.#$())console.warn(`[phlex-reactive] dropped an early "${i.event.type}" trigger: ${c}`);continue}this.#oe(i)}}#oe({event:e,el:t,descs:r,win:n}){let i=xt(e,t,n),o=this.application?.schema?.keyMappings,a=(t.getAttribute("data-action")??"").split(/\s+/),s=n?this.element:t;for(let c of r){if(!a.includes(c.token))continue;if(c.filter&&!D(c.filter,e,o))continue;if(/#\w+.*:once\b/.test(c.token)){if(!Rt(s,c,n&&JSON.stringify(i.params)))continue;this.#N.add(s)}if(Pt(e,s,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#ne(),this.#de(),this.#he(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(P,this.#t);z().connected.delete(this.element),this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#N)C.delete(e);this.#N.clear()}dispatch(e){if(pe(e,"dispatch",this.application?.schema?.keyMappings,this.element))return;let{action:t,params:r,debounce:n,throttle:i,confirm:o,confirmWhen:a,outside:s,window:c,optimistic:l,shortcut:d}=e.params;if(!t)return;if(d!=null&&!ae(d,e,this.application?.schema?.keyMappings))return;let m=e.params.busy??e.params.loading;if(s&&this.element.contains(e.target))return;let f=e.currentTarget??e.target;if((d!=null||!c)&&!this.#Ee(l,f))e.preventDefault();if(t===Ke){let w=()=>{{let h=this.#r.get("defer");if(h)return h.materialize(this)}if(this.tokenValue)return this.#O(f,t,"{}")};return this.#f?this.featuresReady.then(w):w()}let g=this.#H(o,a),v=()=>this.#O(f,t,r,n,i,l,m);if(!g)return v();if(g instanceof Promise)return g.then((w)=>w?this.#A(w,f,v):v());this.#A(g,f,v)}#A(e,t,r){return Promise.resolve().then(()=>Z(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#H(e,t){if(e)return e;if(!t)return null;{let r=p.get("bindings");if(r)return r.confirmMessage(this,this.#e(),t);return this.#V("bindings").then((n)=>n&&n.confirmMessage(this,this.#e(),t))}}#V(e){{let t;return Promise.race([E(e).catch((r)=>(M(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),K()))]).finally(()=>clearTimeout(t))}}runOps(e){if(pe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(mt(e,this))return;let t=e.params??{},r=e.currentTarget??e.target,n=dt(t.ops),i=n.filter((a)=>ce(a,e,null)),o=i.length<=1?i:i.filter((a)=>ce(a,e,this.application?.schema?.keyMappings));if(o.length===0&&n.length>0){if(this.#$())this.#v((a)=>a.noBinding(this,e));return}for(let a of o){if(a.outside&&e[k])continue;if(!ft(a,e))continue;if(a.shortcut!=null&&!ae(a.shortcut,e,this.application?.schema?.keyMappings))continue;if(ht(this,e,a))continue;this.#ae(a.legacy?{...t,ops:a.ops}:a,e,r)}}#ae({ops:e,confirm:t,confirmWhen:r,outside:n,window:i,shortcut:o},a,s){if(n&&this.element.contains(a.target))return;if(o!=null||!i)a.preventDefault();let c=this.#H(t,r),l=()=>this.#Te(this.#Ae(e));if(!c)return l();if(c instanceof Promise)return c.then((d)=>d?this.#A(d,s,l):l());this.#A(c,s,l)}recompute(e){return p.get("compute")?.recompute(this,this.#e(),e)}tagsAdd(e){if(e?.defaultPrevented)return;if(this.#y(e).some((t)=>t.hasAttribute?.("data-reactive-highlighted")))return;return this.#b("tagsAdd",e)}tagsPick(e){return this.#b("tagsPick",e)}tagsRemove(e){return this.#b("tagsRemove",e)}nestedAdd(e){return this.#b("nestedAdd",e)}nestedRemove(e){return this.#b("nestedRemove",e)}syncNestedJson(e){return p.get("bindings")?.syncNestedJson(this,this.#e(),e)}#b(e,t){{let r=p.get("bindings");if(r)return r[e](this,this.#e(),t);t?.preventDefault?.();let n={currentTarget:t?.currentTarget??null,target:t?.target??null,preventDefault(){}};return b("bindings",(i)=>i[e](this,this.#e(),n))}}trackDirty(){(this.#r.get("form")??p.get("form"))?.scan(this,this.#e())}listnavNext(e){this.#T(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#T(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#T(e,()=>0)}listnavLast(e){this.#T(e,(t,r)=>r-1)}listnavPick(e){let t=this.#y(e),r=t.findIndex((n)=>n.hasAttribute("data-reactive-highlighted"));if(r<0)return;e.preventDefault(),t[r].click()}listnavClose(e){for(let t of this.#y(e))t.removeAttribute("data-reactive-highlighted")}#T(e,t){let r=this.#y(e);if(!r.length)return;e.preventDefault();let n=this.#ce(e),i=globalThis.document?.activeElement,o=n?r.findIndex((s)=>s===i||i!=null&&s.contains?.(i)):r.findIndex((s)=>s.hasAttribute("data-reactive-highlighted")),a=r[t(o,r.length)];if(n)a.focus?.();else{for(let s of r)s.removeAttribute("data-reactive-highlighted");a.setAttribute("data-reactive-highlighted","true")}a.scrollIntoView?.({block:"nearest"})}#ce(e){return(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-focus-param")==="true"}#y(e){let r=(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!r)return[];let n=this.#D();return Array.from(this.element.querySelectorAll(r)).filter((i)=>!i.hidden&&n(i))}#O(e,t,r,n,i,o,a){if(this.#s("reactive:before-dispatch",{action:t,params:this.#Z(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#le(e,c,t,r,o,a);let l=Number(i)||0;if(l>0)return this.#fe(e,l,t,r,o,a);return this.#E(t,r,o,e,a)}#E(e,t,r,n,i){let o={inverse:null,undo:[],resurrect:null},a=this.#Fe(e,n,o),s=Boolean(r||i),c=(f)=>{if(!s||!f)return;let g=this.#e();if(o.inverse=f.optimistic(this,g,r,n),o.undo.push(...f.busy(this,g,i,n)),this.#C())o.resurrect=f.resurrection(this,g,r,n)},l=p.get("hints");if(!s||l)c(l);let d=()=>this.#be(e,t,o,a),m=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>s&&!l?this.#ue().then(c).then(m):m()),this.queue}#ue(){return this.#V("hints")}#le(e,t,r,n,i,o){this.#M(e);let a=()=>{this.#M(e),this.#E(r,n,i,e,o)},s=setTimeout(a,t);e?.addEventListener?.("blur",a,{once:!0}),this.#S.set(e,{timer:s,flush:a})}#M(e){let t=this.#S.get(e);if(!t)return;clearTimeout(t.timer),e?.removeEventListener?.("blur",t.flush),this.#S.delete(e)}#de(){for(let e of[...this.#S.keys()])this.#M(e)}#fe(e,t,r,n,i,o){let a=this.#l.get(e)??new Map;if(a.has(r))return;let s=setTimeout(()=>{if(a.delete(r),a.size===0)this.#l.delete(e)},t);return a.set(r,s),this.#l.set(e,a),this.#E(r,n,i,e,o)}#he(){for(let e of this.#l.values())for(let t of e.values())clearTimeout(t);this.#l.clear()}#s(e,t,{cancelable:r=!1}={}){let n=new CustomEvent(e,{bubbles:!0,composed:!0,cancelable:r,detail:t});return(this.element.isConnected?this.element:document).dispatchEvent(n),n}#o(e,t,r,n){let i=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#E(e,t)};this.#s("reactive:error",{action:e,params:r,...n,retry:i})}#i(e){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",e)}#me(){this.element?.removeAttribute?.("data-reactive-error")}#pe(){let e=document.querySelector("[data-reactive-error-flash]");if(!e?.content)return;let t=e.getAttribute("data-reactive-error-flash")||"flash",r=document.getElementById(t);if(!r)return;r.appendChild(e.content.cloneNode(!0))}#ge(){{let e=p.get("devtools");if(e)return e.delay();if(ye())return E("devtools").then((t)=>t.delay(),()=>{})}}#C(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#G(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}async#be(e,t,r,n){let{fields:i,files:o}=this.#X(),a=this.#Z(t),s={...i,...a},c=this.#a,l=o.length>0,d=l?this.#Se(c,e,s,o):JSON.stringify({token:c,act:e,params:s}),m=this.#C()?{action:e,paramNames:Object.keys(a),fieldNames:Object.keys(i),encoding:l?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#G()}:null;await this.#ge();try{if(navigator.onLine===!1){this.#c(r.inverse),this.#i("offline"),this.#o(e,t,s,{kind:"offline"});return}let f;try{let h={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#Pe()};if(!l)h["Content-Type"]="application/json";let T=this.#Ie();if(T)h["X-Pgbus-Connection"]=T;let x=xe(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(x)h["X-Reactive-Presence"]=x;Te("action"),f=await fetch(this.#xe(),{method:"POST",headers:h,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#Re())})}catch(h){if(console.error("[phlex-reactive] action error",h),this.#c(r.inverse),h?.name==="TimeoutError"||h?.name==="AbortError"){this.#i("timeout"),this.#o(e,t,s,{kind:"timeout"});return}this.#pe(),this.#i("network"),this.#o(e,t,s,{kind:"network"});return}if(m)m.status=f.status;if(f.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#c(r.inverse),this.#i("redirected"),this.#o(e,t,s,{kind:"redirected",status:f.status});return}if(!f.ok){let h=await f.text();if(console.error(`[phlex-reactive] action failed: HTTP ${f.status}`,h),this.#c(r.inverse),(f.headers.get("Content-Type")||"").includes("turbo-stream")){let T=this.#Y(h);if(this.#a=T??this.#a,m)this.#v((x)=>x.recordBody(m,h,T));window.Turbo.renderStreamMessage(h)}this.#i("http"),this.#o(e,t,s,{kind:"http",status:f.status,body:h});return}let g=f.headers.get("Content-Type")||"";if(!g.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${g}" — no update applied`),this.#c(r.inverse),this.#i("content-type"),this.#o(e,t,s,{kind:"content-type",status:f.status});return}let v=await f.text(),w=this.#Y(v);if(this.#a=w??this.#a,m)this.#v((h)=>h.recordBody(m,v,w));if(window.Turbo.renderStreamMessage(v),r.resurrect)queueMicrotask(r.resurrect);return this.#me(),this.#s("reactive:applied",{action:e,params:s,html:v}),v}catch(f){console.error("[phlex-reactive] action error",f),this.#c(r.inverse),this.#s("reactive:error",{action:e,params:s,kind:"apply"})}finally{if(n?.(),m)this.#v((f)=>f.trace(this,{...m,ms:this.#G()-m.started}))}}get#a(){return this.#_??this.tokenValue}set#a(e){this.#_=e}tokenValueChanged(){this.#_=void 0}#Y(e){let t=this.element.id;if(!t)return e.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:r,self:n}=this.#ye(t),i=e.match(r);if(i)return i[1];let o=e.match(n);if(o)return o[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#ye(e){let t=this.#j;if(t&&t.id===e)return t;let r=Ye(e);return this.#j={id:e,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${r}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${r}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#F(e){return e.closest('[data-controller~="reactive"]')===this.element}#D(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#F(t)}#X(){let e={},t=[],r=this.#D(),n=[];this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((s)=>{if(!r(s))return;if(s.type==="file")for(let c of s.files??[])t.push({name:s.name,file:c,multiple:s.multiple});else n.push(s)});let i=[];this.element.querySelectorAll(`[name]${rt}`).forEach((s)=>{if(r(s))i.push(s)});let o=this.#ve(n),a=this.#_e(n);for(let s of n)if(o.has(s.name)){let c=e[s.name]??(e[s.name]=[]);if(s.type==="checkbox"||s.type==="radio"){if(s.checked)c.push(s.value)}else if(s.type==="hidden"){if(!a.has(s.name))c.push(s.value)}else if(s.multiple&&s.options){for(let l of s.options)if(l.selected)c.push(l.value)}else c.push(s.value)}else if(s.type==="checkbox")e[s.name]=s.checked;else if(s.type==="radio"){if(s.checked)e[s.name]=s.value}else e[s.name]=s.value;return i.forEach((s)=>{let c=s.getAttribute("name");if(!c)return;let l=s.getAttribute("data-reactive-editable")!=null?F(s):s.value??s.textContent??s.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!it(s))return;if(String(c).endsWith("[]")&&(d===void 0||Array.isArray(d))){(Array.isArray(d)?d:e[c]=[]).push(l);return}if(d==null||d==="")e[c]=l}),{fields:e,files:t}}#ve(e){let t=new Set;for(let r of e){if(r.type==="radio")continue;if(String(r.name).endsWith("[]"))t.add(r.name)}return t}#_e(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#Se(e,t,r,n){let i=new FormData;i.append("token",e),i.append("act",t);let o=[];for(let[s,c]of Object.entries(r))if(Array.isArray(c)&&String(s).endsWith("[]"))if(c.length===0)o.push(String(s).slice(0,-2));else{let l=`${this.#L(s)}[]`;for(let d of c)i.append(l,String(d))}else this.#q(i,this.#L(s),c);for(let s of o)i.append("empty_groups[]",s);let a=this.#we(n);for(let{name:s,file:c,multiple:l}of n){let m=l||a.has(s)?`${this.#L(s)}[]`:this.#L(s);i.append(m,c,c.name)}return i}#L(e){let t=String(e),r=t.indexOf("[");if(r===-1)return`params[${t}]`;return`params${[t.slice(0,r),...t.slice(r).match(/[^\[\]]+/g)??[]].map((i)=>`[${i}]`).join("")}`}#q(e,t,r){if(r==null)e.append(t,"");else if(Array.isArray(r))r.forEach((n,i)=>this.#q(e,`${t}[${i}]`,n));else if(typeof r==="object")for(let[n,i]of Object.entries(r))this.#q(e,`${t}[${n}]`,i);else e.append(t,String(r))}#we(e){let t=new Map;for(let{name:r}of e)t.set(r,(t.get(r)??0)+1);return new Set([...t].filter(([,r])=>r>1).map(([r])=>r))}#Z(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#Ae(e){return X(e)}#Te(e){V(e,(t)=>this.#W(t),(t,r)=>this.#B(`client op "${t}"`,r))}#$(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#C()}#B(e,t){if(!this.#$())return;this.#v((r)=>r.diagnose(this,e,t))}#v(e){b("devtools",e)}#W(e){let t=e.to;if(t==="@root")return[this.element];if(typeof t!=="string"||t==="")return[];if(e.global)return[...document.querySelectorAll(t)];return[...this.element.querySelectorAll(t)].filter((r)=>this.#F(r))}#Ee(e,t){if(e?.checked!=="keep")return!1;let r=t?.type;return r==="checkbox"||r==="radio"}#c(e){if(!e)return;if(!this.element.isConnected)return;for(let t of e)t()}#Fe(e,t,r){this.#Le(e,t),_e();let n=!1;return()=>{if(n)return;n=!0,this.#ke(e,t),Se();for(let i of r.undo)i()}}#Le(e,t){if(this.#u(t,e,1),this.#u(this.element,e,1),this.#d.set(e,(this.#d.get(e)??0)+1),this.#x++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#Q(e))this.#u(r,e,1)}#ke(e,t){this.#u(t,e,-1),this.#u(this.element,e,-1);let r=(this.#d.get(e)??1)-1;if(r<=0)this.#d.delete(e);else this.#d.set(e,r);if(--this.#x<=0)this.#x=0,this.element.removeAttribute("aria-busy");for(let n of this.#Q(e))this.#u(n,e,-1)}#u(e,t,r){if(!e||typeof e.getAttribute!=="function")return;let n=this.#R.get(e)??new Map,i=(n.get(t)??0)+r;if(i<=0)n.delete(t);else n.set(t,i);if(n.size===0){this.#R.delete(e),e.removeAttribute("data-reactive-busy");return}this.#R.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#Q(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#F(r))}#xe(){return this.#ee??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#Re(){if(this.#k!=null)return this.#k;let e=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,t=Number(e);return this.#k=Number.isFinite(t)&&t>0?t:30000}#Pe(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#Ie(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}if(typeof window<"u")if(window.Turbo)ne();else document.addEventListener("turbo:load",ne,{once:!0});y("persist",()=>import("phlex/reactive/features/persist"),Nt);y("defer",()=>import("phlex/reactive/features/defer"));y("form",()=>import("phlex/reactive/features/form"));y("bindings",()=>import("phlex/reactive/features/bindings"));y("compute",()=>import("phlex/reactive/features/compute"),Ot);y("sortable",()=>import("phlex/reactive/features/sortable"));y("presence",()=>import("phlex/reactive/features/presence"));y("effects",()=>import("phlex/reactive/features/effects"));y("hints",()=>import("phlex/reactive/features/hints"));y("devtools",()=>import("phlex/reactive/features/devtools"));G();function Nt(e,t){let r=()=>{t.edited=!0},n=(o)=>{let a=o.target;if(o.detail?.success&&a?.tagName==="FORM"&&a.contains?.(e))t.submitted=!0},i=["input","change","lexxy:change","trix-change"];for(let o of i)e.addEventListener?.(o,r);return document.addEventListener("turbo:submit-end",n),()=>{for(let o of i)e.removeEventListener?.(o,r);document.removeEventListener("turbo:submit-end",n)}}function Ot(e,t){let r=()=>{t.edited=!0};return e.addEventListener?.("input",r),e.addEventListener?.("change",r),()=>{e.removeEventListener?.("input",r),e.removeEventListener?.("change",r)}}var Mt=1000,A=null,Me,q=new Set;function Ct(e){return Ie(e).then((t)=>{if(e!=="effects")return;Me=t,t?.sweep()})}ge((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,o=Pe(Dt(i)).filter((s)=>!q.has(s));if(!t&&!q.has("effects")&&qt(i))o.push("effects");if(o.length===0&&!A)return t?.wrap(e);if(o.length>0){for(let c of o)q.add(c);let s=A=Promise.race([Promise.all([A,...o.map(Ct)]),new Promise((c)=>setTimeout(c,Mt))]).then(()=>{if(A!==s)return;A=null,q.clear()})}let a=A;r.render=async(s)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??Me)?.wrap(c),await c.detail.render(s)}});function Dt(e){let t=e?.querySelector?.("template")?.content;if(!t)return[];let r=[...t.querySelectorAll?.('[data-controller~="reactive"]')??[]];for(let n of t.children??[])if(n.matches?.('[data-controller~="reactive"]')&&!r.includes(n))r.unshift(n);return r.push(t),r}function qt(e){return Boolean(e?.hasAttribute?.("data-reactive-effect")||document.getElementById?.(e?.getAttribute?.("target"))?.matches?.("[data-reactive-effect-update],[data-reactive-effect-exit]")||e?.querySelector?.("template")?.content?.querySelector?.("[data-reactive-effect-enter],[data-reactive-dismiss-after]")||document.querySelector?.("[data-reactive-dismiss-after]:not([data-reactive-dismiss-scheduled])"))}var Xt=Oe;export{ve as ACTIVE_ATTR,rt as EDITOR_SELECTOR,nt as EDITOR_TAGS,Ae as REQUESTS_ATTR,Xe as checkReactiveRegistration,Te as countReactiveRequest,Xt as default,F as editableValue,_e as enterReactiveActivity,Ye as escapeRegExp,Se as exitReactiveActivity,Ie as loadReactiveFeature,ge as onReactiveStreamWithoutEffects,jt as reactiveActivityCount,Kt as reactiveFeatureNames,ne as registerReactiveActions,Be as registerReactiveDefer,G as registerReactiveDev,We as registerReactiveDismiss,We as registerReactiveEffects,Jt as registerReactiveFeature,y as registerReactiveFeatureLoader,$e as registerReactiveJs,Je as registerReactiveMorphFocus,ze as registerReactiveOffline,Ue as registerReactivePlaintext,We as registerReactiveStreamRender,qe as registerReactiveToken,De as registerReactiveVisit,Ut as resetReactiveActivity,Le as serverText,Pe as unloadedFeaturesFor};
5
+ `).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var M=new WeakMap;function ee(e){if(e?.hasAttribute?.("data-reactive-editable")&&!M.has(e))M.set(e,F(e))}function Ne(e){return ee(e),M.get(e)}function ft(e){return dt.has(e.localName)?typeof e.value==="string":!0}var ue=Object.freeze({show:(e,t,r)=>J(e,!1,t,r),hide:(e,t,r)=>J(e,!0,t,r),toggle:(e,t,r)=>J(e,!e.hidden,t,r),add_class:(e,t)=>e.classList.add(...t.classes??[]),remove_class:(e,t)=>e.classList.remove(...t.classes??[]),toggle_class:(e,t)=>(t.classes??[]).forEach((r)=>e.classList.toggle(r)),set_attr:(e,t)=>{if(K(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(K(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!K(t.name))return;if(Array.isArray(t.values)){let[r,n]=t.values;e.setAttribute(t.name,e.getAttribute(t.name)===r?n:r)}else if(e.hasAttribute(t.name))e.removeAttribute(t.name);else e.setAttribute(t.name,"")},focus:(e)=>e.focus?.(),focus_first:(e)=>bt(e)?.focus?.(),show_modal:(e)=>_e(e),close_dialog:(e)=>Ge(e),text:(e,t)=>{let r=String(t.value??"");if(e.textContent!==r)e.textContent=r},check_group:(e,t)=>{let r=t.global?document.querySelectorAll('[data-controller~="reactive"]'):[e];for(let n of r)b("bindings",(i)=>i.checkGroup(n,t.group,t.checked))},presence:(e,t)=>b("presence",(r)=>r.set(e,t.state)),dispatch:(e,t)=>{e.dispatchEvent(new CustomEvent(t.name,{bubbles:!0,composed:!0,detail:t.detail??{}}))},submit:(e,t,r)=>{let n=ht(e);if(!n)return;let i=null;if(t?.submitter!=null&&typeof r==="function"){if(i=r({...t,to:t.submitter})[0]??null,!(i?.form===n&&(i.type==="submit"||i.type==="image")))console.warn(`[phlex-reactive] submitter ${t.submitter} is not a submit control of the form — ignored`),i=null}i?n.requestSubmit?.(i):n.requestSubmit?.()},paste_into:(e)=>mt(e),persist_state:(e,t)=>b("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>b("persist",(t)=>t.clearRoot(e))});function ht(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function mt(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;if(e.value=r,typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}));e.focus?.()}).catch(()=>{})}function pt(e,t,r){if(r?.transition)ct(e,r.transition,()=>e.hidden=t);else e.hidden=t}function J(e,t,r,n){if(pt(e,t,r),r?.expanded==null||typeof n!=="function")return;for(let i of n({...r,to:r.expanded}))i.setAttribute?.("aria-expanded",String(!t))}function K(e){if(!at(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}var gt='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function bt(e){return e.querySelectorAll?.(gt)?.[0]??null}function te(e){if(Array.isArray(e))return e;if(typeof e!=="string")return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}var le=Object.freeze({backspace:"Backspace",delete:"Delete",enter:"Enter",tab:"Tab",esc:"Escape",space:" ",up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight",home:"Home",end:"End",page_up:"PageUp",page_down:"PageDown"}),de=Object.freeze(["meta","ctrl","alt","shift"]);function q(e,t,r){let n=e.split("+");for(let a of de)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!de.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let o=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(le,i)?le[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof o==="string"&&o.toLowerCase()===t.key.toLowerCase()}var yt=(e)=>e&&typeof e==="object"?e.keys:String(e);function z(e,t,r){let n=t.target;if(e?.inEditable!==!0&&(n?.isContentEditable||/^(input|textarea|select)$/.test(n?.localName)))return!1;let i=/[Mm]ac|iP/.test(navigator.userAgentData?.platform??navigator.platform)?"meta":"ctrl";return q(yt(e).replace(/^mod\+/,`${i}+`),t,r)}function vt(e){if(Array.isArray(e))return[{ops:e,legacy:!0}];if(e&&typeof e==="object")return[e];if(typeof e!=="string")return[];let t=e.trim();if(t.startsWith("["))return[{ops:te(t),legacy:!0}];let r=[];for(let n of t.split(" ")){if(n==="")continue;let i=null;try{i=JSON.parse(n)}catch{i=null}if(i&&typeof i==="object"&&!Array.isArray(i))r.push(i);else console.warn(`[phlex-reactive] malformed on_client binding record ${JSON.stringify(n)} — skipped`)}return r}function fe(e,t,r){if(e.legacy)return!0;let n=e.on;if(typeof n!=="string"||n==="")return!1;let i=n.indexOf(".");if(t.type!==(i<0?n:n.slice(0,i)))return!1;if(Boolean(e.window)!==qe(t.currentTarget))return!1;return i<0||r===null||q(n.slice(i+1),t,r)}function _t(e,t){let r=e.detail;if(r===void 0)return!0;if(r===null||typeof r!=="object"||Array.isArray(r))return!1;let n=t.detail;if(n===null||typeof n!=="object")return!1;return Object.keys(r).every((i)=>n[i]===r[i])}var he=new WeakMap;function wt(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=he.get(e);if(!i)i=new WeakMap,he.set(e,i);let o=i.get(n);if(!o)o=new Set,i.set(n,o);let a=t.params?.ops,c=(n===globalThis.window?`${typeof a==="string"?a:JSON.stringify(a??null)}|`:"")+JSON.stringify(r);if(o.has(c))return!0;return o.add(c),!1}var me=new WeakMap;function St(e,t){if(e===null||typeof e!=="object")return!1;let r=e.params?.ops,n=typeof r==="string"?r:JSON.stringify(r??null),i=me.get(e);if(!i)i=new WeakMap,me.set(e,i);let o=i.get(t);if(!o)o=new Map,i.set(t,o);let a=o.get(e.currentTarget);if(!a)a=new Set,o.set(e.currentTarget,a);if(a.has(n))return!0;return a.add(n),!1}function Y(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,o={}]=n;if(!Object.hasOwn(ue,i)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(i)} — skipped`);continue}let a=t(o);if(a.length===0&&r)r(i,o);for(let s of a)ue[i](s,o,t)}}function At(e,t){let r=e.to;if(t){if(r==="@root")return[t];if(typeof r!=="string"||r==="")return[];if(e.global)return[...document.querySelectorAll(r)];return[...t.querySelectorAll(r)]}if(typeof r!=="string"||r===""||r==="@root")return[];return[...document.querySelectorAll(r)]}function Et(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function Ie(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}function Tt(e){return(e.getAttribute?.("data-action")??"").includes("reactive#trackDirty")||e.getAttribute?.("data-reactive-clipboard")!=null||e.querySelector?.('[data-action*="reactive#trackDirty"],[data-reactive-clipboard]')!=null}function Ft(e){return["show-targets","group-targets","on-complete","filter-input","tags-field"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)||(e.querySelectorAll?.("[data-reactive-show-field], [data-reactive-show]")??[]).length>0||e.querySelector?.("[data-reactive-nested-json], [data-reactive-nested-list], [data-reactive-confirm-when-param], [data-reactive-enable], [data-reactive-select-all], [data-reactive-count], [data-reactive-editable]")!=null}function Lt(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function kt(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function Oe(e){return e.getAttribute?.("data-reactive-presence")!=null}var xt=[["persist",[Et,null,null,!0]],["defer",[Ie,null]],["form",[Tt,null]],["bindings",[Ft,null,null,!0]],["compute",[Lt,null,null,!0]],["sortable",[kt,null]],["presence",[Oe,null]],["effects",[(e)=>["enter","update","exit"].some((t)=>e.getAttribute?.(`data-reactive-effect-${t}`)!=null),null]],["hints",[(e)=>e.querySelector?.("[data-reactive-optimistic-param], [data-reactive-busy-param], [data-reactive-loading-param]")!=null,null]],["devtools",[(e)=>e.getAttribute?.("data-reactive-debug")==="true",null]]],_=new Map(xt),pe=new Map,p=new Map,Rt=new Map;function y(e,t,r){Me.set(e,[t,r]),Pt(e)}var Me=new Map;function Pt(e){let t=_.get(e),[r,n]=Me.get(e);t[1]=r,t[2]=n}function Zt(e,t){t.install?.(L),p.set(e,t),Rt.set(e,t)}function Ce(e){let t=[];for(let[r,[n]]of _){if(!n||p.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function De(e){return T(e).catch((t)=>C(e,"load",t))}function T(e){let t=pe.get(e);if(!t)t=(_.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(L),p.set(e,n),n)),pe.set(e,t);return t}var ge=new Set;function C(e,t,r){let n=e+t;if(ge.has(n))return;ge.add(n),console.error(`[phlex-reactive] the "${e}" feature module (phlex/reactive/features/${e}) is unavailable: ${t}. If you bundle or vendor the client, alias or pin phlex/reactive/features/* (README: esbuild / webpack / bun).`,r)}function b(e,t){let r=p.get(e);if(r)return t(r);T(e).then(t,(n)=>C(e,"load",n))}var Nt=1e4;function H(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:Nt}function Qt(){return[..._.keys()]}var be=Promise.resolve();function ye(e,t,r){let n=L.waiting.get(e);if(n&&n[t]===r)delete n[t]}var L={enter:Te,exit:Fe,count:xe,text:F,served:Ne,waiting:new WeakMap};var k=Symbol.for("phlex-reactive.early"),It=1e4,Ot=1500,qe=(e)=>e!=null&&(e===globalThis.window||e.window===e);function G(){return globalThis[k]??={queue:[],connected:new WeakSet},globalThis[k]}function Mt(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:It}function Ct(e){let t={};for(let{name:r,value:n}of Array.from(e.attributes??[])){let i=/^data-reactive-(.+)-param$/i.exec(r);if(!i)continue;let o;try{o=JSON.parse(n)}catch{o=n}t[i[1].replace(/[-_]([a-z0-9])/g,(a,s)=>s.toUpperCase())]=o}return t}function Dt(e,t,r){return{[k]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:Ct(t),key:e.key,code:e.code,metaKey:e.metaKey,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,button:e.button,submitter:e.submitter,bubbles:e.bubbles,timeStamp:e.timeStamp,defaultPrevented:e.defaultPrevented,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var D=new WeakMap;function qt(e,{token:t,type:r,method:n,filter:i,win:o},a){let s=D.get(e);if(!s)D.set(e,s=new Map);let c=o?`${t} ${a}`:t;if(s.has(c))return!1;return s.set(c,{type:r,method:n,filter:i,win:o,params:a,armed:!0}),!0}function ve(e,t,r,n){if(e?.[k])return!1;let i=qe(e?.currentTarget),o=i?n:e?.currentTarget,a=Bt(e,o,i?`@${t}`:t),s=D.get(o),c=i&&JSON.stringify(e.params);for(let l of s?.values()??[]){if(!l.armed||l.method!==t||l.type!==e.type||Boolean(l.win)!==i)continue;if(i&&l.params!==c)continue;if(l.filter&&!q(l.filter,e,r))continue;return l.armed=!1,!0}return a}var I=new WeakMap;function $t(e,t,r){let n=I.get(e);if(!n)I.set(e,n=new Map),setTimeout(()=>I.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Bt(e,t,r){let n=e&&I.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class $e extends We{static values={token:String};#_;#w=new Map;#l=new Map;#ee;#k;#j;#x=0;#d=new Map;#R=new WeakMap;#t;featuresReady=be;#r=new Map;#P=new Set;#f=!1;#n=null;#h=new Map;#S=new Map;#m=new Map;#p=0;#U;#Ie=0;#Oe=0;connect(){if(Pe=!0,G().connected.add(this.element),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-token-value")!=null||Ie(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===P)this.#z();this.#J(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(P,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(ee),this.#p++,this.featuresReady=be,this.#J(),O(this.element),this.#ie()}#Me(e){}#Ce(e,t,r,n){}#De(){}#qe(e,t){}#J(e){{let t=this.#p,r=[];for(let[o,[a]]of _){if(!a||this.#P.has(o))continue;let s=p.get(o);if(s&&!s.connect)continue;try{if(a(this.element))r.push(o)}catch(c){this.#g(o,"detect",c)}}if(r.length===0)return;for(let o of r)this.#P.add(o);if(!this.#f&&r.every((o)=>p.has(o))){for(let o of r)this.#N(t,o,p.get(o),e);return}for(let o of r){let a=this.#te(t,o),s=[];for(let l of _.keys()){if(l===o)break;if(this.#m.has(l))s.push(this.#m.get(l))}let c=Promise.all(s).then(()=>a).then((l)=>l&&this.#N(t,o,l,e));if(this.#m.set(o,c),_.get(o)[3])this.#n=c}let n=this.#n;n?.then(()=>{if(this.#n===n)this.#n=null}),this.#f=!0;let i=Promise.all(this.#m.values()).then(()=>{if(this.featuresReady===i)this.#f=!1});this.featuresReady=i}}#te(e,t){{let r=()=>e===this.#p;return this.#re(t),new Promise((n)=>{let i=!1,o=setTimeout(()=>{if(this.#h.delete(o),i=!0,r())this.#g(t,"timeout",Error(`not loaded after ${H()} ms`));n(null)},H());this.#h.set(o,n);let a=()=>{clearTimeout(o),this.#h.delete(o)};T(t).then((s)=>{if(a(),i)queueMicrotask(()=>this.#N(e,t,s));else n(s)},(s)=>{if(a(),r())this.#g(t,"load",s);n(null)})})}}#re(e){{let t=_.get(e)[2];if(!t)return;let r={};try{this.#S.set(e,[t(this.element,r),r]),L.waiting.set(this.element,{...L.waiting.get(this.element),[e]:r})}catch(n){this.#g(e,"detect",n)}}}#K(e,t){{let[r,n]=this.#S.get(e)??[];if(this.#S.delete(e),!t)ye(this.element,e,n);try{r?.()}catch(i){console.error(`[phlex-reactive] the "${e}" feature module failed to stop waiting`,i)}return n}}#N(e,t,r,n){{if(e!==this.#p)return;let i=this.#K(t);try{r.connect?.(this,this.#e(),n,i),this.#r.set(t,r)}catch(o){this.#g(t,"connect",o)}}}#e(){return this.#U??={emit:(e,t,r)=>this.#s(e,t,r),reseed:()=>this.#z(),proceed:(e,t,r,n)=>this.#O(e,t,r,0,0,null,n),forgetToken:()=>{this.#_=void 0},owns:(e)=>this.#F(e),ownership:()=>this.#D(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#B(e,t),applyOps:(e,t)=>Y(e,(r)=>this.#W(t!=null&&r.to==null?{...r,to:t}:r),(r,n)=>this.#B(`client op "${r}"`,n)),listnavOptions:(e)=>this.#y(e),collectFields:()=>this.#X(),plain:Se,text:F,served:Ne,confirm:(e,t)=>Promise.resolve().then(()=>re(e,t)).catch(()=>!1)},this.#U}#z(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#g(e,t,r){if(C(e,t,r),this.#i("feature"),t==="load"&&this.element.getAttribute?.("data-reactive-defer-pending"))this.element.removeAttribute("data-reactive-defer-pending"),this.element.removeAttribute("aria-busy");this.#s("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#ne(){{this.#p++;for(let[t,r]of this.#h)clearTimeout(t),r(null);this.#h.clear();for(let t of[...this.#S.keys()]){let r=this.#K(t,!0),n=this.element;b(t,(i)=>{i.abandon?.(n,r),ye(n,t,r)})}this.#P.clear(),this.#m.clear(),this.#f=!1,this.#n=null;let e=[...this.#r];this.#r.clear();for(let[t,r]of e)try{r.disconnect?.(this,this.#e())}catch(n){console.error(`[phlex-reactive] the "${t}" feature module failed to disconnect`,n)}}}#ie(){if(this.element.setAttribute?.("data-reactive-connected",""),this.element.isConnected)this.element.dispatchEvent?.(new CustomEvent("reactive:connect",{bubbles:!0,composed:!0,detail:{id:this.element.id}}));this.#se()}#I=new Set;#se(){let{queue:e}=G();if(e.length===0)return;let t=[];for(let i=e.length-1;i>=0;i--){let{root:o}=e[i];if(o===this.element||!o.isConnected)t.unshift(...e.splice(i,1))}let r=Mt(),n=new Map;for(let i of t){let o=n.get(i.event)??[new Set,new Set];n.set(i.event,o);let a=o[+!!i.win];if(a.has(i.el))continue;a.add(i.el);let s=i.win?Math.min(Ot,r):r,c=i.root!==this.element?"its root left the page before a controller connected":performance.now()-i.at>s?`it is older than the ${s} ms ${i.win?"window-trigger":"early-event"} TTL`:i.el.isConnected&&this.element.contains(i.el)?null:"its element left the root before the controller connected";if(c){if(this.#$())console.warn(`[phlex-reactive] dropped an early "${i.event.type}" trigger: ${c}`);continue}this.#oe(i)}}#oe({event:e,el:t,descs:r,win:n}){let i=Dt(e,t,n),o=this.application?.schema?.keyMappings,a=(t.getAttribute("data-action")??"").split(/\s+/),s=n?this.element:t;for(let c of r){if(!a.includes(c.token))continue;if(c.filter&&!q(c.filter,e,o))continue;if(/#\w+.*:once\b/.test(c.token)){if(!qt(s,c,n&&JSON.stringify(i.params)))continue;this.#I.add(s)}if($t(e,s,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#ne(),this.#de(),this.#he(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(P,this.#t);G().connected.delete(this.element),this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)D.delete(e);this.#I.clear()}dispatch(e){let t=e.params?.shortcut;if(t!=null&&!z(t,e,this.application?.schema?.keyMappings))return;if(ve(e,"dispatch",this.application?.schema?.keyMappings,this.element))return;let{action:r,params:n,debounce:i,throttle:o,confirm:a,confirmWhen:s,outside:c,window:l,optimistic:d}=e.params;if(!r)return;let m=e.params.busy??e.params.loading;if(c&&this.element.contains(e.target))return;let f=e.currentTarget??e.target;if((t!=null||!l)&&!this.#Te(d,f))e.preventDefault();if(r===Qe){let S=()=>{{let h=this.#r.get("defer");if(h)return h.materialize(this)}if(this.tokenValue)return this.#O(f,r,"{}")};return this.#f?this.featuresReady.then(S):S()}let g=this.#H(a,s),v=()=>this.#O(f,r,n,i,o,d,m);if(!g)return v();if(g instanceof Promise)return g.then((S)=>S?this.#A(S,f,v):v());this.#A(g,f,v)}#A(e,t,r){return Promise.resolve().then(()=>re(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#H(e,t){if(e)return e;if(!t)return null;{let r=p.get("bindings");if(r)return r.confirmMessage(this,this.#e(),t);return this.#G("bindings").then((n)=>n&&n.confirmMessage(this,this.#e(),t))}}#G(e){{let t;return Promise.race([T(e).catch((r)=>(C(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),H()))]).finally(()=>clearTimeout(t))}}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!z(t.shortcut,e,this.application?.schema?.keyMappings))return;if(ve(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(St(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=vt(r.ops),o=i.filter((s)=>fe(s,e,null)),a=o.length<=1?o:o.filter((s)=>fe(s,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#$())this.#v((s)=>s.noBinding(this,e));return}for(let s of a){if(s.outside&&e[k])continue;if(!_t(s,e))continue;if(s.shortcut!=null&&!z(s.shortcut,e,this.application?.schema?.keyMappings))continue;if(wt(this,e,s))continue;this.#ae(s.legacy?{...r,ops:s.ops}:s,e,n)}}#ae({ops:e,confirm:t,confirmWhen:r,outside:n,window:i,shortcut:o},a,s){if(n&&this.element.contains(a.target))return;if(o!=null||!i)a.preventDefault();let c=this.#H(t,r),l=()=>this.#Ee(this.#Ae(e));if(!c)return l();if(c instanceof Promise)return c.then((d)=>d?this.#A(d,s,l):l());this.#A(c,s,l)}recompute(e){return p.get("compute")?.recompute(this,this.#e(),e)}tagsAdd(e){if(e?.defaultPrevented)return;if(this.#y(e).some((t)=>t.hasAttribute?.("data-reactive-highlighted")))return;return this.#b("tagsAdd",e)}tagsPick(e){return this.#b("tagsPick",e)}tagsRemove(e){return this.#b("tagsRemove",e)}nestedAdd(e){return this.#b("nestedAdd",e)}nestedRemove(e){return this.#b("nestedRemove",e)}syncNestedJson(e){return p.get("bindings")?.syncNestedJson(this,this.#e(),e)}#b(e,t){{let r=p.get("bindings");if(r)return r[e](this,this.#e(),t);t?.preventDefault?.();let n={currentTarget:t?.currentTarget??null,target:t?.target??null,preventDefault(){}};return b("bindings",(i)=>i[e](this,this.#e(),n))}}trackDirty(){(this.#r.get("form")??p.get("form"))?.scan(this,this.#e())}listnavNext(e){this.#E(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#E(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#E(e,()=>0)}listnavLast(e){this.#E(e,(t,r)=>r-1)}listnavPick(e){let t=this.#y(e),r=t.findIndex((n)=>n.hasAttribute("data-reactive-highlighted"));if(r<0)return;e.preventDefault(),t[r].click()}listnavClose(e){for(let t of this.#y(e))t.removeAttribute("data-reactive-highlighted")}#E(e,t){let r=this.#y(e);if(!r.length)return;e.preventDefault();let n=this.#ce(e),i=globalThis.document?.activeElement,o=n?r.findIndex((s)=>s===i||i!=null&&s.contains?.(i)):r.findIndex((s)=>s.hasAttribute("data-reactive-highlighted")),a=r[t(o,r.length)];if(n)a.focus?.();else{for(let s of r)s.removeAttribute("data-reactive-highlighted");a.setAttribute("data-reactive-highlighted","true")}a.scrollIntoView?.({block:"nearest"})}#ce(e){return(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-focus-param")==="true"}#y(e){let r=(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-option-param")??this.element.getAttribute("data-reactive-listnav-option-param");if(!r)return[];let n=this.#D();return Array.from(this.element.querySelectorAll(r)).filter((i)=>!i.hidden&&n(i))}#O(e,t,r,n,i,o,a){if(this.#s("reactive:before-dispatch",{action:t,params:this.#Z(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#le(e,c,t,r,o,a);let l=Number(i)||0;if(l>0)return this.#fe(e,l,t,r,o,a);return this.#T(t,r,o,e,a)}#T(e,t,r,n,i){let o={inverse:null,undo:[],resurrect:null},a=this.#Fe(e,n,o),s=Boolean(r||i),c=(f)=>{if(!s||!f)return;let g=this.#e();if(o.inverse=f.optimistic(this,g,r,n),o.undo.push(...f.busy(this,g,i,n)),this.#C())o.resurrect=f.resurrection(this,g,r,n)},l=p.get("hints");if(!s||l)c(l);let d=()=>this.#be(e,t,o,a),m=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>s&&!l?this.#ue().then(c).then(m):m()),this.queue}#ue(){return this.#G("hints")}#le(e,t,r,n,i,o){this.#M(e);let a=()=>{this.#M(e),this.#T(r,n,i,e,o)},s=setTimeout(a,t);e?.addEventListener?.("blur",a,{once:!0}),this.#w.set(e,{timer:s,flush:a})}#M(e){let t=this.#w.get(e);if(!t)return;clearTimeout(t.timer),e?.removeEventListener?.("blur",t.flush),this.#w.delete(e)}#de(){for(let e of[...this.#w.keys()])this.#M(e)}#fe(e,t,r,n,i,o){let a=this.#l.get(e)??new Map;if(a.has(r))return;let s=setTimeout(()=>{if(a.delete(r),a.size===0)this.#l.delete(e)},t);return a.set(r,s),this.#l.set(e,a),this.#T(r,n,i,e,o)}#he(){for(let e of this.#l.values())for(let t of e.values())clearTimeout(t);this.#l.clear()}#s(e,t,{cancelable:r=!1}={}){let n=new CustomEvent(e,{bubbles:!0,composed:!0,cancelable:r,detail:t});return(this.element.isConnected?this.element:document).dispatchEvent(n),n}#o(e,t,r,n){let i=()=>{if(!this.element.isConnected){console.warn("[phlex-reactive] retry() ignored — the reactive root left the DOM");return}return this.#T(e,t)};this.#s("reactive:error",{action:e,params:r,...n,retry:i})}#i(e){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",e)}#me(){this.element?.removeAttribute?.("data-reactive-error")}#pe(){let e=document.querySelector("[data-reactive-error-flash]");if(!e?.content)return;let t=e.getAttribute("data-reactive-error-flash")||"flash",r=document.getElementById(t);if(!r)return;r.appendChild(e.content.cloneNode(!0))}#ge(){{let e=p.get("devtools");if(e)return e.delay();if(Ae())return T("devtools").then((t)=>t.delay(),()=>{})}}#C(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#V(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}async#be(e,t,r,n){let{fields:i,files:o}=this.#X(),a=this.#Z(t),s={...i,...a},c=this.#a,l=o.length>0,d=l?this.#we(c,e,s,o):JSON.stringify({token:c,act:e,params:s}),m=this.#C()?{action:e,paramNames:Object.keys(a),fieldNames:Object.keys(i),encoding:l?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#V()}:null;await this.#ge();try{if(navigator.onLine===!1){this.#c(r.inverse),this.#i("offline"),this.#o(e,t,s,{kind:"offline"});return}let f;try{let h={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#Pe()};if(!l)h["Content-Type"]="application/json";let E=this.#Ne();if(E)h["X-Pgbus-Connection"]=E;let x=Oe(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(x)h["X-Reactive-Presence"]=x;xe("action"),f=await fetch(this.#xe(),{method:"POST",headers:h,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#Re())})}catch(h){if(console.error("[phlex-reactive] action error",h),this.#c(r.inverse),h?.name==="TimeoutError"||h?.name==="AbortError"){this.#i("timeout"),this.#o(e,t,s,{kind:"timeout"});return}this.#pe(),this.#i("network"),this.#o(e,t,s,{kind:"network"});return}if(m)m.status=f.status;if(f.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#c(r.inverse),this.#i("redirected"),this.#o(e,t,s,{kind:"redirected",status:f.status});return}if(!f.ok){let h=await f.text();if(console.error(`[phlex-reactive] action failed: HTTP ${f.status}`,h),this.#c(r.inverse),(f.headers.get("Content-Type")||"").includes("turbo-stream")){let E=this.#Y(h);if(this.#a=E??this.#a,m)this.#v((x)=>x.recordBody(m,h,E));window.Turbo.renderStreamMessage(h)}this.#i("http"),this.#o(e,t,s,{kind:"http",status:f.status,body:h});return}let g=f.headers.get("Content-Type")||"";if(!g.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${g}" — no update applied`),this.#c(r.inverse),this.#i("content-type"),this.#o(e,t,s,{kind:"content-type",status:f.status});return}let v=await f.text(),S=this.#Y(v);if(this.#a=S??this.#a,m)this.#v((h)=>h.recordBody(m,v,S));if(window.Turbo.renderStreamMessage(v),r.resurrect)queueMicrotask(r.resurrect);return this.#me(),this.#s("reactive:applied",{action:e,params:s,html:v}),v}catch(f){console.error("[phlex-reactive] action error",f),this.#c(r.inverse),this.#s("reactive:error",{action:e,params:s,kind:"apply"})}finally{if(n?.(),m)this.#v((f)=>f.trace(this,{...m,ms:this.#V()-m.started}))}}get#a(){return this.#_??this.tokenValue}set#a(e){this.#_=e}tokenValueChanged(){this.#_=void 0}#Y(e){let t=this.element.id;if(!t)return e.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:r,self:n}=this.#ye(t),i=e.match(r);if(i)return i[1];let o=e.match(n);if(o)return o[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#ye(e){let t=this.#j;if(t&&t.id===e)return t;let r=it(e);return this.#j={id:e,token:new RegExp(`<turbo-stream\\b[^>]*\\baction="reactive:token"[^>]*\\btarget="${r}"[^>]*\\bdata-reactive-token-value="([^"]+)"`),self:new RegExp(`<turbo-stream\\b[^>]*\\baction="(?:replace|update)"[^>]*\\btarget="${r}"[^>]*>([\\s\\S]*?)</turbo-stream>`)}}#F(e){return e.closest('[data-controller~="reactive"]')===this.element}#D(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#F(t)}#X(){let e={},t=[],r=this.#D(),n=[];this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((s)=>{if(!r(s))return;if(s.type==="file")for(let c of s.files??[])t.push({name:s.name,file:c,multiple:s.multiple});else n.push(s)});let i=[];this.element.querySelectorAll(`[name]${lt}`).forEach((s)=>{if(r(s))i.push(s)});let o=this.#ve(n),a=this.#_e(n);for(let s of n)if(o.has(s.name)){let c=e[s.name]??(e[s.name]=[]);if(s.type==="checkbox"||s.type==="radio"){if(s.checked)c.push(s.value)}else if(s.type==="hidden"){if(!a.has(s.name))c.push(s.value)}else if(s.multiple&&s.options){for(let l of s.options)if(l.selected)c.push(l.value)}else c.push(s.value)}else if(s.type==="checkbox")e[s.name]=s.checked;else if(s.type==="radio"){if(s.checked)e[s.name]=s.value}else e[s.name]=s.value;return i.forEach((s)=>{let c=s.getAttribute("name");if(!c)return;let l=s.getAttribute("data-reactive-editable")!=null?F(s):s.value??s.textContent??s.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!ft(s))return;if(String(c).endsWith("[]")&&(d===void 0||Array.isArray(d))){(Array.isArray(d)?d:e[c]=[]).push(l);return}if(d==null||d==="")e[c]=l}),{fields:e,files:t}}#ve(e){let t=new Set;for(let r of e){if(r.type==="radio")continue;if(String(r.name).endsWith("[]"))t.add(r.name)}return t}#_e(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#we(e,t,r,n){let i=new FormData;i.append("token",e),i.append("act",t);let o=[];for(let[s,c]of Object.entries(r))if(Array.isArray(c)&&String(s).endsWith("[]"))if(c.length===0)o.push(String(s).slice(0,-2));else{let l=`${this.#L(s)}[]`;for(let d of c)i.append(l,String(d))}else this.#q(i,this.#L(s),c);for(let s of o)i.append("empty_groups[]",s);let a=this.#Se(n);for(let{name:s,file:c,multiple:l}of n){let m=l||a.has(s)?`${this.#L(s)}[]`:this.#L(s);i.append(m,c,c.name)}return i}#L(e){let t=String(e),r=t.indexOf("[");if(r===-1)return`params[${t}]`;return`params${[t.slice(0,r),...t.slice(r).match(/[^\[\]]+/g)??[]].map((i)=>`[${i}]`).join("")}`}#q(e,t,r){if(r==null)e.append(t,"");else if(Array.isArray(r))r.forEach((n,i)=>this.#q(e,`${t}[${i}]`,n));else if(typeof r==="object")for(let[n,i]of Object.entries(r))this.#q(e,`${t}[${n}]`,i);else e.append(t,String(r))}#Se(e){let t=new Map;for(let{name:r}of e)t.set(r,(t.get(r)??0)+1);return new Set([...t].filter(([,r])=>r>1).map(([r])=>r))}#Z(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#Ae(e){return te(e)}#Ee(e){Y(e,(t)=>this.#W(t),(t,r)=>this.#B(`client op "${t}"`,r))}#$(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#C()}#B(e,t){if(!this.#$())return;this.#v((r)=>r.diagnose(this,e,t))}#v(e){b("devtools",e)}#W(e){let t=e.to;if(t==="@root")return[this.element];if(typeof t!=="string"||t==="")return[];if(e.global)return[...document.querySelectorAll(t)];return[...this.element.querySelectorAll(t)].filter((r)=>this.#F(r))}#Te(e,t){if(e?.checked!=="keep")return!1;let r=t?.type;return r==="checkbox"||r==="radio"}#c(e){if(!e)return;if(!this.element.isConnected)return;for(let t of e)t()}#Fe(e,t,r){this.#Le(e,t),Te();let n=!1;return()=>{if(n)return;n=!0,this.#ke(e,t),Fe();for(let i of r.undo)i()}}#Le(e,t){if(this.#u(t,e,1),this.#u(this.element,e,1),this.#d.set(e,(this.#d.get(e)??0)+1),this.#x++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#Q(e))this.#u(r,e,1)}#ke(e,t){this.#u(t,e,-1),this.#u(this.element,e,-1);let r=(this.#d.get(e)??1)-1;if(r<=0)this.#d.delete(e);else this.#d.set(e,r);if(--this.#x<=0)this.#x=0,this.element.removeAttribute("aria-busy");for(let n of this.#Q(e))this.#u(n,e,-1)}#u(e,t,r){if(!e||typeof e.getAttribute!=="function")return;let n=this.#R.get(e)??new Map,i=(n.get(t)??0)+r;if(i<=0)n.delete(t);else n.set(t,i);if(n.size===0){this.#R.delete(e),e.removeAttribute("data-reactive-busy");return}this.#R.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#Q(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#F(r))}#xe(){return this.#ee??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#Re(){if(this.#k!=null)return this.#k;let e=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,t=Number(e);return this.#k=Number.isFinite(t)&&t>0?t:30000}#Pe(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#Ne(){return document.querySelector("pgbus-stream-source[connection-id]")?.getAttribute("connection-id")||document.querySelector('meta[name="pgbus-connection-id"]')?.content||null}}if(typeof window<"u")if(window.Turbo)ce();else document.addEventListener("turbo:load",ce,{once:!0});y("persist",()=>import("phlex/reactive/features/persist"),Wt);y("defer",()=>import("phlex/reactive/features/defer"));y("form",()=>import("phlex/reactive/features/form"));y("bindings",()=>import("phlex/reactive/features/bindings"));y("compute",()=>import("phlex/reactive/features/compute"),jt);y("sortable",()=>import("phlex/reactive/features/sortable"));y("presence",()=>import("phlex/reactive/features/presence"));y("effects",()=>import("phlex/reactive/features/effects"));y("hints",()=>import("phlex/reactive/features/hints"));y("devtools",()=>import("phlex/reactive/features/devtools"));Q();function Wt(e,t){let r=()=>{t.edited=!0},n=(o)=>{let a=o.target;if(o.detail?.success&&a?.tagName==="FORM"&&a.contains?.(e))t.submitted=!0},i=["input","change","lexxy:change","trix-change"];for(let o of i)e.addEventListener?.(o,r);return document.addEventListener("turbo:submit-end",n),()=>{for(let o of i)e.removeEventListener?.(o,r);document.removeEventListener("turbo:submit-end",n)}}function jt(e,t){let r=()=>{t.edited=!0};return e.addEventListener?.("input",r),e.addEventListener?.("change",r),()=>{e.removeEventListener?.("input",r),e.removeEventListener?.("change",r)}}var Ut=1000,A=null,Be,B=new Set;function Jt(e){return De(e).then((t)=>{if(e!=="effects")return;Be=t,t?.sweep()})}we((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,o=Ce(Kt(i)).filter((s)=>!B.has(s));if(!t&&!B.has("effects")&&zt(i))o.push("effects");if(o.length===0&&!A)return t?.wrap(e);if(o.length>0){for(let c of o)B.add(c);let s=A=Promise.race([Promise.all([A,...o.map(Jt)]),new Promise((c)=>setTimeout(c,Ut))]).then(()=>{if(A!==s)return;A=null,B.clear()})}let a=A;r.render=async(s)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??Be)?.wrap(c),await c.detail.render(s)}});function Kt(e){let t=e?.querySelector?.("template")?.content;if(!t)return[];let r=[...t.querySelectorAll?.('[data-controller~="reactive"]')??[]];for(let n of t.children??[])if(n.matches?.('[data-controller~="reactive"]')&&!r.includes(n))r.unshift(n);return r.push(t),r}function zt(e){return Boolean(e?.hasAttribute?.("data-reactive-effect")||document.getElementById?.(e?.getAttribute?.("target"))?.matches?.("[data-reactive-effect-update],[data-reactive-effect-exit]")||e?.querySelector?.("template")?.content?.querySelector?.("[data-reactive-effect-enter],[data-reactive-dismiss-after]")||document.querySelector?.("[data-reactive-dismiss-after]:not([data-reactive-dismiss-scheduled])"))}var sr=$e;export{Ee as ACTIVE_ATTR,lt as EDITOR_SELECTOR,dt as EDITOR_TAGS,ke as REQUESTS_ATTR,st as checkReactiveRegistration,xe as countReactiveRequest,sr as default,F as editableValue,Te as enterReactiveActivity,it as escapeRegExp,Fe as exitReactiveActivity,De as loadReactiveFeature,we as onReactiveStreamWithoutEffects,Yt as reactiveActivityCount,Qt as reactiveFeatureNames,ce as registerReactiveActions,Ke as registerReactiveDefer,Q as registerReactiveDev,ze as registerReactiveDismiss,ze as registerReactiveEffects,Zt as registerReactiveFeature,y as registerReactiveFeatureLoader,Je as registerReactiveJs,Ye as registerReactiveModals,Ze as registerReactiveMorphFocus,et as registerReactiveOffline,Xe as registerReactivePlaintext,ze as registerReactiveStreamRender,Ue as registerReactiveToken,je as registerReactiveVisit,Xt as resetReactiveActivity,Ne as serverText,Ce as unloadedFeaturesFor};
6
6
 
7
- //# debugId=5A39010F1CEBA74764756E2164756E21
7
+ //# debugId=33F26A90370DFFF564756E2164756E21
8
8
  //# sourceMappingURL=core.min.js.map