phlex-reactive 0.16.8 → 0.16.10

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: ad6b3f36ee0adf55ba7b675fe501c336b8e36cd721a4a2295a5a09d0c8090db0
4
- data.tar.gz: 9b18d1f2902dffe6dda93294d4a1b1c2c1459b2a4e17f2e885657fe084fbd32c
3
+ metadata.gz: fe73d6104157ba5f7134664ab8c7b3c6f168b36b2ac3ea10ede454469f442e85
4
+ data.tar.gz: 100e377a09a2a80e48af02a91808f3b8ce5d29c7b89aa2e6616dd880b6719460
5
5
  SHA512:
6
- metadata.gz: 1341aa9749c4e1ba1670addad51dc9595dd76de7cca4c565a634a17ef5f9b733b5140c6571eb3a5ffb6b1ffd1376fed37f31fce91d3600ab2319d67d02d43120
7
- data.tar.gz: 335953b023c4b62026c30a2fdf31a283413bcf5203b07d29a534658068fd5647abfcf9e6d60e5be0b5de9c3454e082341cc7ed8c229a17e746c9c3b9af339f17
6
+ metadata.gz: e9007ecf1e1e4628a4183a03b2d66152a85a004e00b90a2b65ac6c1395f248643a7a2e6067e11dbfb7cfa8619f38d836c871a97f84f7da96a87b2ae2032a12cd
7
+ data.tar.gz: 1cafa86d8dc5f8399f61856969ef2d8fc2668aaa74ce906382b0bb670f5e25b51923b7a4bc886fc0e005145958c13553ff06ec5f7b0e158855a3ca868e9faca1
data/CHANGELOG.md CHANGED
@@ -6,6 +6,68 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.16.10] - 2026-10-19
10
+
11
+ ### Fixed
12
+
13
+ - **`reactive_image_fallback` marks an `img` that failed before Turbo
14
+ inserted it (#452).** Turbo's frame render imports the fetched frame into
15
+ the document and inserts it a few awaits later; an `img` starts loading as
16
+ soon as it is imported, so one whose request failed in that gap fired
17
+ `error` on a detached node, where the client's document listener could not
18
+ hear it, and stayed on screen as a broken image. Once Turbo has inserted
19
+ new content (`turbo:frame-render` for the frame, `turbo:render` for the
20
+ page, and after a stream whose content holds a marked `img` has rendered),
21
+ the client now reads the result off every `img[data-reactive-image-fallback]`
22
+ that has no `data-reactive-image-state` yet and has finished: a
23
+ `naturalWidth` means `loaded`, otherwise `decode()` decides, as the scan at
24
+ registration already did. An `img` already marked is not touched, one still
25
+ loading is left to its own event, and nothing is fetched again.
26
+
27
+ ## [0.16.9] - 2026-10-19
28
+
29
+ ### Added
30
+
31
+ - **One client binding for a whole list: `:trigger`, `from:`/`attr:` reads and
32
+ `on_client(…, within:)` (#442).** Every client-op argument was a literal baked
33
+ at render, so a pickable list whose rows each write their own value and label
34
+ carried a full op chain on every row, differing in two or three literals.
35
+ Three parts now let the list bind once:
36
+ - **`:trigger`** (wire `"@trigger"`) targets the element whose `on_client`
37
+ binding fired, wherever an op takes a target (`to`, `expanded:`,
38
+ `submit(submitter:)`, `copy_media(from:)`). `set_value`, `paste_into` and
39
+ `preview_file` refuse it as their field. `JS.normalize_target` (pending
40
+ hints, `reactive_css_vars`) still refuses it.
41
+ - **`from:` + `attr:`** on `set_value`, `text` and `set_attr` read the value in
42
+ the browser off an element instead of a literal:
43
+ `js.set_value("#item-value", from: :trigger, attr: "data-value")`. `from:` is
44
+ `:trigger`, `:root` or a selector (the op's own scoping, `global:` included,
45
+ first match); `attr:` is a `data-*` attribute or `:text` (textContent),
46
+ enforced at render and again in the client. A missing attribute reads `""`;
47
+ a `from:` matching nothing skips the op. Exactly one of the value or `from:`.
48
+ **`dispatch(…, detail_from: { id: "data-id" })`** builds the event detail off
49
+ the trigger the same way, merged over `detail:` (a key in both raises).
50
+ - **`on_client(:click, ops, within: "[role=option]")`** runs the record only
51
+ for an event from inside an element matching the selector, under the bound
52
+ element and owned by this root; that element is the ops' `:trigger`.
53
+ Anywhere else is a complete no-op (no `preventDefault`, no confirm, no ops).
54
+ Keyboard picking through `reactive_listnav` and a click before the root
55
+ connects reach the same binding; before connect, `phlex/reactive/early`
56
+ leaves a click outside every row alone (a link in the list navigates). A
57
+ `within:` selector that does not parse runs nothing (verbose: warned). The bound element is not forced to
58
+ `type="button"`. `within:` raises with `window:`, `outside:`, `shortcut:` and
59
+ `once:` (Stimulus would drop a `:once` listener on its first event, a miss
60
+ included).
61
+
62
+ A server-pushed op has no trigger: `reply.js`, `broadcast_to(js:)` and
63
+ `reactive_on_complete` refuse `@trigger` and `detail_from:` (a chain or a raw
64
+ list). In the browser a stream op naming `@trigger`, or one in a window-bound
65
+ binding, resolves to nothing (verbose: warned). Every record that
66
+ asks for none of this is byte-identical. Client: the core gains 314 B
67
+ gzipped, the default bundle 364 B, `phlex/reactive/early` 129 B.
68
+
69
+ ## [0.16.8] - 2026-10-19
70
+
9
71
  ### Changed
10
72
 
11
73
  - **A `reactive_shared_field` drives its host's client bindings too (#440).**
@@ -4364,7 +4426,10 @@ room for dogfood fixes.
4364
4426
  scaffolds a reactive component (and an RSpec spec when the app uses RSpec),
4365
4427
  state-backed by default or record-backed with `--record`.
4366
4428
 
4367
- [Unreleased]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.7...HEAD
4429
+ [Unreleased]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.10...HEAD
4430
+ [0.16.10]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.9...v0.16.10
4431
+ [0.16.9]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.8...v0.16.9
4432
+ [0.16.8]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.7...v0.16.8
4368
4433
  [0.16.7]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.6...v0.16.7
4369
4434
  [0.16.6]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.5...v0.16.6
4370
4435
  [0.16.5]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.4...v0.16.5
data/README.md CHANGED
@@ -696,7 +696,7 @@ Use in controllers: `render turbo_stream: Counter.replace(counter)`.
696
696
  | `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). |
697
697
  | `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; `{ same: :email }` compares two fields, `{ digits: 10 }` checks a digit format, `after: :blur` waits for the field's first blur, and `clear:`/`focus:`/`scroll:` run when the section changes visibility. See [Value-conditional visibility](#value-conditional-visibility-reactive_show). |
698
698
  | `reactive_media(from:, pool:, take:, match:, when:, 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); `when:` (same rules) tests the **whole field** before the pool lookup while the key stays the prefix, so `take: 3, when: /\A\d{3,24}\z/` keeps `007bad` pending (#390); `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). |
699
- | `reactive_image_fallback(hide: true, show_alt: nil, wrap: 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; `wrap:` (#392) hides the box around it (marked `data-reactive-wrap-hidden`, shown again only when it carries that mark, its text never written); `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). |
699
+ | `reactive_image_fallback(hide: true, show_alt: nil, wrap: 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; `wrap:` (#392) hides the box around it (marked `data-reactive-wrap-hidden`, shown again only when it carries that mark, its text never written); `load` sets `"loaded"`. An `img` that finished before Turbo inserted it (a frame, a page or a stream render, #452) is marked once it is in. 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). |
700
700
  | `reactive_countdown(until:, format: :ms, waiting:, done:)` | A server **deadline counted down** on the client (#400): `until:` is an ISO8601 date-time with a zone (or a `Time`); the text is the time left from `Date.now` (`1:30`), as `textContent`, once a second and again when a hidden tab is shown. At zero (or already past on connect) it reads `0:00`, `data-reactive-countdown-state="done"`, `waiting:` hides, `done:` shows and `reactive:countdown-done` fires **once per deadline** (a morph that keeps `until:` does not fire again; a new `until:` restarts). The server renders the first text and visibility. No request, no frame reload. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
701
701
  | `reactive_css_vars(to:, vars:, global: false)` | Fields that **feed CSS custom properties** on an element (#417), for a preview that follows a control with no request: `vars: { "--light" => "light", "--turn" => { field: "turn", unit: "deg" } }`. Each field is read as `reactive_show` reads one (a checkbox gives `1`/`0`, a radio group its checked value) and parsed as a **finite number**; the client writes `number + unit` with `style.setProperty`, and anything else (empty, text) removes the property so the `var()` fallback applies. No text from a field reaches CSS. Units: `""`, `px`, `%`, `deg`, `turn`, `ms`, `s`, `em`, `rem`, `fr`; names match `--[a-zA-Z0-9-]+`; a bad name or unit or a blank field raises at render. Runs on connect, on `input`/`change` and after a morph. `to:` resolves like a client op's (`:root`, inside the root, `global: true`, an Array). Render the same properties inline for the first paint. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
702
702
  | `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). |
@@ -1357,9 +1357,64 @@ vocabulary is a fixed whitelist mirrored by the client: `show`/`hide`/`toggle`
1357
1357
  flip the `hidden` attribute; `add_class`/`remove_class`/`toggle_class` take one
1358
1358
  or more classes. Targets are CSS selectors resolved **within the component's
