phlex-reactive 0.15.5 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +344 -142
- data/README.md +100 -3
- data/app/controllers/phlex/reactive/actions_controller.rb +10 -0
- data/app/controllers/phlex/reactive/fragments_controller.rb +4 -3
- data/app/javascript/phlex/reactive/core.js +1 -0
- data/app/javascript/phlex/reactive/core.min.js +4 -4
- data/app/javascript/phlex/reactive/core.min.js.map +4 -4
- data/app/javascript/phlex/reactive/features/bindings.js +81 -4
- data/app/javascript/phlex/reactive/features/bindings.min.js +2 -2
- data/app/javascript/phlex/reactive/features/bindings.min.js.map +3 -3
- data/app/javascript/phlex/reactive/features/drag.js +522 -0
- data/app/javascript/phlex/reactive/features/drag.min.js +4 -0
- data/app/javascript/phlex/reactive/features/drag.min.js.map +10 -0
- data/app/javascript/phlex/reactive/reactive_controller.js +2 -0
- data/app/javascript/phlex/reactive/reactive_controller.min.js +4 -4
- data/app/javascript/phlex/reactive/reactive_controller.min.js.map +7 -6
- data/app/javascript/phlex/reactive/runtime.js +57 -23
- data/lib/generators/phlex/reactive/install/templates/phlex_reactive.rb.erb +2 -1
- data/lib/phlex/reactive/apm/subscriber.rb +5 -0
- data/lib/phlex/reactive/apm.rb +5 -6
- data/lib/phlex/reactive/authorization.rb +31 -5
- data/lib/phlex/reactive/client_bindings.rb +19 -0
- data/lib/phlex/reactive/component/css_vars_binding.rb +118 -0
- data/lib/phlex/reactive/component/drag.rb +270 -0
- data/lib/phlex/reactive/component/dsl.rb +15 -1
- data/lib/phlex/reactive/component/helpers.rb +9 -1
- data/lib/phlex/reactive/component/identity.rb +17 -6
- data/lib/phlex/reactive/component/lazy.rb +4 -0
- data/lib/phlex/reactive/component/presence_declaration.rb +4 -0
- data/lib/phlex/reactive/component/registry.rb +76 -6
- data/lib/phlex/reactive/component/sortable.rb +3 -0
- data/lib/phlex/reactive/component.rb +4 -0
- data/lib/phlex/reactive/defer.rb +4 -4
- data/lib/phlex/reactive/doctor/ractor_readiness.rb +65 -0
- data/lib/phlex/reactive/doctor.rb +2 -0
- data/lib/phlex/reactive/engine.rb +31 -4
- data/lib/phlex/reactive/fragment.rb +5 -4
- data/lib/phlex/reactive/held_fields.rb +21 -1
- data/lib/phlex/reactive/param_schema.rb +3 -2
- data/lib/phlex/reactive/pending/markup.rb +27 -9
- data/lib/phlex/reactive/pending.rb +4 -4
- data/lib/phlex/reactive/response.rb +55 -4
- data/lib/phlex/reactive/shareable.rb +87 -0
- data/lib/phlex/reactive/store.rb +73 -0
- data/lib/phlex/reactive/streamable.rb +49 -19
- data/lib/phlex/reactive/test_helpers.rb +6 -0
- data/lib/phlex/reactive/version.rb +1 -1
- data/lib/phlex/reactive.rb +293 -122
- data/sig/phlex/reactive/component.rbs +108 -0
- data/sig/phlex/reactive/param_schema.rbs +23 -0
- data/sig/phlex/reactive/response.rbs +73 -0
- data/sig/phlex/reactive/streamable.rbs +62 -0
- data/sig/phlex/reactive.rbs +231 -0
- metadata +14 -1
data/README.md
CHANGED
|
@@ -299,9 +299,10 @@ imports one the first time a root on the page needs it:
|
|
|
299
299
|
| `phlex/reactive/features/defer` (`reply.defer`, `reactive_lazy`) | 2.8 KB | inside the one file | fetched when a root is a `reactive_lazy` shell, a morph turns one into a shell, or a `reply.defer` arrives |
|
|
300
300
|
| `phlex/reactive/features/form` (dirty tracking, `warn_unsaved`, the paste-trigger gate) | 1.0 KB | inside the one file | fetched when a root tracks dirty fields or holds a `paste_into` trigger |
|
|
301
301
|
| `phlex/reactive/features/effects` (`reactive_effects`, `dismiss_after`) | 1.7 KB | inside the one file | fetched when a root declares an effect, or when the first stream that needs it arrives: one with an effect, or with a dismissing flash |
|
|
302
|
-
| `phlex/reactive/features/bindings` (`reactive_show`, show targets, `reactive_on_complete`, `reactive_filter`, `reactive_tags`, nested rows, the conditional `confirm:`) |
|
|
302
|
+
| `phlex/reactive/features/bindings` (`reactive_show`, show targets, `reactive_on_complete`, `reactive_filter`, `reactive_tags`, `reactive_css_vars`, nested rows, the conditional `confirm:`) | 8.2 KB | inside the one file | fetched when a root declares one of them, or holds a trigger with a conditional confirm |
|
|
303
303
|
| `phlex/reactive/features/compute` (`reactive_compute`, `reactive_text`) | 2.1 KB | inside the one file | fetched when a root carries a compute binding |
|
|
304
304
|
| `phlex/reactive/features/sortable` (`reactive_sortable` drag and drop) | 3.1 KB | inside the one file | fetched when a root is or holds a sortable or source list |
|
|
305
|
+
| `phlex/reactive/features/drag` (`reactive_box`, `reactive_point` draggable regions) | 3.5 KB | inside the one file | fetched when a root is or holds a frame, a box or a point |
|
|
305
306
|
| `phlex/reactive/features/countdown` (`reactive_countdown`) | 1.0 KB | inside the one file | fetched when a root is or holds a countdown |
|
|
306
307
|
| `phlex/reactive/features/hints` (`optimistic:`, `busy:`) | 1.0 KB | inside the one file | fetched when a root holds a trigger that declares a hint |
|
|
307
308
|
| `phlex/reactive/features/devtools` (the latency simulator, the zero-target warnings, the debug trace) | 1.6 KB | inside the one file | fetched with the core on a page that carries `<meta name="phlex-reactive-env" content="development">` or while a delay is stored for the tab; at connect for a root in debug mode; otherwise the first time a verbose root has something to warn about. In production with none of these, never |
|
|
@@ -693,6 +694,7 @@ Use in controllers: `render turbo_stream: Counter.replace(counter)`.
|
|
|
693
694
|
| `reactive_media(from:, pool:, take:, match:, when:, pending:, label:, blank_label:)` | A preview `<img>` that **follows a field** (#373): the field's value (its first `take:` characters, or all of it) is a key into `pool`, whose values are **selectors** for `<img>` elements the server rendered — never URLs. A hit copies that image's `src`/`srcset`/`alt` like `js.copy_media` (a pool `<img>` with an `alt` and no `src` is a hit without an image, #381); a miss clears the preview. `label:` gets the `alt` (or `blank_label`) as `textContent`. Below `take:` characters, or while `match:` (a JavaScript-compatible Regexp over the whole key) rejects the key, the binding is **pending** (#380) — never `blank_label` (Regexp options or Ruby-only syntax raise at render); `when:` (same rules) tests the **whole field** before the pool lookup while the key stays the prefix, so `take: 3, when: /\A\d{3,24}\z/` keeps `007bad` pending (#390); `pending: :clear` (default) clears the preview and label, `:keep` leaves them. The preview's `data-reactive-media-state` reads `pending`/`hit`/`miss`, so CSS can hide its row. See [Media previews](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
|
|
694
695
|
| `reactive_image_fallback(hide: true, show_alt: nil, wrap: nil)` | An `<img>` that **falls back and recovers** (#383): on `error` it gets `data-reactive-image-state="error"`; `hide:` (default `true`) also hides it, and `show_alt:`, independently, writes its `alt` into that node and shows it; `wrap:` (#392) hides the box around it (marked `data-reactive-wrap-hidden`, shown again only when it carries that mark, its text never written); `load` sets `"loaded"`. A later `src` (from `copy_media`, `reactive_media`, `preview_file`, a morph, or any `src` that loads) shows it again; removing the `src` is not an error. Composes with `reactive_media(…, **reactive_image_fallback)`. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
|
|
695
696
|
| `reactive_countdown(until:, format: :ms, waiting:, done:)` | A server **deadline counted down** on the client (#400): `until:` is an ISO8601 date-time with a zone (or a `Time`); the text is the time left from `Date.now` (`1:30`), as `textContent`, once a second and again when a hidden tab is shown. At zero (or already past on connect) it reads `0:00`, `data-reactive-countdown-state="done"`, `waiting:` hides, `done:` shows and `reactive:countdown-done` fires **once per deadline** (a morph that keeps `until:` does not fire again; a new `until:` restarts). The server renders the first text and visibility. No request, no frame reload. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
|
|
697
|
+
| `reactive_css_vars(to:, vars:, global: false)` | Fields that **feed CSS custom properties** on an element (#417), for a preview that follows a control with no request: `vars: { "--light" => "light", "--turn" => { field: "turn", unit: "deg" } }`. Each field is read as `reactive_show` reads one (a checkbox gives `1`/`0`, a radio group its checked value) and parsed as a **finite number**; the client writes `number + unit` with `style.setProperty`, and anything else (empty, text) removes the property so the `var()` fallback applies. No text from a field reaches CSS. Units: `""`, `px`, `%`, `deg`, `turn`, `ms`, `s`, `em`, `rem`, `fr`; names match `--[a-zA-Z0-9-]+`; a bad name or unit or a blank field raises at render. Runs on connect, on `input`/`change` and after a morph. `to:` resolves like a client op's (`:root`, inside the root, `global: true`, an Array). Render the same properties inline for the first paint. See [Client-only ops](https://phlex-reactive.zoolutions.llc/docs/example-client-ops). |
|
|
696
698
|
| `reactive_enable(if:/if_any:/unless:)` | The sibling of `reactive_show` that flips the element's **own `disabled`** (a button, a fieldset) instead of `hidden` — same conditions, same `reactive_values` first paint. `button(**reactive_enable(if: { "ids[]" => { checked: 1.. } }))`. See [Bulk selection](#bulk-selection-reactive_select_all-reactive_count-reactive_enable). |
|
|
697
699
|
| `reactive_select_all("ids[]")` / `reactive_count("ids[]")` | A checkbox **group**'s header box (ticks/unticks every owned box; shows checked / indeterminate / unchecked) and its ticked count as text — re-synced on every change and when rows are appended or removed. `under: "a.b"` makes a nested header over the leaves whose `data-reactive-group` is in that path. See [Bulk selection](#bulk-selection-reactive_select_all-reactive_count-reactive_enable). |
|
|
698
700
|
| `reactive_group_targets("ids[]", count: "#c", enable: { "#b" => 1.. })` | Spread on the root that **owns** a checkbox group: drives a count and an enable on outside, id-allowlisted elements (a bulk bar the page renders). `reactive_group_target_attrs` gives that outside markup its first paint. See [A bulk bar outside the list's root](#a-bulk-bar-outside-the-lists-root-reactive_group_targets). |
|
|
@@ -1900,6 +1902,87 @@ list; a reply that morphs the list puts the rows in the server's order.
|
|
|
1900
1902
|
|
|
1901
1903
|
Full guide: [Sortable lists](https://phlex-reactive.zoolutions.llc/docs/sortable-lists).
|
|
1902
1904
|
|
|
1905
|
+
### Draggable regions (`reactive_box`, `reactive_point`)
|
|
1906
|
+
|
|
1907
|
+
Move and resize a box, or move a point, over an image, a chart or a diagram —
|
|
1908
|
+
with a mouse, a pen, a finger or the keyboard — and its fields always hold
|
|
1909
|
+
where it is, as fractions of the frame (0..1 on each axis). A crop box, a
|
|
1910
|
+
focal point, a hotspot, a selection: no Stimulus controller of your own.
|
|
1911
|
+
|
|
1912
|
+
```ruby
|
|
1913
|
+
class CropPicker < Phlex::HTML
|
|
1914
|
+
include Phlex::Reactive::Component
|
|
1915
|
+
|
|
1916
|
+
reactive_record :photo
|
|
1917
|
+
action :crop, params: { x: :float, y: :float, width: :float, height: :float }
|
|
1918
|
+
|
|
1919
|
+
def crop(x:, y:, width:, height:)
|
|
1920
|
+
authorize! @photo, :update?
|
|
1921
|
+
# The schema casts; it does not range-check. A forged box outside the frame changes nothing.
|
|
1922
|
+
return reply.morph unless inside?(x, width) && inside?(y, height)
|
|
1923
|
+
|
|
1924
|
+
@photo.update!(crop: { x:, y:, width:, height: })
|
|
1925
|
+
reply.morph
|
|
1926
|
+
end
|
|
1927
|
+
|
|
1928
|
+
def view_template
|
|
1929
|
+
div(**reactive_root) do
|
|
1930
|
+
div(**mix(reactive_frame, class: "relative")) do
|
|
1931
|
+
img(src: @photo.url, alt: "", class: "block w-full")
|
|
1932
|
+
div(**reactive_box(fields: { x: "crop[x]", y: "crop[y]", width: "crop[width]", height: "crop[height]" },
|
|
1933
|
+
value: @photo.crop, aspect: "aspect", min: 0.05, action: :crop)) do
|
|
1934
|
+
%i[nw n ne e se s sw w].each { span(**reactive_box_handle(it)) }
|
|
1935
|
+
span(**reactive_point(fields: { x: "focus[x]", y: "focus[y]" }, value: @photo.focus,
|
|
1936
|
+
within: "[data-reactive-box]"))
|
|
1937
|
+
end
|
|
1938
|
+
end
|
|
1939
|
+
# the fields: hidden inputs named crop[x] … focus[y], and the aspect radios
|
|
1940
|
+
end
|
|
1941
|
+
end
|
|
1942
|
+
|
|
1943
|
+
private
|
|
1944
|
+
|
|
1945
|
+
# The fields round to 4 decimals, so x + width may reach 1.0001.
|
|
1946
|
+
def inside?(at, size) = at.between?(0, 1) && size.positive? && at + size <= 1.0001
|
|
1947
|
+
end
|
|
1948
|
+
```
|
|
1949
|
+
|
|
1950
|
+
The helpers render the box's `left`/`top`/`width`/`height` (and the point's
|
|
1951
|
+
`left`/`top`) as percentages from `value:`, so the first paint is right with
|
|
1952
|
+
no JavaScript and a re-render with new values moves them. The frame must be
|
|
1953
|
+
positioned (`relative`, or `absolute` for an overlay); its padding box is the
|
|
1954
|
+
coordinate space.
|
|
1955
|
+
|
|
1956
|
+
- **Pointer**: a press on the box moves it, a press on a handle resizes from
|
|
1957
|
+
that edge or corner; the box stays inside the frame and never goes below
|
|
1958
|
+
`min:`. A drag starts after a 4 px move; `touch-action: none` keeps a finger
|
|
1959
|
+
drag from scrolling the page.
|
|
1960
|
+
- **Fields**: written as `set_value` writes them (the live `.value`, rounded to
|
|
1961
|
+
4 decimals, a bubbling `input` at most once per field per frame), so
|
|
1962
|
+
`reactive_show`, compute reducers and other bindings follow the box. One
|
|
1963
|
+
`change` fires on release.
|
|
1964
|
+
- **`aspect:`**: a Numeric (`16/9r`) or the name of a field holding `"16:9"`, a
|
|
1965
|
+
decimal or `""` (free), read at drag start. When the field changes (a preset
|
|
1966
|
+
radio), the box re-fits to the new ratio around its centre.
|
|
1967
|
+
- **`action:`** (optional): sent once on release through the root's pipeline,
|
|
1968
|
+
with `x`, `y`, `width`, `height` (a point: `x`, `y`). Without it the binding
|
|
1969
|
+
is client-only and works on a `ClientBindings` root. The `:float` schema casts
|
|
1970
|
+
but does not range-check: refuse values outside 0..1, a `width` or `height`
|
|
1971
|
+
of 0, and `x + width` or `y + height` past 1.0001 (the fields' rounding)
|
|
1972
|
+
before you store them, since `reactive_box` refuses to render such a box.
|
|
1973
|
+
- **Points**: `reactive_point` moves within the frame, or — placed inside a box
|
|
1974
|
+
with `within:` — within that box, its fractions of the box.
|
|
1975
|
+
- **Keyboard**: the box and the point are focusable; arrows move 1% (Shift:
|
|
1976
|
+
10%), Alt+arrows resize from the bottom-right corner or the focused handle,
|
|
1977
|
+
Escape puts it back. Each step is announced through a live region; translate
|
|
1978
|
+
the words with `messages:` (`{x}`, `{y}`, `{width}`, `{height}` as whole
|
|
1979
|
+
percents). Letting go of the key is the release.
|
|
1980
|
+
- **Styling**: `data-reactive-frame-active` (the frame) and
|
|
1981
|
+
`data-reactive-dragging` (the pressed box, handle or point). A morph that
|
|
1982
|
+
lands mid-drag does not interrupt it.
|
|
1983
|
+
|
|
1984
|
+
Full guide: [Draggable regions](https://phlex-reactive.zoolutions.llc/docs/draggable-regions).
|
|
1985
|
+
|
|
1903
1986
|
### Presence (`reactive_presence`)
|
|
1904
1987
|
|
|
1905
1988
|
Who is viewing a stream, one entry per browser tab, each tab with a small
|
|
@@ -2857,6 +2940,7 @@ def update(quantity:, price:) = (@item.update!(quantity:, price:); reply.streams
|
|
|
2857
2940
|
| `.also(target => content, …)` | **UPDATE** (inner HTML) companion elements by DOM id; `content` is a plain string (escaped) or a Phlex component. The argument *type* picks the action — pairs mean `update` |
|
|
2858
2941
|
| `.also(component, morph: false)` | **REPLACE** another Streamable component at its own `#id` (`morph: true` morphs in place). A component argument means `replace` |
|
|
2859
2942
|
| `.flash(level, content, target: …)` | append a flash; `content` is a plain string (escaped, wrapped in a level-carrying `<div>` — see [Flash levels](#flash-levels)) or a Phlex component (rendered verbatim; off-request — no Rails `flash`); target defaults to `Phlex::Reactive.flash_target` (`"flash"`) |
|
|
2943
|
+
| `.refused(*names)` | the reply **answers the posted values without storing them**: the client keeps the fields a morph held (`data-reactive-held`, #370), so the root's next action names them in `reactive_held_fields` again instead of saving over the other change. No names keeps every mark; names (the fields' `name` attributes) keep only those. Chain it on a morph (`reply.morph.refused`): a plain `replace` swaps the marked field out. Still a 200: no error marker, no `reactive:error` (#413) |
|
|
2860
2944
|
| `reply.remove` | remove the element (backed by `Streamable#to_stream_remove`) |
|
|
2861
2945
|
| `reply.redirect(url)` | client-side `Turbo.visit` (pass a `*_url`); rides a `reactive:visit` turbo-stream, not an HTTP 3xx |
|
|
2862
2946
|
| `reply.streams(*streams)` | **partial update** — emit exactly these streams (no full-self replace) + a tiny token-only refresh, so live inputs survive; for per-field grid editing (issue #30) |
|
|
@@ -3936,8 +4020,10 @@ Phlex::Reactive.authorization_errors = [Pundit::NotAuthorizedError]
|
|
|
3936
4020
|
Phlex::Reactive.authorization_methods = %i[authorize! authorize allowed_to?]
|
|
3937
4021
|
# Phlex::Reactive.verify_authorized = false # turn the guard off (not recommended)
|
|
3938
4022
|
|
|
3939
|
-
# Use your ApplicationController to render components (app helpers / Current)
|
|
3940
|
-
|
|
4023
|
+
# Use your ApplicationController to render components (app helpers / Current).
|
|
4024
|
+
# By name, like base_controller_name, it follows a code reload in development;
|
|
4025
|
+
# a Class keeps rendering the class object it was given:
|
|
4026
|
+
Phlex::Reactive.renderer = "ApplicationController"
|
|
3941
4027
|
|
|
3942
4028
|
# Sign tokens with a dedicated key instead of secret_key_base:
|
|
3943
4029
|
Phlex::Reactive.verifier = ActiveSupport::MessageVerifier.new(ENV["REACTIVE_KEY"])
|
|
@@ -3989,6 +4075,17 @@ Phlex::Reactive.around_action do |ctx, &action|
|
|
|
3989
4075
|
end
|
|
3990
4076
|
```
|
|
3991
4077
|
|
|
4078
|
+
**The configuration is finalized at boot.** Once the app has booted (after your
|
|
4079
|
+
initializers and every `after_initialize` block), the engine calls
|
|
4080
|
+
`Phlex::Reactive.finalize!` for you: the param-type and named-schema registries
|
|
4081
|
+
freeze, and every setting is stored as a frozen, Ractor-shareable copy (the
|
|
4082
|
+
objects you handed in are not frozen). Append to `authorization_errors` in an
|
|
4083
|
+
initializer; after boot, assign a new list (`<<` raises `FrozenError`). A value
|
|
4084
|
+
no Ractor can share (a block written in an initializer, a lambda that closes
|
|
4085
|
+
over app state, a logger, an APM object, the verifier) is kept as it is and
|
|
4086
|
+
works on the main Ractor only: finalizing never raises for it. Booting without
|
|
4087
|
+
the engine? Call `Phlex::Reactive.finalize!` at the end of your own boot.
|
|
4088
|
+
|
|
3992
4089
|
#### Two seams: HTTP-layer (`base_controller_name`) vs component-layer (`around_action`)
|
|
3993
4090
|
|
|
3994
4091
|
There are two places to wrap a reactive action, and they see different things:
|
|
@@ -215,6 +215,7 @@ module Phlex
|
|
|
215
215
|
result = run_action(component, action_def, coerced)
|
|
216
216
|
|
|
217
217
|
event[:outcome] = :ok
|
|
218
|
+
mark_refused(result)
|
|
218
219
|
render turbo_stream: response_streams(result, component)
|
|
219
220
|
rescue Phlex::Reactive::AuthorizationNotVerified
|
|
220
221
|
# A developer error (a forgotten authorize!), NOT a client fault — it
|
|
@@ -416,6 +417,15 @@ module Phlex
|
|
|
416
417
|
end.call
|
|
417
418
|
end
|
|
418
419
|
|
|
420
|
+
# A reply that refused the posted values (issue #413) names the held
|
|
421
|
+
# fields the client keeps, instead of releasing them after the render.
|
|
422
|
+
def mark_refused(result)
|
|
423
|
+
return unless result.is_a?(Phlex::Reactive::Response) && result.refused?
|
|
424
|
+
|
|
425
|
+
response.headers[Phlex::Reactive::HeldFields::REFUSED_HEADER] =
|
|
426
|
+
Phlex::Reactive::HeldFields.refused_header(result.refused_fields)
|
|
427
|
+
end
|
|
428
|
+
|
|
419
429
|
# Turn the action's return value into the turbo-stream(s) to render for
|
|
420
430
|
# the actor. A Phlex::Reactive::Response is honored explicitly; any other
|
|
421
431
|
# value (the legacy contract — return value ignored) falls back to the
|
|
@@ -45,8 +45,9 @@ module Phlex
|
|
|
45
45
|
# the session it was minted for.
|
|
46
46
|
CSRF_TOKEN_NAMES = %w[authenticity_token csrf-token].freeze
|
|
47
47
|
# One compiled pattern per forgery-protection field name (it is a
|
|
48
|
-
# class-level setting, so in practice one entry), not one per request
|
|
49
|
-
|
|
48
|
+
# class-level setting, so in practice one entry), not one per request:
|
|
49
|
+
# memoized in the per-Ractor table (Phlex::Reactive::Store) under this key.
|
|
50
|
+
CSRF_TOKEN_PATTERNS_KEY = :phlex_reactive_csrf_token_patterns
|
|
50
51
|
|
|
51
52
|
# Stands in for the response when asking the cookie jar what it WOULD
|
|
52
53
|
# write (CookieJar#write calls set_cookie / delete_cookie per pending
|
|
@@ -261,7 +262,7 @@ module Phlex
|
|
|
261
262
|
# An API base controller has no forgery protection (and so no such
|
|
262
263
|
# setting): the built-in names alone are checked then.
|
|
263
264
|
token_name = respond_to?(:request_forgery_protection_token, true) ? request_forgery_protection_token.to_s : ""
|
|
264
|
-
|
|
265
|
+
Phlex::Reactive::Store.table(CSRF_TOKEN_PATTERNS_KEY).fetch(token_name) do
|
|
265
266
|
names = (CSRF_TOKEN_NAMES | [token_name]).reject(&:empty?).map { Regexp.escape(it) }
|
|
266
267
|
/\bname\s*=\s*["']?(?:#{names.join("|")})(?![\w-])/i
|
|
267
268
|
end
|
|
@@ -27,6 +27,7 @@ registerReactiveFeatureLoader("form", () => import("phlex/reactive/features/form
|
|
|
27
27
|
registerReactiveFeatureLoader("bindings", () => import("phlex/reactive/features/bindings"))
|
|
28
28
|
registerReactiveFeatureLoader("compute", () => import("phlex/reactive/features/compute"), waitingForEdit)
|
|
29
29
|
registerReactiveFeatureLoader("sortable", () => import("phlex/reactive/features/sortable"))
|
|
30
|
+
registerReactiveFeatureLoader("drag", () => import("phlex/reactive/features/drag"))
|
|
30
31
|
registerReactiveFeatureLoader("presence", () => import("phlex/reactive/features/presence"))
|
|
31
32
|
registerReactiveFeatureLoader("countdown", () => import("phlex/reactive/features/countdown"))
|
|
32
33
|
registerReactiveFeatureLoader("effects", () => import("phlex/reactive/features/effects"))
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{Controller as kt}from"@hotwired/stimulus";import{confirmResolver as Fe}from"phlex/reactive/confirm";function xt(){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 Rt(){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 Nt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=Ae(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}de(t,(s)=>br(s,i),n?(s,a)=>y("devtools",(o)=>o.diagnoseStream(s,a,i)):void 0)}}function Ot(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){y("defer",(t)=>t.streamAction(this))}}var Le=!1,ae=null;function It(){if(Le)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Le=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Ht(e),Pt(e),Ct(e),ae)ae(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var W="reactive:streamed";function Pt(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(W))}}function he(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function me(e){try{return e.matches(":modal")}catch{return!1}}function Ze(e){if(!he(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||me(e))return;if(e.open)e.close();e.showModal()}function Mt(e){if(he(e)&&e.open)e.close()}function J(e){let r=[...e?.querySelectorAll?.("dialog[data-reactive-modal]")??[]];if(e?.matches?.("dialog[data-reactive-modal]"))r.push(e);for(let n of r)if(n.open&&!me(n))Ze(n)}function Ct(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target;if(typeof r!=="function"||!n?.querySelector?.("template")?.content?.querySelector?.("dialog"))return;t.render=async(i)=>{await r(i),J(document)}}var ke=!1;function Dt(){if(ke)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;ke=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))J(t.target)}),document.addEventListener("turbo:morph",()=>J(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!he(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||!me(r))return;e.delete(r),t.preventDefault(),r.close()})}var ce=new WeakMap;function Qe(e,t,r,n){let i=ce.get(e)??new Map;ce.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"))bt(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}))Qe(a,"set_attr",{name:"aria-expanded"})}}var xe=!1;function $t(){if(xe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;xe=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of ce.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 et="data-reactive-image-fallback",k="data-reactive-image-state",ue="data-reactive-image-hidden",Z=null,le="data-reactive-wrap-hidden";function tt(e){if(e.hasAttribute("hidden"))return;e.setAttribute("hidden",""),e.setAttribute(le,"")}function rt(e){if(!e.hasAttribute(le))return;e.removeAttribute("hidden"),e.removeAttribute(le)}function x(e){if(e?.localName!=="img")return null;let t=e.getAttribute(et);if(t==null)return null;try{return JSON.parse(t)||{}}catch{return{}}}var nt=(e)=>e.getAttribute("src")||e.getAttribute("srcset");function pe(e,t){if(typeof t!=="string"||!t)return null;try{return e.closest('[data-controller~="reactive"]')?.querySelector(t)??null}catch{return null}}function it(e,t){let r=pe(e,t.alt);return r&&!r.contains(e)?r:null}function H(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(ue,"");if(t.wrap){let i=pe(e,t.wrap);if(i)tt(i);else console.warn(`[phlex-reactive] reactive_image_fallback wrap: ${JSON.stringify(t.wrap)} is not in the root — skipped`)}let n=it(e,t);if(n)n.textContent=e.getAttribute("alt")??"",n.hidden=!1}else G(e,t);e.setAttribute(k,r)}function G(e,t=x(e)){if(!t||e.getAttribute(k)==null)return;if(e.getAttribute(k)==="error"){if(e.hasAttribute(ue))e.removeAttribute("hidden");let r=pe(e,t.wrap);if(r)rt(r);let n=it(e,t);if(n)n.hidden=!0}e.removeAttribute(k),e.removeAttribute(ue)}function Re(e){let t=e.target,r=x(t);if(!r)return;if(e.type==="load")H(t,r,"loaded");else if(nt(t))H(t,r,"error");else G(t,r)}function qt(){if(Z)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;Z={error:Re,load:Re,"turbo:before-morph-element":(t)=>{let r=t.target,n=t.detail?.newElement,i=r?.getAttribute?.(k);if(i==null||!n||!x(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=x(r);if(i)H(r,i,n)})}};for(let[t,r]of Object.entries(Z))document.addEventListener(t,r,!0);for(let t of document.querySelectorAll?.(`img[${et}]`)??[]){if(!t.complete||!nt(t))continue;let r=`${t.getAttribute("src")} ${t.getAttribute("srcset")}`,n=(i)=>`${t.getAttribute("src")} ${t.getAttribute("srcset")}`===r&&H(t,x(t)??{},i);if(t.naturalWidth>0)n("loaded");else if(typeof t.decode==="function")t.decode().then(()=>n("loaded"),()=>n("error"));else n("error")}}function ot(e){ae=e}var C,Q=null,Ne="[data-reactive-editable][contenteditable=plaintext-only]";function st(){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 B(e){if(e.matches?.(Ne))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Ne).forEach(B)}function Wt(){if(Q||typeof document>"u"||typeof document.createElement!=="function")return;if(st())return;B(document),Q=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")B(t.target);else t.addedNodes.forEach(B)}),Q.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var Oe=!1;function Ie(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 Bt(){if(Oe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Oe=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=Ie(t);if(n)Ut(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(K.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)=>_e(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&Ie(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&be(t)===ye(t))t.removeAttribute(_)})}var _="data-reactive-held",ge='[data-controller~="reactive"]',j=null,T=new Map;function be(e){return e.hasAttribute("data-reactive-editable")?E(e):e.value}function ye(e){return e.hasAttribute("data-reactive-editable")?we(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 Ut(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||T.has(e.closest(ge)))return;let n=jt(t);if(n===be(e))return e.removeAttribute(_);if(n===ye(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function Jt(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(ge)!==e)continue;let n=r.getAttribute("name");if(be(r)===ye(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 at(e){for(let t of e.querySelectorAll(`[${_}]`))if(t.closest(ge)===e)t.removeAttribute(_)}function Pe(e,t,r=!0){let n={root:e,streams:0,release:r},i=j;j=n;try{window.Turbo.renderStreamMessage(t)}finally{j=i}if(r&&n.streams===0)at(e)}function Ht(e){let t=j,r=e.detail,n=r?.render;if(!t||typeof n!=="function")return;t.streams++,r.render=async(i)=>{T.set(t.root,(T.get(t.root)||0)+1);try{return await n(i)}finally{let s=T.get(t.root)-1;if(s)T.set(t.root,s);else T.delete(t.root);if(t.release)at(t.root)}}}var Me="__materialize",Ce=!1;function Kt(){if(Ce)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;Ce=!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 zt="phlex-reactive:latency";function ct(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(zt))}function ve(){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||ct())y("devtools",(t)=>e&&t.attach())}var ut="data-reactive-active",A=0;function lt(){if(A++,A===1)ft("reactive:busy")}function dt(){if(A===0)return;if(A--,A===0)ft("reactive:idle")}function zr(){return A}function Vr(){A=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(ut)}function ft(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(ut,A>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:A}}))}var ht="data-reactive-requests";function mt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Vt(t))return;let r=Gt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(ht,JSON.stringify(r))}function Vt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Gt(e){try{let t=JSON.parse(e.getAttribute(ht));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function De(){xt(),Rt(),Nt(),Ot(),It(),Bt(),Dt(),$t(),qt(),Wt(),Kt(),ve()}function Yt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var pt=Symbol.for("phlex-reactive.core");if(globalThis[pt])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[pt]=!0;var gt=!1;function Xt(){if(gt)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(Xt,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var Zt=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function bt(e){let t=String(e).toLowerCase();return t.startsWith("on")||Zt.has(t)}var ee=new WeakMap;function Qt(e,t,r){let[n,i,s]=t;ee.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,ee.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};ee.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,er(e))}function er(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 tr=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",rr=new Set(["lexxy-editor","trix-editor"]);function E(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
|
|
1
|
+
import{Controller as Lt}from"@hotwired/stimulus";import{confirmResolver as Fe}from"phlex/reactive/confirm";function Rt(){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 xt(){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 Nt(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:js"])return;e["reactive:js"]=function(){let t=Ae(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}de(t,(s)=>yr(s,i),n?(s,a)=>y("devtools",(o)=>o.diagnoseStream(s,a,i)):void 0)}}function Ot(){let e=window.Turbo?.StreamActions;if(!e||e["reactive:defer"])return;e["reactive:defer"]=function(){y("defer",(t)=>t.streamAction(this))}}var ke=!1,ae=null;function It(){if(ke)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;ke=!0,document.addEventListener("turbo:before-stream-render",(e)=>{if(Kt(e),Pt(e),Ct(e),ae)ae(e,p.get("effects"));else p.get("effects")?.wrap(e)})}var W="reactive:streamed";function Pt(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(W))}}function he(e){return e?.tagName==="DIALOG"&&typeof e.showModal==="function"}function me(e){try{return e.matches(":modal")}catch{return!1}}function Ze(e){if(!he(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||me(e))return;if(e.open)e.close();e.showModal()}function Mt(e){if(he(e)&&e.open)e.close()}function J(e){let r=[...e?.querySelectorAll?.("dialog[data-reactive-modal]")??[]];if(e?.matches?.("dialog[data-reactive-modal]"))r.push(e);for(let n of r)if(n.open&&!me(n))Ze(n)}function Ct(e){let t=e.detail,r=t?.render,n=t?.newStream??e.target;if(typeof r!=="function"||!n?.querySelector?.("template")?.content?.querySelector?.("dialog"))return;t.render=async(i)=>{await r(i),J(document)}}var Le=!1;function Dt(){if(Le)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Le=!0,document.addEventListener("turbo:morph-element",(t)=>{if(t.target?.matches?.('[data-controller~="reactive"]'))J(t.target)}),document.addEventListener("turbo:morph",()=>J(document));let e=new WeakSet;document.addEventListener("turbo:before-morph-element",(t)=>{let r=t.target,n=t.detail?.newElement;if(!he(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||!me(r))return;e.delete(r),t.preventDefault(),r.close()})}var ce=new WeakMap;function Qe(e,t,r,n){let i=ce.get(e)??new Map;ce.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"))bt(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}))Qe(a,"set_attr",{name:"aria-expanded"})}}var Re=!1;function $t(){if(Re)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Re=!0,document.addEventListener("turbo:morph-element",(e)=>{let t=e.target;for(let[r,n]of ce.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 et="data-reactive-image-fallback",L="data-reactive-image-state",ue="data-reactive-image-hidden",Z=null,le="data-reactive-wrap-hidden";function tt(e){if(e.hasAttribute("hidden"))return;e.setAttribute("hidden",""),e.setAttribute(le,"")}function rt(e){if(!e.hasAttribute(le))return;e.removeAttribute("hidden"),e.removeAttribute(le)}function R(e){if(e?.localName!=="img")return null;let t=e.getAttribute(et);if(t==null)return null;try{return JSON.parse(t)||{}}catch{return{}}}var nt=(e)=>e.getAttribute("src")||e.getAttribute("srcset");function pe(e,t){if(typeof t!=="string"||!t)return null;try{return e.closest('[data-controller~="reactive"]')?.querySelector(t)??null}catch{return null}}function it(e,t){let r=pe(e,t.alt);return r&&!r.contains(e)?r:null}function H(e,t,r){if(r==="error"){if(t.hide&&!e.hasAttribute("hidden"))e.setAttribute("hidden",""),e.setAttribute(ue,"");if(t.wrap){let i=pe(e,t.wrap);if(i)tt(i);else console.warn(`[phlex-reactive] reactive_image_fallback wrap: ${JSON.stringify(t.wrap)} is not in the root — skipped`)}let n=it(e,t);if(n)n.textContent=e.getAttribute("alt")??"",n.hidden=!1}else V(e,t);e.setAttribute(L,r)}function V(e,t=R(e)){if(!t||e.getAttribute(L)==null)return;if(e.getAttribute(L)==="error"){if(e.hasAttribute(ue))e.removeAttribute("hidden");let r=pe(e,t.wrap);if(r)rt(r);let n=it(e,t);if(n)n.hidden=!0}e.removeAttribute(L),e.removeAttribute(ue)}function xe(e){let t=e.target,r=R(t);if(!r)return;if(e.type==="load")H(t,r,"loaded");else if(nt(t))H(t,r,"error");else V(t,r)}function qt(){if(Z)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;let e=new WeakMap;Z={error:xe,load:xe,"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)H(r,i,n)})}};for(let[t,r]of Object.entries(Z))document.addEventListener(t,r,!0);for(let t of document.querySelectorAll?.(`img[${et}]`)??[]){if(!t.complete||!nt(t))continue;let r=`${t.getAttribute("src")} ${t.getAttribute("srcset")}`,n=(i)=>`${t.getAttribute("src")} ${t.getAttribute("srcset")}`===r&&H(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 ot(e){ae=e}var C,Q=null,Ne="[data-reactive-editable][contenteditable=plaintext-only]";function st(){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 B(e){if(e.matches?.(Ne))e.setAttribute("contenteditable","true");e.querySelectorAll?.(Ne).forEach(B)}function Wt(){if(Q||typeof document>"u"||typeof document.createElement!=="function")return;if(st())return;B(document),Q=new MutationObserver((e)=>{for(let t of e)if(t.type==="attributes")B(t.target);else t.addedNodes.forEach(B)}),Q.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["contenteditable","data-reactive-editable"]})}var Oe=!1;function Ie(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 Bt(){if(Oe)return;if(typeof document>"u"||typeof document.addEventListener!=="function")return;Oe=!0,document.addEventListener("turbo:before-morph-element",(e)=>{let t=e.target,r=e.detail?.newElement;if(!r||e.defaultPrevented)return;let n=Ie(t);if(n)Ut(t,r);if(t.hasAttribute?.("data-reactive-editable")){if(K.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)=>_e(e.target)),document.addEventListener("turbo:before-morph-attribute",(e)=>{let t=e.detail?.attributeName;if((t==="value"||t===_)&&Ie(e.target))e.preventDefault()}),document.addEventListener("input",(e)=>{let t=e.target;if(t?.hasAttribute?.(_)&&be(t)===ye(t))t.removeAttribute(_)})}var _="data-reactive-held",ge='[data-controller~="reactive"]',j=null,T=new Map;function be(e){return e.hasAttribute("data-reactive-editable")?E(e):e.value}function ye(e){return e.hasAttribute("data-reactive-editable")?we(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 Ut(e,t){let r=e.getAttribute("name");if(!r||/^(checkbox|radio)$/.test(e.type)||T.has(e.closest(ge)))return;let n=jt(t);if(n===be(e))return e.removeAttribute(_);if(n===ye(e))return;e.setAttribute(_,""),e.dispatchEvent(new CustomEvent("reactive:held",{bubbles:!0,detail:{name:r,theirs:n}}))}function Jt(e){let t=[];for(let r of e.querySelectorAll(`[${_}]`)){if(r.closest(ge)!==e)continue;let n=r.getAttribute("name");if(be(r)===ye(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 at(e,t){if(t===!0)return;for(let r of e.querySelectorAll(`[${_}]`))if(r.closest(ge)===e&&!t?.includes(r.getAttribute("name")))r.removeAttribute(_)}function Ht(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 Pe(e,t,r=null){let n={root:e,streams:0,keep:r},i=j;j=n;try{window.Turbo.renderStreamMessage(t)}finally{j=i}if(n.streams===0)at(e,r)}function Kt(e){let t=j,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);at(t.root,t.keep)}}}var Me="__materialize",Ce=!1;function zt(){if(Ce)return;if(typeof window>"u"||typeof document>"u")return;if(typeof window.addEventListener!=="function")return;Ce=!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 Gt="phlex-reactive:latency";function ct(){return typeof sessionStorage<"u"&&Boolean(sessionStorage.getItem(Gt))}function ve(){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||ct())y("devtools",(t)=>e&&t.attach())}var ut="data-reactive-active",A=0;function lt(){if(A++,A===1)ft("reactive:busy")}function dt(){if(A===0)return;if(A--,A===0)ft("reactive:idle")}function Vr(){return A}function Yr(){A=0,(typeof document<"u"?document.documentElement:null)?.removeAttribute?.(ut)}function ft(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.toggleAttribute==="function")t.toggleAttribute(ut,A>0);if(typeof document.dispatchEvent==="function"&&typeof CustomEvent==="function")document.dispatchEvent(new CustomEvent(e,{detail:{count:A}}))}var ht="data-reactive-requests";function mt(e){if(typeof document>"u")return;let t=document.documentElement;if(typeof t?.setAttribute!=="function"||!Vt(t))return;let r=Yt(t);r[e]=(Number(r[e])||0)+1,t.setAttribute(ht,JSON.stringify(r))}function Vt(e){return e.hasAttribute?.("data-reactive-verbose")||!!document.querySelector?.('[data-reactive-verbose="true"]')}function Yt(e){try{let t=JSON.parse(e.getAttribute(ht));if(t&&typeof t==="object")return{action:0,defer:0,...t}}catch{}return{action:0,defer:0}}function De(){Rt(),xt(),Nt(),Ot(),It(),Bt(),Dt(),$t(),qt(),Wt(),zt(),ve()}function Xt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var pt=Symbol.for("phlex-reactive.core");if(globalThis[pt])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[pt]=!0;var gt=!1;function Zt(){if(gt)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(Zt,0);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",e,{once:!0});else e()}var Qt=new Set(["href","src","srcset","srcdoc","action","formaction","xlink:href","style"]);function bt(e){let t=String(e).toLowerCase();return t.startsWith("on")||Qt.has(t)}var ee=new WeakMap;function er(e,t,r){let[n,i,s]=t;ee.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,ee.delete(e),clearTimeout(l),globalThis.cancelAnimationFrame?.(o),e.removeEventListener("animationend",c),e.removeEventListener("transitionend",c),e.classList.remove(n,i,s)};ee.set(e,c),e.addEventListener("animationend",c),e.addEventListener("transitionend",c);let l=setTimeout(c,tr(e))}function tr(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 rr=":is(lexxy-editor, trix-editor, [contenteditable=''], [contenteditable=true], [contenteditable=plaintext-only])",nr=new Set(["lexxy-editor","trix-editor"]);function E(e){let t="",r=!1,n=(s)=>{if(r&&t&&!t.endsWith(`
|
|
2
2
|
`))t+=`
|
|
3
3
|
`;r=!1,t+=s},i=(s)=>{for(let a of s.childNodes){let o=/^(div|p|li)$/.test(a.localName);if(o)r=!0;if(a.nodeType===3)a.data&&n(a.data);else if(a.localName==="br")n(`
|
|
4
4
|
`);else if(a.nodeType===1)i(a);if(o)r=!0}};return i(e),t=t.replace(/\r\n?/g,`
|
|
5
|
-
`).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var K=new WeakMap;function _e(e){if(e?.hasAttribute?.("data-reactive-editable")&&!K.has(e))K.set(e,E(e))}function we(e){return _e(e),K.get(e)}function
|
|
6
|
-
`):e.value}function ur(e,t,r){if(r?.transition)Qt(e,r.transition,()=>e.hidden=t);else e.hidden=t}function re(e,t,r,n){if(ur(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 ne(e){if(!bt(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function wt(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)G(e);let s=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==s)e.setAttribute("alt",s);return r?s:!1}var lr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function dr(e){return e.querySelectorAll?.(lr)?.[0]??null}function Ae(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 We=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"}),Be=Object.freeze(["meta","ctrl","alt","shift"]);function Y(e,t,r){let n=e.split("+");for(let a of Be)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Be.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let s=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(We,i)?We[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof s==="string"&&s.toLowerCase()===t.key.toLowerCase()}var fr=(e)=>e&&typeof e==="object"?e.keys:String(e);function ie(e,t,r){let n=t.target;if(e?.inEditable!==!0&&(n?.isContentEditable||/^(input|textarea|select)$/.test(n?.localName)))return!1;let i=/[Mm]ac|iP/.test(navigator.userAgentData?.platform??navigator.platform)?"meta":"ctrl";return Y(fr(e).replace(/^mod\+/,`${i}+`),t,r)}function hr(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:Ae(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)!==Ee(t.currentTarget))return!1;return i<0||r===null||Y(n.slice(i+1),t,r)}function mr(e,t){let r=e.detail;if(r===void 0)return!0;if(r===null||typeof r!=="object"||Array.isArray(r))return!1;let n=t.detail;if(n===null||typeof n!=="object")return!1;return Object.keys(r).every((i)=>n[i]===r[i])}var Ue=new WeakMap;function pr(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=Ue.get(e);if(!i)i=new WeakMap,Ue.set(e,i);let 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 Je=new WeakMap;function gr(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=Je.get(e);if(!i)i=new WeakMap,Je.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 de(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn($e,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($e[i](o,s,t),s?.keep===!0)Qe(o,i,s,t)}}function br(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 yr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function Se(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}var He='[data-controller~="reactive"]',vr='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',fe=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!Se(e);function Ke(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&fe(n))n=n.parentElement?.closest?.(t);return n??null}var D=new WeakMap,q=new WeakMap;function _r(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 wr(e){return["show-targets","group-targets","on-complete","filter-input","tags-field"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)||(e.querySelectorAll?.("[data-reactive-show-field], [data-reactive-show]")??[]).length>0||e.querySelector?.("[data-reactive-nested-json], [data-reactive-nested-list], [data-reactive-confirm-when-param], [data-reactive-enable], [data-reactive-select-all], [data-reactive-count], [data-reactive-editable], [data-reactive-media]")!=null}function Ar(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function Sr(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function At(e){return e.getAttribute?.("data-reactive-presence")!=null}function Er(e){return Boolean(e.matches?.("[data-reactive-countdown]")||e.querySelector?.("[data-reactive-countdown]"))}var Tr=[["persist",[yr,null,null,!0]],["defer",[Se,null]],["form",[_r,null]],["bindings",[wr,null,null,!0]],["compute",[Ar,null,null,!0]],["sortable",[Sr,null]],["presence",[At,null]],["countdown",[Er,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(Tr),ze=new Map,p=new Map,Fr=new Map;function g(e,t,r){St.set(e,[t,r]),Lr(e)}var St=new Map;function Lr(e){let t=w.get(e),[r,n]=St.get(e);t[1]=r,t[2]=n}function Gr(e,t){t.install?.(I),p.set(e,t),Fr.set(e,t)}function Et(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 Tt(e){return O(e).catch((t)=>z(e,"load",t))}function O(e){let t=ze.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)),ze.set(e,t);return t}var Ve=new Set;function z(e,t,r){let n=e+t;if(Ve.has(n))return;Ve.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)=>z(e,"load",n))}var kr=1e4;function oe(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:kr}function Yr(){return[...w.keys()]}var Ge=Promise.resolve();function Ye(e,t,r){let n=I.waiting.get(e);if(n&&n[t]===r)delete n[t]}var I={enter:lt,exit:dt,count:mt,text:E,served:we,waiting:new WeakMap};var P=Symbol.for("phlex-reactive.early"),xr=1e4,Rr=1500,Ee=(e)=>e!=null&&(e===globalThis.window||e.window===e),Nr="dispatch";function se(){return globalThis[P]??={queue:[],connected:new WeakSet},globalThis[P]}function Or(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:xr}function Ir(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 Pr(e,t,r){return{[P]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:Ir(t),key:e.key,code:e.code,metaKey:e.metaKey,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,button:e.button,submitter:e.submitter,bubbles:e.bubbles,timeStamp:e.timeStamp,defaultPrevented:e.defaultPrevented,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var V=new WeakMap;function Mr(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=V.get(e);if(!o)V.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 Xe(e,t,r,n){if(e?.[P])return!1;let i=Ee(e?.currentTarget),s=i?n:e?.currentTarget,a=Dr(e,s,i?`@${t}`:t),o=V.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&&!Y(l.filter,e,r))continue;return l.armed=!1,!0}return a}var U=new WeakMap;function Cr(e,t,r){let n=U.get(e);if(!n)U.set(e,n=new Map),setTimeout(()=>U.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function Dr(e,t,r){let n=e&&U.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Ft extends kt{static values={token:String};#w;#l=new Map;#d=new Map;#ne;#k;#B;#x=0;#f=new Map;#R=new WeakMap;#t;featuresReady=Ge;#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(gt=!0,se().connected.add(this.element),D.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||Se(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===W)this.#H();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(W,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(_e),this.#g++,this.featuresReady=Ge,this.#U(),J(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 ${oe()} ms`));n(null)},oe());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)Ye(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)=>de(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:st,text:E,served:we,copyMedia:wt,setValue:_t,confirm:(e,t)=>Promise.resolve().then(()=>Fe(e,t)).catch(()=>!1)},this.#j}#H(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#b(e,t,r){if(z(e,t,r),this.#i("feature"),t==="load"&&this.element.getAttribute?.("data-reactive-defer-pending"))this.element.removeAttribute("data-reactive-defer-pending"),this.element.removeAttribute("aria-busy");this.#o("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#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),Ye(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 q.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}q.delete(this.element)}#I=new Set;#ce(){let{queue:e}=se();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=Or(),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(Rr,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=Pr(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&&!Y(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!Mr(o,c,n&&JSON.stringify(i.params)))continue;this.#I.add(o)}if(Cr(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?.(W,this.#t);if(se().connected.delete(this.element),D.get(this.element)===this)D.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)V.delete(e);this.#I.clear()}dispatch(e){if(e.params?.action&&e.params.action!==Me&&this.#le())return this.#de(e);let t=e.params?.shortcut;if(t!=null&&!ie(t,e,this.application?.schema?.keyMappings))return;if(Xe(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))e.preventDefault();if(r===Me){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(()=>Fe(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)=>(z(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),oe()))]).finally(()=>clearTimeout(t))}}#le(){return!this.tokenValue&&fe(this.element)}#de(e){let t=Ke(this.element.parentElement,vr);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=D.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:s}=e.params,a=e.currentTarget??e.target;if((n!=null||!i)&&!this.#te(s,a))e.preventDefault();q.set(t,[...q.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&&!ie(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Xe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(gr(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=hr(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(!mr(o,e))continue;if(o.shortcut!=null&&!ie(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(pr(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)t.preventDefault();let d=this.#K(s,a),h=this.#he(e,n,r,()=>this.#Ne(this.#Re(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.#V(r,a,i,n);return()=>this.#G(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.#V(e,Nr,t,()=>this.#T(r,n,i,e,s))}#V(e,t,r,n){this.#M(e,t);let i=()=>{this.#M(e,t),n()},s=setTimeout(i,r);if(!Ee(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.#G(e,r,t,()=>this.#T(r,n,i,e,s))}#G(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(ct())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.#ke(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 L=this.#$e();if(L)m["X-Pgbus-Connection"]=L;let M=At(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(M)m["X-Reactive-Presence"]=M;let Te=Jt(this.element);if(Te)m["X-Reactive-Held"]=Te;mt("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 L=this.#X(m);if(this.#a=L??this.#a,h)this.#_((M)=>M.recordBody(h,m,L));Pe(this.element,m,!1)}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(Pe(this.element,v),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=Yt(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(He);if(e.length===0||[...e].every(fe))return()=>!0;return(t)=>Ke(t,He,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]${tr}`).forEach((o)=>{if(r(o))i.push(o)});let s=this.#Fe(n),a=this.#Le(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("[]")&&!nr(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}#Le(e){let t=new Set;for(let r of e)if(r.type==="checkbox")t.add(r.name);return t}#ke(e,t,r,n){let i=new FormData;i.append("token",e),i.append("act",t);let s=[];for(let[o,c]of Object.entries(r))if(Array.isArray(c)&&String(o).endsWith("[]"))if(c.length===0)s.push(String(o).slice(0,-2));else{let l=`${this.#L(o)}[]`;for(let d of c)i.append(l,String(d))}else this.#D(i,this.#L(o),c);for(let o of s)i.append("empty_groups[]",o);let a=this.#xe(n);for(let{name:o,file:c,multiple:l}of n){let h=l||a.has(o)?`${this.#L(o)}[]`:this.#L(o);i.append(h,c,c.name)}return i}#L(e){let t=String(e),r=t.indexOf("[");if(r===-1)return`params[${t}]`;return`params${[t.slice(0,r),...t.slice(r).match(/[^\[\]]+/g)??[]].map((i)=>`[${i}]`).join("")}`}#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))}#xe(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{}}}#Re(e){return Ae(e)}#Ne(e){de(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),lt();let n=!1;return()=>{if(n)return;n=!0,this.#Pe(e,t),dt();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.#x++===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.#x<=0)this.#x=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.#R.get(e)??new Map,i=(n.get(t)??0)+r;if(i<=0)n.delete(t);else n.set(t,i);if(n.size===0){this.#R.delete(e),e.removeAttribute("data-reactive-busy");return}this.#R.set(e,n),e.setAttribute("data-reactive-busy",[...n.keys()].join(" "))}#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.#k!=null)return this.#k;let e=document.querySelector('meta[name="phlex-reactive-timeout"]')?.content,t=Number(e);return this.#k=Number.isFinite(t)&&t>0?t:30000}#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)De();else document.addEventListener("turbo:load",De,{once:!0});g("persist",()=>import("phlex/reactive/features/persist"),$r);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"),qr);g("sortable",()=>import("phlex/reactive/features/sortable"));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"));ve();function $r(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 qr(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 Wr=1000,F=null,Lt,X=new Set;function Br(e){return Tt(e).then((t)=>{if(e!=="effects")return;Lt=t,t?.sweep()})}ot((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,s=Et(jr(i)).filter((o)=>!X.has(o));if(!t&&!X.has("effects")&&Ur(i))s.push("effects");if(s.length===0&&!F)return t?.wrap(e);if(s.length>0){for(let c of s)X.add(c);let o=F=Promise.race([Promise.all([F,...s.map(Br)]),new Promise((c)=>setTimeout(c,Wr))]).then(()=>{if(F!==o)return;F=null,X.clear()})}let a=F;r.render=async(o)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??Lt)?.wrap(c),await c.detail.render(o)}});function jr(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 Ur(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 rn=Ft;export{ut as ACTIVE_ATTR,tr as EDITOR_SELECTOR,rr as EDITOR_TAGS,ht as REQUESTS_ATTR,Xt as checkReactiveRegistration,mt as countReactiveRequest,rn as default,E as editableValue,lt as enterReactiveActivity,Yt as escapeRegExp,dt as exitReactiveActivity,Tt as loadReactiveFeature,ot as onReactiveStreamWithoutEffects,zr as reactiveActivityCount,Yr as reactiveFeatureNames,De as registerReactiveActions,Ot as registerReactiveDefer,ve as registerReactiveDev,It as registerReactiveDismiss,It as registerReactiveEffects,Gr as registerReactiveFeature,g as registerReactiveFeatureLoader,qt as registerReactiveImageFallback,Nt as registerReactiveJs,$t as registerReactiveKeep,Dt as registerReactiveModals,Bt as registerReactiveMorphFocus,Kt as registerReactiveOffline,Wt as registerReactivePlaintext,It as registerReactiveStreamRender,Rt as registerReactiveToken,xt as registerReactiveVisit,Vr as resetReactiveActivity,we as serverText,Et as unloadedFeaturesFor};
|
|
5
|
+
`).replace(/\n$/,""),e.getAttribute("data-reactive-editable")==="multi"?t:t.replace(/\n/g," ")}var K=new WeakMap;function _e(e){if(e?.hasAttribute?.("data-reactive-editable")&&!K.has(e))K.set(e,E(e))}function we(e){return _e(e),K.get(e)}function ir(e){return nr.has(e.localName)?typeof e.value==="string":!0}var $e=Object.freeze({show:(e,t,r)=>re(e,!1,t,r),hide:(e,t,r)=>re(e,!0,t,r),toggle:(e,t,r)=>re(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(ne(t.name))e.setAttribute(t.name,t.value??"")},remove_attr:(e,t)=>{if(ne(t.name))e.removeAttribute(t.name)},toggle_attr:(e,t)=>{if(!ne(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)=>fr(e)?.focus?.(),blur:(e)=>{let t=e.ownerDocument?.activeElement??globalThis.document?.activeElement;if(t&&(t===e||e.contains?.(t)))t.blur?.()},show_modal:(e)=>Ze(e),close_dialog:(e)=>Mt(e),text:(e,t)=>{let r=String(t.value??"");if(e.textContent!==r)e.textContent=r},copy_media:(e,t,r)=>{let n=null;try{n=r({...t,to:t.from})[0]??null}catch{}wt(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=or(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)=>sr(e),preview_file:(e,t,r)=>ar(e,t,r),set_value:(e,t)=>_t(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 or(e){if(e?.tagName==="FORM")return e;return e?.form??e?.closest?.("form")??null}function sr(e){let t=globalThis.navigator?.clipboard;if(typeof t?.readText!=="function")return;t.readText().then((r)=>{if(!r)return;e.value=r,vt(e),e.focus?.()}).catch(()=>{})}var x=new Map,N=null;function ar(e,t,r){if(e?.tagName!=="INPUT"||e.type!=="file")return te(`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 te(`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=cr(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(yt(n),o){let d=URL.createObjectURL(o);x.set(n,d),n.setAttribute("src",d),ur()}else n.removeAttribute("src");if(V(n),t.wrap!=null){let d=r({...t,to:t.wrap});if(d.length===0)te(`wrap: ${JSON.stringify(t.wrap)} is not on the page`);for(let h of d)o?rt(h):tt(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 cr(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 te(e){console.warn(`[phlex-reactive] preview_file ${e} — skipped`)}function yt(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 ur(){if(N||typeof MutationObserver!=="function"||!document?.documentElement)return;N=new MutationObserver(()=>{for(let[e,t]of x)if(!e.isConnected||e.getAttribute("src")!==t)yt(e)}),N.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]})}function vt(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function _t(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=qe(e);if(e.value=t,qe(e)!==r)vt(e)}function qe(e){return e.type==="select-multiple"?[...e.selectedOptions].map((t)=>t.value).join(`
|
|
6
|
+
`):e.value}function lr(e,t,r){if(r?.transition)er(e,r.transition,()=>e.hidden=t);else e.hidden=t}function re(e,t,r,n){if(lr(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 ne(e){if(!bt(e))return!0;return console.warn(`[phlex-reactive] refused client attr op on ${JSON.stringify(e)} — skipped`),!1}function wt(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)V(e);let s=r?.getAttribute("alt")??"";if(e.getAttribute("alt")!==s)e.setAttribute("alt",s);return r?s:!1}var dr='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function fr(e){return e.querySelectorAll?.(dr)?.[0]??null}function Ae(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 We=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"}),Be=Object.freeze(["meta","ctrl","alt","shift"]);function Y(e,t,r){let n=e.split("+");for(let a of Be)if(n.includes(a)!==Boolean(t[`${a}Key`]))return!1;let i=n.find((a)=>!Be.includes(a));if(i===void 0||typeof t.key!=="string")return!0;let s=r&&Object.hasOwn(r,i)?r[i]:Object.hasOwn(We,i)?We[i]:/^[a-z0-9]$/.test(i)?i:null;return typeof s==="string"&&s.toLowerCase()===t.key.toLowerCase()}var hr=(e)=>e&&typeof e==="object"?e.keys:String(e);function ie(e,t,r){let n=t.target;if(e?.inEditable!==!0&&(n?.isContentEditable||/^(input|textarea|select)$/.test(n?.localName)))return!1;let i=/[Mm]ac|iP/.test(navigator.userAgentData?.platform??navigator.platform)?"meta":"ctrl";return Y(hr(e).replace(/^mod\+/,`${i}+`),t,r)}function mr(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:Ae(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)!==Ee(t.currentTarget))return!1;return i<0||r===null||Y(n.slice(i+1),t,r)}function pr(e,t){let r=e.detail;if(r===void 0)return!0;if(r===null||typeof r!=="object"||Array.isArray(r))return!1;let n=t.detail;if(n===null||typeof n!=="object")return!1;return Object.keys(r).every((i)=>n[i]===r[i])}var Ue=new WeakMap;function gr(e,t,r){if(!r.once)return!1;let n=t.currentTarget??e.element,i=Ue.get(e);if(!i)i=new WeakMap,Ue.set(e,i);let 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 Je=new WeakMap;function br(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=Je.get(e);if(!i)i=new WeakMap,Je.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 de(e,t,r){for(let n of e){if(!Array.isArray(n))continue;let[i,s={}]=n;if(!Object.hasOwn($e,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($e[i](o,s,t),s?.keep===!0)Qe(o,i,s,t)}}function yr(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 vr(e){let t=e.getAttribute?.("data-reactive-persist");return Boolean(t)&&t!=="off"}function Se(e){return["defer-token","defer-src","lazy-on","lazy-visible"].some((t)=>e.getAttribute?.(`data-reactive-${t}`)!=null)}var He='[data-controller~="reactive"]',_r='[data-controller~="reactive"],[data-reactive-dormant~="reactive"]',fe=(e)=>e.getAttribute?.("data-reactive-token-value")==null&&!Se(e);function Ke(e,t,r){let n=e?.closest?.(t);while(n&&n!==r&&fe(n))n=n.parentElement?.closest?.(t);return n??null}var D=new WeakMap,q=new WeakMap;function wr(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 Ar(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 Sr(e){return e.getAttribute?.("data-reactive-compute-inputs-param")!=null}function Er(e){return Boolean(e.matches?.("[data-reactive-sortable],[data-reactive-sortable-source]")||e.querySelector?.("[data-reactive-sortable],[data-reactive-sortable-source]"))}function Tr(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 At(e){return e.getAttribute?.("data-reactive-presence")!=null}function Fr(e){return Boolean(e.matches?.("[data-reactive-countdown]")||e.querySelector?.("[data-reactive-countdown]"))}var kr=[["persist",[vr,null,null,!0]],["defer",[Se,null]],["form",[wr,null]],["bindings",[Ar,null,null,!0]],["compute",[Sr,null,null,!0]],["sortable",[Er,null]],["drag",[Tr,null]],["presence",[At,null]],["countdown",[Fr,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(kr),ze=new Map,p=new Map,Lr=new Map;function g(e,t,r){St.set(e,[t,r]),Rr(e)}var St=new Map;function Rr(e){let t=w.get(e),[r,n]=St.get(e);t[1]=r,t[2]=n}function Xr(e,t){t.install?.(I),p.set(e,t),Lr.set(e,t)}function Et(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 Tt(e){return O(e).catch((t)=>z(e,"load",t))}function O(e){let t=ze.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)),ze.set(e,t);return t}var Ge=new Set;function z(e,t,r){let n=e+t;if(Ge.has(n))return;Ge.add(n),console.error(`[phlex-reactive] the "${e}" feature module (phlex/reactive/features/${e}) is unavailable: ${t}. If you bundle or vendor the client, alias or pin phlex/reactive/features/* (README: esbuild / webpack / bun).`,r)}function y(e,t){let r=p.get(e);if(r)return t(r);O(e).then(t,(n)=>z(e,"load",n))}var xr=1e4;function oe(){let e=Number(globalThis.document?.head?.querySelector?.('meta[name="phlex-reactive-feature-timeout"]')?.content);return Number.isFinite(e)&&e>0?e:xr}function Zr(){return[...w.keys()]}var Ve=Promise.resolve();function Ye(e,t,r){let n=I.waiting.get(e);if(n&&n[t]===r)delete n[t]}var I={enter:lt,exit:dt,count:mt,text:E,served:we,waiting:new WeakMap};var P=Symbol.for("phlex-reactive.early"),Nr=1e4,Or=1500,Ee=(e)=>e!=null&&(e===globalThis.window||e.window===e),Ir="dispatch";function se(){return globalThis[P]??={queue:[],connected:new WeakSet},globalThis[P]}function Pr(){let e=Number(globalThis.document?.querySelector?.('meta[name="phlex-reactive-early-ttl"]')?.content);return Number.isFinite(e)&&e>0?e:Nr}function Mr(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 Cr(e,t,r){return{[P]:!0,type:e.type,detail:e.detail,target:e.target,currentTarget:r?t.ownerDocument.defaultView:t,params:Mr(t),key:e.key,code:e.code,metaKey:e.metaKey,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,button:e.button,submitter:e.submitter,bubbles:e.bubbles,timeStamp:e.timeStamp,defaultPrevented:e.defaultPrevented,preventDefault(){},stopPropagation(){},stopImmediatePropagation(){}}}var G=new WeakMap;function Dr(e,{token:t,type:r,method:n,filter:i,win:s},a){let o=G.get(e);if(!o)G.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 Xe(e,t,r,n){if(e?.[P])return!1;let i=Ee(e?.currentTarget),s=i?n:e?.currentTarget,a=qr(e,s,i?`@${t}`:t),o=G.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&&!Y(l.filter,e,r))continue;return l.armed=!1,!0}return a}var U=new WeakMap;function $r(e,t,r){let n=U.get(e);if(!n)U.set(e,n=new Map),setTimeout(()=>U.delete(e));let i=n.get(t)??{};n.set(t,i),i[r]=(i[r]??0)+1}function qr(e,t,r){let n=e&&U.get(e)?.get(t);if(!n?.[r])return!1;return n[r]-=1,!0}class Ft extends Lt{static values={token:String};#w;#l=new Map;#d=new Map;#ne;#L;#B;#R=0;#f=new Map;#x=new WeakMap;#t;featuresReady=Ve;#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(gt=!0,se().connected.add(this.element),D.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||Se(this.element))this.#t=(e)=>{if(e.type==="focusin"?!e.target.hasAttribute?.("data-reactive-editable"):e.target!==this.element)return;if(e.type===W)this.#H();this.#U(!0)},this.element.addEventListener?.("turbo:morph-element",this.#t),this.element.addEventListener?.("focusin",this.#t),this.element.addEventListener?.(W,this.#t);this.element.querySelectorAll?.("[data-reactive-editable]").forEach(_e),this.#g++,this.featuresReady=Ve,this.#U(),J(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 ${oe()} ms`));n(null)},oe());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)Ye(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)=>de(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:st,text:E,served:we,copyMedia:wt,setValue:_t,confirm:(e,t)=>Promise.resolve().then(()=>Fe(e,t)).catch(()=>!1)},this.#j}#H(){this.#r.get("form")?.reseed(this),this.#r.get("bindings")?.reseed(this),this.#r.get("compute")?.seed(this)}#b(e,t,r){if(z(e,t,r),this.#i("feature"),t==="load"&&this.element.getAttribute?.("data-reactive-defer-pending"))this.element.removeAttribute("data-reactive-defer-pending"),this.element.removeAttribute("aria-busy");this.#o("reactive:error",{kind:"feature",feature:e,phase:t,error:r})}#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),Ye(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 q.get(this.element)??[]){if(e.currentTarget!==t)Object.defineProperty(e,"currentTarget",{value:t,configurable:!0});this.dispatch(e)}q.delete(this.element)}#I=new Set;#ce(){let{queue:e}=se();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=Pr(),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(Or,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=Cr(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&&!Y(c.filter,e,s))continue;if(/#\w+.*:once\b/.test(c.token)){if(!Dr(o,c,n&&JSON.stringify(i.params)))continue;this.#I.add(o)}if($r(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?.(W,this.#t);if(se().connected.delete(this.element),D.get(this.element)===this)D.delete(this.element);this.element.removeAttribute?.("data-reactive-connected");for(let e of this.#I)G.delete(e);this.#I.clear()}dispatch(e){if(e.params?.action&&e.params.action!==Me&&this.#le())return this.#de(e);let t=e.params?.shortcut;if(t!=null&&!ie(t,e,this.application?.schema?.keyMappings))return;if(Xe(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))e.preventDefault();if(r===Me){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(()=>Fe(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)=>(z(e,"load",r),null)),new Promise((r)=>t=setTimeout(()=>r(null),oe()))]).finally(()=>clearTimeout(t))}}#le(){return!this.tokenValue&&fe(this.element)}#de(e){let t=Ke(this.element.parentElement,_r);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=D.get(t);if(r)return r.dispatch(e);let{shortcut:n,window:i,optimistic:s}=e.params,a=e.currentTarget??e.target;if((n!=null||!i)&&!this.#te(s,a))e.preventDefault();q.set(t,[...q.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&&!ie(t.shortcut,e,this.application?.schema?.keyMappings))return;if(Xe(e,"runOps",this.application?.schema?.keyMappings,this.element))return;if(br(e,this))return;let r=e.params??{},n=e.currentTarget??e.target,i=mr(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(!pr(o,e))continue;if(o.shortcut!=null&&!ie(o.shortcut,e,this.application?.schema?.keyMappings))continue;if(gr(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)t.preventDefault();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,Ir,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(!Ee(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(ct())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=At(this.element)&&document.getElementById(`reactive-presence-src-${this.element.id}`)?.getAttribute("connection-id");if(M)m["X-Reactive-Presence"]=M;let Te=Jt(this.element);if(Te)m["X-Reactive-Held"]=Te;mt("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));Pe(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(Pe(this.element,v,Ht(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=Xt(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(He);if(e.length===0||[...e].every(fe))return()=>!0;return(t)=>Ke(t,He,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]${rr}`).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("[]")&&!ir(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 Ae(e)}#Ne(e){de(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),lt();let n=!1;return()=>{if(n)return;n=!0,this.#Pe(e,t),dt();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)De();else document.addEventListener("turbo:load",De,{once:!0});g("persist",()=>import("phlex/reactive/features/persist"),Wr);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"),Br);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"));ve();function Wr(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 Br(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,kt,X=new Set;function Ur(e){return Tt(e).then((t)=>{if(e!=="effects")return;kt=t,t?.sweep()})}ot((e,t)=>{let r=e.detail,n=r?.render;if(typeof n!=="function")return;let i=r.newStream??e.target,s=Et(Jr(i)).filter((o)=>!X.has(o));if(!t&&!X.has("effects")&&Hr(i))s.push("effects");if(s.length===0&&!F)return t?.wrap(e);if(s.length>0){for(let c of s)X.add(c);let o=F=Promise.race([Promise.all([F,...s.map(Ur)]),new Promise((c)=>setTimeout(c,jr))]).then(()=>{if(F!==o)return;F=null,X.clear()})}let a=F;r.render=async(o)=>{await a;let c={target:e.target,detail:{newStream:r.newStream,render:n}};(t??kt)?.wrap(c),await c.detail.render(o)}});function Jr(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 Hr(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 on=Ft;export{ut as ACTIVE_ATTR,rr as EDITOR_SELECTOR,nr as EDITOR_TAGS,ht as REQUESTS_ATTR,Zt as checkReactiveRegistration,mt as countReactiveRequest,on as default,E as editableValue,lt as enterReactiveActivity,Xt as escapeRegExp,dt as exitReactiveActivity,Tt as loadReactiveFeature,ot as onReactiveStreamWithoutEffects,Vr as reactiveActivityCount,Zr as reactiveFeatureNames,De as registerReactiveActions,Ot as registerReactiveDefer,ve as registerReactiveDev,It as registerReactiveDismiss,It as registerReactiveEffects,Xr as registerReactiveFeature,g as registerReactiveFeatureLoader,qt as registerReactiveImageFallback,Nt as registerReactiveJs,$t as registerReactiveKeep,Dt as registerReactiveModals,Bt as registerReactiveMorphFocus,zt as registerReactiveOffline,Wt as registerReactivePlaintext,It as registerReactiveStreamRender,xt as registerReactiveToken,Rt as registerReactiveVisit,Yr as resetReactiveActivity,we as serverText,Et as unloadedFeaturesFor};
|
|
7
7
|
|
|
8
|
-
//# debugId=
|
|
8
|
+
//# debugId=9B15CE84F7802FED64756E2164756E21
|
|
9
9
|
//# sourceMappingURL=core.min.js.map
|