phlex-reactive 0.16.5 → 0.16.7

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: 69a1ca18807351dc48163f7d39a945a00d7dc09c4000f78dfcb048201ddf005f
4
- data.tar.gz: 3e4ffb3965adefed97fa4f384bd2a3dd7ddf8fb213385b8724eef53f702372d7
3
+ metadata.gz: e8f1909cfe6e55962d3346a9168c7e87cd9afcdc11745078b8fcf8fe4b37546f
4
+ data.tar.gz: c5e3cd10571790af59e2763286c2745a47eae77986e69190e06b9802cf0aed8a
5
5
  SHA512:
6
- metadata.gz: eb1f48cf92cfb846068049380ed6a2f13dd5b8b4720b422796053be6435ffb87ead4e8ee216a680823b5b9d67aeef36f95016da989abe57d885ebd4177ebf4b3
7
- data.tar.gz: f52a3b225c879476a92e5d34d59d936f556edaf45a83ec1002f479086641c13dddcd8c6d8be2b7a96fca7a33230b92c1861815693a07bf4f49549f1a5714f449
6
+ metadata.gz: ca11dbe59e2b6db3c60aae38a9ea1bb17b74fdb104c6c340333dc23074fe99357e805d25702f1e31a14811120f0c78aa77b670fb8ebea21eada0e38709d9c5d2
7
+ data.tar.gz: 2b1e10b34dadc2aa77f883f7634500c3bda73ca31f0839be10d94d4a15e8616c49358690e44ffea2bd7d3778ca7b239ed6acda65e43db5e0663bd6804ada18e2
data/CHANGELOG.md CHANGED
@@ -6,6 +6,80 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.16.7] - 2026-10-18
10
+
11
+ ### Added
12
+
13
+ - **`js.preview_file(…, per_file: true)` checks every file of a `multiple`
14
+ input and drops only the refused ones (#439).** The op checked one file, the
15
+ first image its `accept` list took, so on an `<input type="file" multiple>` an
16
+ oversize or wrong-type file next to good ones was never refused, and the only
17
+ way to keep a refused file from being posted was to clear the whole input.
18
+ With `per_file: true` on a `multiple` input every file is checked (`accept:`,
19
+ then `max_bytes:`), `input.files` is rebuilt from the accepted ones (through a
20
+ `DataTransfer`, synchronously, so an `on(:action, event: "change")` mixed in
21
+ after the op posts only those), one `reactive:file-rejected` fires per refused
22
+ file with `detail.reason`, `detail.file`, `detail.index` (its place in the
23
+ pick) and `detail.remaining` (how many files the input keeps), and the first
24
+ accepted image is painted. Every file refused empties the input, and the
25
+ action receives no file. Without a `DataTransfer` the rejections still fire
26
+ and the input keeps every file (`remaining` counts them all; a verbose root
27
+ is told). A single input, and `per_file:` omitted, behave as before;
28
+ `per_file:` takes only `true`, `false` or `nil`.
29
+
30
+ ## [0.16.6] - 2026-10-18
31
+
32
+ ### Added
33
+
34
+ - **A field inside a nested component can post with its host's actions:
35
+ `reactive_shared_field` (#434).** A reactive component rendered inside
36
+ another is its own root, and its named fields are its own (#15), so a form
37
+ widget with actions of its own (a picker that keeps the chosen id in a
38
+ hidden field) could not hand its value to the form around it without a
39
+ second component beside it and a `js.set_value` in every action.
40
+ `input(type: "hidden", **reactive_shared_field(name: "item[choice]", value: @choice))`
41
+ renders the name, the value and a `data-reactive-shared-field` marker: the
42
+ widget's own actions still collect the field, and so do the actions of the
43
+ next server component above it (client-only roots in between stay
44
+ transparent, #410), on the JSON body and the multipart one alike. One level
45
+ only: a component above that host collects it only when the host marks a
46
+ copy of its own. The name is the host's param, verbatim (the widget's own
47
+ actions receive it under that name too, so they declare it there when they
48
+ read it, or the action drops it); a String or Symbol name only, a blank
49
+ one raises at render. Without the marker nothing changes. A conditional
50
+ `confirm:` reads the fields the action posts, so it sees the shared field
51
+ too; dirty tracking, `reactive_persist` and the client bindings keep strict
52
+ ownership. The
53
+ collect walk is unchanged for a root with no nested server component; with
54
+ one, an unmarked foreign control costs one attribute read.
55
+
56
+ - **`prevent: false` lets an element-bound trigger keep the event's native
57
+ default (#433).** By default, a matching element-bound `on`/`on_client`
58
+ trigger calls `preventDefault()` before its ops or action run (only a
59
+ click-bound checkbox/radio with `optimistic: { checked: :keep }` was exempt),
60
+ which cancelled a `drop` a native `<input type="file">` inside the bound
61
+ element needed: the file never reached the input. `on_client(:drop,
62
+ js.remove_class("#zone", "is-over"), prevent: false)` runs the ops and leaves
63
+ the default alone, so the browser sets the input's files and fires `change`
64
+ (verified in Chromium); `on(:track, event: "drop", prevent: false)` does the
65
+ same for a server trigger. The flag belongs to its binding: `on_client` writes
66
+ `"prevent":false` into its binding record (right after `"on"`), `on` writes
67
+ `data-reactive-prevent-param="false"`, and a sibling binding on another event,
68
+ or one on the same event without the flag, is still prevented.
69
+ `phlex/reactive/early` follows the same rule before the controller connects.
70
+ The default, `prevent: true`, renders nothing, so existing markup is
71
+ byte-identical. A `window:` or `outside:` trigger never prevents, so the
72
+ keyword changes nothing there; with `shortcut:` it raises `ArgumentError` at
73
+ render, as does anything but `true`/`false`. A click trigger keeps its forced
74
+ `type="button"`. The default bundle grows by 34 B gzipped (40,880 B), the
75
+ split core by 34 B (18,438 B), `early.min.js` by 103 B (1,746 B).
76
+
77
+ ### Changed
78
+
79
+ - **`prevent:` is a reserved keyword on `on(...)` (#433).** It used to pass
80
+ through as an action param; it now takes `true` or `false` only (anything
81
+ else raises `ArgumentError`). Rename an action param called `prevent`.
82
+
9
83
  ## [0.16.5] - 2026-10-18
10
84
 
11
85
  ### Fixed
@@ -4243,7 +4317,9 @@ room for dogfood fixes.
4243
4317
  scaffolds a reactive component (and an RSpec spec when the app uses RSpec),
4244
4318
  state-backed by default or record-backed with `--record`.
4245
4319
 
4246
- [Unreleased]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.5...HEAD
4320
+ [Unreleased]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.7...HEAD
4321
+ [0.16.7]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.6...v0.16.7
4322
+ [0.16.6]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.5...v0.16.6
4247
4323
  [0.16.5]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.4...v0.16.5
4248
4324
  [0.16.4]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.3...v0.16.4
4249
4325
  [0.16.3]: https://github.com/mhenrixon/phlex-reactive/compare/v0.16.2...v0.16.3
data/README.md CHANGED
@@ -145,9 +145,11 @@ Good to know:
145
145
  - `data-reactive-connected` is set at connect; an in-place morph strips it
146
146
  again. Listen for `reactive:connect` rather than reading the attribute later.
147
147
  - Until the controller connects, a captured link or form trigger has its
148
- native behavior stopped and nothing else happens. If the controller never
148
+ native behavior stopped and nothing else happens (one with `prevent: false`
149
+ keeps it, as it does once connected). If the controller never
149
150
  loads, or the entry is dropped (older than the TTL, its element gone, more
150
- than 50 queued), that click or submit does nothing.
151
+ than 50 queued), a prevented click or submit does nothing (one with
152
+ `prevent: false` still did its native default).
151
153
  - `window:` triggers — how a **hotkey** is usually bound
152
154
  (`on(:toggle, event: "keydown.k", window: true)` or
153
155
  `on_client("keydown.k", …, window: true)`) — are captured too: a hotkey
@@ -685,9 +687,11 @@ Use in controllers: `render turbo_stream: Counter.replace(counter)`.
685
687
  | `on(:save, loading: { disable: true, class: "opacity-50", text: "…" })` | Full loading form: `disable:`, a loading `class:` (on the trigger or a `to:` target), a `text:` swap. Reverts on settle. |
686
688
  | `busy_on(:save)` | Mark any element so it carries `data-reactive-busy` **only while `save` is in flight** — a spinner styled with pure CSS, zero Ruby. See [Loading states](#declarative-loading-states-loading--disable_with). |
687
689
  | `on(:action, once: true)` | Fire at most once, then unbind (Stimulus's native `:once`). |
688
- | `on_client(:click, js.toggle("#menu"))` | **Client-only** trigger: applies declared DOM ops with ZERO round trip — no token, no POST, ever. Takes the same `window:`/`once:`/`outside:` modifiers and `debounce:`/`throttle:` waits (ms) as `on`, plus `detail:` (run only when `event.detail` carries the listed values). See [Client-only ops](#client-only-ops-on_client--js--zero-round-trips). |
690
+ | `on(:track, event: "drop", prevent: false)` | Keep the event's **native default** on an element-bound trigger: the client skips its `preventDefault`. See [Keep the native default](#keep-the-native-default--prevent-false). |
691
+ | `on_client(:click, js.toggle("#menu"))` | **Client-only** trigger: applies declared DOM ops with ZERO round trip — no token, no POST, ever. Takes the same `window:`/`once:`/`outside:` modifiers, `debounce:`/`throttle:` waits (ms) and `prevent: false` as `on`, plus `detail:` (run only when `event.detail` carries the listed values). See [Client-only ops](#client-only-ops-on_client--js--zero-round-trips). |
689
692
  | `js` | The immutable op builder behind `on_client`: `show`/`hide`/`toggle` (the `hidden` attribute, with an optional `transition:` and `expanded:`), `add_class`/`remove_class`/`toggle_class`, `set_attr`/`remove_attr`/`toggle_attr` (allowlisted names; `toggle_attr` also flips between two values), `focus`/`focus_first`/`blur`, `show_modal`/`close_dialog` (a real modal `<dialog>`), `copy_media` (copy `src`/`srcset`/`alt` from a server-rendered `<img>`, no URL argument), `text` (set `textContent` — XSS-safe), `set_value` (set a field's live `.value` and dispatch `input`), `dispatch`, `submit` (requestSubmit the target's own form, optionally through a `submitter:`), `paste_into` (read the clipboard into a field, gesture-gated), `preview_file` (paint a chosen image file onto an `img` through an object URL the client makes and revokes), `check_group` (tick or untick a checkbox group, then re-sync its bindings), and `persist_state`/`persist_clear` (the `reactive_persist` draft) — chainable. `keep: true` on the visibility, class and attr ops makes their result survive a morph. |
690
693
  | `reactive_field(:param, **attrs)` | The attribute hash that binds a control to an action param (no magic `name:`) — spread onto any control: `input(**reactive_field(:value, value: @record.name))`, `select(**reactive_field(:status)) { … }`. |
694
+ | `reactive_shared_field(name:, value: nil, **attrs)` | A control inside a **nested** component that its host's actions post too (#434): `input(type: "hidden", **reactive_shared_field(name: "item[choice]", value: @choice))`. Collected by its own component and by the next server component above it, one level only; `name:` is the host's param, verbatim (never re-scoped); a blank name raises at render. See *Nested reactive components compose* below. |
691
695
  | `reactive_editable(:name, multiline: false, placeholder: nil, on_enter: nil, on_escape: :revert, spellcheck: true)` | A plain-text **editable element** as a field (issue #351): `h3(**reactive_editable(:title)) { @card.title }`. Its text travels under the scope-aware `name`: with `multiline: true` its line breaks are sent as `\n`; a single-line field (the default) folds them to spaces; a morph keeps the focused element's text and caret (attributes still morph); paste is plain text; Enter runs `on_enter:` (a single-line field swallows it); Escape reverts. `reactive_dirty` and `reactive_persist` treat it like an input. See the [Editable text](https://phlex-reactive.zoolutions.llc/docs/editable-text) page. |
692
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). |
693
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). |
@@ -917,6 +921,33 @@ lazy or deferred shell (`reactive_lazy`, `reply.defer`) is never treated as
917
921
  client-only, with or without a token: it is a server component still loading,
918
922
  so it stays a boundary.
919
923
 
924
+ A **shared field** is the opt-in exception for a nested *server* component
925
+ (#434). A form widget with actions of its own (a picker that keeps the chosen
926
+ id in a hidden field) marks the field its host must post:
927
+
928
+ ```ruby
929
+ # Inside the picker component, itself rendered inside the item form:
930
+ input(type: "hidden", **reactive_shared_field(name: "item[choice]", value: @choice))
931
+ # => name="item[choice]" value="…" data-reactive-shared-field
932
+ ```
933
+
934
+ The picker's own actions still collect it, and so do the actions of the next
935
+ server component above the picker (client-only roots in between stay
936
+ transparent). One level only: a component above that host collects it only
937
+ when the host marks a copy of its own. The widget's unmarked fields stay its
938
+ own. The name goes on the wire verbatim (it is the host's param, never
939
+ re-scoped under the widget's `reactive_scope`), on the JSON body and the
940
+ multipart one alike; a name the host also renders follows the usual rule for a
941
+ plain name, the later control in the document wins. The widget's own actions
942
+ receive the field under that same name, so declare it there too when an
943
+ action reads it (`action :pick, params: { item: { choice: :string } }`);
944
+ otherwise the action drops it (with `Phlex::Reactive.verbose_errors` on, the
945
+ default in development and test, the log's dropped-param line names it).
946
+ A conditional `confirm:` judges the fields the action is about to post, so
947
+ it sees the shared field too. Dirty tracking, `reactive_persist` and the client bindings
948
+ (`reactive_show`, computes) keep strict ownership, so the field is the
949
+ widget's there. A native `<form>` posts it anyway, like any named control.
950
+
920
951
  **Debounced triggers (live-as-you-type).** Pass `debounce:` (milliseconds) to
921
952
  coalesce rapid events — typically keystrokes on an `"input"` trigger — into a
922
953
  single action round trip fired after the quiet period, instead of one POST per
@@ -938,7 +969,9 @@ hand-written Stimulus controller:
938
969
  - `window: true` binds the trigger to the window (Stimulus's native `@window`)
939
970
  for page-level events like `scroll`/`resize`. Window-bound triggers are
940
971
  **never `preventDefault`-ed** — a mounted dropdown must not kill link clicks
941
- elsewhere on the page — and skip the forced `type="button"`.
972
+ elsewhere on the page — and skip the forced `type="button"`. An
973
+ element-bound trigger is prevented unless it says `prevent: false` (see
974
+ [Keep the native default](#keep-the-native-default--prevent-false)).
942
975
  - `once: true` fires at most once, then unbinds (Stimulus's `:once`).
943
976
  - `throttle: 250` rate-limits **leading-edge**: the first event fires
944
977
  immediately, further events are dropped until the window elapses. The mirror
@@ -1017,6 +1050,46 @@ handler already handled (a drag's Escape). Keep `once:` off a shortcut that
1017
1050
  can be pressed while the user types or while a drag is on, or pair it with
1018
1051
  `in_editable: true` and `handled: true`.
1019
1052
 
1053
+ #### Keep the native default — `prevent: false`
1054
+
1055
+ An element-bound trigger (`on` or `on_client`) calls `preventDefault()` before
1056
+ its ops or action run, so a bare button inside a `<form>` cannot submit it.
1057
+ (Once the controller is connected, a binding whose key filter, `detail:` or
1058
+ spent `once:` skips the event leaves it alone; before that,
1059
+ `phlex/reactive/early` prevents every firing that matches a descriptor.) Some
1060
+ listeners only observe an event and need the browser to carry on: a drop zone
1061
+ built from a native `<input type="file">` stretched over an area gets the
1062
+ dropped file only when nothing cancelled the `drop`. `prevent: false` (#433)
1063
+ skips the `preventDefault` for that trigger, and its ops or action still run:
1064
+
1065
+ ```ruby
1066
+ div(id: "zone", class: "relative", **mix(
1067
+ on_client(:dragenter, js.add_class("#zone", "is-over")),
1068
+ on_client(:dragleave, js.remove_class("#zone", "is-over")),
1069
+ on_client(:drop, js.remove_class("#zone", "is-over"), prevent: false) # keeps the drop
1070
+ )) do
1071
+ input(type: "file", name: "file", class: "absolute inset-0 opacity-0")
1072
+ plain "Drop a file here"
1073
+ end
1074
+
1075
+ div(**on(:track, event: "drop", prevent: false)) # the same keyword on a server trigger
1076
+ ```
1077
+
1078
+ - The default, `prevent: true`, renders no attribute: existing markup is
1079
+ byte-identical.
1080
+ - It belongs to its own binding: a sibling `on_client` on another event (the
1081
+ `dragenter` above) is still prevented, and so is the event when another
1082
+ binding on the same element and event does not opt out.
1083
+ - A `window:` or `outside:` trigger never prevents, so `prevent: false` changes
1084
+ nothing there; with `shortcut:` (a chord the page claims) it raises
1085
+ `ArgumentError`. Anything but `true`/`false` raises too.
1086
+ - A click trigger keeps its forced `type="button"`; a button that should
1087
+ submit its form natively says so with `mix(on(...), type!: "submit")`.
1088
+ - With `confirm:`, this trigger does not cancel the native default, whatever
1089
+ the dialog answers: the dialog gates only its ops or action.
1090
+ - `phlex/reactive/early` follows the same rule before the controller connects.
1091
+ - `prevent:` is a reserved keyword name on `on(...)`, like the event modifiers.
1092
+
1020
1093
  ### Optimistic visual hints (`optimistic:`)
1021
1094
 
1022
1095
  Every reactive action waits a full round trip for its visual change — and it's
@@ -1371,7 +1444,7 @@ button(**on_client(:click, js
1371
1444
  (a broadcast that reads every subscriber's clipboard would be hostile). The
1372
1445
  op is async fire-and-forget — chained siblings apply immediately, never
1373
1446
  waiting for the read.
1374
- - **`preview_file(to, into:, name: nil, global: false, valid: false, wrap: nil, max_bytes: nil, accept: nil)`** (#375; `global: true`
1447
+ - **`preview_file(to, into:, name: nil, global: false, valid: false, wrap: nil, max_bytes: nil, accept: nil, per_file: false)`** (#375; `global: true`
1375
1448
  resolves `to`, `into:` and `name:` document-wide, for an `img` outside the
1376
1449
  root) paints the file a file input
1377
1450
  holds onto an `img` **before any upload**:
@@ -1408,6 +1481,21 @@ button(**on_client(:click, js
1408
1481
  file clears the preview, hides `wrap:` and dispatches `reactive:file-rejected`
1409
1482
  on the input with `detail.reason` `"type"` or `"size"`; `input.files` and the
1410
1483
  validity are left alone.
1484
+ **Several files (#439):** on an `<input type="file" multiple>`, `per_file: true`
1485
+ checks **every** file (`accept:`, then `max_bytes:`), rebuilds `input.files`
1486
+ from the accepted ones (through a `DataTransfer`, synchronously), dispatches one
1487
+ `reactive:file-rejected` per refused file with `detail.reason`, `detail.file`,
1488
+ `detail.index` (its place in the pick) and `detail.remaining` (how many files
1489
+ the input keeps), and paints the first accepted image. An action mixed in **after** the op
1490
+ on the same event posts only the kept files: `input(type: "file", id: "pick",
1491
+ name: "file", multiple: true, accept: "image/png", **mix(on_client(:change,
1492
+ js.preview_file("#pick", into: "#shot", max_bytes: 1_000_000, accept: true,
1493
+ per_file: true)), on(:upload, event: "change")))`. With every file refused the
1494
+ input is emptied and the action receives none. The reverse `mix` order posts
1495
+ before the op runs. Without a `DataTransfer` the rejections still fire and the
1496
+ input keeps every file (`remaining` counts them all). A single input, and
1497
+ `per_file:` omitted, keep the one-file check above; `per_file:` takes only
1498
+ `true`, `false` or `nil`.
1411
1499
  - **`expanded:`** on `show`/`hide`/`toggle` (#271) keeps a disclosure trigger's
1412
1500
  `aria-expanded` honest: `js.toggle("#menu", expanded: "#trigger")` writes the
1413
1501
  op's **intended** state (`show` → `"true"`, `hide` → `"false"`, `toggle` → the
@@ -1446,6 +1534,9 @@ button(**on_client(:click, js
1446
1534
  `window:`, `once:`, and `outside:` compose exactly like `on(...)`'s event
1447
1535
  modifiers: the dropdown above closes on any click outside the component, and
1448
1536
  window-bound triggers never `preventDefault`, so links elsewhere keep working.
1537
+ An element-bound binding does, unless it says `prevent: false` (a drop that must
1538
+ still reach a native file input; see
1539
+ [Keep the native default](#keep-the-native-default--prevent-false)).
1449
1540
 
1450
1541
  **Gate on the event's payload with `detail:` (#346).** A Hash of top-level
1451
1542
  `event.detail` keys to the value each must strictly equal (`===`). Values are
@@ -1,9 +1,9 @@
1
- import{Controller as xt}from"@hotwired/stimulus";import{confirmResolver as Le}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)}}function It(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=Se(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",(s)=>s.missingRoot(r));return}fe(t,(s)=>_r(s,i),n?(s,a)=>y("devtools",(o)=>o.diagnoseStream(s,a,i)):void 0)}}function Pt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){y("defer",(t)=>t.streamAction(this))}}var Re=!1,ce=null;function Mt(){if(Re)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Re=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Gt(e),Ct(e),$t(e),ce)ce(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var B="reactive:streamed";function Ct(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target,i=n?.getAttribute?.("action"),s=/^(append|prepend|update)$/.test(i);if(typeof r!=="function"||!(s||/^(before|after|replace)$/.test(i)))return;let a=n.getAttribute("target"),o=n.getAttribute("targets"),c=new Set;for(let l of a?[document.getElementById(a)]:o?document.querySelectorAll(o):[]){let d=(s?l:l?.parentElement)?.closest?.('[data-controller~="reactive"]');if(d)c.add(d)}if(c.size===0)return;t.render=async(l)=>{await r(l);for(let d of c)if(d.isConnected)d.dispatchEvent(new Event(B))}}function me(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function pe(e){try{return e.matches(":modal")}catch{return!1}}function et(e){if(!me(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||pe(e))return;if(e.open)e.close();e.showModal()}function Dt(e){if(me(e)&&e.open)e.close()}function K(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&&!pe(n))et(n)}function $t(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),K(document)}}var xe=!1;function qt(){if(xe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;xe=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))K(t.target)}),document.addEventListener("turbo:morph",()=>K(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!me(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||!pe(r))return;e.delete(r),t.preventDefault(),r.close()})}var ue=new WeakMap;function tt(e,t,r,n){let i=ue.get(e)??new Map;ue.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 Ne=!1;function Wt(){if(Ne)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ne=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of ue.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",L="data-reactive-image-state",le="data-reactive-image-hidden",ee=null,de="data-reactive-wrap-hidden";function nt(e){if(e.hasAttribute("hidden"))return;e.setAttribute("hidden",""),e.setAttribute(de,"")}function it(e){if(!e.hasAttribute(de))return;e.removeAttribute("hidden"),e.removeAttribute(de)}function R(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 ge(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=ge(e,t.alt);return r&&!r.contains(e)?r:null}function z(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(le,"");if(t.wrap){let i=ge(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 X(e,t);e.setAttribute(L,r)}function X(e,t=R(e)){if(!t||e.getAttribute(L)==null)return;if(e.getAttribute(L)==="error"){if(e.hasAttribute(le))e.removeAttribute("hidden");let r=ge(e,t.wrap);if(r)it(r);let n=st(e,t);if(n)n.hidden=!0}e.removeAttribute(L),e.removeAttribute(le)}function Oe(e){let t=e.target,r=R(t);if(!r)return;if(e.type==="load")z(t,r,"loaded");else if(ot(t))z(t,r,"error");else X(t,r)}function Bt(){if(ee)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;ee={error:Oe,load:Oe,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(L);if(i==null||!n||!R(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=R(r);if(i)z(r,i,n)})}};for(let[t,r]of Object.entries(ee))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&&z(t,R(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){ce=e}var C,te=null,Ie="[data-reactive-editable][contenteditable=plaintext-only]";function ct(){if(C===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",C=e.contentEditable==="plaintext-only"}catch{C=!1}return C}function j(e){if(e.matches?.(Ie))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Ie).forEach(j)}function jt(){if(te||typeof document>"u"||typeof document.createElement!=="function")return;if(ct())return;j(document),te=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")j(t.target);else t.addedNodes.forEach(j)}),te.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var Pe=!1;function Me(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 Ut(){if(Pe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Pe=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=Me(t);if(n)Ht(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(G.set(t,E(r)),!n)return;for(let{name:s}of[...t.attributes])if(!r.hasAttribute(s)&&s!=="contenteditable"&&s!==_)t.removeAttribute(s);for(let{name:s,value:a}of r.attributes)if(s!=="contenteditable"&&t.getAttribute(s)!==a)t.setAttribute(s,a);return e.preventDefault()}if(t.localName!=="input"||!n)return;let i=r.getAttribute("value");if(i==null)t.removeAttribute("value");else if(t.getAttribute("value")!==i)t.setAttribute("value",i)}),document.addEventListener("focusin",(e)=>we(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&Me(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&ye(t)===ve(t))t.removeAttribute(_)})}var _="data-reactive-held",be='[data-controller~="reactive"]',U=null,T=new Map;function ye(e){return e.hasAttribute("data-reactive-editable")?E(e):e.value}function ve(e){return e.hasAttribute("data-reactive-editable")?Ae(e):e.defaultValue}function Jt(e){if(e.hasAttribute("data-reactive-editable"))return E(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function Ht(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||T.has(e.closest(be)))return;let n=Jt(t);if(n===ye(e))return e.removeAttribute(_);if(n===ve(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(be)!==e)continue;let n=r.getAttribute("name");if(ye(r)===ve(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(be)===e&&!t?.includes(r.getAttribute("name")))r.removeAttribute(_)}function zt(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 Ce(e,t,r=null){let n={root:e,streams:0,keep:r},i=U;U=n;try{window.Turbo.renderStreamMessage(t)}finally{U=i}if(n.streams===0)ut(e,r)}function Gt(e){let t=U,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{T.set(t.root,(T.get(t.root)||0)+1);try{return await n(i)}finally{let s=T.get(t.root)-1;if(s)T.set(t.root,s);else T.delete(t.root);ut(t.root,t.keep)}}}var De="__materialize",$e=!1;function Vt(){if($e)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;$e=!0;let e=()=>{let t=document.documentElement;if(typeof t?.toggleAttribute!=="function")return;t.toggleAttribute("data-reactive-offline",globalThis.navigator?.onLine===!1)};e(),window.addEventListener("online",e),window.addEventListener("offline",e)}var Yt="phlex-reactive:latency";function lt(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Yt))}function _e(){if(typeof document>"u")return;if(!p.has("devtools")&&!w.get("devtools")[1])return;let e=document.querySelector?.('meta[name="phlex-reactive-env"]')?.content==="development";if(e||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 Xr(){return A}function Zr(){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"||!Xt(t))return;let r=Zt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(pt,JSON.stringify(r))}function Xt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Zt(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 qe(){Nt(),Ot(),It(),Pt(),Mt(),Ut(),qt(),Wt(),Bt(),jt(),Vt(),_e()}function Qt(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 er(){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(er,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var tr=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function vt(e){let t=String(e).toLowerCase();return t.startsWith("on")||tr.has(t)}var re=new WeakMap;function rr(e,t,r){let[n,i,s]=t;re.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,re.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};re.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,nr(e))}function nr(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 ir=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",or=new Set(["lexxy-editor","trix-editor"]);function E(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
1
+ import{Controller as xt}from"@hotwired/stimulus";import{confirmResolver as xe}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)}}function It(){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}me(t,(o)=>wr(o,i),n?(o,a)=>y("devtools",(s)=>s.diagnoseStream(o,a,i)):void 0)}}function Pt(){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 Mt(){if(Ne)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Ne=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Gt(e),Ct(e),$t(e),le)le(e,g.get("effects"));else g.get("effects")?.wrap(e)})}var B="reactive:streamed";function Ct(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target,i=n?.getAttribute?.("action"),o=/^(append|prepend|update)$/.test(i);if(typeof r!=="function"||!(o||/^(before|after|replace)$/.test(i)))return;let a=n.getAttribute("target"),s=n.getAttribute("targets"),c=new Set;for(let u of a?[document.getElementById(a)]:s?document.querySelectorAll(s):[]){let d=(o?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(B))}}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 Dt(e){if(ge(e)&&e.open)e.close()}function K(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 $t(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),K(document)}}var Oe=!1;function qt(){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"]'))K(t.target)}),document.addEventListener("turbo:morph",()=>K(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 o=(a,s)=>{i.delete(a),i.set(a,s)};if(t.endsWith("_class"))for(let a of r.classes??[])o(`.${a}`,e.classList.contains(a));else if(t.endsWith("_attr"))vt(r.name)||o(r.name,e.getAttribute(r.name));else if(t==="show"||t==="hide"||t==="toggle"){if(o("hidden",e.getAttribute("hidden")),r.expanded!=null)for(let a of n({...r,to:r.expanded}))tt(a,"set_attr",{name:"aria-expanded"})}}var Ie=!1;function Wt(){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",L="data-reactive-image-state",fe="data-reactive-image-hidden",te=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 R(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 G(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 Z(e,t);e.setAttribute(L,r)}function Z(e,t=R(e)){if(!t||e.getAttribute(L)==null)return;if(e.getAttribute(L)==="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(L),e.removeAttribute(fe)}function Pe(e){let t=e.target,r=R(t);if(!r)return;if(e.type==="load")G(t,r,"loaded");else if(ot(t))G(t,r,"error");else Z(t,r)}function Bt(){if(te)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;te={error:Pe,load:Pe,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(L);if(i==null||!n||!R(r))return;let o=(a)=>r.getAttribute(a)===n.getAttribute?.(a);if(o("src")&&o("srcset"))e.set(r,i)},"turbo:morph-element":(t)=>{let r=t.target,n=e.get(r);if(n===void 0)return;e.delete(r),queueMicrotask(()=>{let i=R(r);if(i)G(r,i,n)})}};for(let[t,r]of Object.entries(te))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&&G(t,R(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 C,re=null,Me="[data-reactive-editable][contenteditable=plaintext-only]";function ct(){if(C===void 0)try{let e=document.createElement("div");e.contentEditable="plaintext-only",C=e.contentEditable==="plaintext-only"}catch{C=!1}return C}function j(e){if(e.matches?.(Me))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Me).forEach(j)}function jt(){if(re||typeof document>"u"||typeof document.createElement!=="function")return;if(ct())return;j(document),re=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")j(t.target);else t.addedNodes.forEach(j)}),re.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 Ut(){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)Ht(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(V.set(t,T(r)),!n)return;for(let{name:o}of[...t.attributes])if(!r.hasAttribute(o)&&o!=="contenteditable"&&o!==_)t.removeAttribute(o);for(let{name:o,value:a}of r.attributes)if(o!=="contenteditable"&&t.getAttribute(o)!==a)t.setAttribute(o,a);return e.preventDefault()}if(t.localName!=="input"||!n)return;let i=r.getAttribute("value");if(i==null)t.removeAttribute("value");else if(t.getAttribute("value")!==i)t.setAttribute("value",i)}),document.addEventListener("focusin",(e)=>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"]',U=null,F=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 Jt(e){if(e.hasAttribute("data-reactive-editable"))return T(e);return e.localName==="textarea"?e.textContent:e.getAttribute("value")??""}function Ht(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||F.has(e.closest(ve)))return;let n=Jt(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 zt(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 Kt(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=U;U=n;try{window.Turbo.renderStreamMessage(t)}finally{U=i}if(n.streams===0)ut(e,r)}function Gt(e){let t=U,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{F.set(t.root,(F.get(t.root)||0)+1);try{return await n(i)}finally{let o=F.get(t.root)-1;if(o)F.set(t.root,o);else F.delete(t.root);ut(t.root,t.keep)}}}var qe="__materialize",We=!1;function Vt(){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 Yt="phlex-reactive:latency";function lt(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Yt))}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 Zr(){return A}function Qr(){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"||!Xt(t))return;let r=Zt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(pt,JSON.stringify(r))}function Xt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Zt(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(),It(),Pt(),Mt(),Ut(),qt(),Wt(),Bt(),jt(),Vt(),Ae()}function Qt(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 er(){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(er,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var tr=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function vt(e){let t=String(e).toLowerCase();return t.startsWith("on")||tr.has(t)}var ne=new WeakMap;function rr(e,t,r){let[n,i,o]=t;ne.get(e)?.(),e.classList.add(n,i),r();let a=!1,s=requestAnimationFrame(()=>{if(a)return;e.classList.remove(i),e.classList.add(o)}),c=(d)=>{if(a||d&&d.target!==e)return;a=!0,ne.delete(e),clearTimeout(u),globalThis.cancelAnimationFrame?.(s),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,o)};ne.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let u=setTimeout(c,nr(e))}function nr(e){let t=0;try{let r=getComputedStyle(e);for(let n of["transition","animation"]){let[i,o]=["Duration","Delay"].map((s)=>String(r[n+s]).split(",").map((c)=>parseFloat(c)*(/ms/.test(c)?1:1000)||0)),a=String(r[n+"IterationCount"]).split(",").map((s)=>/inf/.test(s)?1/0:parseFloat(s)>=0?parseFloat(s):1);for(let s=0;s<i.length||s<o.length||s<a.length;s++){let c=i[s%i.length]*a[s%a.length]||0;t=Math.max(t,c+o[s%o.length])}}}catch{}return Math.min(Math.max(t+50,350),5000)}var ir=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",or=new Set(["lexxy-editor","trix-editor"]);function T(e){let t="",r=!1,n=(o)=>{if(r&&t&&!t.endsWith(`
2
2
  `))t+=`
3
- `;r=!1,t+=s},i=(s)=>{for(let a of s.childNodes){let o=/^(div|p|li)$/.test(a.localName);if(o)r=!0;if(a.nodeType===3)a.data&&n(a.data);else if(a.localName==="br")n(`
4
- `);else if(a.nodeType===1)i(a);if(o)r=!0}};return i(e),t=t.replace(/\r\n?/g,`
5
- `).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var G=new WeakMap;function we(e){if(e?.hasAttribute?.("data-reactive-editable")&&!G.has(e))G.set(e,E(e))}function Ae(e){return we(e),G.get(e)}function sr(e){return or.has(e.localName)?typeof e.value==="string":!0}var We=Object.freeze({show:(e,t,r)=>ie(e,!1,t,r),hide:(e,t,r)=>ie(e,!0,t,r),toggle:(e,t,r)=>ie(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(oe(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(oe(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!oe(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)=>mr(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)=>Dt(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=ar(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)=>cr(e),preview_file:(e,t,r)=>ur(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 ar(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function cr(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 x=new Map,N=null;function ur(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return ne(`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 ne(`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=lr(e,t.accept),a=i.filter((d)=>typeof d?.type==="string"&&s(d)),o=a.find((d)=>d.type.startsWith("image/")),c=i.length>0&&a.length===0?"type":null;if(o&&Number.isInteger(t.max_bytes)&&o.size>t.max_bytes)c="size";let l=c==="size"?o:i[0];if(c)o=null;if(_t(n),o){let d=URL.createObjectURL(o);x.set(n,d),n.setAttribute("src",d),dr()}else n.removeAttribute("src");if(X(n),t.wrap!=null){let d=r({...t,to:t.wrap});if(d.length===0)ne(`wrap: ${JSON.stringify(t.wrap)} is not on the page`);for(let h of d)o?it(h):nt(h)}if(t.name!=null)for(let d of r({...t,to:t.name}))d.textContent=o?o.name:"";if(c)e.dispatchEvent(new CustomEvent("reactive:file-rejected",{bubbles:!0,detail:{reason:c,file:l}}))}function lr(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 ne(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function _t(e){let t=x.get(e);if(t===void 0)return;if(x.delete(e),URL.revokeObjectURL(t),x.size===0)N?.disconnect(),N=null}function dr(){if(N||typeof MutationObserver!=="function"||!document?.documentElement)return;N=new MutationObserver(()=>{for(let[e,t]of x)if(!e.isConnected||e.getAttribute("src")!==t)_t(e)}),N.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=Be(e);if(e.value=t,Be(e)!==r)wt(e)}function Be(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
6
- `):e.value}function fr(e,t,r){if(r?.transition)rr(e,r.transition,()=>e.hidden=t);else e.hidden=t}function ie(e,t,r,n){if(fr(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 oe(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)X(e);let s=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==s)e.setAttribute("alt",s);return r?s:!1}var hr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function mr(e){return e.querySelectorAll?.(hr)?.[0]??null}function Se(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"}),Ue=Object.freeze(["meta","ctrl","alt","shift"]);function Z(e,t,r){let n=e.split("+");for(let a of Ue)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Ue.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 pr=(e)=>e&&typeof e==="object"?e.keys:String(e),Ee=()=>J().prevented??=new WeakSet;function se(e,t){if(t!=null&&!e.defaultPrevented)Ee().add(e);e.preventDefault()}function D(e,t,r){if(t.defaultPrevented&&e?.handled!==!0&&!Ee().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 Z(pr(e).replace(/^mod\+/,`${i}+`),t,r)}function gr(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:Se(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 Je(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)!==Fe(t.currentTarget))return!1;return i<0||r===null||Z(n.slice(i+1),t,r)}function br(e,t){let r=e.detail;if(r===void 0)return!0;if(r===null||typeof r!=="object"||Array.isArray(r))return!1;let n=t.detail;if(n===null||typeof n!=="object")return!1;return Object.keys(r).every((i)=>n[i]===r[i])}var He=new WeakMap;function yr(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=He.get(e);if(!i)i=new WeakMap,He.set(e,i);let 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 Ke=new WeakMap;function vr(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=Ke.get(e);if(!i)i=new WeakMap,Ke.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 fe(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn(We,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(We[i](o,s,t),s?.keep===!0)tt(o,i,s,t)}}function _r(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 wr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function Te(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}var ze='[data-controller~="reactive"]',Ar='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',he=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!Te(e);function Ge(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&he(n))n=n.parentElement?.closest?.(t);return n??null}var q=new WeakMap,W=new WeakMap;function Sr(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 Er(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 Tr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function Fr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function kr(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 Lr(e){return Boolean(e.matches?.("[data-reactive-countdown]")||e.querySelector?.("[data-reactive-countdown]"))}var Rr=[["persist",[wr,null,null,!0]],["defer",[Te,null]],["form",[Sr,null]],["bindings",[Er,null,null,!0]],["compute",[Tr,null,null,!0]],["sortable",[Fr,null]],["drag",[kr,null]],["presence",[Et,null]],["countdown",[Lr,null]],["effects",[(e)=>["enter","update","exit"].some((t)=>e.getAttribute?.(`data-reactive-effect-${t}`)!=null),null]],["hints",[(e)=>e.querySelector?.("[data-reactive-optimistic-param], [data-reactive-busy-param], [data-reactive-loading-param]")!=null,null]],["devtools",[(e)=>e.getAttribute?.("data-reactive-debug")==="true",null]]],w=new Map(Rr),Ve=new Map,p=new Map,xr=new Map;function g(e,t,r){Tt.set(e,[t,r]),Nr(e)}var Tt=new Map;function Nr(e){let t=w.get(e),[r,n]=Tt.get(e);t[1]=r,t[2]=n}function Qr(e,t){t.install?.(I),p.set(e,t),xr.set(e,t)}function Ft(e){let t=[];for(let[r,[n]]of w){if(!n||p.has(r))continue;try{if(e.some((i)=>n(i)))t.push(r)}catch{}}return t}function kt(e){return O(e).catch((t)=>V(e,"load",t))}function O(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?.(I),p.set(e,n),n)),Ve.set(e,t);return t}var Ye=new Set;function V(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=p.get(e);if(r)return t(r);O(e).then(t,(n)=>V(e,"load",n))}var Or=1e4;function ae(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:Or}function en(){return[...w.keys()]}var Xe=Promise.resolve();function Ze(e,t,r){let n=I.waiting.get(e);if(n&&n[t]===r)delete n[t]}var I={enter:ft,exit:ht,count:gt,text:E,served:Ae,waiting:new WeakMap};var P=Symbol.for("phlex-reactive.early"),Ir=1e4,Pr=1500,Fe=(e)=>e!=null&&(e===globalThis.window||e.window===e),Mr="dispatch";function J(){return globalThis[P]??={queue:[],connected:new WeakSet},globalThis[P]}function Cr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:Ir}function Dr(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 $r(e,t,r){return{[P]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:Dr(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&&!Ee().has(e),preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var Y=new WeakMap;function qr(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=Y.get(e);if(!o)Y.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?.[P])return!1;let i=Fe(e?.currentTarget),s=i?n:e?.currentTarget,a=Br(e,s,i?`@${t}`:t),o=Y.get(s),c=i&&JSON.stringify(e.params);for(let l of o?.values()??[]){if(!l.armed||l.method!==t||l.type!==e.type||Boolean(l.win)!==i)continue;if(i&&l.params!==c)continue;if(l.filter&&!Z(l.filter,e,r))continue;return l.armed=!1,!0}return a}var H=new WeakMap;function Wr(e,t,r){let n=H.get(e);if(!n)H.set(e,n=new Map),setTimeout(()=>H.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Br(e,t,r){let n=e&&H.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Lt extends xt{static values={token:String};#w;#l=new Map;#d=new Map;#ne;#L;#B;#R=0;#f=new Map;#x=new WeakMap;#t;featuresReady=Xe;#r=new Map;#N=new Set;#h=!1;#n=null;#m=new Map;#A=new Map;#p=new Map;#g=0;#j;#qe=0;#We=0;connect(){if(yt=!0,J().connected.add(this.element),q.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||Te(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===B)this.#H();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(B,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(we),this.#g++,this.featuresReady=Xe,this.#U(),K(this.element),this.#ae()}#Be(e){}#je(e,t,r,n){}#Ue(){}#Je(e,t){}#U(e){{let t=this.#g,r=[];for(let[s,[a]]of w){if(!a||this.#N.has(s))continue;let o=p.get(s);if(o&&!o.connect)continue;try{if(a(this.element))r.push(s)}catch(c){this.#b(s,"detect",c)}}if(r.length===0)return;for(let s of r)this.#N.add(s);if(!this.#h&&r.every((s)=>p.has(s))){for(let s of r)this.#O(t,s,p.get(s),e);return}for(let s of r){let a=this.#ie(t,s),o=[];for(let l of w.keys()){if(l===s)break;if(this.#p.has(l))o.push(this.#p.get(l))}let c=Promise.all(o).then(()=>a).then((l)=>l&&this.#O(t,s,l,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}}#ie(e,t){{let r=()=>e===this.#g;return this.#oe(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 ${ae()} ms`));n(null)},ae());this.#m.set(s,n);let a=()=>{clearTimeout(s),this.#m.delete(s)};O(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)})})}}#oe(e){{let t=w.get(e)[2];if(!t)return;let r={};try{this.#A.set(e,[t(this.element,r),r]),I.waiting.set(this.element,{...I.waiting.get(this.element),[e]:r})}catch(n){this.#b(e,"detect",n)}}}#J(e,t){{let[r,n]=this.#A.get(e)??[];if(this.#A.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.#w=void 0},owns:(e)=>this.#F(e),ownership:()=>this.#Z(),opTargets:(e)=>this.#W(e),diagnose:(e,t)=>this.#q(e,t),applyOps:(e,t)=>fe(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.#Q(),plain:ct,text:E,served:Ae,copyMedia:St,setValue:At,confirm:(e,t)=>Promise.resolve().then(()=>Le(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(V(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})}#se(){{this.#g++;for(let[t,r]of this.#m)clearTimeout(t),r(null);this.#m.clear();for(let t of[...this.#A.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)}}}#ae(){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.#ce();for(let[e,t]of W.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}W.delete(this.element)}#I=new Set;#ce(){let{queue:e}=J();if(e.length===0)return;let t=[];for(let i=e.length-1;i>=0;i--){let{root:s}=e[i];if(s===this.element||!s.isConnected)t.unshift(...e.splice(i,1))}let r=Cr(),n=new Map;for(let i of t){let s=n.get(i.event)??[new Set,new Set];n.set(i.event,s);let a=s[+!!i.win];if(a.has(i.el))continue;a.add(i.el);let o=i.win?Math.min(Pr,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.#ue(i)}}#ue({event:e,el:t,descs:r,win:n}){let i=$r(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&&!Z(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!qr(o,c,n&&JSON.stringify(i.params)))continue;this.#I.add(o)}if(Wr(e,o,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#se(),this.#be(),this.#ve(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(B,this.#t);if(J().connected.delete(this.element),q.get(this.element)===this)q.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)Y.delete(e);this.#I.clear()}dispatch(e){if(e.params?.action&&e.params.action!==De&&this.#le())return this.#de(e);let t=e.params?.shortcut;if(t!=null&&!D(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:l,optimistic:d}=e.params;if(!r)return;let h=e.params.busy??e.params.loading;if(c&&this.element.contains(e.target))return;let f=e.currentTarget??e.target;if((t!=null||!l)&&!this.#te(d,f))se(e,t);if(r===De){let S=()=>{{let m=this.#r.get("defer");if(m)return m.materialize(this)}if(this.tokenValue)return this.#P(f,r,"{}")};return this.#h?this.featuresReady.then(S):S()}let b=this.#K(a,o),v=()=>this.#P(f,r,n,i,s,d,h);if(!b)return v();if(b instanceof Promise)return b.then((S)=>S?this.#S(S,f,v):v());this.#S(b,f,v)}#S(e,t,r){return Promise.resolve().then(()=>Le(e,{el:t})).catch(()=>!1).then((n)=>{if(n)r()})}#K(e,t){if(e)return e;if(!t)return null;{let r=p.get("bindings");if(r)return r.confirmMessage(this,this.#e(),t);return this.#z("bindings").then((n)=>n&&n.confirmMessage(this,this.#e(),t))}}#z(e){{let t;return Promise.race([O(e).catch((r)=>(V(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),ae()))]).finally(()=>clearTimeout(t))}}#le(){return!this.tokenValue&&he(this.element)}#de(e){let t=Ge(this.element.parentElement,Ar);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=q.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:s}=e.params;if(n!=null&&!D(n,e,this.application?.schema?.keyMappings))return;let a=e.currentTarget??e.target;if((n!=null||!i)&&!this.#te(s,a))se(e,n);W.set(t,[...W.get(t)??[],[e,a]]);let o=t.dataset;if(o.reactiveDormant)o.controller=`${o.controller??""} ${o.reactiveDormant}`.trim(),delete o.reactiveDormant}runOps(e){let t=e.params?.ops;if(t?.shortcut!=null&&!D(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Qe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(vr(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=gr(r.ops),s=i.filter((o)=>Je(o,e,null)),a=s.length<=1?s:s.filter((o)=>Je(o,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#$())this.#_((o)=>o.noBinding(this,e));return}for(let o of a){if(o.outside&&e[P])continue;if(!br(o,e))continue;if(o.shortcut!=null&&!D(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(yr(this,e,o))continue;this.#fe(o.legacy?{...r,ops:o.ops,debounce:void 0,throttle:void 0}:o,e,n,i.indexOf(o))}}#fe(e,t,r,n){let{ops:i,confirm:s,confirmWhen:a,outside:o,window:c,shortcut:l}=e;if(o&&this.element.contains(t.target))return;if(l!=null||!c)se(t,l);let d=this.#K(s,a),h=this.#he(e,n,r,()=>this.#Ne(this.#xe(i)));if(!d)return h();if(d instanceof Promise)return d.then((f)=>f?this.#S(f,r,h):h());this.#S(d,r,h)}#he(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 p.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 p.get("bindings")?.syncNestedJson(this,this.#e(),e)}#y(e,t){{let r=p.get("bindings");if(r)return r[e](this,this.#e(),t);t?.preventDefault?.();let n={currentTarget:t?.currentTarget??null,target:t?.target??null,preventDefault(){}};return y("bindings",(i)=>i[e](this,this.#e(),n))}}trackDirty(){(this.#r.get("form")??p.get("form"))?.scan(this,this.#e())}listnavNext(e){this.#E(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#E(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#E(e,()=>0)}listnavLast(e){this.#E(e,(t,r)=>r-1)}listnavPick(e){let t=this.#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")}#E(e,t){let r=this.#v(e);if(!r.length)return;e.preventDefault();let n=this.#me(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"})}#me(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.#ee(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#ge(e,c,t,r,s,a);let l=Number(i)||0;if(l>0)return this.#ye(e,l,t,r,s,a);return this.#T(t,r,s,e,a)}#T(e,t,r,n,i){let s={inverse:null,undo:[],resurrect:null},a=this.#Oe(e,n,s),o=Boolean(r||i),c=(f)=>{if(!o||!f)return;let b=this.#e();if(s.inverse=f.optimistic(this,b,r,n),s.undo.push(...f.busy(this,b,i,n)),this.#C())s.resurrect=f.resurrection(this,b,r,n)},l=p.get("hints");if(!o||l)c(l);let d=()=>this.#Se(e,t,s,a),h=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>o&&!l?this.#pe().then(c).then(h):h()),this.queue}#pe(){return this.#z("hints")}#ge(e,t,r,n,i,s){this.#G(e,Mr,t,()=>this.#T(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(!Fe(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)}#be(){for(let[e,t]of[...this.#l])for(let r of[...t.keys()])this.#M(e,r)}#ye(e,t,r,n,i,s){return this.#V(e,r,t,()=>this.#T(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()}#ve(){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.#T(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)}#_e(){this.element?.removeAttribute?.("data-reactive-error")}#we(){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))}#Ae(){{let e=p.get("devtools");if(e)return e.delay();if(lt())return O("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#Se(e,t,r,n){let{fields:i,files:s}=this.#Q(),a=this.#ee(t),o={...i,...a},c=this.#a,l=s.length>0,d=l?this.#Le(c,e,o,s):JSON.stringify({token:c,act:e,params:o}),h=this.#C()?{action:e,paramNames:Object.keys(a),fieldNames:Object.keys(i),encoding:l?"multipart":"json",status:null,streams:[],tokenRefreshed:!1,started:this.#Y()}:null;await this.#Ae();try{if(navigator.onLine===!1){this.#c(r.inverse),this.#i("offline"),this.#s(e,t,o,{kind:"offline"});return}let f;try{let m={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#De()};if(!l)m["Content-Type"]="application/json";let k=this.#$e();if(k)m["X-Pgbus-Connection"]=k;let M=Et(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(M)m["X-Reactive-Presence"]=M;let ke=Kt(this.element);if(ke)m["X-Reactive-Held"]=ke;gt("action"),f=await fetch(this.#Me(),{method:"POST",headers:m,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#Ce())})}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.#we(),this.#i("network"),this.#s(e,t,o,{kind:"network"});return}if(h)h.status=f.status;if(f.redirected){console.error("[phlex-reactive] action was redirected (auth/CSRF?) — no update applied"),this.#c(r.inverse),this.#i("redirected"),this.#s(e,t,o,{kind:"redirected",status:f.status});return}if(!f.ok){let m=await f.text();if(console.error(`[phlex-reactive] action failed: HTTP ${f.status}`,m),this.#c(r.inverse),(f.headers.get("Content-Type")||"").includes("turbo-stream")){let k=this.#X(m);if(this.#a=k??this.#a,h)this.#_((M)=>M.recordBody(h,m,k));Ce(this.element,m,!0)}this.#i("http"),this.#s(e,t,o,{kind:"http",status:f.status,body:m});return}let b=f.headers.get("Content-Type")||"";if(!b.includes("turbo-stream")){console.error(`[phlex-reactive] expected a turbo-stream, got "${b}" — no update applied`),this.#c(r.inverse),this.#i("content-type"),this.#s(e,t,o,{kind:"content-type",status:f.status});return}let v=await f.text(),S=this.#X(v);if(this.#a=S??this.#a,h)this.#_((m)=>m.recordBody(h,v,S));if(Ce(this.element,v,zt(f)),r.resurrect)queueMicrotask(r.resurrect);return this.#_e(),this.#o("reactive:applied",{action:e,params:o,html:v}),v}catch(f){console.error("[phlex-reactive] action error",f),this.#c(r.inverse),this.#o("reactive:error",{action:e,params:o,kind:"apply"})}finally{if(n?.(),h)this.#_((f)=>f.trace(this,{...h,ms:this.#Y()-h.started}))}}get#a(){return this.#w??this.tokenValue}set#a(e){this.#w=e}tokenValueChanged(){this.#w=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.#Ee(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}#Ee(e){let t=this.#B;if(t&&t.id===e)return t;let r=Qt(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>`)}}#F(e){return e.closest('[data-controller~="reactive"]')===this.element}#Z(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#F(t)}#Te(){let e=this.element.querySelectorAll(ze);if(e.length===0||[...e].every(he))return()=>!0;return(t)=>Ge(t,ze,this.element)===this.element}#Q(){let e={},t=[],r=this.#Te(),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]${ir}`).forEach((o)=>{if(r(o))i.push(o)});let s=this.#Fe(n),a=this.#ke(n);for(let o of n)if(s.has(o.name)){let c=e[o.name]??(e[o.name]=[]);if(o.type==="checkbox"||o.type==="radio"){if(o.checked)c.push(o.value)}else if(o.type==="hidden"){if(!a.has(o.name))c.push(o.value)}else if(o.multiple&&o.options){for(let l of o.options)if(l.selected)c.push(l.value)}else c.push(o.value)}else if(o.type==="checkbox")e[o.name]=o.checked;else if(o.type==="radio"){if(o.checked)e[o.name]=o.value}else e[o.name]=o.value;return i.forEach((o)=>{let c=o.getAttribute("name");if(!c)return;let l=o.getAttribute("data-reactive-editable")!=null?E(o):o.value??o.textContent??o.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!sr(o))return;if(String(c).endsWith("[]")&&(d===void 0||Array.isArray(d))){(Array.isArray(d)?d:e[c]=[]).push(l);return}if(d==null||d==="")e[c]=l}),{fields:e,files:t}}#Fe(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}#ke(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#Le(e,t,r,n){let i=new FormData;i.append("token",e),i.append("act",t);let s=[];for(let[o,c]of Object.entries(r))if(Array.isArray(c)&&String(o).endsWith("[]"))if(c.length===0)s.push(String(o).slice(0,-2));else{let l=`${this.#k(o)}[]`;for(let d of c)i.append(l,String(d))}else this.#D(i,this.#k(o),c);for(let o of s)i.append("empty_groups[]",o);let a=this.#Re(n);for(let{name:o,file:c,multiple:l}of n){let h=l||a.has(o)?`${this.#k(o)}[]`:this.#k(o);i.append(h,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))}#Re(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))}#ee(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#xe(e){return Se(e)}#Ne(e){fe(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.#_((r)=>r.diagnose(this,e,t))}#_(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.#F(r))}#te(e,t){if(e?.checked!=="keep")return!1;let r=t?.type;return r==="checkbox"||r==="radio"}#c(e){if(!e)return;if(!this.element.isConnected)return;for(let t of e)t()}#Oe(e,t,r){this.#Ie(e,t),ft();let n=!1;return()=>{if(n)return;n=!0,this.#Pe(e,t),ht();for(let i of r.undo)i()}}#Ie(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.#R++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#re(e))this.#u(r,e,1)}#Pe(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.#R<=0)this.#R=0,this.element.removeAttribute("aria-busy");for(let n of this.#re(e))this.#u(n,e,-1)}#u(e,t,r){if(!e||typeof e.getAttribute!=="function")return;let n=this.#x.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.#x.delete(e),e.removeAttribute("data-reactive-busy");return}this.#x.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#re(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#F(r))}#Me(){return this.#ne??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#Ce(){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}#De(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#$e(){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)qe();else document.addEventListener("turbo:load",qe,{once:!0});g("persist",()=>import("phlex/reactive/features/persist"),jr);g("defer",()=>import("phlex/reactive/features/defer"));g("form",()=>import("phlex/reactive/features/form"));g("bindings",()=>import("phlex/reactive/features/bindings"));g("compute",()=>import("phlex/reactive/features/compute"),Ur);g("sortable",()=>import("phlex/reactive/features/sortable"));g("drag",()=>import("phlex/reactive/features/drag"));g("presence",()=>import("phlex/reactive/features/presence"));g("countdown",()=>import("phlex/reactive/features/countdown"));g("effects",()=>import("phlex/reactive/features/effects"));g("hints",()=>import("phlex/reactive/features/hints"));g("devtools",()=>import("phlex/reactive/features/devtools"));_e();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 Ur(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 Jr=1000,F=null,Rt,Q=new Set;function Hr(e){return kt(e).then((t)=>{if(e!=="effects")return;Rt=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(Kr(i)).filter((o)=>!Q.has(o));if(!t&&!Q.has("effects")&&zr(i))s.push("effects");if(s.length===0&&!F)return t?.wrap(e);if(s.length>0){for(let c of s)Q.add(c);let o=F=Promise.race([Promise.all([F,...s.map(Hr)]),new Promise((c)=>setTimeout(c,Jr))]).then(()=>{if(F!==o)return;F=null,Q.clear()})}let a=F;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 Kr(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 an=Lt;export{dt as ACTIVE_ATTR,ir as EDITOR_SELECTOR,or as EDITOR_TAGS,pt as REQUESTS_ATTR,er as checkReactiveRegistration,gt as countReactiveRequest,an as default,E as editableValue,ft as enterReactiveActivity,Qt as escapeRegExp,ht as exitReactiveActivity,kt as loadReactiveFeature,at as onReactiveStreamWithoutEffects,Xr as reactiveActivityCount,en as reactiveFeatureNames,qe as registerReactiveActions,Pt as registerReactiveDefer,_e as registerReactiveDev,Mt as registerReactiveDismiss,Mt as registerReactiveEffects,Qr as registerReactiveFeature,g as registerReactiveFeatureLoader,Bt as registerReactiveImageFallback,It as registerReactiveJs,Wt as registerReactiveKeep,qt as registerReactiveModals,Ut as registerReactiveMorphFocus,Vt as registerReactiveOffline,jt as registerReactivePlaintext,Mt as registerReactiveStreamRender,Ot as registerReactiveToken,Nt as registerReactiveVisit,Zr as resetReactiveActivity,Ae as serverText,Ft as unloadedFeaturesFor};
3
+ `;r=!1,t+=o},i=(o)=>{for(let a of o.childNodes){let s=/^(div|p|li)$/.test(a.localName);if(s)r=!0;if(a.nodeType===3)a.data&&n(a.data);else if(a.localName==="br")n(`
4
+ `);else if(a.nodeType===1)i(a);if(s)r=!0}};return i(e),t=t.replace(/\r\n?/g,`
5
+ `).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var V=new WeakMap;function Se(e){if(e?.hasAttribute?.("data-reactive-editable")&&!V.has(e))V.set(e,T(e))}function Ee(e){return Se(e),V.get(e)}function sr(e){return or.has(e.localName)?typeof e.value==="string":!0}var je=Object.freeze({show:(e,t,r)=>ie(e,!1,t,r),hide:(e,t,r)=>ie(e,!0,t,r),toggle:(e,t,r)=>ie(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(oe(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(oe(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!oe(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)=>pr(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)=>Dt(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=ar(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)=>cr(e),preview_file:(e,t,r)=>ur(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 ar(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function cr(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 x=new Map,N=null;function ur(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return J(`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 J(`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??[]],o=dr(e,t.accept),a=(u)=>Number.isInteger(t.max_bytes)&&u.size>t.max_bytes,s=[],c;if(t.per_file===!0&&e.multiple){let u=i.filter((f,h)=>{let p=typeof f?.type==="string"&&o(f)?a(f)&&"size":"type";if(p)s.push({reason:p,file:f,index:h});return!p}),d=s.length>0&&!lr(e,u)?i.length:u.length;for(let f of s)f.remaining=d;c=u.find((f)=>f.type.startsWith("image/"))}else{let u=i.filter((f)=>typeof f?.type==="string"&&o(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)s.push({reason:d,file:d==="size"?c:i[0]}),c=null}if(_t(n),c){let u=URL.createObjectURL(c);x.set(n,u),n.setAttribute("src",u),fr()}else n.removeAttribute("src");if(Z(n),t.wrap!=null){let u=r({...t,to:t.wrap});if(u.length===0)J(`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 s)e.dispatchEvent(new CustomEvent("reactive:file-rejected",{bubbles:!0,detail:u}))}function lr(e,t){if(typeof DataTransfer!=="function"){if(e.closest?.('[data-reactive-verbose="true"], [data-reactive-debug="true"]'))J("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 dr(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((o)=>o[0]==="."?String(n.name).toLowerCase().endsWith(o):o.endsWith("/*")?i.startsWith(o.slice(0,-1)):i===o)}}function J(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function _t(e){let t=x.get(e);if(t===void 0)return;if(x.delete(e),URL.revokeObjectURL(t),x.size===0)N?.disconnect(),N=null}function fr(){if(N||typeof MutationObserver!=="function"||!document?.documentElement)return;N=new MutationObserver(()=>{for(let[e,t]of x)if(!e.isConnected||e.getAttribute("src")!==t)_t(e)}),N.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 hr(e,t,r){if(r?.transition)rr(e,r.transition,()=>e.hidden=t);else e.hidden=t}function ie(e,t,r,n){if(hr(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 oe(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 s=n?r.getAttribute(a):null;if(s==null){if(e.hasAttribute(a))i=e.removeAttribute(a)??!0}else if(e.getAttribute(a)!==s)i=e.setAttribute(a,s)??!0}if(i)Z(e);let o=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==o)e.setAttribute("alt",o);return r?o:!1}var mr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function pr(e){return e.querySelectorAll?.(mr)?.[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 Q(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 o=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(Je,i)?Je[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof o==="string"&&o.toLowerCase()===t.key.toLowerCase()}var gr=(e)=>e&&typeof e==="object"?e.keys:String(e),Fe=()=>H().prevented??=new WeakSet;function se(e,t){if(t!=null&&!e.defaultPrevented)Fe().add(e);e.preventDefault()}function D(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 Q(gr(e).replace(/^mod\+/,`${i}+`),t,r)}function br(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||Q(n.slice(i+1),t,r)}function yr(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 vr(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 o=i.get(n);if(!o)o=new Set,i.set(n,o);let a=t.params?.ops,c=(n===globalThis.window?`${typeof a==="string"?a:JSON.stringify(a??null)}|`:"")+JSON.stringify(r);if(o.has(c))return!0;return o.add(c),!1}var Ge=new WeakMap;function _r(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 o=i.get(t);if(!o)o=new Map,i.set(t,o);let a=o.get(e.currentTarget);if(!a)a=new Set,o.set(e.currentTarget,a);if(a.has(n))return!0;return a.add(n),!1}function me(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,o={}]=n;if(!Object.hasOwn(je,i)){console.warn(`[phlex-reactive] unknown client op ${JSON.stringify(i)} — skipped`);continue}let a=t(o);if(a.length===0&&r)r(i,o);for(let s of a)if(je[i](s,o,t),o?.keep===!0)tt(s,i,o,t)}}function wr(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 Ar(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 ae='[data-controller~="reactive"]',Sr='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',pe=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!ke(e);function ce(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&pe(n))n=n.parentElement?.closest?.(t);return n??null}var q=new WeakMap,W=new WeakMap;function Er(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 Tr(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 Fr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function kr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function Lr(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 xr=[["persist",[Ar,null,null,!0]],["defer",[ke,null]],["form",[Er,null]],["bindings",[Tr,null,null,!0]],["compute",[Fr,null,null,!0]],["sortable",[kr,null]],["drag",[Lr,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(xr),Ve=new Map,g=new Map,Nr=new Map;function b(e,t,r){Tt.set(e,[t,r]),Or(e)}var Tt=new Map;function Or(e){let t=w.get(e),[r,n]=Tt.get(e);t[1]=r,t[2]=n}function en(e,t){t.install?.(I),g.set(e,t),Nr.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 O(e).catch((t)=>Y(e,"load",t))}function O(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?.(I),g.set(e,n),n)),Ve.set(e,t);return t}var Ye=new Set;function Y(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);O(e).then(t,(n)=>Y(e,"load",n))}var Ir=1e4;function ue(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:Ir}function tn(){return[...w.keys()]}var Xe=Promise.resolve();function Ze(e,t,r){let n=I.waiting.get(e);if(n&&n[t]===r)delete n[t]}var I={enter:ft,exit:ht,count:gt,text:T,served:Ee,waiting:new WeakMap};var P=Symbol.for("phlex-reactive.early"),Pr=1e4,Mr=1500,Le=(e)=>e!=null&&(e===globalThis.window||e.window===e),Cr="dispatch";function H(){return globalThis[P]??={queue:[],connected:new WeakSet},globalThis[P]}function Dr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:Pr}function $r(e){let t={};for(let{name:r,value:n}of Array.from(e.attributes??[])){let i=/^data-reactive-(.+)-param$/i.exec(r);if(!i)continue;let o;try{o=JSON.parse(n)}catch{o=n}t[i[1].replace(/[-_]([a-z0-9])/g,(a,s)=>s.toUpperCase())]=o}return t}function qr(e,t,r){return{[P]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:$r(t),key:e.key,code:e.code,metaKey:e.metaKey,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,button:e.button,submitter:e.submitter,bubbles:e.bubbles,timeStamp:e.timeStamp,defaultPrevented:e.defaultPrevented&&!Fe().has(e),preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var X=new WeakMap;function Wr(e,{token:t,type:r,method:n,filter:i,win:o},a){let s=X.get(e);if(!s)X.set(e,s=new Map);let c=o?`${t} ${a}`:t;if(s.has(c))return!1;return s.set(c,{type:r,method:n,filter:i,win:o,params:a,armed:!0}),!0}function Qe(e,t,r,n){if(e?.[P])return!1;let i=Le(e?.currentTarget),o=i?n:e?.currentTarget,a=jr(e,o,i?`@${t}`:t),s=X.get(o),c=i&&JSON.stringify(e.params);for(let u of s?.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&&!Q(u.filter,e,r))continue;return u.armed=!1,!0}return a}var z=new WeakMap;function Br(e,t,r){let n=z.get(e);if(!n)z.set(e,n=new Map),setTimeout(()=>z.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function jr(e,t,r){let n=e&&z.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Lt extends xt{static values={token:String};#w;#l=new Map;#d=new Map;#ne;#L;#B;#R=0;#f=new Map;#x=new WeakMap;#t;featuresReady=Xe;#r=new Map;#N=new Set;#h=!1;#n=null;#m=new Map;#A=new Map;#p=new Map;#g=0;#j;#qe=0;#We=0;connect(){if(yt=!0,H().connected.add(this.element),q.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===B)this.#H();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(B,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(Se),this.#g++,this.featuresReady=Xe,this.#U(),K(this.element),this.#ae()}#Be(e){}#je(e,t,r,n){}#Ue(){}#Je(e,t){}#U(e){{let t=this.#g,r=[];for(let[o,[a]]of w){if(!a||this.#N.has(o))continue;let s=g.get(o);if(s&&!s.connect)continue;try{if(a(this.element))r.push(o)}catch(c){this.#b(o,"detect",c)}}if(r.length===0)return;for(let o of r)this.#N.add(o);if(!this.#h&&r.every((o)=>g.has(o))){for(let o of r)this.#O(t,o,g.get(o),e);return}for(let o of r){let a=this.#ie(t,o),s=[];for(let u of w.keys()){if(u===o)break;if(this.#p.has(u))s.push(this.#p.get(u))}let c=Promise.all(s).then(()=>a).then((u)=>u&&this.#O(t,o,u,e));if(this.#p.set(o,c),w.get(o)[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}}#ie(e,t){{let r=()=>e===this.#g;return this.#oe(t),new Promise((n)=>{let i=!1,o=setTimeout(()=>{if(this.#m.delete(o),i=!0,r())this.#b(t,"timeout",Error(`not loaded after ${ue()} ms`));n(null)},ue());this.#m.set(o,n);let a=()=>{clearTimeout(o),this.#m.delete(o)};O(t).then((s)=>{if(a(),i)queueMicrotask(()=>this.#O(e,t,s));else n(s)},(s)=>{if(a(),r())this.#b(t,"load",s);n(null)})})}}#oe(e){{let t=w.get(e)[2];if(!t)return;let r={};try{this.#A.set(e,[t(this.element,r),r]),I.waiting.set(this.element,{...I.waiting.get(this.element),[e]:r})}catch(n){this.#b(e,"detect",n)}}}#J(e,t){{let[r,n]=this.#A.get(e)??[];if(this.#A.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(o){this.#b(t,"connect",o)}}}#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.#w=void 0},owns:(e)=>this.#F(e),ownership:()=>this.#Z(),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.#Q(),plain:ct,text:T,served:Ee,copyMedia:St,setValue:At,confirm:(e,t)=>Promise.resolve().then(()=>xe(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(Y(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})}#se(){{this.#g++;for(let[t,r]of this.#m)clearTimeout(t),r(null);this.#m.clear();for(let t of[...this.#A.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)}}}#ae(){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.#ce();for(let[e,t]of W.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}W.delete(this.element)}#I=new Set;#ce(){let{queue:e}=H();if(e.length===0)return;let t=[];for(let i=e.length-1;i>=0;i--){let{root:o}=e[i];if(o===this.element||!o.isConnected)t.unshift(...e.splice(i,1))}let r=Dr(),n=new Map;for(let i of t){let o=n.get(i.event)??[new Set,new Set];n.set(i.event,o);let a=o[+!!i.win];if(a.has(i.el))continue;a.add(i.el);let s=i.win?Math.min(Mr,r):r,c=i.root!==this.element?"its root left the page before a controller connected":performance.now()-i.at>s?`it is older than the ${s} ms ${i.win?"window-trigger":"early-event"} TTL`:i.el.isConnected&&this.element.contains(i.el)?null:"its element left the root before the controller connected";if(c){if(this.#$())console.warn(`[phlex-reactive] dropped an early "${i.event.type}" trigger: ${c}`);continue}this.#ue(i)}}#ue({event:e,el:t,descs:r,win:n}){let i=qr(e,t,n),o=this.application?.schema?.keyMappings,a=(t.getAttribute("data-action")??"").split(/\s+/),s=n?this.element:t;for(let c of r){if(!a.includes(c.token))continue;if(c.filter&&!Q(c.filter,e,o))continue;if(/#\w+.*:once\b/.test(c.token)){if(!Wr(s,c,n&&JSON.stringify(i.params)))continue;this.#I.add(s)}if(Br(e,s,n?`@${c.method}`:c.method),c.method==="runOps")this.runOps(i);else this.dispatch(i)}}disconnect(){if(this.#se(),this.#be(),this.#ve(),this.#t)this.element.removeEventListener?.("turbo:morph-element",this.#t),this.element.removeEventListener?.("focusin",this.#t),this.element.removeEventListener?.(B,this.#t);if(H().connected.delete(this.element),q.get(this.element)===this)q.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)X.delete(e);this.#I.clear()}dispatch(e){if(e.params?.action&&e.params.action!==qe&&this.#le())return this.#de(e);let t=e.params?.shortcut;if(t!=null&&!D(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:o,confirm:a,confirmWhen:s,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.#te(d,p))se(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,s),E=()=>this.#P(p,r,n,i,o,d,h);if(!v)return E();if(v instanceof Promise)return v.then((m)=>m?this.#S(m,p,E):E());this.#S(v,p,E)}#S(e,t,r){return Promise.resolve().then(()=>xe(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([O(e).catch((r)=>(Y(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),ue()))]).finally(()=>clearTimeout(t))}}#le(){return!this.tokenValue&&pe(this.element)}#de(e){let t=ce(this.element.parentElement,Sr);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=q.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:o,prevent:a}=e.params;if(n!=null&&!D(n,e,this.application?.schema?.keyMappings))return;let s=e.currentTarget??e.target;if((n!=null||!i&&a!==!1)&&!this.#te(o,s))se(e,n);W.set(t,[...W.get(t)??[],[e,s]]);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&&!D(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Qe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(_r(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=br(r.ops),o=i.filter((s)=>ze(s,e,null)),a=o.length<=1?o:o.filter((s)=>ze(s,e,this.application?.schema?.keyMappings));if(a.length===0&&i.length>0){if(this.#$())this.#_((s)=>s.noBinding(this,e));return}for(let s of a){if(s.outside&&e[P])continue;if(!yr(s,e))continue;if(s.shortcut!=null&&!D(s.shortcut,e,this.application?.schema?.keyMappings))continue;if(vr(this,e,s))continue;this.#fe(s.legacy?{...r,ops:s.ops,debounce:void 0,throttle:void 0,prevent:void 0}:s,e,n,i.indexOf(s))}}#fe(e,t,r,n){let{ops:i,confirm:o,confirmWhen:a,outside:s,window:c,shortcut:u,prevent:d}=e;if(s&&this.element.contains(t.target))return;if(u!=null||!c&&d!==!1)se(t,u);let f=this.#z(o,a),h=this.#he(e,n,r,()=>this.#Ne(this.#xe(i)));if(!f)return h();if(f instanceof Promise)return f.then((p)=>p?this.#S(p,r,h):h());this.#S(f,r,h)}#he(e,t,r,n){let i=Number(e.debounce)||0,o=Number(e.throttle)||0;if(i<=0&&o<=0)return n;let a=JSON.stringify([t,e]);if(i>0)return()=>this.#G(r,a,i,n);return()=>this.#V(r,a,o,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.#E(e,(t,r)=>t<0?0:(t+1)%r)}listnavPrev(e){this.#E(e,(t,r)=>t<0?r-1:(t-1+r)%r)}listnavFirst(e){this.#E(e,()=>0)}listnavLast(e){this.#E(e,(t,r)=>r-1)}listnavPick(e){let t=this.#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")}#E(e,t){let r=this.#v(e);if(!r.length)return;e.preventDefault();let n=this.#me(e),i=globalThis.document?.activeElement,o=n?r.findIndex((s)=>s===i||i!=null&&s.contains?.(i)):r.findIndex((s)=>s.hasAttribute("data-reactive-highlighted")),a=r[t(o,r.length)];if(n)a.focus?.();else{for(let s of r)s.removeAttribute("data-reactive-highlighted");a.setAttribute("data-reactive-highlighted","true")}a.scrollIntoView?.({block:"nearest"})}#me(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,o,a){if(this.#o("reactive:before-dispatch",{action:t,params:this.#ee(r),element:this.element},{cancelable:!0}).defaultPrevented)return;let c=Number(n)||0;if(c>0)return this.#ge(e,c,t,r,o,a);let u=Number(i)||0;if(u>0)return this.#ye(e,u,t,r,o,a);return this.#T(t,r,o,e,a)}#T(e,t,r,n,i){let o={inverse:null,undo:[],resurrect:null},a=this.#Oe(e,n,o),s=Boolean(r||i),c=(h)=>{if(!s||!h)return;let p=this.#e();if(o.inverse=h.optimistic(this,p,r,n),o.undo.push(...h.busy(this,p,i,n)),this.#C())o.resurrect=h.resurrection(this,p,r,n)},u=g.get("hints");if(!s||u)c(u);let d=()=>this.#Se(e,t,o,a),f=()=>this.#n?this.#n.then(d):d();return this.queue=(this.queue??Promise.resolve()).then(()=>s&&!u?this.#pe().then(c).then(f):f()),this.queue}#pe(){return this.#K("hints")}#ge(e,t,r,n,i,o){this.#G(e,Cr,t,()=>this.#T(r,n,i,e,o))}#G(e,t,r,n){this.#M(e,t);let i=()=>{this.#M(e,t),n()},o=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:o,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)}#be(){for(let[e,t]of[...this.#l])for(let r of[...t.keys()])this.#M(e,r)}#ye(e,t,r,n,i,o){return this.#V(e,r,t,()=>this.#T(r,n,i,e,o))}#V(e,t,r,n){let i=this.#d.get(e)??new Map;if(i.has(t))return;let o=setTimeout(()=>{if(i.delete(t),i.size===0)this.#d.delete(e)},r);return i.set(t,o),this.#d.set(e,i),n()}#ve(){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.#T(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)}#_e(){this.element?.removeAttribute?.("data-reactive-error")}#we(){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))}#Ae(){{let e=g.get("devtools");if(e)return e.delay();if(lt())return O("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#Se(e,t,r,n){let{fields:i,files:o}=this.#Q(),a=this.#ee(t),s={...i,...a},c=this.#a,u=o.length>0,d=u?this.#Le(c,e,s,o):JSON.stringify({token:c,act:e,params:s}),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.#Ae();try{if(navigator.onLine===!1){this.#c(r.inverse),this.#i("offline"),this.#s(e,t,s,{kind:"offline"});return}let h;try{let m={Accept:"text/vnd.turbo-stream.html","X-CSRF-Token":this.#De()};if(!u)m["Content-Type"]="application/json";let S=this.#$e();if(S)m["X-Pgbus-Connection"]=S;let M=Et(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(M)m["X-Reactive-Presence"]=M;let Re=zt(this.element);if(Re)m["X-Reactive-Held"]=Re;gt("action"),h=await fetch(this.#Me(),{method:"POST",headers:m,body:d,credentials:"same-origin",signal:AbortSignal.timeout(this.#Ce())})}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,s,{kind:"timeout"});return}this.#we(),this.#i("network"),this.#s(e,t,s,{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,s,{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.#_((M)=>M.recordBody(f,m,S));$e(this.element,m,!0)}this.#i("http"),this.#s(e,t,s,{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,s,{kind:"content-type",status:h.status});return}let v=await h.text(),E=this.#X(v);if(this.#a=E??this.#a,f)this.#_((m)=>m.recordBody(f,v,E));if($e(this.element,v,Kt(h)),r.resurrect)queueMicrotask(r.resurrect);return this.#_e(),this.#o("reactive:applied",{action:e,params:s,html:v}),v}catch(h){console.error("[phlex-reactive] action error",h),this.#c(r.inverse),this.#o("reactive:error",{action:e,params:s,kind:"apply"})}finally{if(n?.(),f)this.#_((h)=>h.trace(this,{...f,ms:this.#Y()-f.started}))}}get#a(){return this.#w??this.tokenValue}set#a(e){this.#w=e}tokenValueChanged(){this.#w=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.#Ee(t),i=e.match(r);if(i)return i[1];let o=e.match(n);if(o)return o[1].match(/data-reactive-token-value="([^"]+)"/)?.[1];return}#Ee(e){let t=this.#B;if(t&&t.id===e)return t;let r=Qt(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>`)}}#F(e){return e.closest('[data-controller~="reactive"]')===this.element}#Z(){if(this.element.querySelectorAll('[data-controller~="reactive"]').length===0)return()=>!0;return(t)=>this.#F(t)}#Te(){let e=this.element.querySelectorAll(ae);if(e.length===0||[...e].every(pe))return()=>!0;return(t)=>{let r=ce(t,ae,this.element);if(r===this.element)return!0;return t.getAttribute("data-reactive-shared-field")!=null&&ce(r.parentElement,ae,this.element)===this.element}}#Q(){let e={},t=[],r=this.#Te(),n=[];this.element.querySelectorAll("input[name], select[name], textarea[name]").forEach((s)=>{if(!r(s))return;if(s.type==="file")for(let c of s.files??[])t.push({name:s.name,file:c,multiple:s.multiple});else n.push(s)});let i=[];this.element.querySelectorAll(`[name]${ir}`).forEach((s)=>{if(r(s))i.push(s)});let o=this.#Fe(n),a=this.#ke(n);for(let s of n)if(o.has(s.name)){let c=e[s.name]??(e[s.name]=[]);if(s.type==="checkbox"||s.type==="radio"){if(s.checked)c.push(s.value)}else if(s.type==="hidden"){if(!a.has(s.name))c.push(s.value)}else if(s.multiple&&s.options){for(let u of s.options)if(u.selected)c.push(u.value)}else c.push(s.value)}else if(s.type==="checkbox")e[s.name]=s.checked;else if(s.type==="radio"){if(s.checked)e[s.name]=s.value}else e[s.name]=s.value;return i.forEach((s)=>{let c=s.getAttribute("name");if(!c)return;let u=s.getAttribute("data-reactive-editable")!=null?T(s):s.value??s.textContent??s.innerHTML??"",d=e[c];if(String(c).endsWith("[]")&&!sr(s))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}}#Fe(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}#ke(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#Le(e,t,r,n){let i=new FormData;i.append("token",e),i.append("act",t);let o=[];for(let[s,c]of Object.entries(r))if(Array.isArray(c)&&String(s).endsWith("[]"))if(c.length===0)o.push(String(s).slice(0,-2));else{let u=`${this.#k(s)}[]`;for(let d of c)i.append(u,String(d))}else this.#D(i,this.#k(s),c);for(let s of o)i.append("empty_groups[]",s);let a=this.#Re(n);for(let{name:s,file:c,multiple:u}of n){let f=u||a.has(s)?`${this.#k(s)}[]`:this.#k(s);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))}#Re(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))}#ee(e){if(!e)return{};try{return typeof e==="string"?JSON.parse(e):e}catch{return{}}}#xe(e){return Te(e)}#Ne(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.#_((r)=>r.diagnose(this,e,t))}#_(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.#F(r))}#te(e,t){if(e?.checked!=="keep")return!1;let r=t?.type;return r==="checkbox"||r==="radio"}#c(e){if(!e)return;if(!this.element.isConnected)return;for(let t of e)t()}#Oe(e,t,r){this.#Ie(e,t),ft();let n=!1;return()=>{if(n)return;n=!0,this.#Pe(e,t),ht();for(let i of r.undo)i()}}#Ie(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.#R++===0)this.element.setAttribute("aria-busy","true");for(let r of this.#re(e))this.#u(r,e,1)}#Pe(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.#R<=0)this.#R=0,this.element.removeAttribute("aria-busy");for(let n of this.#re(e))this.#u(n,e,-1)}#u(e,t,r){if(!e||typeof e.getAttribute!=="function")return;let n=this.#x.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.#x.delete(e),e.removeAttribute("data-reactive-busy");return}this.#x.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#re(e){return[...this.element.querySelectorAll?.("[data-reactive-busy-on]")??[]].filter((r)=>r.getAttribute("data-reactive-busy-on")===e&&this.#F(r))}#Me(){return this.#ne??=document.querySelector('meta[name="phlex-reactive-action-path"]')?.content||"/reactive/actions"}#Ce(){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}#De(){return document.querySelector('meta[name="csrf-token"]')?.content??""}#$e(){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"),Ur);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"),Jr);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 Ur(e,t){let r=()=>{t.edited=!0},n=(o)=>{let a=o.target;if(o.detail?.success&&a?.tagName==="FORM"&&a.contains?.(e))t.submitted=!0},i=["input","change","lexxy:change","trix-change"];for(let o of i)e.addEventListener?.(o,r);return document.addEventListener("turbo:submit-end",n),()=>{for(let o of i)e.removeEventListener?.(o,r);document.removeEventListener("turbo:submit-end",n)}}function Jr(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 Hr=1000,k=null,Rt,ee=new Set;function zr(e){return kt(e).then((t)=>{if(e!=="effects")return;Rt=t,t?.sweep()})}at((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,o=Ft(Kr(i)).filter((s)=>!ee.has(s));if(!t&&!ee.has("effects")&&Gr(i))o.push("effects");if(o.length===0&&!k)return t?.wrap(e);if(o.length>0){for(let c of o)ee.add(c);let s=k=Promise.race([Promise.all([k,...o.map(zr)]),new Promise((c)=>setTimeout(c,Hr))]).then(()=>{if(k!==s)return;k=null,ee.clear()})}let a=k;r.render=async(s)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??Rt)?.wrap(c),await c.detail.render(s)}});function Kr(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 Gr(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 cn=Lt;export{dt as ACTIVE_ATTR,ir as EDITOR_SELECTOR,or as EDITOR_TAGS,pt as REQUESTS_ATTR,er as checkReactiveRegistration,gt as countReactiveRequest,cn as default,T as editableValue,ft as enterReactiveActivity,Qt as escapeRegExp,ht as exitReactiveActivity,kt as loadReactiveFeature,at as onReactiveStreamWithoutEffects,Zr as reactiveActivityCount,tn as reactiveFeatureNames,Be as registerReactiveActions,Pt as registerReactiveDefer,Ae as registerReactiveDev,Mt as registerReactiveDismiss,Mt as registerReactiveEffects,en as registerReactiveFeature,b as registerReactiveFeatureLoader,Bt as registerReactiveImageFallback,It as registerReactiveJs,Wt as registerReactiveKeep,qt as registerReactiveModals,Ut as registerReactiveMorphFocus,Vt as registerReactiveOffline,jt as registerReactivePlaintext,Mt as registerReactiveStreamRender,Ot as registerReactiveToken,Nt as registerReactiveVisit,Qr as resetReactiveActivity,Ee as serverText,Ft as unloadedFeaturesFor};
7
7
 
8
- //# debugId=149316B4025D3E4464756E2164756E21
8
+ //# debugId=A4008E3BC0B43BC564756E2164756E21
9
9
  //# sourceMappingURL=core.min.js.map