1359
1359
  root** (nested reactive components are never touched — same ownership rule as
1360
- field collection); `:root` targets the root element itself; `global: true` on
1361
- an op escapes to the whole document. An op name the client doesn't recognize
1362
- logs a warning and is skipped — the rest of the chain still applies.
1360
+ field collection); `:root` targets the root element itself; `:trigger` (#442)
1361
+ targets the element whose `on_client` binding fired (see "One binding for a
1362
+ list" below); `global: true` on an op escapes to the whole document. An op name
1363
+ the client doesn't recognize logs a warning and is skipped — the rest of the
1364
+ chain still applies.
1365
+
1366
+ **One binding for a list (#442).** A list whose rows each write their own value
1367
+ binds **once**: `within:` delegates the record to the rows, `:trigger` is the
1368
+ row that was picked, and `from:` + `attr:` read the row's value off it instead
1369
+ of baking a literal into every row:
1370
+
1371
+ ```ruby
1372
+ ul(id: "menu", role: "listbox", **on_client(:click, js
1373
+ .set_value("#item-value", from: :trigger, attr: "data-value")
1374
+ .text("#item-label", from: :trigger, attr: "data-label")
1375
+ .remove_attr("[role=option]", "aria-selected")
1376
+ .set_attr(:trigger, "aria-selected", "true")
1377
+ .dispatch("app:item-picked", detail_from: { id: "data-id", text: :text }),
1378
+ within: "[role=option]")) do
1379
+ @items.each do |item|
1380
+ li { button(role: "option", data: { id: item.id, value: item.value, label: item.label }) { item.label } }
1381
+ end
1382
+ end
1383
+ ```
1384
+
1385
+ - **`within: "[role=option]"`** runs the record only for an event from inside an
1386
+ element matching the selector, under the bound element and owned by this root
1387
+ (a row of a nested reactive root is that root's). That element is the ops'
1388
+ `:trigger`. Anywhere else (the list's padding, a heading) is a complete no-op:
1389
+ no `preventDefault`, no confirm, no ops. Keyboard picking needs
1390
+ `reactive_listnav` on the search input (not on the rows): Enter on the row it
1391
+ highlights clicks that row, which goes through the same binding, and so does a click before the
1392
+ root connects (`phlex/reactive/early` queues a row's click and leaves a click
1393
+ outside every row alone, so a link in the list still navigates; a row inside
1394
+ a nested reactive root is held too, and its replay is a miss). A `within:`
1395
+ selector that does not parse runs nothing, warned under `verbose_errors`. The
1396
+ list is not forced to `type="button"`. It raises with
1397
+ `window:`, `outside:`, `shortcut:` and `once:` (Stimulus drops a `:once`
1398
+ listener on its first event, a miss included).
1399
+ - **`:trigger`** is accepted wherever an op takes a target, and by `expanded:`,
1400
+ `submit(submitter:)` and `copy_media(from:)`. Without `within:` it is the
1401
+ element the binding is on. `set_value`, `paste_into` and `preview_file` refuse
1402
+ it as the field they write.
1403
+ - **`from:` + `attr:`** on `set_value`, `text` and `set_attr` replace the literal
1404
+ value: `from:` is `:trigger`, `:root` or a selector (the op's own scoping,
1405
+ `global:` included, first match); `attr:` is a `data-*` attribute or `:text`
1406
+ (the element's `textContent`) — nothing else, at render and again in the
1407
+ client. A missing attribute reads `""` (it clears); a `from:` that matches
1408
+ nothing skips the op. The write side keeps its own rules (`set_attr`'s name
1409
+ allowlist, `text`'s `textContent`, `set_value`'s `.value`).
1410
+ - **`dispatch(…, detail_from: { key => attr })`** builds the event's detail off
1411
+ the trigger, every value a String, merged over `detail:` (a key in both
1412
+ raises).
1413
+ - A server-pushed op has no trigger: `reply.js`, `broadcast_to(js:)` and
1414
+ `reactive_on_complete` raise on `:trigger`, `from: :trigger` and
1415
+ `detail_from:`. Nor does a window-bound `on_client` (`window:`, `outside:`,
1416
+ `shortcut:`): its `:trigger` ops resolve to nothing, warned under
1417
+ `verbose_errors`.
1363
1418
 
1364
1419
  In development and test (`verbose_errors`), an op whose selector resolves to
1365
1420
  **zero elements** also warns once per unique (op, selector, scope) — with a
@@ -1421,10 +1476,10 @@ button(**on_client(:click, js
1421
1476
  powerful than `set_attr`. With `global: true` it is the **cross-root text
1422
1477
  escape**: paint a value into a recap node outside the component's root
1423
1478
  (`js.text("#sum_total", total, global: true)`).
1424
- - **`dispatch(name, to: nil, detail: {})`** emits a **bubbling `CustomEvent`** so
1479
+ - **`dispatch(name, to: nil, detail: {}, detail_from: {})`** emits a **bubbling `CustomEvent`** so
1425
1480
  another component or a plain Stimulus controller can react to a client-only
1426
1481
  interaction — `to:` picks the element (default: the component root), `detail:`
1427
- is the payload.
1482
+ is the payload, and `detail_from:` (#442) adds values read off the trigger.
1428
1483
  - **`submit(to = :root)`** commits the **target's own form** via
1429
1484
  `requestSubmit()`: the target itself when it *is* a form, its form owner for a
1430
1485
  control (`input.form`, honoring a `form=` attribute), else the nearest ancestor
@@ -1,9 +1,9 @@
1
- import{Controller as Rt}from"@hotwired/stimulus";import{confirmResolver as Re}from"phlex/reactive/confirm";function Nt(){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 Ot(){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)}}var It=["focus","focus_first","blur"];function Pt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=Te(this.getAttribute("data-reactive-ops"));if(!t.length)return;let r=this.getAttribute("target"),n=this.getAttribute("data-reactive-verbose")==="true",i=r?document.getElementById(r):null;if(r&&!i){if(n)y("devtools",(o)=>o.missingRoot(r));return}let s=(o)=>me(o,(c)=>Ar(c,i),n?(c,u)=>y("devtools",(d)=>d.diagnoseStream(c,u,i)):void 0),a=t.findIndex((o)=>It.includes(o?.[0]));if(a<0||typeof requestAnimationFrame!=="function")return s(t);s(t.slice(0,a)),requestAnimationFrame(()=>s(t.slice(a)))}}function Mt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){y("defer",(t)=>t.streamAction(this))}}var Ne=!1,le=null;function Ct(){if(Ne)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ne=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Vt(e),Dt(e),qt(e),le)le(e,g.get("effects"));else g.get("effects")?.wrap(e)})}var U="reactive:streamed";function Dt(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 u of a?[document.getElementById(a)]:o?document.querySelectorAll(o):[]){let d=(s?u:u?.parentElement)?.closest?.('[data-controller~="reactive"]');if(d)c.add(d)}if(c.size===0)return;t.render=async(u)=>{await r(u);for(let d of c)if(d.isConnected)d.dispatchEvent(new Event(U))}}function ge(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function be(e){try{return e.matches(":modal")}catch{return!1}}function et(e){if(!ge(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||be(e))return;if(e.open)e.close();e.showModal()}function $t(e){if(ge(e)&&e.open)e.close()}function V(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&&!be(n))et(n)}function qt(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),V(document)}}var Oe=!1;function Wt(){if(Oe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Oe=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))V(t.target)}),document.addEventListener("turbo:morph",()=>V(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!ge(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||!be(r))return;e.delete(r),t.preventDefault(),r.close()})}var de=new WeakMap;function tt(e,t,r,n){let i=de.get(e)??new Map;de.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"))vt(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}))tt(a,"set_attr",{name:"aria-expanded"})}}var Ie=!1;function Bt(){if(Ie)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ie=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of de.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 rt="data-reactive-image-fallback",R="data-reactive-image-state",fe="data-reactive-image-hidden",ne=null,he="data-reactive-wrap-hidden";function nt(e){if(e.hasAttribute("hidden"))return;e.setAttribute("hidden",""),e.setAttribute(he,"")}function it(e){if(!e.hasAttribute(he))return;e.removeAttribute("hidden"),e.removeAttribute(he)}function N(e){if(e?.localName!=="img")return null;let t=e.getAttribute(rt);if(t==null)return null;try{return JSON.parse(t)||{}}catch{return{}}}var ot=(e)=>e.getAttribute("src")||e.getAttribute("srcset");function ye(e,t){if(typeof t!=="string"||!t)return null;try{return e.closest('[data-controller~="reactive"]')?.querySelector(t)??null}catch{return null}}function st(e,t){let r=ye(e,t.alt);return r&&!r.contains(e)?r:null}function Y(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(fe,"");if(t.wrap){let i=ye(e,t.wrap);if(i)nt(i);else console.warn(`[phlex-reactive] reactive_image_fallback wrap: ${JSON.stringify(t.wrap)} is not in the root — skipped`)}let n=st(e,t);if(n)n.textContent=e.getAttribute("alt")??"",n.hidden=!1}else ee(e,t);e.setAttribute(R,r)}function ee(e,t=N(e)){if(!t||e.getAttribute(R)==null)return;if(e.getAttribute(R)==="error"){if(e.hasAttribute(fe))e.removeAttribute("hidden");let r=ye(e,t.wrap);if(r)it(r);let n=st(e,t);if(n)n.hidden=!0}e.removeAttribute(R),e.removeAttribute(fe)}function Pe(e){let t=e.target,r=N(t);if(!r)return;if(e.type==="load")Y(t,r,"loaded");else if(ot(t))Y(t,r,"error");else ee(t,r)}function jt(){if(ne)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;ne={error:Pe,load:Pe,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(R);if(i==null||!n||!N(r))return;let s=(a)=>r.getAttribute(a)===n.getAttribute?.(a);if(s("src")&&s("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=N(r);if(i)Y(r,i,n)})}};for(let[t,r]of Object.entries(ne))document.addEventListener(t,r,!0);for(let t of document.querySelectorAll?.(`img[${rt}]`)??[]){if(!t.complete||!ot(t))continue;let r=`${t.getAttribute("src")} ${t.getAttribute("srcset")}`,n=(i)=>`${t.getAttribute("src")} ${t.getAttribute("srcset")}`===r&&Y(t,N(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 at(e){le=e}var q,ie=null,Me="[data-reactive-editable][contenteditable=plaintext-only]";function ct(){if(q===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",q=e.contentEditable==="plaintext-only"}catch{q=!1}return q}function J(e){if(e.matches?.(Me))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Me).forEach(J)}function Ut(){if(ie||typeof document>"u"||typeof document.createElement!=="function")return;if(ct())return;J(document),ie=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")J(t.target);else t.addedNodes.forEach(J)}),ie.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var Ce=!1;function De(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 Jt(){if(Ce)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ce=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=De(t);if(n)zt(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(X.set(t,T(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)=>Se(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&De(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&_e(t)===we(t))t.removeAttribute(_)})}var _="data-reactive-held",ve='[data-controller~="reactive"]',H=null,k=new Map;function _e(e){return e.hasAttribute("data-reactive-editable")?T(e):e.value}function we(e){return e.hasAttribute("data-reactive-editable")?Ee(e):e.defaultValue}function Ht(e){if(e.hasAttribute("data-reactive-editable"))return T(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function zt(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||k.has(e.closest(ve)))return;let n=Ht(t);if(n===_e(e))return e.removeAttribute(_);if(n===we(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function Kt(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(ve)!==e)continue;let n=r.getAttribute("name");if(_e(r)===we(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 ut(e,t){if(t===!0)return;for(let r of e.querySelectorAll(`[${_}]`))if(r.closest(ve)===e&&!t?.includes(r.getAttribute("name")))r.removeAttribute(_)}function Gt(e){let t=e.headers.get("X-Reactive-Refused");if(t==="*")return!0;try{let r=JSON.parse(t);return Array.isArray(r)?r:null}catch{return null}}function $e(e,t,r=null){let n={root:e,streams:0,keep:r},i=H;H=n;try{window.Turbo.renderStreamMessage(t)}finally{H=i}if(n.streams===0)ut(e,r)}function Vt(e){let t=H,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{k.set(t.root,(k.get(t.root)||0)+1);try{return await n(i)}finally{let s=k.get(t.root)-1;if(s)k.set(t.root,s);else k.delete(t.root);ut(t.root,t.keep)}}}var qe="__materialize",We=!1;function Yt(){if(We)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;We=!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 Xt="phlex-reactive:latency";function lt(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Xt))}function Ae(){if(typeof document>"u")return;if(!g.has("devtools")&&!w.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||lt())y("devtools",(t)=>e&&t.attach())}var dt="data-reactive-active",A=0;function ft(){if(A++,A===1)mt("reactive:busy")}function ht(){if(A===0)return;if(A--,A===0)mt("reactive:idle")}function Qr(){return A}function en(){A=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(dt)}function mt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(dt,A>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:A}}))}var pt="data-reactive-requests";function gt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Zt(t))return;let r=Qt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(pt,JSON.stringify(r))}function Zt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Qt(e){try{let t=JSON.parse(e.getAttribute(pt));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function Be(){Nt(),Ot(),Pt(),Mt(),Ct(),Jt(),Wt(),Bt(),jt(),Ut(),Yt(),Ae()}function er(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var bt=Symbol.for("phlex-reactive.core");if(globalThis[bt])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[bt]=!0;var yt=!1;function tr(){if(yt)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(tr,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var rr=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function vt(e){let t=String(e).toLowerCase();return t.startsWith("on")||rr.has(t)}var oe=new WeakMap;function nr(e,t,r){let[n,i,s]=t;oe.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,oe.delete(e),clearTimeout(u),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};oe.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let u=setTimeout(c,ir(e))}function ir(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 or=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",sr=new Set(["lexxy-editor","trix-editor"]);function T(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
1
+ import{Controller as Nt}from"@hotwired/stimulus";import{confirmResolver as Oe}from"phlex/reactive/confirm";function Ot(){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 It(){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)}}var Pt=["focus","focus_first","blur"];function Mt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=ke(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)v("devtools",(o)=>o.missingRoot(r));return}let s=(o)=>pe(o,(c)=>Fr(c,i),n?(c,u)=>v("devtools",(d)=>d.diagnoseStream(c,u,i)):void 0),a=t.findIndex((o)=>Pt.includes(o?.[0]));if(a<0||typeof requestAnimationFrame!=="function")return s(t);s(t.slice(0,a)),requestAnimationFrame(()=>s(t.slice(a)))}}function Ct(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){v("defer",(t)=>t.streamAction(this))}}var Ie=!1,de=null;function Dt(){if(Ie)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ie=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Yt(e),$t(e),Wt(e),de)de(e,g.get("effects"));else g.get("effects")?.wrap(e)})}var J="reactive:streamed";function $t(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 u of a?[document.getElementById(a)]:o?document.querySelectorAll(o):[]){let d=(s?u:u?.parentElement)?.closest?.('[data-controller~="reactive"]');if(d)c.add(d)}if(c.size===0)return;t.render=async(u)=>{await r(u);for(let d of c)if(d.isConnected)d.dispatchEvent(new Event(J))}}function be(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function ye(e){try{return e.matches(":modal")}catch{return!1}}function rt(e){if(!be(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||ye(e))return;if(e.open)e.close();e.showModal()}function qt(e){if(be(e)&&e.open)e.close()}function Y(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&&!ye(n))rt(n)}function Wt(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),Y(document)}}var Pe=!1;function Bt(){if(Pe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Pe=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))Y(t.target)}),document.addEventListener("turbo:morph",()=>Y(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!be(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||!ye(r))return;e.delete(r),t.preventDefault(),r.close()})}var fe=new WeakMap;function nt(e,t,r,n){let i=fe.get(e)??new Map;fe.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"))_t(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}))nt(a,"set_attr",{name:"aria-expanded"})}}var Me=!1;function jt(){if(Me)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Me=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of fe.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 ve="data-reactive-image-fallback",L="data-reactive-image-state",he="data-reactive-image-hidden",ie=null,me="data-reactive-wrap-hidden";function it(e){if(e.hasAttribute("hidden"))return;e.setAttribute("hidden",""),e.setAttribute(me,"")}function ot(e){if(!e.hasAttribute(me))return;e.removeAttribute("hidden"),e.removeAttribute(me)}function P(e){if(e?.localName!=="img")return null;let t=e.getAttribute(ve);if(t==null)return null;try{return JSON.parse(t)||{}}catch{return{}}}var st=(e)=>e.getAttribute("src")||e.getAttribute("srcset");function _e(e,t){if(typeof t!=="string"||!t)return null;try{return e.closest('[data-controller~="reactive"]')?.querySelector(t)??null}catch{return null}}function at(e,t){let r=_e(e,t.alt);return r&&!r.contains(e)?r:null}function X(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(he,"");if(t.wrap){let i=_e(e,t.wrap);if(i)it(i);else console.warn(`[phlex-reactive] reactive_image_fallback wrap: ${JSON.stringify(t.wrap)} is not in the root — skipped`)}let n=at(e,t);if(n)n.textContent=e.getAttribute("alt")??"",n.hidden=!1}else te(e,t);e.setAttribute(L,r)}function te(e,t=P(e)){if(!t||e.getAttribute(L)==null)return;if(e.getAttribute(L)==="error"){if(e.hasAttribute(he))e.removeAttribute("hidden");let r=_e(e,t.wrap);if(r)ot(r);let n=at(e,t);if(n)n.hidden=!0}e.removeAttribute(L),e.removeAttribute(he)}function Ce(e){let t=e.target,r=P(t);if(!r)return;if(e.type==="load")X(t,r,"loaded");else if(st(t))X(t,r,"error");else te(t,r)}function Ut(){if(ie)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;ie={error:Ce,load:Ce,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(L);if(i==null||!n||!P(r))return;let s=(a)=>r.getAttribute(a)===n.getAttribute?.(a);if(s("src")&&s("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=P(r);if(i)X(r,i,n)})},"turbo:frame-render":(t)=>q(t.target),"turbo:render":()=>q(document),"turbo:before-stream-render":(t)=>{let r=t.detail,n=r?.render,i=r?.newStream??t.target;if(typeof n!=="function"||!i?.querySelector?.("template")?.content?.querySelector?.(`img[${ve}]`))return;r.render=async(s)=>{await n(s),q(document)}}};for(let[t,r]of Object.entries(ie))document.addEventListener(t,r,!0);q(document)}function q(e){for(let t of e?.querySelectorAll?.(`img[${ve}]`)??[]){if(t.getAttribute(L)!=null||!t.complete||!st(t))continue;let r=`${t.getAttribute("src")} ${t.getAttribute("srcset")}`,n=(i)=>`${t.getAttribute("src")} ${t.getAttribute("srcset")}`===r&&X(t,P(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 ct(e){de=e}var W,oe=null,De="[data-reactive-editable][contenteditable=plaintext-only]";function ut(){if(W===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",W=e.contentEditable==="plaintext-only"}catch{W=!1}return W}function z(e){if(e.matches?.(De))e.setAttribute("contenteditable","true");e.querySelectorAll?.(De).forEach(z)}function Jt(){if(oe||typeof document>"u"||typeof document.createElement!=="function")return;if(ut())return;z(document),oe=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")z(t.target);else t.addedNodes.forEach(z)}),oe.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var $e=!1;function qe(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 zt(){if($e)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;$e=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=qe(t);if(n)Kt(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(Q.set(t,T(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)=>Te(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&qe(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&Ae(t)===Se(t))t.removeAttribute(_)})}var _="data-reactive-held",we='[data-controller~="reactive"]',H=null,k=new Map;function Ae(e){return e.hasAttribute("data-reactive-editable")?T(e):e.value}function Se(e){return e.hasAttribute("data-reactive-editable")?Fe(e):e.defaultValue}function Ht(e){if(e.hasAttribute("data-reactive-editable"))return T(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function Kt(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||k.has(e.closest(we)))return;let n=Ht(t);if(n===Ae(e))return e.removeAttribute(_);if(n===Se(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function Vt(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(we)!==e)continue;let n=r.getAttribute("name");if(Ae(r)===Se(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 lt(e,t){if(t===!0)return;for(let r of e.querySelectorAll(`[${_}]`))if(r.closest(we)===e&&!t?.includes(r.getAttribute("name")))r.removeAttribute(_)}function Gt(e){let t=e.headers.get("X-Reactive-Refused");if(t==="*")return!0;try{let r=JSON.parse(t);return Array.isArray(r)?r:null}catch{return null}}function We(e,t,r=null){let n={root:e,streams:0,keep:r},i=H;H=n;try{window.Turbo.renderStreamMessage(t)}finally{H=i}if(n.streams===0)lt(e,r)}function Yt(e){let t=H,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{k.set(t.root,(k.get(t.root)||0)+1);try{return await n(i)}finally{let s=k.get(t.root)-1;if(s)k.set(t.root,s);else k.delete(t.root);lt(t.root,t.keep)}}}var Be="__materialize",je=!1;function Xt(){if(je)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;je=!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 Qt="phlex-reactive:latency";function dt(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Qt))}function Ee(){if(typeof document>"u")return;if(!g.has("devtools")&&!w.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||dt())v("devtools",(t)=>e&&t.attach())}var ft="data-reactive-active",A=0;function ht(){if(A++,A===1)pt("reactive:busy")}function mt(){if(A===0)return;if(A--,A===0)pt("reactive:idle")}function nn(){return A}function on(){A=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(ft)}function pt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(ft,A>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:A}}))}var gt="data-reactive-requests";function bt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Zt(t))return;let r=er(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(gt,JSON.stringify(r))}function Zt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function er(e){try{let t=JSON.parse(e.getAttribute(gt));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function Ue(){Ot(),It(),Mt(),Ct(),Dt(),zt(),Bt(),jt(),Ut(),Jt(),Xt(),Ee()}function tr(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var yt=Symbol.for("phlex-reactive.core");if(globalThis[yt])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[yt]=!0;var vt=!1;function rr(){if(vt)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(rr,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var nr=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function _t(e){let t=String(e).toLowerCase();return t.startsWith("on")||nr.has(t)}var se=new WeakMap;function ir(e,t,r){let[n,i,s]=t;se.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,se.delete(e),clearTimeout(u),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};se.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let u=setTimeout(c,or(e))}function or(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 sr=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",ar=new Set(["lexxy-editor","trix-editor"]);function T(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
2
2
  `))t+=`
3
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
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 X=new WeakMap;function Se(e){if(e?.hasAttribute?.("data-reactive-editable")&&!X.has(e))X.set(e,T(e))}function Ee(e){return Se(e),X.get(e)}function ar(e){return sr.has(e.localName)?typeof e.value==="string":!0}var je=Object.freeze({show:(e,t,r)=>se(e,!1,t,r),hide:(e,t,r)=>se(e,!0,t,r),toggle:(e,t,r)=>se(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(ae(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(ae(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!ae(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)=>gr(e)?.focus?.(),blur:(e)=>{let t=e.ownerDocument?.activeElement??globalThis.document?.activeElement;if(t&&(t===e||e.contains?.(t)))t.blur?.()},show_modal:(e)=>et(e),close_dialog:(e)=>$t(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{}St(e,n)},check_group:(e,t)=>{let r=t.global?document.querySelectorAll('[data-controller~="reactive"]'):[e];for(let n of r)y("bindings",(i)=>i.checkGroup(n,t.group,t.checked))},presence:(e,t)=>y("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=cr(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)=>ur(e),preview_file:(e,t,r)=>lr(e,t,r),set_value:(e,t)=>At(e,String(t.value??"")),persist_state:(e,t)=>y("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>y("persist",(t)=>t.clearRoot(e))});function cr(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function ur(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;e.value=r,wt(e),e.focus?.()}).catch(()=>{})}var O=new Map,I=null;function lr(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return z(`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 z(`paints an <img>, and ${JSON.stringify(t.into)} is ${n?`a <${n.localName}>`:"not on the page"}`);let i=[...t.valid===!0&&e.validity?.valid===!1?[]:e.files??[]],s=fr(e,t.accept),a=(u)=>Number.isInteger(t.max_bytes)&&u.size>t.max_bytes,o=[],c;if(t.per_file===!0&&e.multiple){let u=i.filter((f,h)=>{let p=typeof f?.type==="string"&&s(f)?a(f)&&"size":"type";if(p)o.push({reason:p,file:f,index:h});return!p}),d=o.length>0&&!dr(e,u)?i.length:u.length;for(let f of o)f.remaining=d;c=u.find((f)=>f.type.startsWith("image/"))}else{let u=i.filter((f)=>typeof f?.type==="string"&&s(f));c=u.find((f)=>f.type.startsWith("image/"));let d=i.length>0&&u.length===0?"type":null;if(c&&a(c))d="size";if(d)o.push({reason:d,file:d==="size"?c:i[0]}),c=null}if(_t(n),c){let u=URL.createObjectURL(c);O.set(n,u),n.setAttribute("src",u),hr()}else n.removeAttribute("src");if(ee(n),t.wrap!=null){let u=r({...t,to:t.wrap});if(u.length===0)z(`wrap: ${JSON.stringify(t.wrap)} is not on the page`);for(let d of u)c?it(d):nt(d)}if(t.name!=null)for(let u of r({...t,to:t.name}))u.textContent=c?c.name:"";for(let u of o)e.dispatchEvent(new CustomEvent("reactive:file-rejected",{bubbles:!0,detail:u}))}function dr(e,t){if(typeof DataTransfer!=="function"){if(e.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))z("per_file: has no DataTransfer to drop the refused files from the input");return!1}let r=new DataTransfer;for(let n of t)r.items.add(n);return e.files=r.files,!0}function fr(e,t){let r=String((t===!0?e.getAttribute("accept"):typeof t==="string"&&t)||"").toLowerCase().split(",").map((n)=>n.trim()).filter(Boolean);if(r.length===0)return(n)=>n.type.startsWith("image/");return(n)=>{let i=n.type.toLowerCase();return r.some((s)=>s[0]==="."?String(n.name).toLowerCase().endsWith(s):s.endsWith("/*")?i.startsWith(s.slice(0,-1)):i===s)}}function z(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function _t(e){let t=O.get(e);if(t===void 0)return;if(O.delete(e),URL.revokeObjectURL(t),O.size===0)I?.disconnect(),I=null}function hr(){if(I||typeof MutationObserver!=="function"||!document?.documentElement)return;I=new MutationObserver(()=>{for(let[e,t]of O)if(!e.isConnected||e.getAttribute("src")!==t)_t(e)}),I.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]})}function wt(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function At(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=Ue(e);if(e.value=t,Ue(e)!==r)wt(e)}function Ue(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
6
- `):e.value}function mr(e,t,r){if(r?.transition)nr(e,r.transition,()=>e.hidden=t);else e.hidden=t}function se(e,t,r,n){if(mr(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 ae(e){if(!vt(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function St(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 o=n?r.getAttribute(a):null;if(o==null){if(e.hasAttribute(a))i=e.removeAttribute(a)??!0}else if(e.getAttribute(a)!==o)i=e.setAttribute(a,o)??!0}if(i)ee(e);let s=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==s)e.setAttribute("alt",s);return r?s:!1}var pr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function gr(e){return e.querySelectorAll?.(pr)?.[0]??null}function Te(e){if(Array.isArray(e))return e;if(typeof e!=="string")return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}var Je=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"}),He=Object.freeze(["meta","ctrl","alt","shift"]);function te(e,t,r){let n=e.split("+");for(let a of He)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!He.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let s=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(Je,i)?Je[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof s==="string"&&s.toLowerCase()===t.key.toLowerCase()}var br=(e)=>e&&typeof e==="object"?e.keys:String(e),Fe=()=>K().prevented??=new WeakSet;function ce(e,t){if(t!=null&&!e.defaultPrevented)Fe().add(e);e.preventDefault()}function W(e,t,r){if(t.defaultPrevented&&e?.handled!==!0&&!Fe().has(t))return!1;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 te(br(e).replace(/^mod\+/,`${i}+`),t,r)}function yr(e){if(Array.isArray(e))return[{ops:e,legacy:!0}];if(e&&typeof e==="object")return[e];if(typeof e!=="string")return[];let t=e.trim();if(t.startsWith("["))return[{ops:Te(t),legacy:!0}];let r=[];for(let n of t.split(" ")){if(n==="")continue;let i=null;try{i=JSON.parse(n)}catch{i=null}if(i&&typeof i==="object"&&!Array.isArray(i))r.push(i);else console.warn(`[phlex-reactive] malformed on_client binding record ${JSON.stringify(n)} — skipped`)}return r}function ze(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)!==Le(t.currentTarget))return!1;return i<0||r===null||te(n.slice(i+1),t,r)}function vr(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 _r(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 Ge=new WeakMap;function wr(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=Ge.get(e);if(!i)i=new WeakMap,Ge.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 me(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn(je,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(je[i](o,s,t),s?.keep===!0)tt(o,i,s,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 Sr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function ke(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}var F='[data-controller~="reactive"]',Er='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',pe=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!ke(e);function x(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&pe(n))n=n.parentElement?.closest?.(t);return n??null}var B=new WeakMap,j=new WeakMap;function Tr(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 Fr(e){return["show-targets","group-targets","on-complete","filter-input","tags-field","css-vars"].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], [data-reactive-css-vars]")!=null}function kr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function Lr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function xr(e){return Boolean(e.matches?.("[data-reactive-frame],[data-reactive-box],[data-reactive-point]")||e.querySelector?.("[data-reactive-frame],[data-reactive-box],[data-reactive-point]"))}function Et(e){return e.getAttribute?.("data-reactive-presence")!=null}function Rr(e){return Boolean(e.matches?.("[data-reactive-countdown]")||e.querySelector?.("[data-reactive-countdown]"))}var Nr=[["persist",[Sr,null,null,!0]],["defer",[ke,null]],["form",[Tr,null]],["bindings",[Fr,null,null,!0]],["compute",[kr,null,null,!0]],["sortable",[Lr,null]],["drag",[xr,null]],["presence",[Et,null]],["countdown",[Rr,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(Nr),Ve=new Map,g=new Map,Or=new Map;function b(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 tn(e,t){t.install?.(M),g.set(e,t),Or.set(e,t)}function Ft(e){let t=[];for(let[r,[n]]of w){if(!n||g.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function kt(e){return P(e).catch((t)=>Z(e,"load",t))}function P(e){let t=Ve.get(e);if(!t)t=(w.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(M),g.set(e,n),n)),Ve.set(e,t);return t}var Ye=new Set;function Z(e,t,r){let n=e+t;if(Ye.has(n))return;Ye.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 y(e,t){let r=g.get(e);if(r)return t(r);P(e).then(t,(n)=>Z(e,"load",n))}var Pr=1e4;function ue(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:Pr}function rn(){return[...w.keys()]}var Xe=Promise.resolve();function Ze(e,t,r){let n=M.waiting.get(e);if(n&&n[t]===r)delete n[t]}var M={enter:ft,exit:ht,count:gt,text:T,served:Ee,waiting:new WeakMap};var C=Symbol.for("phlex-reactive.early"),Mr=1e4,Cr=1500,Le=(e)=>e!=null&&(e===globalThis.window||e.window===e),Dr="dispatch";function K(){return globalThis[C]??={queue:[],connected:new WeakSet},globalThis[C]}function $r(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:Mr}function qr(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 Wr(e,t,r){return{[C]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:qr(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&&!Fe().has(e),preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var Q=new WeakMap;function Br(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=Q.get(e);if(!o)Q.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 Qe(e,t,r,n){if(e?.[C])return!1;let i=Le(e?.currentTarget),s=i?n:e?.currentTarget,a=Ur(e,s,i?`@${t}`:t),o=Q.get(s),c=i&&JSON.stringify(e.params);for(let u of o?.values()??[]){if(!u.armed||u.method!==t||u.type!==e.type||Boolean(u.win)!==i)continue;if(i&&u.params!==c)continue;if(u.filter&&!te(u.filter,e,r))continue;return u.armed=!1,!0}return a}var G=new WeakMap;function jr(e,t,r){let n=G.get(e);if(!n)G.set(e,n=new Map),setTimeout(()=>G.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Ur(e,t,r){let n=e&&G.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Lt extends Rt{static values={token:String};#A;#l=new Map;#d=new Map;#ie;#L;#B;#x=0;#f=new Map;#R=new WeakMap;#t;featuresReady=Xe;#r=new Map;#N=new Set;#h=!1;#n=null;#m=new Map;#S=new Map;#p=new Map;#g=0;#j;#Be=0;#je=0;connect(){if(yt=!0,K().connected.add(this.element),B.set(this.element,this),this.element.id==="")console.warn("[phlex-reactive] a reactive root has no id; its next-action token can't self-match "+"and may fall back to the first token in the response → a silent HTTP 403 on the NEXT action. "+"Put id: on the SAME element as reactive_attrs — use div(**reactive_root) (emits id + token together), "+"or div(id:, **reactive_attrs). The id: must NOT be on a child. See the README.");if(this.element.getAttribute?.("data-reactive-token-value")!=null||ke(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===U)this.#H();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(U,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(Se),this.#g++,this.featuresReady=Xe,this.#U(),V(this.element),this.#ce()}#Ue(e){}#Je(e,t,r,n){}#He(){}#ze(e,t){}#U(e){{let t=this.#g,r=[];for(let[s,[a]]of w){if(!a||this.#N.has(s))continue;let o=g.get(s);if(o&&!o.connect)continue;try{if(a(this.element))r.push(s)}catch(c){this.#b(s,"detect",c)}}if(r.length===0)return;for(let s of r)this.#N.add(s);if(!this.#h&&r.every((s)=>g.has(s))){for(let s of r)this.#O(t,s,g.get(s),e);return}for(let s of r){let a=this.#oe(t,s),o=[];for(let u of w.keys()){if(u===s)break;if(this.#p.has(u))o.push(this.#p.get(u))}let c=Promise.all(o).then(()=>a).then((u)=>u&&this.#O(t,s,u,e));if(this.#p.set(s,c),w.get(s)[3])this.#n=c}let n=this.#n;n?.then(()=>{if(this.#n===n)this.#n=null}),this.#h=!0;let i=Promise.all(this.#p.values()).then(()=>{if(this.featuresReady===i)this.#h=!1});this.featuresReady=i}}#oe(e,t){{let r=()=>e===this.#g;return this.#se(t),new Promise((n)=>{let i=!1,s=setTimeout(()=>{if(this.#m.delete(s),i=!0,r())this.#b(t,"timeout",Error(`not loaded after ${ue()} ms`));n(null)},ue());this.#m.set(s,n);let a=()=>{clearTimeout(s),this.#m.delete(s)};P(t).then((o)=>{if(a(),i)queueMicrotask(()=>this.#O(e,t,o));else n(o)},(o)=>{if(a(),r())this.#b(t,"load",o);n(null)})})}}#se(e){{let t=w.get(e)[2];if(!t)return;let r={};try{this.#S.set(e,[t(this.element,r),r]),M.waiting.set(this.element,{...M.waiting.get(this.element),[e]:r})}catch(n){this.#b(e,"detect",n)}}}#J(e,t){{let[r,n]=this.#S.get(e)??[];if(this.#S.delete(e),!t)Ze(this.element,e,n);try{r?.()}catch(i){console.error(`[phlex-reactive] the "${e}" feature module failed to stop waiting`,i)}return n}}#O(e,t,r,n){{if(e!==this.#g)return;let i=this.#J(t);try{r.connect?.(this,this.#e(),n,i),this.#r.set(t,r)}catch(s){this.#b(t,"connect",s)}}}#e(){return this.#j??={emit:(e,t,r)=>this.#o(e,t,r),reseed:()=>this.#H(),proceed:(e,t,r,n)=>this.#P(e,t,r,0,0,null,n),forgetToken:()=>{this.#A=void 0},owns:(e)=>this.#_(e),ownership:()=>this.#Z(),bindingOwns:(e)=>this.#Q(e),bindingOwnership:()=>this.#ke(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#q(e,t),applyOps:(e,t)=>me(e,(r)=>this.#W(t!=null&&r.to==null?{...r,to:t}:r),(r,n)=>this.#q(`client op "${r}"`,n)),listnavOptions:(e)=>this.#v(e),collectFields:()=>this.#ee(),plain:ct,text:T,served:Ee,copyMedia:St,setValue:At,confirm:(e,t)=>Promise.resolve().then(()=>Re(e,t)).catch(()=>!1)},this.#j}#H(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#b(e,t,r){if(Z(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.#o("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#ae(){{this.#g++;for(let[t,r]of this.#m)clearTimeout(t),r(null);this.#m.clear();for(let t of[...this.#S.keys()]){let r=this.#J(t,!0),n=this.element;y(t,(i)=>{i.abandon?.(n,r),Ze(n,t,r)})}this.#N.clear(),this.#p.clear(),this.#h=!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)}}}#ce(){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.#ue();for(let[e,t]of j.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}j.delete(this.element)}#I=new Set;#ue(){let{queue:e}=K();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=$r(),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(Cr,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.#$())console.warn(`[phlex-reactive] dropped an early "${i.event.type}" trigger: ${c}`);continue}this.#le(i)}}#le({event:e,el:t,descs:r,win:n}){let i=Wr(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&&!te(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!Br(o,c,n&&JSON.stringify(i.params)))continue;this.#I.add(o)}if(jr(e,o,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#ae(),this.#ye(),this.#_e(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(U,this.#t);if(K().connected.delete(this.element),B.get(this.element)===this)B.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)Q.delete(e);this.#I.clear()}dispatch(e){if(e.params?.action&&e.params.action!==qe&&this.#de())return this.#fe(e);let t=e.params?.shortcut;if(t!=null&&!W(t,e,this.application?.schema?.keyMappings))return;if(Qe(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:u,optimistic:d,prevent:f}=e.params;if(!r)return;let h=e.params.busy??e.params.loading;if(c&&this.element.contains(e.target))return;let p=e.currentTarget??e.target;if((t!=null||!u&&f!==!1)&&!this.#re(d,p))ce(e,t);if(r===qe){let m=()=>{{let S=this.#r.get("defer");if(S)return S.materialize(this)}if(this.tokenValue)return this.#P(p,r,"{}")};return this.#h?this.featuresReady.then(m):m()}let v=this.#z(a,o),E=()=>this.#P(p,r,n,i,s,d,h);if(!v)return E();if(v instanceof Promise)return v.then((m)=>m?this.#E(m,p,E):E());this.#E(v,p,E)}#E(e,t,r){return Promise.resolve().then(()=>Re(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#z(e,t){if(e)return e;if(!t)return null;{let r=g.get("bindings");if(r)return r.confirmMessage(this,this.#e(),t);return this.#K("bindings").then((n)=>n&&n.confirmMessage(this,this.#e(),t))}}#K(e){{let t;return Promise.race([P(e).catch((r)=>(Z(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),ue()))]).finally(()=>clearTimeout(t))}}#de(){return!this.tokenValue&&pe(this.element)}#fe(e){let t=x(this.element.parentElement,Er);if(!t){if(this.element.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))console.warn(`[phlex-reactive] "${e.params.action}": no token on this root or above, nothing sent`);return}let r=B.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:s,prevent:a}=e.params;if(n!=null&&!W(n,e,this.application?.schema?.keyMappings))return;let o=e.currentTarget??e.target;if((n!=null||!i&&a!==!1)&&!this.#re(s,o))ce(e,n);j.set(t,[...j.get(t)??[],[e,o]]);let c=t.dataset;if(c.reactiveDormant)c.controller=`${c.controller??""} ${c.reactiveDormant}`.trim(),delete c.reactiveDormant}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!W(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Qe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(wr(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=yr(r.ops),s=i.filter((o)=>ze(o,e,null)),a=s.length<=1?s:s.filter((o)=>ze(o,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#$())this.#w((o)=>o.noBinding(this,e));return}for(let o of a){if(o.outside&&e[C])continue;if(!vr(o,e))continue;if(o.shortcut!=null&&!W(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(_r(this,e,o))continue;this.#he(o.legacy?{...r,ops:o.ops,debounce:void 0,throttle:void 0,prevent:void 0}:o,e,n,i.indexOf(o))}}#he(e,t,r,n){let{ops:i,confirm:s,confirmWhen:a,outside:o,window:c,shortcut:u,prevent:d}=e;if(o&&this.element.contains(t.target))return;if(u!=null||!c&&d!==!1)ce(t,u);let f=this.#z(s,a),h=this.#me(e,n,r,()=>this.#Ie(this.#Oe(i)));if(!f)return h();if(f instanceof Promise)return f.then((p)=>p?this.#E(p,r,h):h());this.#E(f,r,h)}#me(e,t,r,n){let i=Number(e.debounce)||0,s=Number(e.throttle)||0;if(i<=0&&s<=0)return n;let a=JSON.stringify([t,e]);if(i>0)return()=>this.#G(r,a,i,n);return()=>this.#V(r,a,s,n)}recompute(e){return g.get("compute")?.recompute(this,this.#e(),e)}tagsAdd(e){if(e?.defaultPrevented)return;if(this.#v(e).some((t)=>t.hasAttribute?.("data-reactive-highlighted")))return;return this.#y("tagsAdd",e)}tagsPick(e){return this.#y("tagsPick",e)}tagsRemove(e){return this.#y("tagsRemove",e)}nestedAdd(e){return this.#y("nestedAdd",e)}nestedRemove(e){return this.#y("nestedRemove",e)}syncNestedJson(e){return g.get("bindings")?.syncNestedJson(this,this.#e(),e)}#y(e,t){{let r=g.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 y("bindings",(i)=>i[e](this,this.#e(),n))}}trackDirty(){(this.#r.get("form")??g.get("form"))?.scan(this,this.#e())}listnavNext(e){this.#T(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#T(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#T(e,()=>0)}listnavLast(e){this.#T(e,(t,r)=>r-1)}listnavPick(e){let t=this.#v(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.#v(e))t.removeAttribute("data-reactive-highlighted")}#T(e,t){let r=this.#v(e);if(!r.length)return;e.preventDefault();let n=this.#pe(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"})}#pe(e){return(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-focus-param")==="true"}#v(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.#Z();return Array.from(this.element.querySelectorAll(r)).filter((i)=>!i.hidden&&n(i))}#P(e,t,r,n,i,s,a){if(this.#o("reactive:before-dispatch",{action:t,params:this.#te(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#be(e,c,t,r,s,a);let u=Number(i)||0;if(u>0)return this.#ve(e,u,t,r,s,a);return this.#F(t,r,s,e,a)}#F(e,t,r,n,i){let s={inverse:null,undo:[],resurrect:null},a=this.#Pe(e,n,s),o=Boolean(r||i),c=(h)=>{if(!o||!h)return;let p=this.#e();if(s.inverse=h.optimistic(this,p,r,n),s.undo.push(...h.busy(this,p,i,n)),this.#C())s.resurrect=h.resurrection(this,p,r,n)},u=g.get("hints");if(!o||u)c(u);let d=()=>this.#Ee(e,t,s,a),f=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>o&&!u?this.#ge().then(c).then(f):f()),this.queue}#ge(){return this.#K("hints")}#be(e,t,r,n,i,s){this.#G(e,Dr,t,()=>this.#F(r,n,i,e,s))}#G(e,t,r,n){this.#M(e,t);let i=()=>{this.#M(e,t),n()},s=setTimeout(i,r);if(!Le(e))e?.addEventListener?.("blur",i,{once:!0});let a=this.#l.get(e);if(!a)this.#l.set(e,a=new Map);a.set(t,{timer:s,flush:i})}#M(e,t){let r=this.#l.get(e),n=r?.get(t);if(!n)return;if(clearTimeout(n.timer),e?.removeEventListener?.("blur",n.flush),r.delete(t),r.size===0)this.#l.delete(e)}#ye(){for(let[e,t]of[...this.#l])for(let r of[...t.keys()])this.#M(e,r)}#ve(e,t,r,n,i,s){return this.#V(e,r,t,()=>this.#F(r,n,i,e,s))}#V(e,t,r,n){let i=this.#d.get(e)??new Map;if(i.has(t))return;let s=setTimeout(()=>{if(i.delete(t),i.size===0)this.#d.delete(e)},r);return i.set(t,s),this.#d.set(e,i),n()}#_e(){for(let e of this.#d.values())for(let t of e.values())clearTimeout(t);this.#d.clear()}#o(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}#s(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.#F(e,t)};this.#o("reactive:error",{action:e,params:r,...n,retry:i})}#i(e){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",e)}#we(){this.element?.removeAttribute?.("data-reactive-error")}#Ae(){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))}#Se(){{let e=g.get("devtools");if(e)return e.delay();if(lt())return P("devtools").then((t)=>t.delay(),()=>{})}}#C(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#Y(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}async#Ee(e,t,r,n){let{fields:i,files:s}=this.#ee(),a=this.#te(t),o={...i,...a},c=this.#a,u=s.length>0,d=u?this.#Re(c,e,o,s):JSON.stringify({token:c,act:e,params:o}),f=this.#C()?{action:e,paramNames:Object.keys(a),fieldNames:Object.keys(i),encoding:u?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#Y()}:null;await this.#Se();try{if(navigator.onLine===!1){this.#c(r.inverse),this.#i("offline"),this.#s(e,t,o,{kind:"offline"});return}let h;try{let m={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#qe()};if(!u)m["Content-Type"]="application/json";let S=this.#We();if(S)m["X-Pgbus-Connection"]=S;let D=Et(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(D)m["X-Reactive-Presence"]=D;let xe=Kt(this.element);if(xe)m["X-Reactive-Held"]=xe;gt("action"),h=await fetch(this.#De(),{method:"POST",headers:m,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#$e())})}catch(m){if(console.error("[phlex-reactive] action error",m),this.#c(r.inverse),m?.name==="TimeoutError"||m?.name==="AbortError"){this.#i("timeout"),this.#s(e,t,o,{kind:"timeout"});return}this.#Ae(),this.#i("network"),this.#s(e,t,o,{kind:"network"});return}if(f)f.status=h.status;if(h.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#c(r.inverse),this.#i("redirected"),this.#s(e,t,o,{kind:"redirected",status:h.status});return}if(!h.ok){let m=await h.text();if(console.error(`[phlex-reactive] action failed: HTTP ${h.status}`,m),this.#c(r.inverse),(h.headers.get("Content-Type")||"").includes("turbo-stream")){let S=this.#X(m);if(this.#a=S??this.#a,f)this.#w((D)=>D.recordBody(f,m,S));$e(this.element,m,!0)}this.#i("http"),this.#s(e,t,o,{kind:"http",status:h.status,body:m});return}let p=h.headers.get("Content-Type")||"";if(!p.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${p}" — no update applied`),this.#c(r.inverse),this.#i("content-type"),this.#s(e,t,o,{kind:"content-type",status:h.status});return}let v=await h.text(),E=this.#X(v);if(this.#a=E??this.#a,f)this.#w((m)=>m.recordBody(f,v,E));if($e(this.element,v,Gt(h)),r.resurrect)queueMicrotask(r.resurrect);return this.#we(),this.#o("reactive:applied",{action:e,params:o,html:v}),v}catch(h){console.error("[phlex-reactive] action error",h),this.#c(r.inverse),this.#o("reactive:error",{action:e,params:o,kind:"apply"})}finally{if(n?.(),f)this.#w((h)=>h.trace(this,{...f,ms:this.#Y()-f.started}))}}get#a(){return this.#A??this.tokenValue}set#a(e){this.#A=e}tokenValueChanged(){this.#A=void 0}#X(e){let t=this.element.id;if(!t)return e.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:r,self:n}=this.#Te(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}#Te(e){let t=this.#B;if(t&&t.id===e)return t;let r=er(e);return this.#B={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>`)}}#_(e){return e.closest('[data-controller~="reactive"]')===this.element}#Z(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#_(t)}#Fe(){let e=this.element.querySelectorAll(F);if(e.length===0||[...e].every(pe))return()=>!0;return(t)=>{let r=x(t,F,this.element);if(r===this.element)return!0;return t.getAttribute("data-reactive-shared-field")!=null&&x(r.parentElement,F,this.element)===this.element}}#Q(e){if(this.#_(e))return!0;if(e.getAttribute?.("data-reactive-shared-field")==null)return!1;let t=x(e,F,this.element);return t===this.element||x(t?.parentElement,F,this.element)===this.element}#ke(){if(this.element.querySelectorAll(F).length===0)return()=>!0;return(e)=>this.#Q(e)}#ee(){let e={},t=[],r=this.#Fe(),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]${or}`).forEach((o)=>{if(r(o))i.push(o)});let s=this.#Le(n),a=this.#xe(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 u of o.options)if(u.selected)c.push(u.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 u=o.getAttribute("data-reactive-editable")!=null?T(o):o.value??o.textContent??o.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!ar(o))return;if(String(c).endsWith("[]")&&(d===void 0||Array.isArray(d))){(Array.isArray(d)?d:e[c]=[]).push(u);return}if(d==null||d==="")e[c]=u}),{fields:e,files:t}}#Le(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}#xe(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#Re(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 u=`${this.#k(o)}[]`;for(let d of c)i.append(u,String(d))}else this.#D(i,this.#k(o),c);for(let o of s)i.append("empty_groups[]",o);let a=this.#Ne(n);for(let{name:o,file:c,multiple:u}of n){let f=u||a.has(o)?`${this.#k(o)}[]`:this.#k(o);i.append(f,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))}#Ne(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))}#te(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#Oe(e){return Te(e)}#Ie(e){me(e,(t)=>this.#W(t),(t,r)=>this.#q(`client op "${t}"`,r))}#$(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#C()}#q(e,t){if(!this.#$())return;this.#w((r)=>r.diagnose(this,e,t))}#w(e){y("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.#_(r))}#re(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()}#Pe(e,t,r){this.#Me(e,t),ft();let n=!1;return()=>{if(n)return;n=!0,this.#Ce(e,t),ht();for(let i of r.undo)i()}}#Me(e,t){if(this.#u(t,e,1),this.#u(this.element,e,1),this.#f.set(e,(this.#f.get(e)??0)+1),this.#x++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#ne(e))this.#u(r,e,1)}#Ce(e,t){this.#u(t,e,-1),this.#u(this.element,e,-1);let r=(this.#f.get(e)??1)-1;if(r<=0)this.#f.delete(e);else this.#f.set(e,r);if(--this.#x<=0)this.#x=0,this.element.removeAttribute("aria-busy");for(let n of this.#ne(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(" "))}#ne(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#_(r))}#De(){return this.#ie??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#$e(){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}#qe(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#We(){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)Be();else document.addEventListener("turbo:load",Be,{once:!0});b("persist",()=>import("phlex/reactive/features/persist"),Jr);b("defer",()=>import("phlex/reactive/features/defer"));b("form",()=>import("phlex/reactive/features/form"));b("bindings",()=>import("phlex/reactive/features/bindings"));b("compute",()=>import("phlex/reactive/features/compute"),Hr);b("sortable",()=>import("phlex/reactive/features/sortable"));b("drag",()=>import("phlex/reactive/features/drag"));b("presence",()=>import("phlex/reactive/features/presence"));b("countdown",()=>import("phlex/reactive/features/countdown"));b("effects",()=>import("phlex/reactive/features/effects"));b("hints",()=>import("phlex/reactive/features/hints"));b("devtools",()=>import("phlex/reactive/features/devtools"));Ae();function Jr(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 Hr(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 zr=1000,L=null,xt,re=new Set;function Kr(e){return kt(e).then((t)=>{if(e!=="effects")return;xt=t,t?.sweep()})}at((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,s=Ft(Gr(i)).filter((o)=>!re.has(o));if(!t&&!re.has("effects")&&Vr(i))s.push("effects");if(s.length===0&&!L)return t?.wrap(e);if(s.length>0){for(let c of s)re.add(c);let o=L=Promise.race([Promise.all([L,...s.map(Kr)]),new Promise((c)=>setTimeout(c,zr))]).then(()=>{if(L!==o)return;L=null,re.clear()})}let a=L;r.render=async(o)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??xt)?.wrap(c),await c.detail.render(o)}});function Gr(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 un=Lt;export{dt as ACTIVE_ATTR,or as EDITOR_SELECTOR,sr as EDITOR_TAGS,pt as REQUESTS_ATTR,tr as checkReactiveRegistration,gt as countReactiveRequest,un as default,T as editableValue,ft as enterReactiveActivity,er as escapeRegExp,ht as exitReactiveActivity,kt as loadReactiveFeature,at as onReactiveStreamWithoutEffects,Qr as reactiveActivityCount,rn as reactiveFeatureNames,Be as registerReactiveActions,Mt as registerReactiveDefer,Ae as registerReactiveDev,Ct as registerReactiveDismiss,Ct as registerReactiveEffects,tn as registerReactiveFeature,b as registerReactiveFeatureLoader,jt as registerReactiveImageFallback,Pt as registerReactiveJs,Bt as registerReactiveKeep,Wt as registerReactiveModals,Jt as registerReactiveMorphFocus,Yt as registerReactiveOffline,Ut as registerReactivePlaintext,Ct as registerReactiveStreamRender,Ot as registerReactiveToken,Nt as registerReactiveVisit,en as resetReactiveActivity,Ee as serverText,Ft as unloadedFeaturesFor};
5
+ `).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var Q=new WeakMap;function Te(e){if(e?.hasAttribute?.("data-reactive-editable")&&!Q.has(e))Q.set(e,T(e))}function Fe(e){return Te(e),Q.get(e)}function cr(e){return ar.has(e.localName)?typeof e.value==="string":!0}var Je=Object.freeze({show:(e,t,r)=>ae(e,!1,t,r),hide:(e,t,r)=>ae(e,!0,t,r),toggle:(e,t,r)=>ae(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(ce(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(ce(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!ce(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)=>br(e)?.focus?.(),blur:(e)=>{let t=e.ownerDocument?.activeElement??globalThis.document?.activeElement;if(t&&(t===e||e.contains?.(t)))t.blur?.()},show_modal:(e)=>rt(e),close_dialog:(e)=>qt(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{}Et(e,n)},check_group:(e,t)=>{let r=t.global?document.querySelectorAll('[data-controller~="reactive"]'):[e];for(let n of r)v("bindings",(i)=>i.checkGroup(n,t.group,t.checked))},presence:(e,t)=>v("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=ur(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)=>lr(e),preview_file:(e,t,r)=>dr(e,t,r),set_value:(e,t)=>St(e,String(t.value??"")),persist_state:(e,t)=>v("persist",(r)=>r.writeState(e,t.state)),persist_clear:(e)=>v("persist",(t)=>t.clearRoot(e))});function ur(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function lr(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 N=new Map,O=null;function dr(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return K(`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 K(`paints an <img>, and ${JSON.stringify(t.into)} is ${n?`a <${n.localName}>`:"not on the page"}`);let i=[...t.valid===!0&&e.validity?.valid===!1?[]:e.files??[]],s=hr(e,t.accept),a=(u)=>Number.isInteger(t.max_bytes)&&u.size>t.max_bytes,o=[],c;if(t.per_file===!0&&e.multiple){let u=i.filter((f,h)=>{let p=typeof f?.type==="string"&&s(f)?a(f)&&"size":"type";if(p)o.push({reason:p,file:f,index:h});return!p}),d=o.length>0&&!fr(e,u)?i.length:u.length;for(let f of o)f.remaining=d;c=u.find((f)=>f.type.startsWith("image/"))}else{let u=i.filter((f)=>typeof f?.type==="string"&&s(f));c=u.find((f)=>f.type.startsWith("image/"));let d=i.length>0&&u.length===0?"type":null;if(c&&a(c))d="size";if(d)o.push({reason:d,file:d==="size"?c:i[0]}),c=null}if(wt(n),c){let u=URL.createObjectURL(c);N.set(n,u),n.setAttribute("src",u),mr()}else n.removeAttribute("src");if(te(n),t.wrap!=null){let u=r({...t,to:t.wrap});if(u.length===0)K(`wrap: ${JSON.stringify(t.wrap)} is not on the page`);for(let d of u)c?ot(d):it(d)}if(t.name!=null)for(let u of r({...t,to:t.name}))u.textContent=c?c.name:"";for(let u of o)e.dispatchEvent(new CustomEvent("reactive:file-rejected",{bubbles:!0,detail:u}))}function fr(e,t){if(typeof DataTransfer!=="function"){if(e.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))K("per_file: has no DataTransfer to drop the refused files from the input");return!1}let r=new DataTransfer;for(let n of t)r.items.add(n);return e.files=r.files,!0}function hr(e,t){let r=String((t===!0?e.getAttribute("accept"):typeof t==="string"&&t)||"").toLowerCase().split(",").map((n)=>n.trim()).filter(Boolean);if(r.length===0)return(n)=>n.type.startsWith("image/");return(n)=>{let i=n.type.toLowerCase();return r.some((s)=>s[0]==="."?String(n.name).toLowerCase().endsWith(s):s.endsWith("/*")?i.startsWith(s.slice(0,-1)):i===s)}}function K(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function wt(e){let t=N.get(e);if(t===void 0)return;if(N.delete(e),URL.revokeObjectURL(t),N.size===0)O?.disconnect(),O=null}function mr(){if(O||typeof MutationObserver!=="function"||!document?.documentElement)return;O=new MutationObserver(()=>{for(let[e,t]of N)if(!e.isConnected||e.getAttribute("src")!==t)wt(e)}),O.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 St(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=ze(e);if(e.value=t,ze(e)!==r)At(e)}function ze(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
6
+ `):e.value}function pr(e,t,r){if(r?.transition)ir(e,r.transition,()=>e.hidden=t);else e.hidden=t}function ae(e,t,r,n){if(pr(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 ce(e){if(!_t(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function Et(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 o=n?r.getAttribute(a):null;if(o==null){if(e.hasAttribute(a))i=e.removeAttribute(a)??!0}else if(e.getAttribute(a)!==o)i=e.setAttribute(a,o)??!0}if(i)te(e);let s=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==s)e.setAttribute("alt",s);return r?s:!1}var gr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function br(e){return e.querySelectorAll?.(gr)?.[0]??null}function ke(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 He=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"}),Ke=Object.freeze(["meta","ctrl","alt","shift"]);function re(e,t,r){let n=e.split("+");for(let a of Ke)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Ke.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let s=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(He,i)?He[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof s==="string"&&s.toLowerCase()===t.key.toLowerCase()}var yr=(e)=>e&&typeof e==="object"?e.keys:String(e),Le=()=>V().prevented??=new WeakSet;function ue(e,t){if(t!=null&&!e.defaultPrevented)Le().add(e);e.preventDefault()}function B(e,t,r){if(t.defaultPrevented&&e?.handled!==!0&&!Le().has(t))return!1;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 re(yr(e).replace(/^mod\+/,`${i}+`),t,r)}function vr(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:ke(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 Ve(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)!==Re(t.currentTarget))return!1;return i<0||r===null||re(n.slice(i+1),t,r)}function _r(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 Ge=new WeakMap;function wr(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=Ge.get(e);if(!i)i=new WeakMap,Ge.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 Ye=new WeakMap;function Ar(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=Ye.get(e);if(!i)i=new WeakMap,Ye.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 pe(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn(Je,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);if(a.length>0)s=Er(i,s,t,r);if(!s)continue;for(let o of a)if(Je[i](o,s,t),s?.keep===!0)nt(o,i,s,t)}}var Sr=new Set(["set_value","text","set_attr"]);function Er(e,t,r,n){let i=e==="dispatch",s=i?t.detail_from:Sr.has(e)&&t.from!=null&&{value:t.attr};if(!s)return t;let a=i?"@trigger":t.from,o;try{o=r({...t,to:a})[0]}catch{}if(!o)return n?.(e,{...t,to:a}),null;let c=i?{...t.detail}:{};for(let[u,d]of Object.entries(s)){let f=Tr(o,d);if(f==null)return null;c[u]=f}return i?{...t,detail:c}:{...t,...c}}function Tr(e,t){if(t==="@text")return e.textContent??"";if(typeof t==="string"&&/^data-[a-z][a-z0-9-]*$/i.test(t))return e.getAttribute(t)??"";return console.warn(`[phlex-reactive] refused client read of ${JSON.stringify(t)} — skipped`),null}function Fr(e,t){let r=e.to;if(r==="@trigger")return[];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 kr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function xe(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}var F='[data-controller~="reactive"]',Lr='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',ge=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!xe(e);function R(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&ge(n))n=n.parentElement?.closest?.(t);return n??null}var j=new WeakMap,U=new WeakMap;function xr(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 Rr(e){return["show-targets","group-targets","on-complete","filter-input","tags-field","css-vars"].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], [data-reactive-css-vars]")!=null}function Nr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function Or(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function Ir(e){return Boolean(e.matches?.("[data-reactive-frame],[data-reactive-box],[data-reactive-point]")||e.querySelector?.("[data-reactive-frame],[data-reactive-box],[data-reactive-point]"))}function Tt(e){return e.getAttribute?.("data-reactive-presence")!=null}function Pr(e){return Boolean(e.matches?.("[data-reactive-countdown]")||e.querySelector?.("[data-reactive-countdown]"))}var Mr=[["persist",[kr,null,null,!0]],["defer",[xe,null]],["form",[xr,null]],["bindings",[Rr,null,null,!0]],["compute",[Nr,null,null,!0]],["sortable",[Or,null]],["drag",[Ir,null]],["presence",[Tt,null]],["countdown",[Pr,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(Mr),Xe=new Map,g=new Map,Cr=new Map;function y(e,t,r){Ft.set(e,[t,r]),Dr(e)}var Ft=new Map;function Dr(e){let t=w.get(e),[r,n]=Ft.get(e);t[1]=r,t[2]=n}function sn(e,t){t.install?.(M),g.set(e,t),Cr.set(e,t)}function kt(e){let t=[];for(let[r,[n]]of w){if(!n||g.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function Lt(e){return I(e).catch((t)=>Z(e,"load",t))}function I(e){let t=Xe.get(e);if(!t)t=(w.get(e)[1]??(()=>Promise.reject(Error("this entry has no way to import it"))))().then((n)=>(n.install?.(M),g.set(e,n),n)),Xe.set(e,t);return t}var Qe=new Set;function Z(e,t,r){let n=e+t;if(Qe.has(n))return;Qe.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 v(e,t){let r=g.get(e);if(r)return t(r);I(e).then(t,(n)=>Z(e,"load",n))}var $r=1e4;function le(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:$r}function an(){return[...w.keys()]}var Ze=Promise.resolve();function et(e,t,r){let n=M.waiting.get(e);if(n&&n[t]===r)delete n[t]}var M={enter:ht,exit:mt,count:bt,text:T,served:Fe,waiting:new WeakMap};var C=Symbol.for("phlex-reactive.early"),qr=1e4,Wr=1500,Re=(e)=>e!=null&&(e===globalThis.window||e.window===e),Br="dispatch";function V(){return globalThis[C]??={queue:[],connected:new WeakSet},globalThis[C]}function jr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:qr}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 Jr(e,t,r){return{[C]:!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&&!Le().has(e),preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var ee=new WeakMap;function zr(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=ee.get(e);if(!o)ee.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 tt(e,t,r,n){if(e?.[C])return!1;let i=Re(e?.currentTarget),s=i?n:e?.currentTarget,a=Kr(e,s,i?`@${t}`:t),o=ee.get(s),c=i&&JSON.stringify(e.params);for(let u of o?.values()??[]){if(!u.armed||u.method!==t||u.type!==e.type||Boolean(u.win)!==i)continue;if(i&&u.params!==c)continue;if(u.filter&&!re(u.filter,e,r))continue;return u.armed=!1,!0}return a}var G=new WeakMap;function Hr(e,t,r){let n=G.get(e);if(!n)G.set(e,n=new Map),setTimeout(()=>G.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Kr(e,t,r){let n=e&&G.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class xt extends Nt{static values={token:String};#A;#d=new Map;#f=new Map;#ie;#x;#B;#R=0;#h=new Map;#N=new WeakMap;#t;featuresReady=Ze;#r=new Map;#O=new Set;#m=!1;#n=null;#p=new Map;#S=new Map;#g=new Map;#b=0;#j;#je=0;#Ue=0;connect(){if(vt=!0,V().connected.add(this.element),j.set(this.element,this),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||xe(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===J)this.#z();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(J,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(Te),this.#b++,this.featuresReady=Ze,this.#U(),Y(this.element),this.#ce()}#Je(e){}#ze(e,t,r,n){}#He(){}#Ke(e,t){}#U(e){{let t=this.#b,r=[];for(let[s,[a]]of w){if(!a||this.#O.has(s))continue;let o=g.get(s);if(o&&!o.connect)continue;try{if(a(this.element))r.push(s)}catch(c){this.#y(s,"detect",c)}}if(r.length===0)return;for(let s of r)this.#O.add(s);if(!this.#m&&r.every((s)=>g.has(s))){for(let s of r)this.#I(t,s,g.get(s),e);return}for(let s of r){let a=this.#oe(t,s),o=[];for(let u of w.keys()){if(u===s)break;if(this.#g.has(u))o.push(this.#g.get(u))}let c=Promise.all(o).then(()=>a).then((u)=>u&&this.#I(t,s,u,e));if(this.#g.set(s,c),w.get(s)[3])this.#n=c}let n=this.#n;n?.then(()=>{if(this.#n===n)this.#n=null}),this.#m=!0;let i=Promise.all(this.#g.values()).then(()=>{if(this.featuresReady===i)this.#m=!1});this.featuresReady=i}}#oe(e,t){{let r=()=>e===this.#b;return this.#se(t),new Promise((n)=>{let i=!1,s=setTimeout(()=>{if(this.#p.delete(s),i=!0,r())this.#y(t,"timeout",Error(`not loaded after ${le()} ms`));n(null)},le());this.#p.set(s,n);let a=()=>{clearTimeout(s),this.#p.delete(s)};I(t).then((o)=>{if(a(),i)queueMicrotask(()=>this.#I(e,t,o));else n(o)},(o)=>{if(a(),r())this.#y(t,"load",o);n(null)})})}}#se(e){{let t=w.get(e)[2];if(!t)return;let r={};try{this.#S.set(e,[t(this.element,r),r]),M.waiting.set(this.element,{...M.waiting.get(this.element),[e]:r})}catch(n){this.#y(e,"detect",n)}}}#J(e,t){{let[r,n]=this.#S.get(e)??[];if(this.#S.delete(e),!t)et(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.#b)return;let i=this.#J(t);try{r.connect?.(this,this.#e(),n,i),this.#r.set(t,r)}catch(s){this.#y(t,"connect",s)}}}#e(){return this.#j??={emit:(e,t,r)=>this.#o(e,t,r),reseed:()=>this.#z(),proceed:(e,t,r,n)=>this.#M(e,t,r,0,0,null,n),forgetToken:()=>{this.#A=void 0},owns:(e)=>this.#c(e),ownership:()=>this.#Q(),bindingOwns:(e)=>this.#Z(e),bindingOwnership:()=>this.#Le(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#q(e,t),applyOps:(e,t)=>pe(e,(r)=>this.#W(t!=null&&r.to==null?{...r,to:t}:r),(r,n)=>this.#q(`client op "${r}"`,n)),listnavOptions:(e)=>this.#_(e),collectFields:()=>this.#ee(),plain:ut,text:T,served:Fe,copyMedia:Et,setValue:St,confirm:(e,t)=>Promise.resolve().then(()=>Oe(e,t)).catch(()=>!1)},this.#j}#z(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#y(e,t,r){if(Z(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.#o("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#ae(){{this.#b++;for(let[t,r]of this.#p)clearTimeout(t),r(null);this.#p.clear();for(let t of[...this.#S.keys()]){let r=this.#J(t,!0),n=this.element;v(t,(i)=>{i.abandon?.(n,r),et(n,t,r)})}this.#O.clear(),this.#g.clear(),this.#m=!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)}}}#ce(){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.#ue();for(let[e,t]of U.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}U.delete(this.element)}#P=new Set;#ue(){let{queue:e}=V();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=jr(),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(Wr,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.#L())console.warn(`[phlex-reactive] dropped an early "${i.event.type}" trigger: ${c}`);continue}this.#le(i)}}#le({event:e,el:t,descs:r,win:n}){let i=Jr(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&&!re(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!zr(o,c,n&&JSON.stringify(i.params)))continue;this.#P.add(o)}if(Hr(e,o,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#ae(),this.#ve(),this.#we(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(J,this.#t);if(V().connected.delete(this.element),j.get(this.element)===this)j.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#P)ee.delete(e);this.#P.clear()}dispatch(e){if(e.params?.action&&e.params.action!==Be&&this.#de())return this.#fe(e);let t=e.params?.shortcut;if(t!=null&&!B(t,e,this.application?.schema?.keyMappings))return;if(tt(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:u,optimistic:d,prevent:f}=e.params;if(!r)return;let h=e.params.busy??e.params.loading;if(c&&this.element.contains(e.target))return;let p=e.currentTarget??e.target;if((t!=null||!u&&f!==!1)&&!this.#re(d,p))ue(e,t);if(r===Be){let m=()=>{{let S=this.#r.get("defer");if(S)return S.materialize(this)}if(this.tokenValue)return this.#M(p,r,"{}")};return this.#m?this.featuresReady.then(m):m()}let b=this.#H(a,o),E=()=>this.#M(p,r,n,i,s,d,h);if(!b)return E();if(b instanceof Promise)return b.then((m)=>m?this.#E(m,p,E):E());this.#E(b,p,E)}#E(e,t,r){return Promise.resolve().then(()=>Oe(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#H(e,t){if(e)return e;if(!t)return null;{let r=g.get("bindings");if(r)return r.confirmMessage(this,this.#e(),t);return this.#K("bindings").then((n)=>n&&n.confirmMessage(this,this.#e(),t))}}#K(e){{let t;return Promise.race([I(e).catch((r)=>(Z(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),le()))]).finally(()=>clearTimeout(t))}}#de(){return!this.tokenValue&&ge(this.element)}#fe(e){let t=R(this.element.parentElement,Lr);if(!t){if(this.element.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))console.warn(`[phlex-reactive] "${e.params.action}": no token on this root or above, nothing sent`);return}let r=j.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:s,prevent:a}=e.params;if(n!=null&&!B(n,e,this.application?.schema?.keyMappings))return;let o=e.currentTarget??e.target;if((n!=null||!i&&a!==!1)&&!this.#re(s,o))ue(e,n);U.set(t,[...U.get(t)??[],[e,o]]);let c=t.dataset;if(c.reactiveDormant)c.controller=`${c.controller??""} ${c.reactiveDormant}`.trim(),delete c.reactiveDormant}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!B(t.shortcut,e,this.application?.schema?.keyMappings))return;if(tt(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(Ar(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=vr(r.ops),s=i.filter((o)=>Ve(o,e,null)),a=s.length<=1?s:s.filter((o)=>Ve(o,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#L())this.#w((o)=>o.noBinding(this,e));return}for(let o of a){if(o.outside&&e[C])continue;if(!_r(o,e))continue;let c=o.within==null?n:this.#he(o.within,e);if(o.within!=null&&!c)continue;if(o.shortcut!=null&&!B(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(wr(this,e,o))continue;this.#me(o.legacy?{...r,ops:o.ops,debounce:void 0,throttle:void 0,prevent:void 0}:o,e,c,i.indexOf(o),n)}}#he(e,t){let r=t.currentTarget,n=null;try{n=t.target?.closest?.(e)}catch{if(this.#L())console.warn(`[phlex-reactive] on_client within: ${JSON.stringify(e)} is not a selector — nothing ran`)}return n&&n!==r&&r?.contains?.(n)&&this.#c(n)?n:null}#me(e,t,r,n,i=r){let{ops:s,confirm:a,confirmWhen:o,outside:c,window:u,shortcut:d,prevent:f}=e;if(c&&this.element.contains(t.target))return;if(d!=null||!u&&f!==!1)ue(t,d);let h=this.#H(a,o),p=this.#pe(e,n,i,()=>this.#Pe(this.#Ie(s),r));if(!h)return p();if(h instanceof Promise)return h.then((b)=>b?this.#E(b,r,p):p());this.#E(h,r,p)}#pe(e,t,r,n){let i=Number(e.debounce)||0,s=Number(e.throttle)||0;if(i<=0&&s<=0)return n;let a=JSON.stringify([t,e]);if(i>0)return()=>this.#V(r,a,i,n);return()=>this.#G(r,a,s,n)}recompute(e){return g.get("compute")?.recompute(this,this.#e(),e)}tagsAdd(e){if(e?.defaultPrevented)return;if(this.#_(e).some((t)=>t.hasAttribute?.("data-reactive-highlighted")))return;return this.#v("tagsAdd",e)}tagsPick(e){return this.#v("tagsPick",e)}tagsRemove(e){return this.#v("tagsRemove",e)}nestedAdd(e){return this.#v("nestedAdd",e)}nestedRemove(e){return this.#v("nestedRemove",e)}syncNestedJson(e){return g.get("bindings")?.syncNestedJson(this,this.#e(),e)}#v(e,t){{let r=g.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 v("bindings",(i)=>i[e](this,this.#e(),n))}}trackDirty(){(this.#r.get("form")??g.get("form"))?.scan(this,this.#e())}listnavNext(e){this.#T(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#T(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#T(e,()=>0)}listnavLast(e){this.#T(e,(t,r)=>r-1)}listnavPick(e){let t=this.#_(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.#_(e))t.removeAttribute("data-reactive-highlighted")}#T(e,t){let r=this.#_(e);if(!r.length)return;e.preventDefault();let n=this.#ge(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"})}#ge(e){return(e?.currentTarget??e?.target??this.element).getAttribute?.("data-reactive-listnav-focus-param")==="true"}#_(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.#Q();return Array.from(this.element.querySelectorAll(r)).filter((i)=>!i.hidden&&n(i))}#M(e,t,r,n,i,s,a){if(this.#o("reactive:before-dispatch",{action:t,params:this.#te(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#ye(e,c,t,r,s,a);let u=Number(i)||0;if(u>0)return this.#_e(e,u,t,r,s,a);return this.#F(t,r,s,e,a)}#F(e,t,r,n,i){let s={inverse:null,undo:[],resurrect:null},a=this.#Me(e,n,s),o=Boolean(r||i),c=(h)=>{if(!o||!h)return;let p=this.#e();if(s.inverse=h.optimistic(this,p,r,n),s.undo.push(...h.busy(this,p,i,n)),this.#D())s.resurrect=h.resurrection(this,p,r,n)},u=g.get("hints");if(!o||u)c(u);let d=()=>this.#Te(e,t,s,a),f=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>o&&!u?this.#be().then(c).then(f):f()),this.queue}#be(){return this.#K("hints")}#ye(e,t,r,n,i,s){this.#V(e,Br,t,()=>this.#F(r,n,i,e,s))}#V(e,t,r,n){this.#C(e,t);let i=()=>{this.#C(e,t),n()},s=setTimeout(i,r);if(!Re(e))e?.addEventListener?.("blur",i,{once:!0});let a=this.#d.get(e);if(!a)this.#d.set(e,a=new Map);a.set(t,{timer:s,flush:i})}#C(e,t){let r=this.#d.get(e),n=r?.get(t);if(!n)return;if(clearTimeout(n.timer),e?.removeEventListener?.("blur",n.flush),r.delete(t),r.size===0)this.#d.delete(e)}#ve(){for(let[e,t]of[...this.#d])for(let r of[...t.keys()])this.#C(e,r)}#_e(e,t,r,n,i,s){return this.#G(e,r,t,()=>this.#F(r,n,i,e,s))}#G(e,t,r,n){let i=this.#f.get(e)??new Map;if(i.has(t))return;let s=setTimeout(()=>{if(i.delete(t),i.size===0)this.#f.delete(e)},r);return i.set(t,s),this.#f.set(e,i),n()}#we(){for(let e of this.#f.values())for(let t of e.values())clearTimeout(t);this.#f.clear()}#o(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}#s(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.#F(e,t)};this.#o("reactive:error",{action:e,params:r,...n,retry:i})}#i(e){if(this.element?.isConnected===!1)return;this.element?.setAttribute?.("data-reactive-error",e)}#Ae(){this.element?.removeAttribute?.("data-reactive-error")}#Se(){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))}#Ee(){{let e=g.get("devtools");if(e)return e.delay();if(dt())return I("devtools").then((t)=>t.delay(),()=>{})}}#D(){return this.element?.getAttribute?.("data-reactive-debug")==="true"}#Y(){return typeof performance<"u"&&typeof performance.now==="function"?performance.now():Date.now()}async#Te(e,t,r,n){let{fields:i,files:s}=this.#ee(),a=this.#te(t),o={...i,...a},c=this.#a,u=s.length>0,d=u?this.#Ne(c,e,o,s):JSON.stringify({token:c,act:e,params:o}),f=this.#D()?{action:e,paramNames:Object.keys(a),fieldNames:Object.keys(i),encoding:u?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#Y()}:null;await this.#Ee();try{if(navigator.onLine===!1){this.#u(r.inverse),this.#i("offline"),this.#s(e,t,o,{kind:"offline"});return}let h;try{let m={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#We()};if(!u)m["Content-Type"]="application/json";let S=this.#Be();if(S)m["X-Pgbus-Connection"]=S;let D=Tt(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(D)m["X-Reactive-Presence"]=D;let Ne=Vt(this.element);if(Ne)m["X-Reactive-Held"]=Ne;bt("action"),h=await fetch(this.#$e(),{method:"POST",headers:m,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#qe())})}catch(m){if(console.error("[phlex-reactive] action error",m),this.#u(r.inverse),m?.name==="TimeoutError"||m?.name==="AbortError"){this.#i("timeout"),this.#s(e,t,o,{kind:"timeout"});return}this.#Se(),this.#i("network"),this.#s(e,t,o,{kind:"network"});return}if(f)f.status=h.status;if(h.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#u(r.inverse),this.#i("redirected"),this.#s(e,t,o,{kind:"redirected",status:h.status});return}if(!h.ok){let m=await h.text();if(console.error(`[phlex-reactive] action failed: HTTP ${h.status}`,m),this.#u(r.inverse),(h.headers.get("Content-Type")||"").includes("turbo-stream")){let S=this.#X(m);if(this.#a=S??this.#a,f)this.#w((D)=>D.recordBody(f,m,S));We(this.element,m,!0)}this.#i("http"),this.#s(e,t,o,{kind:"http",status:h.status,body:m});return}let p=h.headers.get("Content-Type")||"";if(!p.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${p}" — no update applied`),this.#u(r.inverse),this.#i("content-type"),this.#s(e,t,o,{kind:"content-type",status:h.status});return}let b=await h.text(),E=this.#X(b);if(this.#a=E??this.#a,f)this.#w((m)=>m.recordBody(f,b,E));if(We(this.element,b,Gt(h)),r.resurrect)queueMicrotask(r.resurrect);return this.#Ae(),this.#o("reactive:applied",{action:e,params:o,html:b}),b}catch(h){console.error("[phlex-reactive] action error",h),this.#u(r.inverse),this.#o("reactive:error",{action:e,params:o,kind:"apply"})}finally{if(n?.(),f)this.#w((h)=>h.trace(this,{...f,ms:this.#Y()-f.started}))}}get#a(){return this.#A??this.tokenValue}set#a(e){this.#A=e}tokenValueChanged(){this.#A=void 0}#X(e){let t=this.element.id;if(!t)return e.match(/data-reactive-token-value="([^"]+)"/)?.[1];let{token:r,self:n}=this.#Fe(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}#Fe(e){let t=this.#B;if(t&&t.id===e)return t;let r=tr(e);return this.#B={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>`)}}#c(e){return e.closest('[data-controller~="reactive"]')===this.element}#Q(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#c(t)}#ke(){let e=this.element.querySelectorAll(F);if(e.length===0||[...e].every(ge))return()=>!0;return(t)=>{let r=R(t,F,this.element);if(r===this.element)return!0;return t.getAttribute("data-reactive-shared-field")!=null&&R(r.parentElement,F,this.element)===this.element}}#Z(e){if(this.#c(e))return!0;if(e.getAttribute?.("data-reactive-shared-field")==null)return!1;let t=R(e,F,this.element);return t===this.element||R(t?.parentElement,F,this.element)===this.element}#Le(){if(this.element.querySelectorAll(F).length===0)return()=>!0;return(e)=>this.#Z(e)}#ee(){let e={},t=[],r=this.#ke(),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]${sr}`).forEach((o)=>{if(r(o))i.push(o)});let s=this.#xe(n),a=this.#Re(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 u of o.options)if(u.selected)c.push(u.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 u=o.getAttribute("data-reactive-editable")!=null?T(o):o.value??o.textContent??o.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!cr(o))return;if(String(c).endsWith("[]")&&(d===void 0||Array.isArray(d))){(Array.isArray(d)?d:e[c]=[]).push(u);return}if(d==null||d==="")e[c]=u}),{fields:e,files:t}}#xe(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}#Re(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#Ne(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 u=`${this.#k(o)}[]`;for(let d of c)i.append(u,String(d))}else this.#$(i,this.#k(o),c);for(let o of s)i.append("empty_groups[]",o);let a=this.#Oe(n);for(let{name:o,file:c,multiple:u}of n){let f=u||a.has(o)?`${this.#k(o)}[]`:this.#k(o);i.append(f,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("")}`}#$(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))}#Oe(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))}#te(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#Ie(e){return ke(e)}#Pe(e,t){pe(e,(r)=>this.#W(r,t),(r,n)=>this.#q(`client op "${r}"`,n))}#L(){return this.element?.getAttribute?.("data-reactive-verbose")==="true"||this.#D()}#q(e,t){if(!this.#L())return;this.#w((r)=>r.diagnose(this,e,t))}#w(e){v("devtools",e)}#W(e,t){let r=e.to;if(r==="@root")return[this.element];if(r==="@trigger")return t?.nodeType===1?[t]:[];if(typeof r!=="string"||r==="")return[];if(e.global)return[...document.querySelectorAll(r)];return[...this.element.querySelectorAll(r)].filter((n)=>this.#c(n))}#re(e,t){if(e?.checked!=="keep")return!1;let r=t?.type;return r==="checkbox"||r==="radio"}#u(e){if(!e)return;if(!this.element.isConnected)return;for(let t of e)t()}#Me(e,t,r){this.#Ce(e,t),ht();let n=!1;return()=>{if(n)return;n=!0,this.#De(e,t),mt();for(let i of r.undo)i()}}#Ce(e,t){if(this.#l(t,e,1),this.#l(this.element,e,1),this.#h.set(e,(this.#h.get(e)??0)+1),this.#R++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#ne(e))this.#l(r,e,1)}#De(e,t){this.#l(t,e,-1),this.#l(this.element,e,-1);let r=(this.#h.get(e)??1)-1;if(r<=0)this.#h.delete(e);else this.#h.set(e,r);if(--this.#R<=0)this.#R=0,this.element.removeAttribute("aria-busy");for(let n of this.#ne(e))this.#l(n,e,-1)}#l(e,t,r){if(!e||typeof e.getAttribute!=="function")return;let n=this.#N.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.#N.delete(e),e.removeAttribute("data-reactive-busy");return}this.#N.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#ne(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#c(r))}#$e(){return this.#ie??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#qe(){if(this.#x!=null)return this.#x;let e=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,t=Number(e);return this.#x=Number.isFinite(t)&&t>0?t:30000}#We(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#Be(){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)Ue();else document.addEventListener("turbo:load",Ue,{once:!0});y("persist",()=>import("phlex/reactive/features/persist"),Vr);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"),Gr);y("sortable",()=>import("phlex/reactive/features/sortable"));y("drag",()=>import("phlex/reactive/features/drag"));y("presence",()=>import("phlex/reactive/features/presence"));y("countdown",()=>import("phlex/reactive/features/countdown"));y("effects",()=>import("phlex/reactive/features/effects"));y("hints",()=>import("phlex/reactive/features/hints"));y("devtools",()=>import("phlex/reactive/features/devtools"));Ee();function Vr(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 Gr(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 Yr=1000,x=null,Rt,ne=new Set;function Xr(e){return Lt(e).then((t)=>{if(e!=="effects")return;Rt=t,t?.sweep()})}ct((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,s=kt(Qr(i)).filter((o)=>!ne.has(o));if(!t&&!ne.has("effects")&&Zr(i))s.push("effects");if(s.length===0&&!x)return t?.wrap(e);if(s.length>0){for(let c of s)ne.add(c);let o=x=Promise.race([Promise.all([x,...s.map(Xr)]),new Promise((c)=>setTimeout(c,Yr))]).then(()=>{if(x!==o)return;x=null,ne.clear()})}let a=x;r.render=async(o)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??Rt)?.wrap(c),await c.detail.render(o)}});function Qr(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 Zr(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 hn=xt;export{ft as ACTIVE_ATTR,sr as EDITOR_SELECTOR,ar as EDITOR_TAGS,gt as REQUESTS_ATTR,rr as checkReactiveRegistration,bt as countReactiveRequest,hn as default,T as editableValue,ht as enterReactiveActivity,tr as escapeRegExp,mt as exitReactiveActivity,Lt as loadReactiveFeature,ct as onReactiveStreamWithoutEffects,nn as reactiveActivityCount,an as reactiveFeatureNames,Ue as registerReactiveActions,Ct as registerReactiveDefer,Ee as registerReactiveDev,Dt as registerReactiveDismiss,Dt as registerReactiveEffects,sn as registerReactiveFeature,y as registerReactiveFeatureLoader,Ut as registerReactiveImageFallback,Mt as registerReactiveJs,jt as registerReactiveKeep,Bt as registerReactiveModals,zt as registerReactiveMorphFocus,Xt as registerReactiveOffline,Jt as registerReactivePlaintext,Dt as registerReactiveStreamRender,It as registerReactiveToken,Ot as registerReactiveVisit,on as resetReactiveActivity,Fe as serverText,kt as unloadedFeaturesFor};
7
7
 
8
- //# debugId=C593E57D5736626364756E2164756E21
8
+ //# debugId=657C41040377349A64756E2164756E21
9
9
  //# sourceMappingURL=core.min.js.map