phlex-reactive 0.15.2 → 0.15.3

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: 7dd7744e88ad5a6633b0bce1b77232cb143909f65daf878150eb1750389ccae2
4
- data.tar.gz: 853207f674648c4aa58d48fdfcd39db5b58eb887f557958b4b9791049dcd5d9a
3
+ metadata.gz: 2fb24b631e6cd4fec31a0635a1d522f3b3423cdf67ad1e41eecb279fcc1c279b
4
+ data.tar.gz: 82f859da94e60c3a691d3b39a9aa51ead6e52fc44c3ead8b32d23b1f5b079143
5
5
  SHA512:
6
- metadata.gz: 36328a18b6289fba46a228b5864021645e9487dbf4164937c25c6eaef468bb22ee347e9774b30c74028e3ce9c6fd144aa57ba699a7b6f113279ee8b91b1bee3b
7
- data.tar.gz: 9ce053b691b4c5ae42d0c149d01183ff7646a3985467bbeeb67c18f7eb2512acee6cf129d0bb726e2cff6825f0708bfbfc0874b1212f621731c3f4efe7dce2d9
6
+ metadata.gz: 03f24931aedcb275d1e938ededb4adfb0820660114373a96187999c3eaeb30fc532a26b6aee61dc4eb222ddb06accaf2f1c0242d8296329b8a55cf0bf3f5b836
7
+ data.tar.gz: 4afa1a62e2872e6ba17394e342d41aa129d9377a1cfe47681f28f18c6caa3fefa0f5e19a94cd1b503048a7219b4e771eb5a4abbb72337b2f4a99bf99f5d1fb82
data/CHANGELOG.md CHANGED
@@ -8,12 +8,32 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
9
  ### Added
10
10
 
11
+ - **An image fallback that recovers — `reactive_image_fallback(hide: true, show_alt: nil)` (#383).**
12
+ `img(**reactive_image_fallback)` marks an `<img>` whose `src` fails with
13
+ `data-reactive-image-state="error"` and hides it; `show_alt: "#bank-name"`
14
+ also writes its `alt` (as `textContent`) into that node inside the root and
15
+ shows it; `hide: false` only sets the state, for CSS. `load` sets
16
+ `"loaded"`. A later `src` tries again: `copy_media`, `reactive_media` and
17
+ `preview_file` clear the error as they write the `src`, any `src` that loads
18
+ clears it, and a morph that changes the `src` lets the browser retry (one
19
+ that keeps it keeps the state). Removing the `src` is not an error. Only the
20
+ `hidden` the fallback added is ever removed. Composes with `reactive_media`
21
+ (`reactive_media(…, **reactive_image_fallback)`). The client listens once on
22
+ the document in the capture phase (`error`/`load` do not bubble) and reads
23
+ images that failed before it registered; nothing runs per root at connect.
24
+ No URL in any argument; `set_attr` still refuses `src`/`srcset`. `hide:`
25
+ that is not a boolean, or a `show_alt:` that is not a non-blank String (or
26
+ is `@root`), raises at render; a String that is not a valid CSS selector is
27
+ ignored by the client. Client: +597 B gzipped in the default bundle,
28
+ +550 B in the split core. Docs: "An image that falls back, and recovers" on
29
+ the client-ops example.
30
+
11
31
  - **Media previews — `js.copy_media` and `reactive_media` (#373).**
12
32
  `js.copy_media("#logo", from: "#logo-007")` copies `src`, `srcset` and `alt`
13
33
  from an `<img>` the server rendered onto a preview `<img>`; the URL is read
14
34
  from the live source element and is never an op argument, so `set_attr`
15
- still refuses `src` (#96). A missing source, a non-`<img>` source or one
16
- without `src` clears the target; a target that is not an `<img>` (an
35
+ still refuses `src` (#96). A missing source or a non-`<img>` source clears
36
+ the target (an `<img>` source without `src` keeps its `alt`, #381); a target that is not an `<img>` (an
17
37
  `iframe`, `script`, `object`, `embed`, `frame`) is warned about and skipped;
18
38
  the same URL twice is not written again. `img(**reactive_media(from: :code,
19
39
  take: 3, pool: { "007" => "#logo-007" }, label: "#caption", blank_label:
@@ -215,6 +235,48 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
215
235
 
216
236
  ### Fixed
217
237
 
238
+ - **`reactive_media` waits for `take` characters before calling a key a miss
239
+ (#380).** A value shorter than `take:` sliced to a short key, missed the
240
+ pool and wrote `blank_label` while the user was still typing. It is now
241
+ *pending*: `blank_label` only names a full-length key that misses. New
242
+ options: `match:` (a Regexp, anchored to the whole key; a key it rejects is
243
+ pending too) and `pending: :clear` (default: clear the preview, empty the
244
+ label) or `:keep` (leave both alone). The preview carries
245
+ `data-reactive-media-state="pending|hit|miss"`, so a row can hide itself
246
+ with CSS. `match:` reaches the browser as a JS pattern: its `\A`/`\z`
247
+ anchors are dropped (a trailing `\Z` becomes `\n?`), and what JS reads
248
+ differently raises at render (options, escapes such as `\h`/`\p{…}`/`\s`/
249
+ `\u{…}`, POSIX and nested classes, `&&`, `(?i)`/`(?>…)`, characters above
250
+ U+FFFF). **Behaviour change:** with `take:`, a short value now leaves the
251
+ label empty instead of writing `blank_label`. Without `take:` or `match:`
252
+ nothing changes. Client: +160 B gzipped in the default bundle (+152 B on
253
+ top of #381/#382), +152 B in the bindings module, the split core unchanged. Docs: "Media
254
+ previews" on the client-ops example.
255
+
256
+ - **A pool `<img>` with an `alt` and no `src` keeps its name (#381).**
257
+ `js.copy_media` and `reactive_media` treated a source `<img>` without `src`
258
+ as a clear: the preview's `alt` was emptied and `label:` got `blank_label`,
259
+ so a known entry with no logo file lost its name. Such a source is now a hit
260
+ without an image: the target's `src` and `srcset` are removed, its `alt` is
261
+ set, and `label:` gets that `alt`. Only a pool miss, a selector that matches
262
+ nothing, or a source that is not an `<img>` clears. Client: +1 B gzipped in
263
+ the default bundle, −2 B in the split core; the bindings module is
264
+ unchanged.
265
+
266
+ - **`js.preview_file` follows an app's upload validation (#382).** A preview
267
+ ran once, on `change`, so a file the app then rejected (cleared with
268
+ `input.value = ""`, no new `change`) stayed on screen. Two pieces fix it.
269
+ `js.preview_file(…, valid: true)` treats an input whose `validity.valid` is
270
+ false (`setCustomValidity`, `required`) as empty: it never gets a preview,
271
+ and one it had is cleared and its URL revoked. And `reactive:file-changed`
272
+ is the documented event for "the app changed this input's files without a
273
+ `change` event": bind the op to it as well,
274
+ `mix(on_client(:change, op), on_client("reactive:file-changed", op))`, and
275
+ the app dispatches it after it clears or invalidates the field. That works
276
+ whichever `change` listener runs first. Without `valid:` the op behaves as
277
+ before. Client: +22 B gzipped in the default bundle, +34 B in the split
278
+ core (on top of #381). Docs: "Preview a chosen image" on the client-ops example.
279
+
218
280
  - **A stream that renders into a connected root wires what its content needs
219
281
  (#356).** A root read its feature markers only at connect and after a morph
220
282
  of itself, so a `reactive_show` target, select-all/count group, filter,
@@ -251,6 +313,43 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
251
313
  first paint already were. A target with any value term keeps the skip when
252
314
  none of its fields is owned.
253
315
 
316
+ ### Performance
317
+
318
+ - **Guarded and persisted forms connect in linear time.** Each `warn_unsaved`
319
+ root added its own `beforeunload` / `turbo:before-visit` pair on `window`,
320
+ and each persisted root its own `turbo:submit-end` listener on `document`.
321
+ A browser scans a target's listeners on every add and remove, so connecting
322
+ and disconnecting N of them was quadratic. One shared listener per window or
323
+ document now serves them all, added with the first root and removed with
324
+ the last; behaviour is unchanged (live dirty count, one prompt per visit,
325
+ #298). Headless Chromium, insert + connect: 4,000 guarded roots ~306 ->
326
+ ~227 ms, 4,000 persisted roots ~280 -> ~230 ms. +194 B gzipped in the
327
+ default bundle (110 B for the guard, 84 B for persist).
328
+ - **A record-backed token no longer builds a GlobalID URI.** For a record
329
+ whose `to_gid` is GlobalID's own and whose id is an Integer, the gid is
330
+ built directly as `gid://<app>/<Class>/<id>` (byte-identical, pinned by
331
+ `identity_gid_spec.rb`); anything else still calls `to_gid`. The token goes
332
+ from ~11.4 µs and 54 objects to ~5.2 µs and 20 (in-place A/B).
333
+ - **`rake bench:browser`.** Connect, disconnect and a heap soak for the
334
+ shipped client in headless Chromium. The happy-dom connect bench is
335
+ engine-relative and missed the quadratic above; this is the one to trust.
336
+ - **The doctor's authorization check is linear, not quadratic.** It rebuilt
337
+ the Inspector's whole component list (a Prism scan per action) once for
338
+ every component. It now reads it once: `doctor.checks` over the dummy app's
339
+ 90 components drops from 1,337 ms to 55 ms, and an app with a few hundred
340
+ components no longer waits tens of seconds on `rake phlex_reactive:doctor`.
341
+ - **`on()` checks for removed keywords without building arrays.** Every
342
+ trigger ran `params.keys & REMOVED_ON_KWARGS.keys`. It now returns at once
343
+ when there are no extra keywords. `on(:increment)` allocates 5 objects
344
+ instead of 8; a 7-trigger component's `render_component` 118 instead of 136
345
+ (~5% faster in an in-place A/B, a method-level win that shows on broadcast
346
+ fan-out, not request latency).
347
+ - **The request bench measures production, not a file watcher.** The dummy
348
+ app's test env left code reloading on, so every request globbed `app/`:
349
+ `rake bench:request` read ~1.7-2.0 ms and 1,272 objects per state-backed
350
+ action, against ~0.30-0.35 ms and 824 objects with it off (same machine,
351
+ interleaved). Test-env only; the gem is unchanged.
352
+
254
353
  ## [0.14.1] - 2026-10-07
255
354
 
256
355
  ### Added
data/README.md CHANGED
@@ -689,7 +689,8 @@ Use in controllers: `render turbo_stream: Counter.replace(counter)`.
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). |
691
691
  | `reactive_show(if:/if_any:/unless:)` | **Value-conditional visibility** (the `x-show`/`data-show` case): spread onto the element to show/hide — it toggles `hidden` from the fields' **current values**, client-only, zero round trip. One conditions language: a **Hash is an AND**, an **Array is membership**, a **Range is a threshold**, `if_any:` is OR-of-AND, `unless:` negates. `reactive_values` computes first paint; `disable:` disables a hidden section's controls. See [Value-conditional visibility](#value-conditional-visibility-reactive_show). |
692
- | `reactive_media(from:, pool:, take:, label:, blank_label:)` | A preview `<img>` that **follows a field** (#373): the field's value (its first `take:` characters, or all of it) is a key into `pool`, whose values are **selectors** for `<img>` elements the server rendered — never URLs. A hit copies that image's `src`/`srcset`/`alt` like `js.copy_media`; a miss clears the preview. `label:` gets the `alt` (or `blank_label`) as `textContent`. See [Media previews](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
692
+ | `reactive_media(from:, pool:, take:, match:, pending:, label:, blank_label:)` | A preview `<img>` that **follows a field** (#373): the field's value (its first `take:` characters, or all of it) is a key into `pool`, whose values are **selectors** for `<img>` elements the server rendered — never URLs. A hit copies that image's `src`/`srcset`/`alt` like `js.copy_media` (a pool `<img>` with an `alt` and no `src` is a hit without an image, #381); a miss clears the preview. `label:` gets the `alt` (or `blank_label`) as `textContent`. Below `take:` characters, or while `match:` (a JavaScript-compatible Regexp over the whole key) rejects the key, the binding is **pending** (#380) — never `blank_label` (Regexp options or Ruby-only syntax raise at render); `pending: :clear` (default) clears the preview and label, `:keep` leaves them. The preview's `data-reactive-media-state` reads `pending`/`hit`/`miss`, so CSS can hide its row. See [Media previews](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
693
+ | `reactive_image_fallback(hide: true, show_alt: nil)` | An `<img>` that **falls back and recovers** (#383): on `error` it gets `data-reactive-image-state="error"`; `hide:` (default `true`) also hides it, and `show_alt:`, independently, writes its `alt` into that node and shows it; `load` sets `"loaded"`. A later `src` (from `copy_media`, `reactive_media`, `preview_file`, a morph, or any `src` that loads) shows it again; removing the `src` is not an error. Composes with `reactive_media(…, **reactive_image_fallback)`. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
693
694
  | `reactive_enable(if:/if_any:/unless:)` | The sibling of `reactive_show` that flips the element's **own `disabled`** (a button, a fieldset) instead of `hidden` — same conditions, same `reactive_values` first paint. `button(**reactive_enable(if: { "ids[]" => { checked: 1.. } }))`. See [Bulk selection](#bulk-selection-reactive_select_all-reactive_count-reactive_enable). |
694
695
  | `reactive_select_all("ids[]")` / `reactive_count("ids[]")` | A checkbox **group**'s header box (ticks/unticks every owned box; shows checked / indeterminate / unchecked) and its ticked count as text — re-synced on every change and when rows are appended or removed. See [Bulk selection](#bulk-selection-reactive_select_all-reactive_count-reactive_enable). |
695
696
  | `reactive_group_targets("ids[]", count: "#c", enable: { "#b" => 1.. })` | Spread on the root that **owns** a checkbox group: drives a count and an enable on outside, id-allowlisted elements (a bulk bar the page renders). `reactive_group_target_attrs` gives that outside markup its first paint. See [A bulk bar outside the list's root](#a-bulk-bar-outside-the-lists-root-reactive_group_targets). |
@@ -1267,8 +1268,9 @@ button(**on_client(:click, js
1267
1268
  `from` `<img>` onto the `to` `<img>` — how a preview shows an image the server
1268
1269
  already rendered while `src` stays refused. Both are elements (`:root` or a
1269
1270
  selector); the URL is read from the live source element, never passed. A
1270
- missing source, a non-`<img>` source or one without `src` clears the target;
1271
- a non-`<img>` target is warned about and skipped; an attribute that already
1271
+ missing source or a non-`<img>` source clears the target; an `<img>` source
1272
+ without `src` removes the target's `src`/`srcset` and copies its `alt` (#381),
1273
+ so an entry with no image keeps its name; a non-`<img>` target is warned about and skipped; an attribute that already
1272
1274
  holds the copied value is not rewritten, so the same image twice does not
1273
1275
  reload. Allowed in a broadcast (it only reads the subscriber's own page).
1274
1276
  - **`focus(to)`** focuses the first match; **`focus_first(to)`** focuses the first
@@ -1339,7 +1341,7 @@ button(**on_client(:click, js
1339
1341
  (a broadcast that reads every subscriber's clipboard would be hostile). The
1340
1342
  op is async fire-and-forget — chained siblings apply immediately, never
1341
1343
  waiting for the read.
1342
- - **`preview_file(to, into:, name: nil, global: false)`** (#375; `global: true`
1344
+ - **`preview_file(to, into:, name: nil, global: false, valid: false)`** (#375; `global: true`
1343
1345
  resolves `to`, `into:` and `name:` document-wide, for an `img` outside the
1344
1346
  root) paints the file a file input
1345
1347
  holds onto an `img` **before any upload**:
@@ -1356,6 +1358,14 @@ button(**on_client(:click, js
1356
1358
  and revokes it on a re-pick, a clear, and when the `img` leaves the page or a
1357
1359
  morph strips its `src` — a server re-render resets the preview like any other
1358
1360
  op. **Actor-only**: refused in `broadcast_to(js:)`.
1361
+ **Upload validation (#382):** `valid: true` treats an input whose
1362
+ `validity.valid` is false (`setCustomValidity`, `required`) as empty, so a
1363
+ rejected file never gets a preview. An app that clears the input itself
1364
+ (`input.value = ""` fires no `change`) dispatches `reactive:file-changed` on
1365
+ it; bind the op to that event too and the preview, the name and the URL are
1366
+ cleared: `op = js.preview_file("#photo-file", into: "#photo", valid: true)`,
1367
+ `input(type: "file", id: "photo-file", **mix(on_client(:change, op),
1368
+ on_client("reactive:file-changed", op)))`.
1359
1369
  - **`expanded:`** on `show`/`hide`/`toggle` (#271) keeps a disclosure trigger's
1360
1370
  `aria-expanded` honest: `js.toggle("#menu", expanded: "#trigger")` writes the
1361
1371
  op's **intended** state (`show` → `"true"`, `hide` → `"false"`, `toggle` → the
@@ -1,9 +1,9 @@
1
- import{Controller as at}from"@hotwired/stimulus";import{confirmResolver as fe}from"phlex/reactive/confirm";function ct(){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 ut(){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 lt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=le(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",(s)=>s.missingRoot(r));return}te(t,(s)=>Yt(s,i),n?(s,a)=>b("devtools",(o)=>o.diagnoseStream(s,a,i)):void 0)}}function dt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){b("defer",(t)=>t.streamAction(this))}}var he=!1,Q=null;function ft(){if(he)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;he=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(St(e),ht(e),pt(e),Q)Q(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var M="reactive:streamed";function ht(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target,i=n?.getAttribute?.("action"),s=/^(append|prepend|update)$/.test(i);if(typeof r!=="function"||!(s||/^(before|after|replace)$/.test(i)))return;let a=n.getAttribute("target"),o=n.getAttribute("targets"),c=new Set;for(let l of a?[document.getElementById(a)]:o?document.querySelectorAll(o):[]){let d=(s?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(M))}}function re(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function ne(e){try{return e.matches(":modal")}catch{return!1}}function Me(e){if(!re(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||ne(e))return;if(e.open)e.close();e.showModal()}function mt(e){if(re(e)&&e.open)e.close()}function B(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&&!ne(n))Me(n)}function pt(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),B(document)}}var me=!1;function gt(){if(me)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;me=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))B(t.target)}),document.addEventListener("turbo:morph",()=>B(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!re(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||!ne(r))return;e.delete(r),t.preventDefault(),r.close()})}var ee=new WeakMap;function Ce(e,t,r,n){let i=ee.get(e)??new Map;ee.set(e,i);let s=(a,o)=>{i.delete(a),i.set(a,o)};if(t.endsWith("_class"))for(let a of r.classes??[])s(`.${a}`,e.classList.contains(a));else if(t.endsWith("_attr"))Ge(r.name)||s(r.name,e.getAttribute(r.name));else if(t==="show"||t==="hide"||t==="toggle"){if(s("hidden",e.getAttribute("hidden")),r.expanded!=null)for(let a of n({...r,to:r.expanded}))Ce(a,"set_attr",{name:"aria-expanded"})}}var pe=!1;function bt(){if(pe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;pe=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of ee.get(t)??[])if(r[0]===".")t.classList.toggle(r.slice(1),n);else if(n==null)t.removeAttribute(r);else if(t.getAttribute(r)!==n)t.setAttribute(r,n)})}function De(e){Q=e}var O,K=null,ge="[data-reactive-editable][contenteditable=plaintext-only]";function $e(){if(O===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",O=e.contentEditable==="plaintext-only"}catch{O=!1}return O}function C(e){if(e.matches?.(ge))e.setAttribute("contenteditable","true");e.querySelectorAll?.(ge).forEach(C)}function yt(){if(K||typeof document>"u"||typeof document.createElement!=="function")return;if($e())return;C(document),K=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")C(t.target);else t.addedNodes.forEach(C)}),K.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var be=!1;function ye(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 vt(){if(be)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;be=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=ye(t);if(n)wt(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(W.set(t,E(r)),!n)return;for(let{name:s}of[...t.attributes])if(!r.hasAttribute(s)&&s!=="contenteditable"&&s!==_)t.removeAttribute(s);for(let{name:s,value:a}of r.attributes)if(s!=="contenteditable"&&t.getAttribute(s)!==a)t.setAttribute(s,a);return e.preventDefault()}if(t.localName!=="input"||!n)return;let i=r.getAttribute("value");if(i==null)t.removeAttribute("value");else if(t.getAttribute("value")!==i)t.setAttribute("value",i)}),document.addEventListener("focusin",(e)=>ce(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&ye(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&se(t)===oe(t))t.removeAttribute(_)})}var _="data-reactive-held",ie='[data-controller~="reactive"]',D=null,T=new Map;function se(e){return e.hasAttribute("data-reactive-editable")?E(e):e.value}function oe(e){return e.hasAttribute("data-reactive-editable")?ue(e):e.defaultValue}function _t(e){if(e.hasAttribute("data-reactive-editable"))return E(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function wt(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||T.has(e.closest(ie)))return;let n=_t(t);if(n===se(e))return e.removeAttribute(_);if(n===oe(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function At(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(ie)!==e)continue;let n=r.getAttribute("name");if(se(r)===oe(r))r.removeAttribute(_);else if(n&&!t.includes(n))t.push(n)}if(t.length===0)return null;return JSON.stringify(t).replace(/[\u007f-￿]/g,(r)=>`\\u${r.charCodeAt(0).toString(16).padStart(4,"0")}`)}function qe(e){for(let t of e.querySelectorAll(`[${_}]`))if(t.closest(ie)===e)t.removeAttribute(_)}function ve(e,t,r=!0){let n={root:e,streams:0,release:r},i=D;D=n;try{window.Turbo.renderStreamMessage(t)}finally{D=i}if(r&&n.streams===0)qe(e)}function St(e){let t=D,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{T.set(t.root,(T.get(t.root)||0)+1);try{return await n(i)}finally{let s=T.get(t.root)-1;if(s)T.set(t.root,s);else T.delete(t.root);if(t.release)qe(t.root)}}}var Et="__materialize",_e=!1;function Tt(){if(_e)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;_e=!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 Ft="phlex-reactive:latency";function Be(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Ft))}function ae(){if(typeof document>"u")return;if(!p.has("devtools")&&!w.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||Be())b("devtools",(t)=>e&&t.attach())}var We="data-reactive-active",A=0;function je(){if(A++,A===1)Je("reactive:busy")}function Ue(){if(A===0)return;if(A--,A===0)Je("reactive:idle")}function Sr(){return A}function Er(){A=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(We)}function Je(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(We,A>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:A}}))}var He="data-reactive-requests";function Ke(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Lt(t))return;let r=kt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(He,JSON.stringify(r))}function Lt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function kt(e){try{let t=JSON.parse(e.getAttribute(He));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function we(){ct(),ut(),lt(),dt(),ft(),vt(),gt(),bt(),yt(),Tt(),ae()}function xt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ze=Symbol.for("phlex-reactive.core");if(globalThis[ze])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[ze]=!0;var Ve=!1;function Rt(){if(Ve)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(Rt,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var Nt=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function Ge(e){let t=String(e).toLowerCase();return t.startsWith("on")||Nt.has(t)}var z=new WeakMap;function Pt(e,t,r){let[n,i,s]=t;z.get(e)?.(),e.classList.add(n,i),r();let a=!1,o=requestAnimationFrame(()=>{if(a)return;e.classList.remove(i),e.classList.add(s)}),c=(d)=>{if(a||d&&d.target!==e)return;a=!0,z.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};z.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,It(e))}function It(e){let t=0;try{let r=getComputedStyle(e);for(let n of["transition","animation"]){let[i,s]=["Duration","Delay"].map((o)=>String(r[n+o]).split(",").map((c)=>parseFloat(c)*(/ms/.test(c)?1:1000)||0)),a=String(r[n+"IterationCount"]).split(",").map((o)=>/inf/.test(o)?1/0:parseFloat(o)>=0?parseFloat(o):1);for(let o=0;o<i.length||o<s.length||o<a.length;o++){let c=i[o%i.length]*a[o%a.length]||0;t=Math.max(t,c+s[o%s.length])}}}catch{}return Math.min(Math.max(t+50,350),5000)}var Ot=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",Mt=new Set(["lexxy-editor","trix-editor"]);function E(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
1
+ import{Controller as bt}from"@hotwired/stimulus";import{confirmResolver as ye}from"phlex/reactive/confirm";function yt(){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 vt(){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 _t(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=ge(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}ae(t,(o)=>ar(o,i),n?(o,a)=>b("devtools",(s)=>s.diagnoseStream(o,a,i)):void 0)}}function At(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){b("defer",(t)=>t.streamAction(this))}}var ve=!1,ie=null;function wt(){if(ve)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;ve=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Ot(e),St(e),Tt(e),ie)ie(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var D="reactive:streamed";function St(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(D))}}function ce(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function ue(e){try{return e.matches(":modal")}catch{return!1}}function je(e){if(!ce(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||ue(e))return;if(e.open)e.close();e.showModal()}function Et(e){if(ce(e)&&e.open)e.close()}function j(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&&!ue(n))je(n)}function Tt(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),j(document)}}var _e=!1;function Ft(){if(_e)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;_e=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))j(t.target)}),document.addEventListener("turbo:morph",()=>j(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!ce(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||!ue(r))return;e.delete(r),t.preventDefault(),r.close()})}var se=new WeakMap;function Ue(e,t,r,n){let i=se.get(e)??new Map;se.set(e,i);let o=(a,s)=>{i.delete(a),i.set(a,s)};if(t.endsWith("_class"))for(let a of r.classes??[])o(`.${a}`,e.classList.contains(a));else if(t.endsWith("_attr"))st(r.name)||o(r.name,e.getAttribute(r.name));else if(t==="show"||t==="hide"||t==="toggle"){if(o("hidden",e.getAttribute("hidden")),r.expanded!=null)for(let a of n({...r,to:r.expanded}))Ue(a,"set_attr",{name:"aria-expanded"})}}var Ae=!1;function kt(){if(Ae)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ae=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of se.get(t)??[])if(r[0]===".")t.classList.toggle(r.slice(1),n);else if(n==null)t.removeAttribute(r);else if(t.getAttribute(r)!==n)t.setAttribute(r,n)})}var Je="data-reactive-image-fallback",L="data-reactive-image-state",oe="data-reactive-image-hidden",Y=null;function x(e){if(e?.localName!=="img")return null;let t=e.getAttribute(Je);if(t==null)return null;try{return JSON.parse(t)||{}}catch{return{}}}var He=(e)=>e.getAttribute("src")||e.getAttribute("srcset");function Ke(e,t){if(typeof t.alt!=="string"||!t.alt)return null;try{let r=e.closest('[data-controller~="reactive"]')?.querySelector(t.alt);return r&&!r.contains(e)?r:null}catch{return null}}function U(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(oe,"");let n=Ke(e,t);if(n)n.textContent=e.getAttribute("alt")??"",n.hidden=!1}else z(e,t);e.setAttribute(L,r)}function z(e,t=x(e)){if(!t||e.getAttribute(L)==null)return;if(e.getAttribute(L)==="error"){if(e.hasAttribute(oe))e.removeAttribute("hidden");let r=Ke(e,t);if(r)r.hidden=!0}e.removeAttribute(L),e.removeAttribute(oe)}function we(e){let t=e.target,r=x(t);if(!r)return;if(e.type==="load")U(t,r,"loaded");else if(He(t))U(t,r,"error");else z(t,r)}function Lt(){if(Y)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;Y={error:we,load:we,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(L);if(i==null||!n||!x(r))return;let o=(a)=>r.getAttribute(a)===n.getAttribute?.(a);if(o("src")&&o("srcset"))e.set(r,i)},"turbo:morph-element":(t)=>{let r=t.target,n=e.get(r);if(n===void 0)return;e.delete(r),queueMicrotask(()=>{let i=x(r);if(i)U(r,i,n)})}};for(let[t,r]of Object.entries(Y))document.addEventListener(t,r,!0);for(let t of document.querySelectorAll?.(`img[${Je}]`)??[]){if(!t.complete||!He(t))continue;let r=`${t.getAttribute("src")} ${t.getAttribute("srcset")}`,n=(i)=>`${t.getAttribute("src")} ${t.getAttribute("srcset")}`===r&&U(t,x(t)??{},i);if(t.naturalWidth>0)n("loaded");else if(typeof t.decode==="function")t.decode().then(()=>n("loaded"),()=>n("error"));else n("error")}}function ze(e){ie=e}var C,X=null,Se="[data-reactive-editable][contenteditable=plaintext-only]";function Ve(){if(C===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",C=e.contentEditable==="plaintext-only"}catch{C=!1}return C}function q(e){if(e.matches?.(Se))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Se).forEach(q)}function xt(){if(X||typeof document>"u"||typeof document.createElement!=="function")return;if(Ve())return;q(document),X=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")q(t.target);else t.addedNodes.forEach(q)}),X.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var Ee=!1;function Te(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 Rt(){if(Ee)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ee=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=Te(t);if(n)It(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(J.set(t,E(r)),!n)return;for(let{name:o}of[...t.attributes])if(!r.hasAttribute(o)&&o!=="contenteditable"&&o!==_)t.removeAttribute(o);for(let{name:o,value:a}of r.attributes)if(o!=="contenteditable"&&t.getAttribute(o)!==a)t.setAttribute(o,a);return e.preventDefault()}if(t.localName!=="input"||!n)return;let i=r.getAttribute("value");if(i==null)t.removeAttribute("value");else if(t.getAttribute("value")!==i)t.setAttribute("value",i)}),document.addEventListener("focusin",(e)=>me(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&Te(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&de(t)===fe(t))t.removeAttribute(_)})}var _="data-reactive-held",le='[data-controller~="reactive"]',B=null,T=new Map;function de(e){return e.hasAttribute("data-reactive-editable")?E(e):e.value}function fe(e){return e.hasAttribute("data-reactive-editable")?pe(e):e.defaultValue}function Nt(e){if(e.hasAttribute("data-reactive-editable"))return E(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function It(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||T.has(e.closest(le)))return;let n=Nt(t);if(n===de(e))return e.removeAttribute(_);if(n===fe(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function Pt(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(le)!==e)continue;let n=r.getAttribute("name");if(de(r)===fe(r))r.removeAttribute(_);else if(n&&!t.includes(n))t.push(n)}if(t.length===0)return null;return JSON.stringify(t).replace(/[\u007f-￿]/g,(r)=>`\\u${r.charCodeAt(0).toString(16).padStart(4,"0")}`)}function Ge(e){for(let t of e.querySelectorAll(`[${_}]`))if(t.closest(le)===e)t.removeAttribute(_)}function Fe(e,t,r=!0){let n={root:e,streams:0,release:r},i=B;B=n;try{window.Turbo.renderStreamMessage(t)}finally{B=i}if(r&&n.streams===0)Ge(e)}function Ot(e){let t=B,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{T.set(t.root,(T.get(t.root)||0)+1);try{return await n(i)}finally{let o=T.get(t.root)-1;if(o)T.set(t.root,o);else T.delete(t.root);if(t.release)Ge(t.root)}}}var Mt="__materialize",ke=!1;function Ct(){if(ke)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;ke=!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 $t="phlex-reactive:latency";function Ye(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem($t))}function he(){if(typeof document>"u")return;if(!p.has("devtools")&&!A.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 Xe="data-reactive-active",w=0;function Ze(){if(w++,w===1)et("reactive:busy")}function Qe(){if(w===0)return;if(w--,w===0)et("reactive:idle")}function Or(){return w}function Mr(){w=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(Xe)}function et(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(Xe,w>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:w}}))}var tt="data-reactive-requests";function rt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Dt(t))return;let r=qt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(tt,JSON.stringify(r))}function Dt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function qt(e){try{let t=JSON.parse(e.getAttribute(tt));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function Le(){yt(),vt(),_t(),At(),wt(),Rt(),Ft(),kt(),Lt(),xt(),Ct(),he()}function Bt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var nt=Symbol.for("phlex-reactive.core");if(globalThis[nt])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[nt]=!0;var it=!1;function Wt(){if(it)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(Wt,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var jt=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function st(e){let t=String(e).toLowerCase();return t.startsWith("on")||jt.has(t)}var Z=new WeakMap;function Ut(e,t,r){let[n,i,o]=t;Z.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,Z.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(s),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,o)};Z.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,Jt(e))}function Jt(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 Ht=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",Kt=new Set(["lexxy-editor","trix-editor"]);function E(e){let t="",r=!1,n=(o)=>{if(r&&t&&!t.endsWith(`
2
2
  `))t+=`
3
- `;r=!1,t+=s},i=(s)=>{for(let a of s.childNodes){let o=/^(div|p|li)$/.test(a.localName);if(o)r=!0;if(a.nodeType===3)a.data&&n(a.data);else if(a.localName==="br")n(`
4
- `);else if(a.nodeType===1)i(a);if(o)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 W=new WeakMap;function ce(e){if(e?.hasAttribute?.("data-reactive-editable")&&!W.has(e))W.set(e,E(e))}function ue(e){return ce(e),W.get(e)}function Ct(e){return Mt.has(e.localName)?typeof e.value==="string":!0}var Ae=Object.freeze({show:(e,t,r)=>V(e,!1,t,r),hide:(e,t,r)=>V(e,!0,t,r),toggle:(e,t,r)=>V(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(G(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(G(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!G(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)=>Jt(e)?.focus?.(),show_modal:(e)=>Me(e),close_dialog:(e)=>mt(e),text:(e,t)=>{let r=String(t.value??"");if(e.textContent!==r)e.textContent=r},copy_media:(e,t,r)=>{let n=null;try{n=r({...t,to:t.from})[0]??null}catch{}Ze(e,n)},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=Dt(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)=>$t(e),preview_file:(e,t,r)=>qt(e,t,r),set_value:(e,t)=>Wt(e,String(t.value??"")),persist_state:(e,t)=>b("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>b("persist",(t)=>t.clearRoot(e))});function Dt(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function $t(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;e.value=r,Xe(e),e.focus?.()}).catch(()=>{})}var k=new Map,x=null;function qt(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return Se(`reads an input[type=file], not <${e?.localName}>`);let n=typeof r==="function"?r({...t,to:t.into})[0]:null;if(n?.tagName!=="IMG")return Se(`paints an <img>, and ${JSON.stringify(t.into)} is ${n?`a <${n.localName}>`:"not on the page"}`);let i=[...e.files??[]].find((s)=>typeof s?.type==="string"&&s.type.startsWith("image/"));if(Ye(n),i){let s=URL.createObjectURL(i);k.set(n,s),n.setAttribute("src",s),Bt()}else n.removeAttribute("src");if(t.name==null)return;for(let s of r({...t,to:t.name}))s.textContent=i?i.name:""}function Se(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function Ye(e){let t=k.get(e);if(t===void 0)return;if(k.delete(e),URL.revokeObjectURL(t),k.size===0)x?.disconnect(),x=null}function Bt(){if(x||typeof MutationObserver!=="function"||!document?.documentElement)return;x=new MutationObserver(()=>{for(let[e,t]of k)if(!e.isConnected||e.getAttribute("src")!==t)Ye(e)}),x.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]})}function Xe(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function Wt(e,t){if(!/^(input|textarea|select)$/.test(e.localName)||e.type==="file"&&t!==""){console.warn("[phlex-reactive] set_value skipped: not a field it can write",e);return}let r=Ee(e);if(e.value=t,Ee(e)!==r)Xe(e)}function Ee(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
6
- `):e.value}function jt(e,t,r){if(r?.transition)Pt(e,r.transition,()=>e.hidden=t);else e.hidden=t}function V(e,t,r,n){if(jt(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 G(e){if(!Ge(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function Ze(e,t){if(e?.localName!=="img")return console.warn(`[phlex-reactive] copy_media targets an <img>, not <${e?.localName}> — skipped`),null;let r=t?.localName==="img"?t.getAttribute("src"):null,n=(s)=>r?t.getAttribute(s):null;for(let s of["srcset","src"]){let a=n(s);if(a==null){if(e.hasAttribute(s))e.removeAttribute(s)}else if(e.getAttribute(s)!==a)e.setAttribute(s,a)}let i=n("alt")??"";if(e.getAttribute("alt")!==i)e.setAttribute("alt",i);return r?i:!1}var Ut='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Jt(e){return e.querySelectorAll?.(Ut)?.[0]??null}function le(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 Te=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"}),Fe=Object.freeze(["meta","ctrl","alt","shift"]);function J(e,t,r){let n=e.split("+");for(let a of Fe)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Fe.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let s=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(Te,i)?Te[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof s==="string"&&s.toLowerCase()===t.key.toLowerCase()}var Ht=(e)=>e&&typeof e==="object"?e.keys:String(e);function Y(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 J(Ht(e).replace(/^mod\+/,`${i}+`),t,r)}function Kt(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:le(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 Le(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)!==it(t.currentTarget))return!1;return i<0||r===null||J(n.slice(i+1),t,r)}function zt(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 ke=new WeakMap;function Vt(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=ke.get(e);if(!i)i=new WeakMap,ke.set(e,i);let s=i.get(n);if(!s)s=new Set,i.set(n,s);let a=t.params?.ops,c=(n===globalThis.window?`${typeof a==="string"?a:JSON.stringify(a??null)}|`:"")+JSON.stringify(r);if(s.has(c))return!0;return s.add(c),!1}var xe=new WeakMap;function Gt(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=xe.get(e);if(!i)i=new WeakMap,xe.set(e,i);let s=i.get(t);if(!s)s=new Map,i.set(t,s);let a=s.get(e.currentTarget);if(!a)a=new Set,s.set(e.currentTarget,a);if(a.has(n))return!0;return a.add(n),!1}function te(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn(Ae,i)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(i)} — skipped`);continue}let a=t(s);if(a.length===0&&r)r(i,s);for(let o of a)if(Ae[i](o,s,t),s?.keep===!0)Ce(o,i,s,t)}}function Yt(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 Xt(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function Qe(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}function Zt(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 Qt(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], [data-reactive-media]")!=null}function er(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function tr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function et(e){return e.getAttribute?.("data-reactive-presence")!=null}var rr=[["persist",[Xt,null,null,!0]],["defer",[Qe,null]],["form",[Zt,null]],["bindings",[Qt,null,null,!0]],["compute",[er,null,null,!0]],["sortable",[tr,null]],["presence",[et,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]]],w=new Map(rr),Re=new Map,p=new Map,nr=new Map;function y(e,t,r){tt.set(e,[t,r]),ir(e)}var tt=new Map;function ir(e){let t=w.get(e),[r,n]=tt.get(e);t[1]=r,t[2]=n}function Tr(e,t){t.install?.(N),p.set(e,t),nr.set(e,t)}function rt(e){let t=[];for(let[r,[n]]of w){if(!n||p.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function nt(e){return R(e).catch((t)=>j(e,"load",t))}function R(e){let t=Re.get(e);if(!t)t=(w.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(N),p.set(e,n),n)),Re.set(e,t);return t}var Ne=new Set;function j(e,t,r){let n=e+t;if(Ne.has(n))return;Ne.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);R(e).then(t,(n)=>j(e,"load",n))}var sr=1e4;function X(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:sr}function Fr(){return[...w.keys()]}var Pe=Promise.resolve();function Ie(e,t,r){let n=N.waiting.get(e);if(n&&n[t]===r)delete n[t]}var N={enter:je,exit:Ue,count:Ke,text:E,served:ue,waiting:new WeakMap};var P=Symbol.for("phlex-reactive.early"),or=1e4,ar=1500,it=(e)=>e!=null&&(e===globalThis.window||e.window===e);function Z(){return globalThis[P]??={queue:[],connected:new WeakSet},globalThis[P]}function cr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:or}function ur(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 s;try{s=JSON.parse(n)}catch{s=n}t[i[1].replace(/[-_]([a-z0-9])/g,(a,o)=>o.toUpperCase())]=s}return t}function lr(e,t,r){return{[P]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:ur(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 U=new WeakMap;function dr(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=U.get(e);if(!o)U.set(e,o=new Map);let c=s?`${t} ${a}`:t;if(o.has(c))return!1;return o.set(c,{type:r,method:n,filter:i,win:s,params:a,armed:!0}),!0}function Oe(e,t,r,n){if(e?.[P])return!1;let i=it(e?.currentTarget),s=i?n:e?.currentTarget,a=hr(e,s,i?`@${t}`:t),o=U.get(s),c=i&&JSON.stringify(e.params);for(let l of o?.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&&!J(l.filter,e,r))continue;return l.armed=!1,!0}return a}var q=new WeakMap;function fr(e,t,r){let n=q.get(e);if(!n)q.set(e,n=new Map),setTimeout(()=>q.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function hr(e,t,r){let n=e&&q.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class st extends at{static values={token:String};#_;#w=new Map;#l=new Map;#ee;#k;#j;#x=0;#d=new Map;#R=new WeakMap;#t;featuresReady=Pe;#r=new Map;#N=new Set;#f=!1;#n=null;#h=new Map;#A=new Map;#m=new Map;#p=0;#U;#Ie=0;#Oe=0;connect(){if(Ve=!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||Qe(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===M)this.#K();this.#J(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(M,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(ce),this.#p++,this.featuresReady=Pe,this.#J(),B(this.element),this.#ie()}#Me(e){}#Ce(e,t,r,n){}#De(){}#$e(e,t){}#J(e){{let t=this.#p,r=[];for(let[s,[a]]of w){if(!a||this.#N.has(s))continue;let o=p.get(s);if(o&&!o.connect)continue;try{if(a(this.element))r.push(s)}catch(c){this.#g(s,"detect",c)}}if(r.length===0)return;for(let s of r)this.#N.add(s);if(!this.#f&&r.every((s)=>p.has(s))){for(let s of r)this.#P(t,s,p.get(s),e);return}for(let s of r){let a=this.#te(t,s),o=[];for(let l of w.keys()){if(l===s)break;if(this.#m.has(l))o.push(this.#m.get(l))}let c=Promise.all(o).then(()=>a).then((l)=>l&&this.#P(t,s,l,e));if(this.#m.set(s,c),w.get(s)[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,s=setTimeout(()=>{if(this.#h.delete(s),i=!0,r())this.#g(t,"timeout",Error(`not loaded after ${X()} ms`));n(null)},X());this.#h.set(s,n);let a=()=>{clearTimeout(s),this.#h.delete(s)};R(t).then((o)=>{if(a(),i)queueMicrotask(()=>this.#P(e,t,o));else n(o)},(o)=>{if(a(),r())this.#g(t,"load",o);n(null)})})}}#re(e){{let t=w.get(e)[2];if(!t)return;let r={};try{this.#A.set(e,[t(this.element,r),r]),N.waiting.set(this.element,{...N.waiting.get(this.element),[e]:r})}catch(n){this.#g(e,"detect",n)}}}#H(e,t){{let[r,n]=this.#A.get(e)??[];if(this.#A.delete(e),!t)Ie(this.element,e,n);try{r?.()}catch(i){console.error(`[phlex-reactive] the "${e}" feature module failed to stop waiting`,i)}return n}}#P(e,t,r,n){{if(e!==this.#p)return;let i=this.#H(t);try{r.connect?.(this,this.#e(),n,i),this.#r.set(t,r)}catch(s){this.#g(t,"connect",s)}}}#e(){return this.#U??={emit:(e,t,r)=>this.#s(e,t,r),reseed:()=>this.#K(),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)=>te(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:$e,text:E,served:ue,copyMedia:Ze,confirm:(e,t)=>Promise.resolve().then(()=>fe(e,t)).catch(()=>!1)},this.#U}#K(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#g(e,t,r){if(j(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.#A.keys()]){let r=this.#H(t,!0),n=this.element;b(t,(i)=>{i.abandon?.(n,r),Ie(n,t,r)})}this.#N.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}=Z();if(e.length===0)return;let t=[];for(let i=e.length-1;i>=0;i--){let{root:s}=e[i];if(s===this.element||!s.isConnected)t.unshift(...e.splice(i,1))}let r=cr(),n=new Map;for(let i of t){let s=n.get(i.event)??[new Set,new Set];n.set(i.event,s);let a=s[+!!i.win];if(a.has(i.el))continue;a.add(i.el);let o=i.win?Math.min(ar,r):r,c=i.root!==this.element?"its root left the page before a controller connected":performance.now()-i.at>o?`it is older than the ${o} 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.#q())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=lr(e,t,n),s=this.application?.schema?.keyMappings,a=(t.getAttribute("data-action")??"").split(/\s+/),o=n?this.element:t;for(let c of r){if(!a.includes(c.token))continue;if(c.filter&&!J(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!dr(o,c,n&&JSON.stringify(i.params)))continue;this.#I.add(o)}if(fr(e,o,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?.(M,this.#t);Z().connected.delete(this.element),this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)U.delete(e);this.#I.clear()}dispatch(e){let t=e.params?.shortcut;if(t!=null&&!Y(t,e,this.application?.schema?.keyMappings))return;if(Oe(e,"dispatch",this.application?.schema?.keyMappings,this.element))return;let{action:r,params:n,debounce:i,throttle:s,confirm:a,confirmWhen:o,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===Et){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.#z(a,o),v=()=>this.#O(f,r,n,i,s,d,m);if(!g)return v();if(g instanceof Promise)return g.then((S)=>S?this.#S(S,f,v):v());this.#S(g,f,v)}#S(e,t,r){return Promise.resolve().then(()=>fe(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#z(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([R(e).catch((r)=>(j(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),X()))]).finally(()=>clearTimeout(t))}}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!Y(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Oe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(Gt(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=Kt(r.ops),s=i.filter((o)=>Le(o,e,null)),a=s.length<=1?s:s.filter((o)=>Le(o,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#q())this.#v((o)=>o.noBinding(this,e));return}for(let o of a){if(o.outside&&e[P])continue;if(!zt(o,e))continue;if(o.shortcut!=null&&!Y(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(Vt(this,e,o))continue;this.#ae(o.legacy?{...r,ops:o.ops}:o,e,n)}}#ae({ops:e,confirm:t,confirmWhen:r,outside:n,window:i,shortcut:s},a,o){if(n&&this.element.contains(a.target))return;if(s!=null||!i)a.preventDefault();let c=this.#z(t,r),l=()=>this.#Ee(this.#Se(e));if(!c)return l();if(c instanceof Promise)return c.then((d)=>d?this.#S(d,o,l):l());this.#S(c,o,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,s=n?r.findIndex((o)=>o===i||i!=null&&o.contains?.(i)):r.findIndex((o)=>o.hasAttribute("data-reactive-highlighted")),a=r[t(s,r.length)];if(n)a.focus?.();else{for(let o of r)o.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,s,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,s,a);let l=Number(i)||0;if(l>0)return this.#fe(e,l,t,r,s,a);return this.#T(t,r,s,e,a)}#T(e,t,r,n,i){let s={inverse:null,undo:[],resurrect:null},a=this.#Fe(e,n,s),o=Boolean(r||i),c=(f)=>{if(!o||!f)return;let g=this.#e();if(s.inverse=f.optimistic(this,g,r,n),s.undo.push(...f.busy(this,g,i,n)),this.#C())s.resurrect=f.resurrection(this,g,r,n)},l=p.get("hints");if(!o||l)c(l);let d=()=>this.#be(e,t,s,a),m=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>o&&!l?this.#ue().then(c).then(m):m()),this.queue}#ue(){return this.#V("hints")}#le(e,t,r,n,i,s){this.#M(e);let a=()=>{this.#M(e),this.#T(r,n,i,e,s)},o=setTimeout(a,t);e?.addEventListener?.("blur",a,{once:!0}),this.#w.set(e,{timer:o,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,s){let a=this.#l.get(e)??new Map;if(a.has(r))return;let o=setTimeout(()=>{if(a.delete(r),a.size===0)this.#l.delete(e)},t);return a.set(r,o),this.#l.set(e,a),this.#T(r,n,i,e,s)}#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(Be())return R("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:s}=this.#X(),a=this.#Z(t),o={...i,...a},c=this.#a,l=s.length>0,d=l?this.#we(c,e,o,s):JSON.stringify({token:c,act:e,params:o}),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,o,{kind:"offline"});return}let f;try{let h={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#Ne()};if(!l)h["Content-Type"]="application/json";let L=this.#Pe();if(L)h["X-Pgbus-Connection"]=L;let I=et(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(I)h["X-Reactive-Presence"]=I;let de=At(this.element);if(de)h["X-Reactive-Held"]=de;Ke("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,o,{kind:"timeout"});return}this.#pe(),this.#i("network"),this.#o(e,t,o,{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,o,{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 L=this.#Y(h);if(this.#a=L??this.#a,m)this.#v((I)=>I.recordBody(m,h,L));ve(this.element,h,!1)}this.#i("http"),this.#o(e,t,o,{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,o,{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(ve(this.element,v),r.resurrect)queueMicrotask(r.resurrect);return this.#me(),this.#s("reactive:applied",{action:e,params:o,html:v}),v}catch(f){console.error("[phlex-reactive] action error",f),this.#c(r.inverse),this.#s("reactive:error",{action:e,params:o,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 s=e.match(n);if(s)return s[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#ye(e){let t=this.#j;if(t&&t.id===e)return t;let r=xt(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((o)=>{if(!r(o))return;if(o.type==="file")for(let c of o.files??[])t.push({name:o.name,file:c,multiple:o.multiple});else n.push(o)});let i=[];this.element.querySelectorAll(`[name]${Ot}`).forEach((o)=>{if(r(o))i.push(o)});let s=this.#ve(n),a=this.#_e(n);for(let o of n)if(s.has(o.name)){let c=e[o.name]??(e[o.name]=[]);if(o.type==="checkbox"||o.type==="radio"){if(o.checked)c.push(o.value)}else if(o.type==="hidden"){if(!a.has(o.name))c.push(o.value)}else if(o.multiple&&o.options){for(let l of o.options)if(l.selected)c.push(l.value)}else c.push(o.value)}else if(o.type==="checkbox")e[o.name]=o.checked;else if(o.type==="radio"){if(o.checked)e[o.name]=o.value}else e[o.name]=o.value;return i.forEach((o)=>{let c=o.getAttribute("name");if(!c)return;let l=o.getAttribute("data-reactive-editable")!=null?E(o):o.value??o.textContent??o.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!Ct(o))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 s=[];for(let[o,c]of Object.entries(r))if(Array.isArray(c)&&String(o).endsWith("[]"))if(c.length===0)s.push(String(o).slice(0,-2));else{let l=`${this.#L(o)}[]`;for(let d of c)i.append(l,String(d))}else this.#$(i,this.#L(o),c);for(let o of s)i.append("empty_groups[]",o);let a=this.#Ae(n);for(let{name:o,file:c,multiple:l}of n){let m=l||a.has(o)?`${this.#L(o)}[]`:this.#L(o);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("")}`}#$(e,t,r){if(r==null)e.append(t,"");else if(Array.isArray(r))r.forEach((n,i)=>this.#$(e,`${t}[${i}]`,n));else if(typeof r==="object")for(let[n,i]of Object.entries(r))this.#$(e,`${t}[${n}]`,i);else e.append(t,String(r))}#Ae(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{}}}#Se(e){return le(e)}#Ee(e){te(e,(t)=>this.#W(t),(t,r)=>this.#B(`client op "${t}"`,r))}#q(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#C()}#B(e,t){if(!this.#q())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),je();let n=!1;return()=>{if(n)return;n=!0,this.#ke(e,t),Ue();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}#Ne(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#Pe(){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)we();else document.addEventListener("turbo:load",we,{once:!0});y("persist",()=>import("phlex/reactive/features/persist"),mr);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"),pr);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"));ae();function mr(e,t){let r=()=>{t.edited=!0},n=(s)=>{let a=s.target;if(s.detail?.success&&a?.tagName==="FORM"&&a.contains?.(e))t.submitted=!0},i=["input","change","lexxy:change","trix-change"];for(let s of i)e.addEventListener?.(s,r);return document.addEventListener("turbo:submit-end",n),()=>{for(let s of i)e.removeEventListener?.(s,r);document.removeEventListener("turbo:submit-end",n)}}function pr(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 gr=1000,F=null,ot,H=new Set;function br(e){return nt(e).then((t)=>{if(e!=="effects")return;ot=t,t?.sweep()})}De((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,s=rt(yr(i)).filter((o)=>!H.has(o));if(!t&&!H.has("effects")&&vr(i))s.push("effects");if(s.length===0&&!F)return t?.wrap(e);if(s.length>0){for(let c of s)H.add(c);let o=F=Promise.race([Promise.all([F,...s.map(br)]),new Promise((c)=>setTimeout(c,gr))]).then(()=>{if(F!==o)return;F=null,H.clear()})}let a=F;r.render=async(o)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??ot)?.wrap(c),await c.detail.render(o)}});function yr(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 vr(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 Pr=st;export{We as ACTIVE_ATTR,Ot as EDITOR_SELECTOR,Mt as EDITOR_TAGS,He as REQUESTS_ATTR,Rt as checkReactiveRegistration,Ke as countReactiveRequest,Pr as default,E as editableValue,je as enterReactiveActivity,xt as escapeRegExp,Ue as exitReactiveActivity,nt as loadReactiveFeature,De as onReactiveStreamWithoutEffects,Sr as reactiveActivityCount,Fr as reactiveFeatureNames,we as registerReactiveActions,dt as registerReactiveDefer,ae as registerReactiveDev,ft as registerReactiveDismiss,ft as registerReactiveEffects,Tr as registerReactiveFeature,y as registerReactiveFeatureLoader,lt as registerReactiveJs,bt as registerReactiveKeep,gt as registerReactiveModals,vt as registerReactiveMorphFocus,Tt as registerReactiveOffline,yt as registerReactivePlaintext,ft as registerReactiveStreamRender,ut as registerReactiveToken,ct as registerReactiveVisit,Er as resetReactiveActivity,ue as serverText,rt as unloadedFeaturesFor};
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
+ `);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 J=new WeakMap;function me(e){if(e?.hasAttribute?.("data-reactive-editable")&&!J.has(e))J.set(e,E(e))}function pe(e){return me(e),J.get(e)}function zt(e){return Kt.has(e.localName)?typeof e.value==="string":!0}var xe=Object.freeze({show:(e,t,r)=>Q(e,!1,t,r),hide:(e,t,r)=>Q(e,!0,t,r),toggle:(e,t,r)=>Q(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(ee(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(ee(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!ee(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)=>tr(e)?.focus?.(),show_modal:(e)=>je(e),close_dialog:(e)=>Et(e),text:(e,t)=>{let r=String(t.value??"");if(e.textContent!==r)e.textContent=r},copy_media:(e,t,r)=>{let n=null;try{n=r({...t,to:t.from})[0]??null}catch{}ct(e,n)},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=Vt(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)=>Gt(e),preview_file:(e,t,r)=>Yt(e,t,r),set_value:(e,t)=>Zt(e,String(t.value??"")),persist_state:(e,t)=>b("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>b("persist",(t)=>t.clearRoot(e))});function Vt(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function Gt(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;e.value=r,at(e),e.focus?.()}).catch(()=>{})}var R=new Map,N=null;function Yt(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return Re(`reads an input[type=file], not <${e?.localName}>`);let n=typeof r==="function"?r({...t,to:t.into})[0]:null;if(n?.tagName!=="IMG")return Re(`paints an <img>, and ${JSON.stringify(t.into)} is ${n?`a <${n.localName}>`:"not on the page"}`);let o=[...t.valid===!0&&e.validity?.valid===!1?[]:e.files??[]].find((a)=>typeof a?.type==="string"&&a.type.startsWith("image/"));if(ot(n),o){let a=URL.createObjectURL(o);R.set(n,a),n.setAttribute("src",a),Xt()}else n.removeAttribute("src");if(z(n),t.name==null)return;for(let a of r({...t,to:t.name}))a.textContent=o?o.name:""}function Re(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function ot(e){let t=R.get(e);if(t===void 0)return;if(R.delete(e),URL.revokeObjectURL(t),R.size===0)N?.disconnect(),N=null}function Xt(){if(N||typeof MutationObserver!=="function"||!document?.documentElement)return;N=new MutationObserver(()=>{for(let[e,t]of R)if(!e.isConnected||e.getAttribute("src")!==t)ot(e)}),N.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]})}function at(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function Zt(e,t){if(!/^(input|textarea|select)$/.test(e.localName)||e.type==="file"&&t!==""){console.warn("[phlex-reactive] set_value skipped: not a field it can write",e);return}let r=Ne(e);if(e.value=t,Ne(e)!==r)at(e)}function Ne(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
6
+ `):e.value}function Qt(e,t,r){if(r?.transition)Ut(e,r.transition,()=>e.hidden=t);else e.hidden=t}function Q(e,t,r,n){if(Qt(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 ee(e){if(!st(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function ct(e,t){if(e?.localName!=="img")return console.warn(`[phlex-reactive] copy_media targets an <img>, not <${e?.localName}> — skipped`),null;let r=t?.localName==="img"?t:null,n=r?.getAttribute("src"),i=!1;for(let a of["srcset","src"]){let s=n?r.getAttribute(a):null;if(s==null){if(e.hasAttribute(a))i=e.removeAttribute(a)??!0}else if(e.getAttribute(a)!==s)i=e.setAttribute(a,s)??!0}if(i)z(e);let o=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==o)e.setAttribute("alt",o);return r?o:!1}var er='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function tr(e){return e.querySelectorAll?.(er)?.[0]??null}function ge(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 Ie=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"}),Pe=Object.freeze(["meta","ctrl","alt","shift"]);function V(e,t,r){let n=e.split("+");for(let a of Pe)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Pe.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let o=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(Ie,i)?Ie[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof o==="string"&&o.toLowerCase()===t.key.toLowerCase()}var rr=(e)=>e&&typeof e==="object"?e.keys:String(e);function te(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 V(rr(e).replace(/^mod\+/,`${i}+`),t,r)}function nr(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:ge(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 Oe(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)!==mt(t.currentTarget))return!1;return i<0||r===null||V(n.slice(i+1),t,r)}function ir(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 Me=new WeakMap;function sr(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=Me.get(e);if(!i)i=new WeakMap,Me.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 Ce=new WeakMap;function or(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=Ce.get(e);if(!i)i=new WeakMap,Ce.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 ae(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,o={}]=n;if(!Object.hasOwn(xe,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)if(xe[i](s,o,t),o?.keep===!0)Ue(s,i,o,t)}}function ar(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 cr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function ut(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}function ur(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 lr(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], [data-reactive-media]")!=null}function dr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function fr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function lt(e){return e.getAttribute?.("data-reactive-presence")!=null}var hr=[["persist",[cr,null,null,!0]],["defer",[ut,null]],["form",[ur,null]],["bindings",[lr,null,null,!0]],["compute",[dr,null,null,!0]],["sortable",[fr,null]],["presence",[lt,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]]],A=new Map(hr),$e=new Map,p=new Map,mr=new Map;function y(e,t,r){dt.set(e,[t,r]),pr(e)}var dt=new Map;function pr(e){let t=A.get(e),[r,n]=dt.get(e);t[1]=r,t[2]=n}function Cr(e,t){t.install?.(P),p.set(e,t),mr.set(e,t)}function ft(e){let t=[];for(let[r,[n]]of A){if(!n||p.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function ht(e){return I(e).catch((t)=>H(e,"load",t))}function I(e){let t=$e.get(e);if(!t)t=(A.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(P),p.set(e,n),n)),$e.set(e,t);return t}var De=new Set;function H(e,t,r){let n=e+t;if(De.has(n))return;De.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);I(e).then(t,(n)=>H(e,"load",n))}var gr=1e4;function re(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:gr}function $r(){return[...A.keys()]}var qe=Promise.resolve();function Be(e,t,r){let n=P.waiting.get(e);if(n&&n[t]===r)delete n[t]}var P={enter:Ze,exit:Qe,count:rt,text:E,served:pe,waiting:new WeakMap};var O=Symbol.for("phlex-reactive.early"),br=1e4,yr=1500,mt=(e)=>e!=null&&(e===globalThis.window||e.window===e);function ne(){return globalThis[O]??={queue:[],connected:new WeakSet},globalThis[O]}function vr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:br}function _r(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 Ar(e,t,r){return{[O]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:_r(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 K=new WeakMap;function wr(e,{token:t,type:r,method:n,filter:i,win:o},a){let s=K.get(e);if(!s)K.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 We(e,t,r,n){if(e?.[O])return!1;let i=mt(e?.currentTarget),o=i?n:e?.currentTarget,a=Er(e,o,i?`@${t}`:t),s=K.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&&!V(l.filter,e,r))continue;return l.armed=!1,!0}return a}var W=new WeakMap;function Sr(e,t,r){let n=W.get(e);if(!n)W.set(e,n=new Map),setTimeout(()=>W.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Er(e,t,r){let n=e&&W.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class pt extends bt{static values={token:String};#_;#A=new Map;#l=new Map;#ee;#L;#j;#x=0;#d=new Map;#R=new WeakMap;#t;featuresReady=qe;#r=new Map;#N=new Set;#f=!1;#n=null;#h=new Map;#w=new Map;#m=new Map;#p=0;#U;#Pe=0;#Oe=0;connect(){if(it=!0,ne().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||ut(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===D)this.#K();this.#J(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(D,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(me),this.#p++,this.featuresReady=qe,this.#J(),j(this.element),this.#ie()}#Me(e){}#Ce(e,t,r,n){}#$e(){}#De(e,t){}#J(e){{let t=this.#p,r=[];for(let[o,[a]]of A){if(!a||this.#N.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.#N.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 A.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),A.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 ${re()} ms`));n(null)},re());this.#h.set(o,n);let a=()=>{clearTimeout(o),this.#h.delete(o)};I(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=A.get(e)[2];if(!t)return;let r={};try{this.#w.set(e,[t(this.element,r),r]),P.waiting.set(this.element,{...P.waiting.get(this.element),[e]:r})}catch(n){this.#g(e,"detect",n)}}}#H(e,t){{let[r,n]=this.#w.get(e)??[];if(this.#w.delete(e),!t)Be(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.#H(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.#K(),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.#$(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#B(e,t),applyOps:(e,t)=>ae(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:Ve,text:E,served:pe,copyMedia:ct,confirm:(e,t)=>Promise.resolve().then(()=>ye(e,t)).catch(()=>!1)},this.#U}#K(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#g(e,t,r){if(H(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.#H(t,!0),n=this.element;b(t,(i)=>{i.abandon?.(n,r),Be(n,t,r)})}this.#N.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()}#P=new Set;#se(){let{queue:e}=ne();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=vr(),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(yr,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.#q())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=Ar(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&&!V(c.filter,e,o))continue;if(/#\w+.*:once\b/.test(c.token)){if(!wr(s,c,n&&JSON.stringify(i.params)))continue;this.#P.add(s)}if(Sr(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?.(D,this.#t);ne().connected.delete(this.element),this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#P)K.delete(e);this.#P.clear()}dispatch(e){let t=e.params?.shortcut;if(t!=null&&!te(t,e,this.application?.schema?.keyMappings))return;if(We(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===Mt){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.#z(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.#S(S,f,v):v());this.#S(g,f,v)}#S(e,t,r){return Promise.resolve().then(()=>ye(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#z(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([I(e).catch((r)=>(H(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),re()))]).finally(()=>clearTimeout(t))}}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!te(t.shortcut,e,this.application?.schema?.keyMappings))return;if(We(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(or(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=nr(r.ops),o=i.filter((s)=>Oe(s,e,null)),a=o.length<=1?o:o.filter((s)=>Oe(s,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#q())this.#v((s)=>s.noBinding(this,e));return}for(let s of a){if(s.outside&&e[O])continue;if(!ir(s,e))continue;if(s.shortcut!=null&&!te(s.shortcut,e,this.application?.schema?.keyMappings))continue;if(sr(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.#z(t,r),l=()=>this.#Ee(this.#Se(e));if(!c)return l();if(c instanceof Promise)return c.then((d)=>d?this.#S(d,s,l):l());this.#S(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.#$();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.#V("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.#A.set(e,{timer:s,flush:a})}#M(e){let t=this.#A.get(e);if(!t)return;clearTimeout(t.timer),e?.removeEventListener?.("blur",t.flush),this.#A.delete(e)}#de(){for(let e of[...this.#A.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(Ye())return I("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.#Ae(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.#Ne()};if(!l)h["Content-Type"]="application/json";let k=this.#Ie();if(k)h["X-Pgbus-Connection"]=k;let M=lt(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(M)h["X-Reactive-Presence"]=M;let be=Pt(this.element);if(be)h["X-Reactive-Held"]=be;rt("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 k=this.#Y(h);if(this.#a=k??this.#a,m)this.#v((M)=>M.recordBody(m,h,k));Fe(this.element,h,!1)}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(Fe(this.element,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=Bt(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}#$(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#F(t)}#X(){let e={},t=[],r=this.#$(),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]${Ht}`).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?E(s):s.value??s.textContent??s.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!zt(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}#Ae(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.#k(s)}[]`;for(let d of c)i.append(l,String(d))}else this.#D(i,this.#k(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.#k(s)}[]`:this.#k(s);i.append(m,c,c.name)}return i}#k(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("")}`}#D(e,t,r){if(r==null)e.append(t,"");else if(Array.isArray(r))r.forEach((n,i)=>this.#D(e,`${t}[${i}]`,n));else if(typeof r==="object")for(let[n,i]of Object.entries(r))this.#D(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{}}}#Se(e){return ge(e)}#Ee(e){ae(e,(t)=>this.#W(t),(t,r)=>this.#B(`client op "${t}"`,r))}#q(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#C()}#B(e,t){if(!this.#q())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.#ke(e,t),Ze();let n=!1;return()=>{if(n)return;n=!0,this.#Le(e,t),Qe();for(let i of r.undo)i()}}#ke(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)}#Le(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.#L!=null)return this.#L;let e=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,t=Number(e);return this.#L=Number.isFinite(t)&&t>0?t:30000}#Ne(){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)Le();else document.addEventListener("turbo:load",Le,{once:!0});y("persist",()=>import("phlex/reactive/features/persist"),Tr);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"),Fr);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"));he();function Tr(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 Fr(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 kr=1000,F=null,gt,G=new Set;function Lr(e){return ht(e).then((t)=>{if(e!=="effects")return;gt=t,t?.sweep()})}ze((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,o=ft(xr(i)).filter((s)=>!G.has(s));if(!t&&!G.has("effects")&&Rr(i))o.push("effects");if(o.length===0&&!F)return t?.wrap(e);if(o.length>0){for(let c of o)G.add(c);let s=F=Promise.race([Promise.all([F,...o.map(Lr)]),new Promise((c)=>setTimeout(c,kr))]).then(()=>{if(F!==s)return;F=null,G.clear()})}let a=F;r.render=async(s)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??gt)?.wrap(c),await c.detail.render(s)}});function xr(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 Rr(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 Ur=pt;export{Xe as ACTIVE_ATTR,Ht as EDITOR_SELECTOR,Kt as EDITOR_TAGS,tt as REQUESTS_ATTR,Wt as checkReactiveRegistration,rt as countReactiveRequest,Ur as default,E as editableValue,Ze as enterReactiveActivity,Bt as escapeRegExp,Qe as exitReactiveActivity,ht as loadReactiveFeature,ze as onReactiveStreamWithoutEffects,Or as reactiveActivityCount,$r as reactiveFeatureNames,Le as registerReactiveActions,At as registerReactiveDefer,he as registerReactiveDev,wt as registerReactiveDismiss,wt as registerReactiveEffects,Cr as registerReactiveFeature,y as registerReactiveFeatureLoader,Lt as registerReactiveImageFallback,_t as registerReactiveJs,kt as registerReactiveKeep,Ft as registerReactiveModals,Rt as registerReactiveMorphFocus,Ct as registerReactiveOffline,xt as registerReactivePlaintext,wt as registerReactiveStreamRender,vt as registerReactiveToken,yt as registerReactiveVisit,Mr as resetReactiveActivity,pe as serverText,ft as unloadedFeaturesFor};
7
7
 
8
- //# debugId=C54300D531C86AC164756E2164756E21
8
+ //# debugId=6910A0CAAAD8BBBF64756E2164756E21
9
9
  //# sourceMappingURL=core.min.js.map