phlex-reactive 0.16.6 → 0.16.8
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 +70 -1
- data/README.md +62 -6
- data/app/javascript/phlex/reactive/core.min.js +4 -4
- data/app/javascript/phlex/reactive/core.min.js.map +3 -3
- data/app/javascript/phlex/reactive/features/bindings.js +52 -17
- 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/compute.js +32 -4
- data/app/javascript/phlex/reactive/features/compute.min.js +2 -2
- data/app/javascript/phlex/reactive/features/compute.min.js.map +3 -3
- data/app/javascript/phlex/reactive/reactive_controller.min.js +4 -4
- data/app/javascript/phlex/reactive/reactive_controller.min.js.map +5 -5
- data/app/javascript/phlex/reactive/runtime.js +107 -23
- data/lib/phlex/reactive/js.rb +25 -2
- data/lib/phlex/reactive/version.rb +1 -1
- metadata +1 -1
|
@@ -68,6 +68,7 @@ export function connect(controller, core) {
|
|
|
68
68
|
// here, and again from reseed() — a stream can render a root's first show
|
|
69
69
|
// target, filter or nested list into it after connect (issue #356).
|
|
70
70
|
let resetting
|
|
71
|
+
let sharing
|
|
71
72
|
let filtering
|
|
72
73
|
let tagging
|
|
73
74
|
let serializing
|
|
@@ -105,10 +106,11 @@ export function connect(controller, core) {
|
|
|
105
106
|
listen(c, "input change", c.show)
|
|
106
107
|
// The after: gate (issue #396): an owned field's first blur marks its
|
|
107
108
|
// name touched for this controller (a morph keeps it, a new one starts
|
|
108
|
-
// without), and re-syncs once if a binding waits on a blur.
|
|
109
|
+
// without), and re-syncs once if a binding waits on a blur. A shared
|
|
110
|
+
// field just below counts as owned here (issue #440).
|
|
109
111
|
listen(c, "focusout", (event) => {
|
|
110
112
|
const name = event.target?.getAttribute?.("name")
|
|
111
|
-
if (!name || c.touched?.has(name) || !c.core.
|
|
113
|
+
if (!name || c.touched?.has(name) || !c.core.bindingOwns(event.target)) return
|
|
112
114
|
;(c.touched ??= new Set()).add(name)
|
|
113
115
|
if (c.root.querySelector?.("[data-reactive-show-after]")) syncShow(c)
|
|
114
116
|
})
|
|
@@ -151,6 +153,21 @@ export function connect(controller, core) {
|
|
|
151
153
|
)
|
|
152
154
|
}
|
|
153
155
|
|
|
156
|
+
// Issue #440: a nested root that comes back through a plain replace (a
|
|
157
|
+
// morph already bubbles turbo:morph-element here) brings a fresh shared
|
|
158
|
+
// field: a hidden disable: true group must disable it again, and the
|
|
159
|
+
// bindings read its new value. So does one whose draft restore wrote its
|
|
160
|
+
// fields without an input event. Each announces itself with a bubbling
|
|
161
|
+
// event; only a root holding a shared field this root reads (one level,
|
|
162
|
+
// core.bindingOwns) re-syncs it.
|
|
163
|
+
if (!sharing && (sharing = c.show || c.arm)) {
|
|
164
|
+
listen(c, "reactive:connect reactive:persist-restored", (event) => {
|
|
165
|
+
if (event.target === c.root || !sharedWith(c, event.target)) return
|
|
166
|
+
c.show?.()
|
|
167
|
+
c.arm?.()
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
154
171
|
// Option filtering (issue #163) — ONLY when the root declares the binding
|
|
155
172
|
// (reactive_filter emits both attrs together), so a component without one
|
|
156
173
|
// pays two attribute reads. ONE delegated input listener on the root — the
|
|
@@ -201,6 +218,11 @@ export function connect(controller, core) {
|
|
|
201
218
|
listen(c, "input", (event) => editableEmptied(c, event))
|
|
202
219
|
}
|
|
203
220
|
|
|
221
|
+
// Whether `root` holds a shared field this root's bindings read (issue #440).
|
|
222
|
+
function sharedWith(c, root) {
|
|
223
|
+
return [...(root.querySelectorAll?.("[data-reactive-shared-field]") ?? [])].some(c.core.bindingOwns)
|
|
224
|
+
}
|
|
225
|
+
|
|
204
226
|
// Remove every listener connect() added, so a stray event after a Turbo
|
|
205
227
|
// morph/navigation never re-evaluates against a detached root.
|
|
206
228
|
export function disconnect(controller) {
|
|
@@ -423,7 +445,7 @@ function syncOnComplete(c, event) {
|
|
|
423
445
|
const bindings = onCompleteBindings(c)
|
|
424
446
|
if (!bindings.length) return
|
|
425
447
|
|
|
426
|
-
const fieldValue = fieldResolver(c, c.core.
|
|
448
|
+
const fieldValue = fieldResolver(c, c.core.bindingOwnership())
|
|
427
449
|
bindings.forEach((binding, i) => {
|
|
428
450
|
const matches = anyOfAllsMatches(binding.any, fieldValue)
|
|
429
451
|
if (matches === null) return
|
|
@@ -443,15 +465,21 @@ function syncOnComplete(c, event) {
|
|
|
443
465
|
// pass). A binding whose field can't be resolved, or whose predicate is
|
|
444
466
|
// malformed, leaves visibility ALONE — a bad binding must never break or
|
|
445
467
|
// blank the page (client-side default-deny).
|
|
468
|
+
//
|
|
469
|
+
// Two predicates (issue #440): `owns` picks the binding ELEMENTS this root
|
|
470
|
+
// evaluates (a nested root's are its own); `reads` picks the FIELDS they read,
|
|
471
|
+
// and the controls disable:/clear: may write: this root's own, plus a control
|
|
472
|
+
// marked data-reactive-shared-field just below (core.bindingOwnership).
|
|
446
473
|
function syncShow(c) {
|
|
447
474
|
if (typeof c.root?.querySelectorAll !== "function") return
|
|
448
475
|
|
|
449
476
|
const owns = c.core.ownership()
|
|
477
|
+
const reads = c.core.bindingOwnership()
|
|
450
478
|
const scope = c.root.getAttribute?.("data-reactive-scope") || null
|
|
451
479
|
// A memoized resolver shared by every binding in this pass — a field driving
|
|
452
480
|
// several bindings (and several DNF terms) reads exactly once. Scope-aware:
|
|
453
481
|
// a bare field `director` resolves as `[name="scope[director]"]` (issue #180).
|
|
454
|
-
const fieldValue = fieldResolver(c,
|
|
482
|
+
const fieldValue = fieldResolver(c, reads)
|
|
455
483
|
// Bindings whose visibility flipped this pass and that declare transition
|
|
456
484
|
// work (issue #394) — run after the pass, so the `input` a clear dispatches
|
|
457
485
|
// re-syncs from fresh values instead of this pass's memo.
|
|
@@ -469,7 +497,7 @@ function syncShow(c) {
|
|
|
469
497
|
// after: (issue #396) keeps it hidden until its field has blurred once.
|
|
470
498
|
const after = el.getAttribute("data-reactive-show-after")
|
|
471
499
|
const visible = match && (after == null || !!c.touched?.has(wireName(after, scope)))
|
|
472
|
-
applyShowVisibility(el, visible,
|
|
500
|
+
applyShowVisibility(el, visible, reads)
|
|
473
501
|
// The previous visibility lives on this controller (absent on connect,
|
|
474
502
|
// kept by a morph), so first paint never counts as a change.
|
|
475
503
|
// Tracked for every binding, so a morph that drops the transition attrs
|
|
@@ -488,17 +516,17 @@ function syncShow(c) {
|
|
|
488
516
|
if (value === null) continue // no owned field with that name — leave it be
|
|
489
517
|
const match = showBindingMatches(el, value)
|
|
490
518
|
if (match === null) continue // malformed predicate — warned + skipped
|
|
491
|
-
applyShowVisibility(el, match,
|
|
519
|
+
applyShowVisibility(el, match, reads)
|
|
492
520
|
}
|
|
493
521
|
|
|
494
522
|
// The group bindings (issue #319) and the cross-root pass (issue #164)
|
|
495
523
|
// share the same owned-field memo, so a field driving several reads once.
|
|
496
524
|
if (c.groups) syncGroups(c, fieldValue, owns, scope)
|
|
497
525
|
syncMedia(c, fieldValue, owns)
|
|
498
|
-
syncCssVars(c, fieldValue, owns, scope)
|
|
526
|
+
syncCssVars(c, fieldValue, owns, scope, reads)
|
|
499
527
|
syncShowTargets(c, fieldValue)
|
|
500
528
|
syncGroupTargets(c, fieldValue)
|
|
501
|
-
for (const el of moved) showMoved(c, el,
|
|
529
|
+
for (const el of moved) showMoved(c, el, reads, scope)
|
|
502
530
|
}
|
|
503
531
|
|
|
504
532
|
// The transition attrs a show binding may declare (issue #394).
|
|
@@ -542,8 +570,9 @@ function showMoved(c, el, owns, scope) {
|
|
|
542
570
|
// the `disabled` of every owned named control inside it) from a match result
|
|
543
571
|
// (issue #180). Disabling a hidden section's controls stops them submitting —
|
|
544
572
|
// the stale-value fix. A visible section re-enables them. Controls a nested
|
|
545
|
-
// reactive root owns are left alone (#15 ownership)
|
|
546
|
-
|
|
573
|
+
// reactive root owns are left alone (#15 ownership), except one marked
|
|
574
|
+
// data-reactive-shared-field: it declared itself the host's too (issue #440).
|
|
575
|
+
function applyShowVisibility(el, match, owns) {
|
|
547
576
|
el.hidden = !match
|
|
548
577
|
if (el.getAttribute("data-reactive-show-disable") !== "true") return
|
|
549
578
|
if (typeof el.querySelectorAll !== "function") return
|
|
@@ -556,8 +585,9 @@ function applyShowVisibility(el, match, owns, scope) {
|
|
|
556
585
|
|
|
557
586
|
// Apply the declared cross-root show targets (issue #164) — the visibility
|
|
558
587
|
// parallel of #applyComputeMirrors. For each declared field: read the OWNED
|
|
559
|
-
// field's current value (never a nested root's
|
|
560
|
-
//
|
|
588
|
+
// field's current value (never a nested root's, except a shared field just
|
|
589
|
+
// below, issue #440 — you can only drive outside visibility from a field this
|
|
590
|
+
// root reads), then for each "#id" → predicate
|
|
561
591
|
// entry: guard the selector id-only (warn-and-skip; the Ruby helper raised
|
|
562
592
|
// at declare time — two-sided default-deny), resolve it DOCUMENT-WIDE, and
|
|
563
593
|
// toggle `hidden`. A target id not on the page is silently skipped (an
|
|
@@ -694,7 +724,9 @@ function wireName(name, scope) {
|
|
|
694
724
|
// The per-pass field resolver every DNF fold reads (show, enable, on-complete).
|
|
695
725
|
// fieldValue(name) is the field's string value; fieldValue(name, true) is how
|
|
696
726
|
// many owned boxes of that checkbox group are ticked (the checked_* terms,
|
|
697
|
-
// issue #319).
|
|
727
|
+
// issue #319). `owns` is what the bindings read: core.bindingOwnership, so a
|
|
728
|
+
// shared field just below counts as owned (issue #440). Memoized, so a field
|
|
729
|
+
// driving several bindings reads once.
|
|
698
730
|
function fieldResolver(c, owns) {
|
|
699
731
|
const scope = c.root.getAttribute?.("data-reactive-scope") || null
|
|
700
732
|
const values = new Map()
|
|
@@ -795,7 +827,7 @@ const CSS_VARS_SELECTOR = "[data-reactive-css-vars]"
|
|
|
795
827
|
const CSS_VAR_NAME = /^--[a-z0-9-]+$/i
|
|
796
828
|
const CSS_VAR_UNITS = ["", "px", "%", "deg", "turn", "ms", "s", "em", "rem", "fr"]
|
|
797
829
|
|
|
798
|
-
function syncCssVars(c, fieldValue, owns, scope) {
|
|
830
|
+
function syncCssVars(c, fieldValue, owns, scope, reads) {
|
|
799
831
|
const nodes = [...c.root.querySelectorAll(CSS_VARS_SELECTOR)].filter(owns)
|
|
800
832
|
if (c.root.hasAttribute("data-reactive-css-vars")) nodes.unshift(c.root)
|
|
801
833
|
for (const el of nodes) {
|
|
@@ -825,7 +857,7 @@ function syncCssVars(c, fieldValue, owns, scope) {
|
|
|
825
857
|
console.warn(`[phlex-reactive] refused reactive_css_vars entry ${JSON.stringify(name)} — skipped`)
|
|
826
858
|
continue
|
|
827
859
|
}
|
|
828
|
-
const number = cssVarNumber(c, fieldValue, spec.field,
|
|
860
|
+
const number = cssVarNumber(c, fieldValue, spec.field, reads, scope)
|
|
829
861
|
if (number === undefined) continue
|
|
830
862
|
const value = number === null ? "" : `${number}${unit}`
|
|
831
863
|
for (const target of targets) {
|
|
@@ -872,7 +904,9 @@ function hasGroups(c) {
|
|
|
872
904
|
}
|
|
873
905
|
|
|
874
906
|
// The owned checkboxes of a group (a nested root's boxes are its own, #15).
|
|
875
|
-
//
|
|
907
|
+
// `owns` decides which: strict for a select-all header and the boxes it
|
|
908
|
+
// ticks; core.bindingOwnership for a count, which takes a shared box just
|
|
909
|
+
// below too (issue #440). With `under` (a nested header, issue #398) only the boxes whose
|
|
876
910
|
// data-reactive-group is that path or below it, on whole segments.
|
|
877
911
|
function groupBoxes(c, name, owns, scope, under) {
|
|
878
912
|
return [...c.root.querySelectorAll(namedSelector(name, scope))].filter(
|
|
@@ -957,7 +991,8 @@ function syncGroups(c, fieldValue, owns, scope) {
|
|
|
957
991
|
// The declared cross-root group targets (issue #343) — the count and enable
|
|
958
992
|
// parallel of syncShowTargets, declared on the root that OWNS the group:
|
|
959
993
|
// { group: { count: ["#id", …], enable: { "#id": { any: … } } } }. The count
|
|
960
|
-
// is this root's owned ticked boxes (a nested root's are its own, #15
|
|
994
|
+
// is this root's owned ticked boxes (a nested root's are its own, #15, except
|
|
995
|
+
// a shared box just below, issue #440), the
|
|
961
996
|
// enable folds its DNF payload with the same owned-field memo as every other
|
|
962
997
|
// binding. Targets are id-only (warn-skip — the Ruby helper raised at
|
|
963
998
|
// declare time) and resolved document-wide; a missing one is skipped.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{confirmPredicate as de}from"phlex/reactive/confirm_predicate";var v=new WeakMap,k=new WeakMap;function h(e,r){let t=v.get(e);if(!t){if(v.set(e,t={root:e.element,core:r,nestedIndex:0}),t.root)k.set(t.root,t)}return t}function g(e,r,t){for(let n of r.split(" "))e.root.addEventListener?.(n,t),e.offs.push(()=>e.root.removeEventListener?.(n,t))}function b(e,r){g(e,"turbo:morph-element",r),e.seeds.push(r),r()}function ot(e,r){let t=h(e,r);t.offs=[],t.seeds=[];let n,o,i,a;(t.wire=()=>{if(!t.show&&ve(t))t.show=(s)=>{if(t.flipping)return;if(s?.type==="input"||s?.type==="change")Re(t,s.target);else t.groups=Ee(t),F(t);L(t)},g(t,"input change",t.show),g(t,"focusout",(s)=>{let c=s.target?.getAttribute?.("name");if(!c||t.touched?.has(c)||!t.core.owns(s.target))return;if((t.touched??=new Set).add(c),t.root.querySelector?.("[data-reactive-show-after]"))L(t)}),b(t,t.show);if(!t.arm&&me(t))g(t,"input change",(s)=>D(t,s)),b(t,t.arm=()=>{D(t,null),F(t)});if(!n&&(n=t.show||t.arm))g(t,"reset",()=>setTimeout(()=>{if(v.get(e)!==t)return;t.show?.(),t.arm?.()},0));if(!o&&(o=x(t)))g(t,"input",(s)=>Te(t,s)&&A(t)),b(t,()=>A(t));if(!i&&(i=N(t)))b(t,()=>te(t));if(!a&&(a=De(t)))g(t,"input change",(s)=>ie(t,s)),b(t,()=>T(t))})(),g(t,"keydown",(s)=>et(t,s)),g(t,"paste drop",(s)=>tt(t,s)),g(t,"input",(s)=>rt(t,s))}function it(e){let r=v.get(e);if(!r)return;v.delete(e),k.delete(r.root);for(let t of r.offs??[])t();r.groupObserver?.disconnect()}function st(e){let r=v.get(e);if(!r)return;for(let t of r.seeds)t();r.wire()}function y(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function at(e,r,t){return ie(h(e,r),t)}function ct(e,r,t){return ue(h(e,r),t)}var pe=/^#[A-Za-z_][\w-]*$/,K="[data-reactive-show-field], [data-reactive-show]";function ge(e,r){let t=e.getAttribute("data-reactive-show-equals");if(t!==null)return r===t;let n=e.getAttribute("data-reactive-show-not");if(n!==null)return r!==n;let o=e.getAttribute("data-reactive-show-in");if(o!==null){try{let i=JSON.parse(o);if(Array.isArray(i))return i.includes(r)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(o)} — skipped`),null}for(let i of se){let a=e.getAttribute(`data-reactive-show-${i}`);if(a!==null)return ce(i,a,r)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}function H(e){try{let r=JSON.parse(e);if(r&&typeof r==="object"&&!Array.isArray(r))return r}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(e)} — skipped`),null}function he(e){try{let r=JSON.parse(e);if(Array.isArray(r)&&r.every((t)=>t&&typeof t==="object"&&Array.isArray(t.any)&&Array.isArray(t.ops)))return r}catch{}return console.warn(`[phlex-reactive] malformed reactive_on_complete payload ${JSON.stringify(e)} — skipped`),[]}function V(e,r){if(!e||typeof e!=="object")return null;let t=e.any;if(Array.isArray(t)&&(t.length===0||Array.isArray(t[0])))return w(t,r);return ye(e,r)}function ye(e,r){let t=Array.isArray(e.all)?"all":Array.isArray(e.any)?"any":null;if(!t)return null;let n=e[t];if(n.length===0)return null;let o=n.map((i)=>J(i,r));return t==="all"?o.every(Boolean):o.some(Boolean)}function S(e,r="show"){if(typeof e==="string"&&pe.test(e))return!0;return console.warn(`[phlex-reactive] refused cross-root ${r} target ${JSON.stringify(e)} — skipped`),!1}function ve(e){if(e.root.getAttribute?.("data-reactive-show-targets"))return!0;if(e.root.getAttribute?.("data-reactive-group-targets"))return!0;let r=e.root.querySelectorAll?.(K)??[];for(let t of r)if(e.core.owns(t))return!0;for(let t of e.root.querySelectorAll?.(_)??[])if(e.core.owns(t))return!0;for(let t of e.root.querySelectorAll?.(`${U}, ${Z}`)??[])if(e.core.owns(t))return!0;return e.root.hasAttribute?.("data-reactive-css-vars")??!1}function me(e){return!!e.root.getAttribute?.("data-reactive-on-complete")}function be(e){let r=e.root.getAttribute?.("data-reactive-on-complete")??null;if(r!==e.onCompleteRaw)e.onCompleteRaw=r,e.onCompleteParsed=r==null?[]:he(r),e.onCompleteStates=e.onCompleteParsed.map(()=>!1);return e.onCompleteParsed}function D(e,r){let t=be(e);if(!t.length)return;let n=Y(e,e.core.ownership());t.forEach((o,i)=>{let a=w(o.any,n);if(a===null)return;let s=a&&!e.onCompleteStates[i]&&Boolean(r);if(e.onCompleteStates[i]=a,s)e.core.applyOps(o.ops,"@root")})}function L(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.core.ownership(),t=e.root.getAttribute?.("data-reactive-scope")||null,n=Y(e,r),o=[];for(let i of e.root.querySelectorAll(K)){if(!r(i))continue;let a=i.getAttribute("data-reactive-show");if(a!==null){let u=V(H(a),n);if(u===null)continue;let d=i.getAttribute("data-reactive-show-after"),f=u&&(d==null||!!e.touched?.has(E(d,t)));W(i,f,r,t);let p=(e.shown??=new WeakMap).get(i);if(e.shown.set(i,f),Ae.some((fe)=>i.hasAttribute(`data-reactive-show-${fe}`))&&p!==void 0&&p!==f)o.push(i);continue}let s=i.getAttribute("data-reactive-show-field");if(!s)continue;let c=n(s);if(c===null)continue;let l=ge(i,c);if(l===null)continue;W(i,l,r,t)}if(e.groups)je(e,n,r,t);Ne(e,n,r),ke(e,n,r,t),Se(e,n),Me(e,n);for(let i of o)we(e,i,r,t)}var Ae=["clear","focus","scroll"];function we(e,r,t,n){if(r.hidden){let s=[];try{s=JSON.parse(r.getAttribute("data-reactive-show-clear")??"[]")}catch{}let c=new Set((Array.isArray(s)?s:[]).map((l)=>E(String(l),n)));for(let l of c.size?e.root.querySelectorAll("[name]"):[]){if(!c.has(l.getAttribute("name"))||!t(l)||l.type==="file")continue;if(l.type==="checkbox"||l.type==="radio"){if(l.checked)l.checked=!1,y(l)}else e.core.setValue(l,"")}return}let o=r.getAttribute("data-reactive-show-scroll")==="true";if(o)r.scrollIntoView?.({block:"nearest"});let i=r.getAttribute("data-reactive-show-focus"),a=null;try{a=i?e.root.querySelector(i):null}catch{}a?.focus?.(o?{preventScroll:!0}:void 0)}function W(e,r,t,n){if(e.hidden=!r,e.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof e.querySelectorAll!=="function")return;for(let o of e.querySelectorAll("input[name], select[name], textarea[name]"))if(t(o))o.disabled=!r;if(e.name&&t(e))e.disabled=!r}function Se(e,r){let t=z(e);for(let[n,o]of Object.entries(t)){if(n.startsWith("#")){xe(n,o,r);continue}if(!o||typeof o!=="object"||Array.isArray(o))continue;let i=r(n);if(i===null)continue;let a=(s,c)=>c?r(n,!0):i;for(let[s,c]of Object.entries(o)){if(!S(s))continue;let l;if(Array.isArray(c)){if(c.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${s} — skipped`);continue}l=c.every((u)=>J(u,a))}else{let u=le(c,i);if(u===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${s} — skipped`);continue}l=u}for(let u of document.querySelectorAll(s))u.hidden=!l}}}function xe(e,r,t){if(!S(e))return;let n=r&&typeof r==="object"&&!Array.isArray(r)?r.any:null,o=Qe(n);if(o===null){console.warn(`[phlex-reactive] malformed reactive_show_targets conditions for ${e} — skipped`);return}if(o.every((a)=>t(a)===null)&&!Xe(n))return;let i=w(n,t);if(i===null)return;for(let a of document.querySelectorAll(e))a.hidden=!i}function z(e,r="show",t="mode: { ... }, kind: { ... }"){let n=e.root.getAttribute?.(`data-reactive-${r}-targets`);if(!n)return{};try{let o=JSON.parse(n);if(o&&typeof o==="object"&&!Array.isArray(o))return o}catch{}return console.warn(`[phlex-reactive] malformed data-reactive-${r}-targets — ignored. `+`Did two reactive_${r}_targets calls collide on one root? Declare every entry in ONE call: reactive_${r}_targets(${t})`),{}}function _e(e,r,t,n){let o=!1,i=null;for(let a of e.root.querySelectorAll(q(r,n))){if(!t(a))continue;if(a.type==="checkbox")return a.checked?"true":"false";if(a.type==="radio"){if(a.checked)return a.value??"";o=!0;continue}i??=a}if(i)return i.value??"";return o?"":null}function q(e,r){return`[name="${E(e,r)}"]`}function E(e,r){return r&&!e.includes("[")?`${r}[${e}]`:e}function Y(e,r){let t=e.root.getAttribute?.("data-reactive-scope")||null,n=new Map;return(o,i)=>{let a=i?`#${o}`:o;if(!n.has(a))n.set(a,i?R(e,o,r,t).filter((s)=>s.checked).length:_e(e,o,r,t));return n.get(a)}}var U="[data-reactive-media]";function Ne(e,r,t){for(let n of e.root.querySelectorAll(U)){if(!t(n))continue;let o,i,a;try{if(o=JSON.parse(n.getAttribute("data-reactive-media")),o?.match!=null)i=new RegExp(`^(?:${o.match})$`);if(o?.when!=null)a=new RegExp(`^(?:${o.when})$`)}catch{}if(typeof o?.field!=="string"||!o.pool||typeof o.pool!=="object"||o.match!=null&&!i||o.when!=null&&!a){console.warn("[phlex-reactive] malformed data-reactive-media — skipped");continue}let s=r(o.field);if(s===null)continue;let c=o.take>0?[...s]:null,l=c?c.slice(0,o.take).join(""):s,u=c?.length<o.take||i?.test(l)===!1||a?.test(s)===!1;if(u&&o.pending==="keep"){P(n,"pending");continue}let d=!u&&Object.hasOwn(o.pool,l)?G(e,o.pool[l])[0]:null,f=e.core.copyMedia(n,d??null);if(f===null)continue;if(P(n,u?"pending":f===!1?"miss":"hit"),typeof o.label!=="string")continue;let p=u?"":f===!1?String(o.blank??""):f;for(let m of G(e,o.label))if(m.textContent!==p)m.textContent=p}}function P(e,r){if(e.getAttribute("data-reactive-media-state")!==r)e.setAttribute("data-reactive-media-state",r)}function G(e,r){try{return r==="@root"?[]:e.core.opTargets({to:r})}catch{return[]}}var Z="[data-reactive-css-vars]",Ce=/^--[a-z0-9-]+$/i,Oe=["","px","%","deg","turn","ms","s","em","rem","fr"];function ke(e,r,t,n){let o=[...e.root.querySelectorAll(Z)].filter(t);if(e.root.hasAttribute("data-reactive-css-vars"))o.unshift(e.root);for(let i of o){let a;try{a=JSON.parse(i.getAttribute("data-reactive-css-vars"))}catch{}if(!Array.isArray(a?.to)||!a.vars||typeof a.vars!=="object"){console.warn("[phlex-reactive] malformed data-reactive-css-vars — skipped (two reactive_css_vars on one element?)");continue}let s=a.to.flatMap((c)=>{let l={to:c,global:a.global===!0},u=[];try{u=e.core.opTargets(l)}catch{}if(!u.length)e.core.diagnose("reactive_css_vars",l);return u});for(let[c,l]of Object.entries(a.vars)){let u=l?.unit??"";if(!Ce.test(c)||!Oe.includes(u)||typeof l?.field!=="string"){console.warn(`[phlex-reactive] refused reactive_css_vars entry ${JSON.stringify(c)} — skipped`);continue}let d=qe(e,r,l.field,t,n);if(d===void 0)continue;let f=d===null?"":`${d}${u}`;for(let p of s){if(p.style.getPropertyValue(c)===f)continue;if(f)p.style.setProperty(c,f);else p.style.removeProperty(c)}}}}function qe(e,r,t,n,o){let i=r(t);if(i===null)return;if((i==="true"||i==="false")&&[...e.root.querySelectorAll(q(t,o))].some((s)=>n(s)&&s.type==="checkbox"))return i==="true"?1:0;let a=i.trim()?Number(i):NaN;return Number.isFinite(a)?a:null}var _="[data-reactive-enable], [data-reactive-select-all], [data-reactive-count]";function Ee(e){return!!e.root.querySelector?.(_)}function R(e,r,t,n,o){return[...e.root.querySelectorAll(q(r,n))].filter((i)=>i.type==="checkbox"&&t(i)&&(!o||$e(i.getAttribute("data-reactive-group"),o)))}function $e(e,r){return e===r||!!e?.startsWith(`${r}.`)}function Re(e,r){let t=r?.getAttribute?.("data-reactive-select-all");if(t&&e.core.owns(r))Q(e,t,r.checked,r,r.getAttribute("data-reactive-select-all-under"))}function lt(e,r,t){if(!r)return;let n=k.get(e)??{root:e,core:{ownership:()=>(o)=>o.closest('[data-controller~="reactive"]')===e}};Q(n,r,t!==!1),n.show?.()}function Q(e,r,t,n,o){let i=e.root.getAttribute?.("data-reactive-scope")||null,a=R(e,r,e.core.ownership(),i,o).filter((s)=>s!==n&&s.checked!==t);for(let s of a)s.checked=t;e.flipping=!0;try{for(let s of a)for(let c of["input","change"])s.dispatchEvent?.(new Event(c,{bubbles:!0}))}finally{e.flipping=!1}}function je(e,r,t,n){for(let o of e.root.querySelectorAll(_)){if(!t(o))continue;let i=o.getAttribute("data-reactive-enable");if(i!==null){let c=V(H(i),r);if(c!==null)o.disabled=!c}let a=o.getAttribute("data-reactive-count");if(a){let c=String(r(a,!0));if(o.textContent!==c)o.textContent=c}let s=o.getAttribute("data-reactive-select-all");if(s){let c=o.getAttribute("data-reactive-select-all-under"),l=R(e,s,t,n,c).filter((d)=>d!==o),u=l.filter((d)=>d.checked).length;o.checked=u>0&&u===l.length,o.indeterminate=u>0&&u<l.length}}}function Me(e,r){for(let[t,n]of Object.entries(z(e,"group",'"ids[]" => { ... }, "tags[]" => { ... }'))){if(!n||typeof n!=="object"||Array.isArray(n))continue;let o=String(r(t,!0));for(let a of Array.isArray(n.count)?n.count:[]){if(!S(a,"group"))continue;for(let s of document.querySelectorAll(a))if(s.textContent!==o)s.textContent=o}let i=n.enable&&typeof n.enable==="object"?n.enable:{};for(let[a,s]of Object.entries(i)){if(!S(a,"group"))continue;let c=w(s?.any,r);if(c===null){console.warn(`[phlex-reactive] malformed reactive_group_targets enable for ${a} — skipped`);continue}for(let l of document.querySelectorAll(a))l.disabled=!c}}}function F(e){if(e.groupObserver||typeof MutationObserver!=="function")return;let r=(o)=>e.root.getAttribute?.(`data-reactive-${o}`)?.includes("checked_");if(!e.root.getAttribute?.("data-reactive-group-targets")&&!e.root.querySelector?.(`${_}, [data-reactive-show*=checked_]`)&&!r("show-targets")&&!r("on-complete"))return;let n=(o)=>o.nodeType===1&&(o.matches('input[type="checkbox"]')||!!o.querySelector('input[type="checkbox"]'));e.groupObserver=new MutationObserver((o)=>{if(!o.some((i)=>[...i.addedNodes,...i.removedNodes].some(n)))return;e.show?.(),e.arm?.()}),e.groupObserver.observe(e.root,{childList:!0,subtree:!0})}function x(e){return!!(e.root.getAttribute?.("data-reactive-filter-input")&&e.root.getAttribute?.("data-reactive-filter-option"))}function Te(e,r){let t=e.root.getAttribute("data-reactive-filter-input");return!!t&&typeof r.target?.matches==="function"&&r.target.matches(t)}var Je=/[\s\-'(),./]/;function Ie(e,r,t){if(e==="prefix")return r.startsWith(t);if(e!=="word_start")return r.includes(t);for(let n=r.indexOf(t);n!==-1;n=r.indexOf(t,n+1))if(n===0||Je.test(r[n-1]))return!0;return!1}function A(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.root.getAttribute("data-reactive-filter-input"),t=e.root.getAttribute("data-reactive-filter-option");if(!r||!t)return;let n=e.core.ownership(),o=[...e.root.querySelectorAll(r)].find(n);if(!o)return;let i=e.root.getAttribute("data-reactive-filter-match"),a=e.root.hasAttribute?.("data-reactive-filter-fold"),s=(f)=>{let p=(f??"").toLowerCase().trim();return a?p.normalize("NFD").replace(/\p{M}/gu,""):p},c=s(o.value),l=0;for(let f of e.root.querySelectorAll(t)){if(!n(f))continue;let p=f.hasAttribute?.("data-reactive-tags-selected")||c!==""&&!Ie(i,s(f.getAttribute("data-reactive-filter-text")??f.textContent),c);if(f.hidden=p,p)f.removeAttribute("data-reactive-highlighted");else l++}let u=e.root.getAttribute("data-reactive-filter-group");if(u)for(let f of e.root.querySelectorAll(u)){if(!n(f))continue;let p=[...f.querySelectorAll(t)].filter(n);if(p.length===0)continue;f.hidden=p.every((m)=>m.hidden)}let d=e.root.getAttribute("data-reactive-filter-empty");if(d){for(let f of e.root.querySelectorAll(d))if(n(f))f.hidden=l>0}}function N(e){return!!e.root.getAttribute?.("data-reactive-tags-field")}function De(e){if(typeof e.root?.querySelector!=="function")return!1;return!!e.root.querySelector("[data-reactive-nested-json]")}function j(e){if(typeof e.root?.querySelectorAll!=="function")return null;let r=e.root.getAttribute("data-reactive-tags-field");if(!r)return null;let t=e.core.ownership();return[...e.root.querySelectorAll(r)].find(t)??null}function M(e){let r=new Set,t=[];for(let n of String(e.value??"").split(",")){let o=n.trim();if(o===""||r.has(o.toLowerCase()))continue;r.add(o.toLowerCase()),t.push(o)}return t}function X(e,r){let t=j(e);if(!t)return!1;let n=M(t),o=new Set(n.map((a)=>a.toLowerCase())),i=!1;for(let a of r){let s=String(a??"").trim();if(s===""||o.has(s.toLowerCase()))continue;o.add(s.toLowerCase()),n.push(s),i=!0}if(i)ee(e,t,n);return i}function ee(e,r,t){r.value=t.join(","),y(r),te(e)}function Le(e){if(typeof e.root?.querySelectorAll!=="function")return null;let r=e.root.getAttribute("data-reactive-filter-input");if(!r)return null;let t=e.core.ownership();return[...e.root.querySelectorAll(r)].find(t)??null}function te(e){let r=j(e);if(!r)return;let t=M(r),n=e.core.ownership();We(e,t,n),Pe(e,t,n)}function We(e,r,t){let n=[...e.root.querySelectorAll("[data-reactive-tags-list]")].find(t);if(!n)return;let i=[...e.root.querySelectorAll("[data-reactive-tags-template]")].find(t)?.content?.firstElementChild;if(!i){if(!e.tagsWarnedTemplate)console.warn("[phlex-reactive] reactive_tags: no chip <template data-reactive-tags-template> found in this root — "+"chips will not render (the hidden field still updates). Add a template with a [data-reactive-tag-text] node and a reactive_tags_remove button."),e.tagsWarnedTemplate=!0;return}while(n.firstChild)n.removeChild(n.firstChild);for(let a of r){let s=i.cloneNode(!0);s.setAttribute?.("data-reactive-tag",a);let c=s.matches?.("[data-reactive-tag-text]")?s:(s.querySelectorAll?.("[data-reactive-tag-text]")??[])[0];if(c)c.textContent=a;let l=[...s.querySelectorAll?.('[data-action*="reactive#tagsRemove"]')??[]];if(s.matches?.('[data-action*="reactive#tagsRemove"]'))l.push(s);for(let u of l)u.setAttribute?.("data-reactive-tag-param",a);n.appendChild(s)}}function Pe(e,r,t){let n=new Set(r.map((o)=>o.toLowerCase()));for(let o of e.root.querySelectorAll("[role=option]")){if(!t(o))continue;let i=o.getAttribute?.("data-reactive-tag-param");if(!i)continue;if(n.has(i.toLowerCase()))o.setAttribute("data-reactive-tags-selected","true"),o.hidden=!0,o.removeAttribute?.("data-reactive-highlighted");else if(o.hasAttribute?.("data-reactive-tags-selected")){if(o.removeAttribute("data-reactive-tags-selected"),!x(e))o.hidden=!1}}if(x(e))A(e)}function Ge(e){return e.nestedIndex=Math.max(e.nestedIndex+1,Date.now()),e.nestedIndex}function Fe(e,r){let t=[e,...e.querySelectorAll?.("*")??[]];for(let n of t)for(let o of["name","id","for"]){let i=n.getAttribute?.(o);if(i&&i.includes("NEW_ROW"))n.setAttribute?.(o,i.replaceAll("NEW_ROW",String(r)))}}function Be(e,r){if(e.nestedWarned)return;console.warn(`[phlex-reactive] nested rows: no owned [data-reactive-nested-list="${r}"] container + <template data-reactive-nested-template="${r}"> pair found in this root — the add `+"trigger did nothing. Render both inside the same reactive root (reactive_nested_list / reactive_nested_template)."),e.nestedWarned=!0}function Ke(e,r,t,n){if(!t)return null;let o;try{o=JSON.parse(t)}catch{return null}if(!o||typeof o!=="object")return null;let i=e.core.ownership(),a=[...r.querySelectorAll?.("input, select, textarea")??[]],s=[];for(let[c,l]of Object.entries(o)){let u=[...e.root.querySelectorAll?.(l)??[]].find(i);if(!u)continue;let d=a.find((f)=>ne(f.getAttribute?.("name"))===c);if(!d)continue;He(d,u),s.push(u)}if(n)for(let c of s)Ve(c);return s[0]??null}function He(e,r){if(e.type==="checkbox")e.checked=r.type==="checkbox"?!!r.checked:C(r)!=="";else e.value=C(r);y(e)}function Ve(e){if(e.type==="checkbox")e.checked=!1;else e.value="";y(e)}function ze(e,r){if(!e.includes("%{"))return e;return e.replace(/%\{(\w+)\}/g,(t,n)=>Object.prototype.hasOwnProperty.call(r,n)?r[n]:t)}function B(e,r){let t=[...r.querySelectorAll?.('input[name$="[_destroy]"]')??[]][0];if(t)t.value="1",y(t),r.hidden=!0;else r.parentNode?.removeChild?.(r);T(e)}function T(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.core.ownership();for(let t of[...e.root.querySelectorAll("[data-reactive-nested-json]")].filter(r))oe(e,t.getAttribute("data-reactive-nested-json"))}function Ye(e,r){let t=r.getAttribute?.("data-reactive-nested-json-field");if(!t)return null;let n=e.core.ownership();return[...e.root.querySelectorAll(t)].find(n)??null}function re(e,r){let t={},n=e.core.ownership();for(let o of[...r.querySelectorAll?.("input, select, textarea")??[]]){if(o.matches(":disabled")||o.type==="radio"&&!o.checked||!n(o))continue;let i=ne(o.getAttribute?.("name"));if(i===null||i==="_destroy")continue;t[i]=C(o)}return t}function ne(e){if(!e)return null;let r=e.match(/\[([^\][]+)\]$/);return r?r[1]:e}function C(e){if(e.type==="checkbox")return e.checked?e.value||"on":"";return e.value??""}function oe(e,r){let t=e.core.ownership(),n=[...e.root.querySelectorAll(`[data-reactive-nested-list="${r}"]`)].find(t);if(!n)return;let o=Ye(e,n);if(!o)return;let i=[];for(let s of[...n.querySelectorAll?.("[data-reactive-nested-row]")??[]]){if(!t(s)||s.hidden)continue;i.push(re(e,s))}let a=JSON.stringify(i);if(o.value===a)return;o.value=a,y(o)}function ut(e,r,t){let n=h(e,r);if(!N(n))return;if(t?.defaultPrevented)return;if(n.core.listnavOptions(t).some((a)=>a.hasAttribute?.("data-reactive-highlighted")))return;t?.preventDefault?.();let o=t?.currentTarget??t?.target;if(!o)return;if(!X(n,String(o.value??"").split(",")))return;if(o.value="",x(n))A(n)}function ft(e,r,t){let n=h(e,r);if(!N(n))return;t?.preventDefault?.();let i=(t?.currentTarget??t?.target)?.getAttribute?.("data-reactive-tag-param");if(!i)return;if(!X(n,[i]))return;let a=Le(n);if(!a)return;a.value="",A(n),a.focus?.()}function dt(e,r,t){let n=h(e,r);if(!N(n))return;t?.preventDefault?.();let i=(t?.currentTarget??t?.target)?.getAttribute?.("data-reactive-tag-param");if(!i)return;let a=j(n);if(!a)return;let s=M(a),c=s.filter((l)=>l.toLowerCase()!==i.toLowerCase());if(c.length===s.length)return;ee(n,a,c)}function pt(e,r,t){let n=h(e,r);t?.preventDefault?.();let o=t?.currentTarget??t?.target,i=o?.getAttribute?.("data-reactive-association-param");if(!i)return;if(typeof n.root?.querySelectorAll!=="function")return;let a=n.core.ownership(),s=[...n.root.querySelectorAll(`[data-reactive-nested-list="${i}"]`)].find(a),l=[...n.root.querySelectorAll(`[data-reactive-nested-template="${i}"]`)].find(a)?.content?.firstElementChild;if(!s||!l){Be(n,i);return}let u=l.cloneNode(!0);Fe(u,Ge(n)),s.appendChild(u);let d=o?.getAttribute?.("data-reactive-nested-from-param"),f=o?.getAttribute?.("data-reactive-nested-clear-param")==="true",p=Ke(n,u,d,f);if(d)p?.focus?.();else[...u.querySelectorAll?.("input, select, textarea")??[]][0]?.focus?.();if(s.getAttribute?.("data-reactive-nested-json")===i)oe(n,i)}function gt(e,r,t){let n=h(e,r);t?.preventDefault?.();let o=t?.currentTarget??t?.target,i=o?.closest?.("[data-reactive-nested-row]");if(!i)return;if(i.closest?.('[data-controller~="reactive"]')!==n.root)return;let a=o?.getAttribute?.("data-reactive-confirm-param"),s=o?.getAttribute?.("data-reactive-confirm-when-param"),c=a||(s?ue(n,s):null);if(!c)return B(n,i);let l=re(n,i),u=ze(c,l);return n.core.confirm(u,{el:o,row:i,fields:l}).then((d)=>{if(d)B(n,i)})}function ie(e,r){let t=r?.target;if(!t||!e.core.owns(t))return;T(e)}var se=["gte","gt","lte","lt"],Ue=["len_eq","len_gte","len_gt","len_lte","len_lt"],ae=["checked_eq","checked_gte","checked_gt","checked_lte","checked_lt"],Ze=["digits_eq","digits_gte","digits_lt","digits_lte"];function O(e,r,t){if(!Number.isInteger(r))return console.warn(`[phlex-reactive] reactive_show ${e}: needs an integer literal, got ${JSON.stringify(r)} — skipped`),null;switch(e.slice(e.indexOf("_")+1)){case"eq":return t===r;case"gte":return t>=r;case"gt":return t>r;case"lte":return t<=r;case"lt":return t<r;default:return null}}function ce(e,r,t){let n=Number(r);if(Number.isNaN(n))return console.warn(`[phlex-reactive] reactive_show ${e}: needs a numeric literal, got ${JSON.stringify(r)} — skipped`),null;let o=t==null?"":String(t).trim(),i=o===""?NaN:Number(o);if(Number.isNaN(i))return!1;switch(e){case"gte":return i>=n;case"gt":return i>n;case"lte":return i<=n;case"lt":return i<n;default:return null}}function le(e,r){if(!e||typeof e!=="object")return null;if(typeof e.equals==="string")return r===e.equals;if(typeof e.not==="string")return r!==e.not;if(Array.isArray(e.in))return e.in.includes(r);for(let t of se)if(t in e)return ce(t,e[t],r);for(let t of Ue)if(t in e)return O(t,e[t],[...String(r??"")].length);return null}function J(e,r){if(!e||typeof e!=="object"||typeof e.field!=="string")return!1;let t=ae.find((i)=>(i in e));if(t){let i=r(e.field,!0);return O(t,e[t],Array.isArray(i)?i.length:Number(i)||0)===!0}if(typeof e.same==="string"){let i=(a)=>{let s=String(r(a)??"");return e.fold===!0?s.replace(/[A-Z]/g,(c)=>String.fromCharCode(c.charCodeAt(0)+32)):s};return i(e.field)===i(e.same)!==(e.negate===!0)}let n=Ze.filter((i)=>(i in e));if(n.length){let i=String(r(e.field)??"");if(!n.every((s)=>Number.isInteger(e[s]))||e.prefix!=null&&typeof e.prefix!=="string")return!1;return(/^[0-9]*$/.test(i)&&n.every((s)=>O(s,e[s],i.length))&&i.startsWith(e.prefix??""))!==(e.negate===!0)}let o=r(e.field)??"";return le(e,o)===!0}function w(e,r){if(!Array.isArray(e)||e.length===0)return null;return e.some((t)=>Array.isArray(t)&&t.length>0&&t.every((n)=>J(n,r)))}function Qe(e){if(!Array.isArray(e)||e.length===0)return null;let r=new Set;for(let t of e){if(!Array.isArray(t))continue;for(let n of t){if(n&&typeof n==="object"&&typeof n.field==="string")r.add(n.field);if(typeof n?.same==="string")r.add(n.same)}}return r.size>0?[...r]:null}function Xe(e){return e.flat().every((r)=>ae.some((t)=>(t in Object(r))))}function ue(e,r){let t=r;if(typeof r==="string")try{t=JSON.parse(r)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(r)} — skipped`),null}if(!t||typeof t!=="object")return null;let{fields:n}=e.core.collectFields(),o=(a)=>n[a],i;if(typeof t.predicate==="string"){let a=de(t.predicate);if(!a)return console.warn(`[phlex-reactive] confirm predicate "${t.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;i=!!a(n)}else i=w(t.groups?.any,o)===!0;return i?t.message:null}function I(e,r){let t=r.target?.closest?.("[data-reactive-editable]");return t&&e.core.owns(t)?t:null}function et(e,r){let t=I(e,r);if(!t||r.isComposing||r.keyCode===229)return;if(r.key==="Enter"){let n=t.getAttribute("data-reactive-editable-enter");if(t.getAttribute("data-reactive-editable")==="multi"&&(n==null||r.shiftKey))return;if(r.preventDefault(),n==="submit")t.closest("form")?.requestSubmit();else if(n)e.core.applyOps(JSON.parse(n),"@root")}else if(r.key==="Escape"&&t.hasAttribute("data-reactive-editable-escape"))r.preventDefault(),t.textContent=e.core.served(t),y(t),t.blur()}function tt(e,r){let t=I(e,r),n=t?.getAttribute("data-reactive-editable")!=="multi",o=(r.clipboardData??r.dataTransfer)?.getData("text/plain");if(!t||o==null||e.core.plain()&&!(n&&/[\r\n]/.test(o)))return;if(r.preventDefault(),n)o=o.replace(/\r?\n|\r/g," ");t.focus(),document.execCommand("insertText",!1,o)}function rt(e,r){let t=I(e,r);if(t?.firstChild&&e.core.text(t)==="")t.replaceChildren()}export{lt as checkGroup,ct as confirmMessage,ot as connect,it as disconnect,pt as nestedAdd,gt as nestedRemove,st as reseed,at as syncNestedJson,ut as tagsAdd,ft as tagsPick,dt as tagsRemove};
|
|
1
|
+
import{confirmPredicate as de}from"phlex/reactive/confirm_predicate";var m=new WeakMap,k=new WeakMap;function y(e,r){let t=m.get(e);if(!t){if(m.set(e,t={root:e.element,core:r,nestedIndex:0}),t.root)k.set(t.root,t)}return t}function h(e,r,t){for(let n of r.split(" "))e.root.addEventListener?.(n,t),e.offs.push(()=>e.root.removeEventListener?.(n,t))}function b(e,r){h(e,"turbo:morph-element",r),e.seeds.push(r),r()}function st(e,r){let t=y(e,r);t.offs=[],t.seeds=[];let n,o,i,s,a;(t.wire=()=>{if(!t.show&&me(t))t.show=(c)=>{if(t.flipping)return;if(c?.type==="input"||c?.type==="change")je(t,c.target);else t.groups=$e(t),F(t);W(t)},h(t,"input change",t.show),h(t,"focusout",(c)=>{let l=c.target?.getAttribute?.("name");if(!l||t.touched?.has(l)||!t.core.bindingOwns(c.target))return;if((t.touched??=new Set).add(l),t.root.querySelector?.("[data-reactive-show-after]"))W(t)}),b(t,t.show);if(!t.arm&&be(t))h(t,"input change",(c)=>D(t,c)),b(t,t.arm=()=>{D(t,null),F(t)});if(!n&&(n=t.show||t.arm))h(t,"reset",()=>setTimeout(()=>{if(m.get(e)!==t)return;t.show?.(),t.arm?.()},0));if(!o&&(o=t.show||t.arm))h(t,"reactive:connect reactive:persist-restored",(c)=>{if(c.target===t.root||!pe(t,c.target))return;t.show?.(),t.arm?.()});if(!i&&(i=x(t)))h(t,"input",(c)=>Je(t,c)&&A(t)),b(t,()=>A(t));if(!s&&(s=O(t)))b(t,()=>te(t));if(!a&&(a=We(t)))h(t,"input change",(c)=>ie(t,c)),b(t,()=>T(t))})(),h(t,"keydown",(c)=>tt(t,c)),h(t,"paste drop",(c)=>rt(t,c)),h(t,"input",(c)=>nt(t,c))}function pe(e,r){return[...r.querySelectorAll?.("[data-reactive-shared-field]")??[]].some(e.core.bindingOwns)}function at(e){let r=m.get(e);if(!r)return;m.delete(e),k.delete(r.root);for(let t of r.offs??[])t();r.groupObserver?.disconnect()}function ct(e){let r=m.get(e);if(!r)return;for(let t of r.seeds)t();r.wire()}function v(e){if(typeof e.dispatchEvent==="function")e.dispatchEvent(new Event("input",{bubbles:!0}))}function lt(e,r,t){return ie(y(e,r),t)}function ut(e,r,t){return ue(y(e,r),t)}var ge=/^#[A-Za-z_][\w-]*$/,K="[data-reactive-show-field], [data-reactive-show]";function he(e,r){let t=e.getAttribute("data-reactive-show-equals");if(t!==null)return r===t;let n=e.getAttribute("data-reactive-show-not");if(n!==null)return r!==n;let o=e.getAttribute("data-reactive-show-in");if(o!==null){try{let i=JSON.parse(o);if(Array.isArray(i))return i.includes(r)}catch{}return console.warn(`[phlex-reactive] malformed reactive_show in: list ${JSON.stringify(o)} — skipped`),null}for(let i of se){let s=e.getAttribute(`data-reactive-show-${i}`);if(s!==null)return ce(i,s,r)}return console.warn("[phlex-reactive] a reactive_show binding declares no predicate — skipped"),null}function H(e){try{let r=JSON.parse(e);if(r&&typeof r==="object"&&!Array.isArray(r))return r}catch{}return console.warn(`[phlex-reactive] malformed compound reactive_show payload ${JSON.stringify(e)} — skipped`),null}function ye(e){try{let r=JSON.parse(e);if(Array.isArray(r)&&r.every((t)=>t&&typeof t==="object"&&Array.isArray(t.any)&&Array.isArray(t.ops)))return r}catch{}return console.warn(`[phlex-reactive] malformed reactive_on_complete payload ${JSON.stringify(e)} — skipped`),[]}function V(e,r){if(!e||typeof e!=="object")return null;let t=e.any;if(Array.isArray(t)&&(t.length===0||Array.isArray(t[0])))return w(t,r);return ve(e,r)}function ve(e,r){let t=Array.isArray(e.all)?"all":Array.isArray(e.any)?"any":null;if(!t)return null;let n=e[t];if(n.length===0)return null;let o=n.map((i)=>J(i,r));return t==="all"?o.every(Boolean):o.some(Boolean)}function S(e,r="show"){if(typeof e==="string"&&ge.test(e))return!0;return console.warn(`[phlex-reactive] refused cross-root ${r} target ${JSON.stringify(e)} — skipped`),!1}function me(e){if(e.root.getAttribute?.("data-reactive-show-targets"))return!0;if(e.root.getAttribute?.("data-reactive-group-targets"))return!0;let r=e.root.querySelectorAll?.(K)??[];for(let t of r)if(e.core.owns(t))return!0;for(let t of e.root.querySelectorAll?.(_)??[])if(e.core.owns(t))return!0;for(let t of e.root.querySelectorAll?.(`${U}, ${Z}`)??[])if(e.core.owns(t))return!0;return e.root.hasAttribute?.("data-reactive-css-vars")??!1}function be(e){return!!e.root.getAttribute?.("data-reactive-on-complete")}function Ae(e){let r=e.root.getAttribute?.("data-reactive-on-complete")??null;if(r!==e.onCompleteRaw)e.onCompleteRaw=r,e.onCompleteParsed=r==null?[]:ye(r),e.onCompleteStates=e.onCompleteParsed.map(()=>!1);return e.onCompleteParsed}function D(e,r){let t=Ae(e);if(!t.length)return;let n=Y(e,e.core.bindingOwnership());t.forEach((o,i)=>{let s=w(o.any,n);if(s===null)return;let a=s&&!e.onCompleteStates[i]&&Boolean(r);if(e.onCompleteStates[i]=s,a)e.core.applyOps(o.ops,"@root")})}function W(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.core.ownership(),t=e.core.bindingOwnership(),n=e.root.getAttribute?.("data-reactive-scope")||null,o=Y(e,t),i=[];for(let s of e.root.querySelectorAll(K)){if(!r(s))continue;let a=s.getAttribute("data-reactive-show");if(a!==null){let d=V(H(a),o);if(d===null)continue;let f=s.getAttribute("data-reactive-show-after"),p=d&&(f==null||!!e.touched?.has(E(f,n)));L(s,p,t);let g=(e.shown??=new WeakMap).get(s);if(e.shown.set(s,p),we.some((fe)=>s.hasAttribute(`data-reactive-show-${fe}`))&&g!==void 0&&g!==p)i.push(s);continue}let c=s.getAttribute("data-reactive-show-field");if(!c)continue;let l=o(c);if(l===null)continue;let u=he(s,l);if(u===null)continue;L(s,u,t)}if(e.groups)Me(e,o,r,n);Ne(e,o,r),qe(e,o,r,n,t),xe(e,o),Te(e,o);for(let s of i)Se(e,s,t,n)}var we=["clear","focus","scroll"];function Se(e,r,t,n){if(r.hidden){let a=[];try{a=JSON.parse(r.getAttribute("data-reactive-show-clear")??"[]")}catch{}let c=new Set((Array.isArray(a)?a:[]).map((l)=>E(String(l),n)));for(let l of c.size?e.root.querySelectorAll("[name]"):[]){if(!c.has(l.getAttribute("name"))||!t(l)||l.type==="file")continue;if(l.type==="checkbox"||l.type==="radio"){if(l.checked)l.checked=!1,v(l)}else e.core.setValue(l,"")}return}let o=r.getAttribute("data-reactive-show-scroll")==="true";if(o)r.scrollIntoView?.({block:"nearest"});let i=r.getAttribute("data-reactive-show-focus"),s=null;try{s=i?e.root.querySelector(i):null}catch{}s?.focus?.(o?{preventScroll:!0}:void 0)}function L(e,r,t){if(e.hidden=!r,e.getAttribute("data-reactive-show-disable")!=="true")return;if(typeof e.querySelectorAll!=="function")return;for(let n of e.querySelectorAll("input[name], select[name], textarea[name]"))if(t(n))n.disabled=!r;if(e.name&&t(e))e.disabled=!r}function xe(e,r){let t=z(e);for(let[n,o]of Object.entries(t)){if(n.startsWith("#")){_e(n,o,r);continue}if(!o||typeof o!=="object"||Array.isArray(o))continue;let i=r(n);if(i===null)continue;let s=(a,c)=>c?r(n,!0):i;for(let[a,c]of Object.entries(o)){if(!S(a))continue;let l;if(Array.isArray(c)){if(c.length===0){console.warn(`[phlex-reactive] malformed reactive_show_targets group for ${a} — skipped`);continue}l=c.every((u)=>J(u,s))}else{let u=le(c,i);if(u===null){console.warn(`[phlex-reactive] malformed reactive_show_targets predicate for ${a} — skipped`);continue}l=u}for(let u of document.querySelectorAll(a))u.hidden=!l}}}function _e(e,r,t){if(!S(e))return;let n=r&&typeof r==="object"&&!Array.isArray(r)?r.any:null,o=Xe(n);if(o===null){console.warn(`[phlex-reactive] malformed reactive_show_targets conditions for ${e} — skipped`);return}if(o.every((s)=>t(s)===null)&&!et(n))return;let i=w(n,t);if(i===null)return;for(let s of document.querySelectorAll(e))s.hidden=!i}function z(e,r="show",t="mode: { ... }, kind: { ... }"){let n=e.root.getAttribute?.(`data-reactive-${r}-targets`);if(!n)return{};try{let o=JSON.parse(n);if(o&&typeof o==="object"&&!Array.isArray(o))return o}catch{}return console.warn(`[phlex-reactive] malformed data-reactive-${r}-targets — ignored. `+`Did two reactive_${r}_targets calls collide on one root? Declare every entry in ONE call: reactive_${r}_targets(${t})`),{}}function Oe(e,r,t,n){let o=!1,i=null;for(let s of e.root.querySelectorAll(q(r,n))){if(!t(s))continue;if(s.type==="checkbox")return s.checked?"true":"false";if(s.type==="radio"){if(s.checked)return s.value??"";o=!0;continue}i??=s}if(i)return i.value??"";return o?"":null}function q(e,r){return`[name="${E(e,r)}"]`}function E(e,r){return r&&!e.includes("[")?`${r}[${e}]`:e}function Y(e,r){let t=e.root.getAttribute?.("data-reactive-scope")||null,n=new Map;return(o,i)=>{let s=i?`#${o}`:o;if(!n.has(s))n.set(s,i?R(e,o,r,t).filter((a)=>a.checked).length:Oe(e,o,r,t));return n.get(s)}}var U="[data-reactive-media]";function Ne(e,r,t){for(let n of e.root.querySelectorAll(U)){if(!t(n))continue;let o,i,s;try{if(o=JSON.parse(n.getAttribute("data-reactive-media")),o?.match!=null)i=new RegExp(`^(?:${o.match})$`);if(o?.when!=null)s=new RegExp(`^(?:${o.when})$`)}catch{}if(typeof o?.field!=="string"||!o.pool||typeof o.pool!=="object"||o.match!=null&&!i||o.when!=null&&!s){console.warn("[phlex-reactive] malformed data-reactive-media — skipped");continue}let a=r(o.field);if(a===null)continue;let c=o.take>0?[...a]:null,l=c?c.slice(0,o.take).join(""):a,u=c?.length<o.take||i?.test(l)===!1||s?.test(a)===!1;if(u&&o.pending==="keep"){P(n,"pending");continue}let d=!u&&Object.hasOwn(o.pool,l)?G(e,o.pool[l])[0]:null,f=e.core.copyMedia(n,d??null);if(f===null)continue;if(P(n,u?"pending":f===!1?"miss":"hit"),typeof o.label!=="string")continue;let p=u?"":f===!1?String(o.blank??""):f;for(let g of G(e,o.label))if(g.textContent!==p)g.textContent=p}}function P(e,r){if(e.getAttribute("data-reactive-media-state")!==r)e.setAttribute("data-reactive-media-state",r)}function G(e,r){try{return r==="@root"?[]:e.core.opTargets({to:r})}catch{return[]}}var Z="[data-reactive-css-vars]",Ce=/^--[a-z0-9-]+$/i,ke=["","px","%","deg","turn","ms","s","em","rem","fr"];function qe(e,r,t,n,o){let i=[...e.root.querySelectorAll(Z)].filter(t);if(e.root.hasAttribute("data-reactive-css-vars"))i.unshift(e.root);for(let s of i){let a;try{a=JSON.parse(s.getAttribute("data-reactive-css-vars"))}catch{}if(!Array.isArray(a?.to)||!a.vars||typeof a.vars!=="object"){console.warn("[phlex-reactive] malformed data-reactive-css-vars — skipped (two reactive_css_vars on one element?)");continue}let c=a.to.flatMap((l)=>{let u={to:l,global:a.global===!0},d=[];try{d=e.core.opTargets(u)}catch{}if(!d.length)e.core.diagnose("reactive_css_vars",u);return d});for(let[l,u]of Object.entries(a.vars)){let d=u?.unit??"";if(!Ce.test(l)||!ke.includes(d)||typeof u?.field!=="string"){console.warn(`[phlex-reactive] refused reactive_css_vars entry ${JSON.stringify(l)} — skipped`);continue}let f=Ee(e,r,u.field,o,n);if(f===void 0)continue;let p=f===null?"":`${f}${d}`;for(let g of c){if(g.style.getPropertyValue(l)===p)continue;if(p)g.style.setProperty(l,p);else g.style.removeProperty(l)}}}}function Ee(e,r,t,n,o){let i=r(t);if(i===null)return;if((i==="true"||i==="false")&&[...e.root.querySelectorAll(q(t,o))].some((a)=>n(a)&&a.type==="checkbox"))return i==="true"?1:0;let s=i.trim()?Number(i):NaN;return Number.isFinite(s)?s:null}var _="[data-reactive-enable], [data-reactive-select-all], [data-reactive-count]";function $e(e){return!!e.root.querySelector?.(_)}function R(e,r,t,n,o){return[...e.root.querySelectorAll(q(r,n))].filter((i)=>i.type==="checkbox"&&t(i)&&(!o||Re(i.getAttribute("data-reactive-group"),o)))}function Re(e,r){return e===r||!!e?.startsWith(`${r}.`)}function je(e,r){let t=r?.getAttribute?.("data-reactive-select-all");if(t&&e.core.owns(r))Q(e,t,r.checked,r,r.getAttribute("data-reactive-select-all-under"))}function ft(e,r,t){if(!r)return;let n=k.get(e)??{root:e,core:{ownership:()=>(o)=>o.closest('[data-controller~="reactive"]')===e}};Q(n,r,t!==!1),n.show?.()}function Q(e,r,t,n,o){let i=e.root.getAttribute?.("data-reactive-scope")||null,s=R(e,r,e.core.ownership(),i,o).filter((a)=>a!==n&&a.checked!==t);for(let a of s)a.checked=t;e.flipping=!0;try{for(let a of s)for(let c of["input","change"])a.dispatchEvent?.(new Event(c,{bubbles:!0}))}finally{e.flipping=!1}}function Me(e,r,t,n){for(let o of e.root.querySelectorAll(_)){if(!t(o))continue;let i=o.getAttribute("data-reactive-enable");if(i!==null){let c=V(H(i),r);if(c!==null)o.disabled=!c}let s=o.getAttribute("data-reactive-count");if(s){let c=String(r(s,!0));if(o.textContent!==c)o.textContent=c}let a=o.getAttribute("data-reactive-select-all");if(a){let c=o.getAttribute("data-reactive-select-all-under"),l=R(e,a,t,n,c).filter((d)=>d!==o),u=l.filter((d)=>d.checked).length;o.checked=u>0&&u===l.length,o.indeterminate=u>0&&u<l.length}}}function Te(e,r){for(let[t,n]of Object.entries(z(e,"group",'"ids[]" => { ... }, "tags[]" => { ... }'))){if(!n||typeof n!=="object"||Array.isArray(n))continue;let o=String(r(t,!0));for(let s of Array.isArray(n.count)?n.count:[]){if(!S(s,"group"))continue;for(let a of document.querySelectorAll(s))if(a.textContent!==o)a.textContent=o}let i=n.enable&&typeof n.enable==="object"?n.enable:{};for(let[s,a]of Object.entries(i)){if(!S(s,"group"))continue;let c=w(a?.any,r);if(c===null){console.warn(`[phlex-reactive] malformed reactive_group_targets enable for ${s} — skipped`);continue}for(let l of document.querySelectorAll(s))l.disabled=!c}}}function F(e){if(e.groupObserver||typeof MutationObserver!=="function")return;let r=(o)=>e.root.getAttribute?.(`data-reactive-${o}`)?.includes("checked_");if(!e.root.getAttribute?.("data-reactive-group-targets")&&!e.root.querySelector?.(`${_}, [data-reactive-show*=checked_]`)&&!r("show-targets")&&!r("on-complete"))return;let n=(o)=>o.nodeType===1&&(o.matches('input[type="checkbox"]')||!!o.querySelector('input[type="checkbox"]'));e.groupObserver=new MutationObserver((o)=>{if(!o.some((i)=>[...i.addedNodes,...i.removedNodes].some(n)))return;e.show?.(),e.arm?.()}),e.groupObserver.observe(e.root,{childList:!0,subtree:!0})}function x(e){return!!(e.root.getAttribute?.("data-reactive-filter-input")&&e.root.getAttribute?.("data-reactive-filter-option"))}function Je(e,r){let t=e.root.getAttribute("data-reactive-filter-input");return!!t&&typeof r.target?.matches==="function"&&r.target.matches(t)}var Ie=/[\s\-'(),./]/;function De(e,r,t){if(e==="prefix")return r.startsWith(t);if(e!=="word_start")return r.includes(t);for(let n=r.indexOf(t);n!==-1;n=r.indexOf(t,n+1))if(n===0||Ie.test(r[n-1]))return!0;return!1}function A(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.root.getAttribute("data-reactive-filter-input"),t=e.root.getAttribute("data-reactive-filter-option");if(!r||!t)return;let n=e.core.ownership(),o=[...e.root.querySelectorAll(r)].find(n);if(!o)return;let i=e.root.getAttribute("data-reactive-filter-match"),s=e.root.hasAttribute?.("data-reactive-filter-fold"),a=(f)=>{let p=(f??"").toLowerCase().trim();return s?p.normalize("NFD").replace(/\p{M}/gu,""):p},c=a(o.value),l=0;for(let f of e.root.querySelectorAll(t)){if(!n(f))continue;let p=f.hasAttribute?.("data-reactive-tags-selected")||c!==""&&!De(i,a(f.getAttribute("data-reactive-filter-text")??f.textContent),c);if(f.hidden=p,p)f.removeAttribute("data-reactive-highlighted");else l++}let u=e.root.getAttribute("data-reactive-filter-group");if(u)for(let f of e.root.querySelectorAll(u)){if(!n(f))continue;let p=[...f.querySelectorAll(t)].filter(n);if(p.length===0)continue;f.hidden=p.every((g)=>g.hidden)}let d=e.root.getAttribute("data-reactive-filter-empty");if(d){for(let f of e.root.querySelectorAll(d))if(n(f))f.hidden=l>0}}function O(e){return!!e.root.getAttribute?.("data-reactive-tags-field")}function We(e){if(typeof e.root?.querySelector!=="function")return!1;return!!e.root.querySelector("[data-reactive-nested-json]")}function j(e){if(typeof e.root?.querySelectorAll!=="function")return null;let r=e.root.getAttribute("data-reactive-tags-field");if(!r)return null;let t=e.core.ownership();return[...e.root.querySelectorAll(r)].find(t)??null}function M(e){let r=new Set,t=[];for(let n of String(e.value??"").split(",")){let o=n.trim();if(o===""||r.has(o.toLowerCase()))continue;r.add(o.toLowerCase()),t.push(o)}return t}function X(e,r){let t=j(e);if(!t)return!1;let n=M(t),o=new Set(n.map((s)=>s.toLowerCase())),i=!1;for(let s of r){let a=String(s??"").trim();if(a===""||o.has(a.toLowerCase()))continue;o.add(a.toLowerCase()),n.push(a),i=!0}if(i)ee(e,t,n);return i}function ee(e,r,t){r.value=t.join(","),v(r),te(e)}function Le(e){if(typeof e.root?.querySelectorAll!=="function")return null;let r=e.root.getAttribute("data-reactive-filter-input");if(!r)return null;let t=e.core.ownership();return[...e.root.querySelectorAll(r)].find(t)??null}function te(e){let r=j(e);if(!r)return;let t=M(r),n=e.core.ownership();Pe(e,t,n),Ge(e,t,n)}function Pe(e,r,t){let n=[...e.root.querySelectorAll("[data-reactive-tags-list]")].find(t);if(!n)return;let i=[...e.root.querySelectorAll("[data-reactive-tags-template]")].find(t)?.content?.firstElementChild;if(!i){if(!e.tagsWarnedTemplate)console.warn("[phlex-reactive] reactive_tags: no chip <template data-reactive-tags-template> found in this root — "+"chips will not render (the hidden field still updates). Add a template with a [data-reactive-tag-text] node and a reactive_tags_remove button."),e.tagsWarnedTemplate=!0;return}while(n.firstChild)n.removeChild(n.firstChild);for(let s of r){let a=i.cloneNode(!0);a.setAttribute?.("data-reactive-tag",s);let c=a.matches?.("[data-reactive-tag-text]")?a:(a.querySelectorAll?.("[data-reactive-tag-text]")??[])[0];if(c)c.textContent=s;let l=[...a.querySelectorAll?.('[data-action*="reactive#tagsRemove"]')??[]];if(a.matches?.('[data-action*="reactive#tagsRemove"]'))l.push(a);for(let u of l)u.setAttribute?.("data-reactive-tag-param",s);n.appendChild(a)}}function Ge(e,r,t){let n=new Set(r.map((o)=>o.toLowerCase()));for(let o of e.root.querySelectorAll("[role=option]")){if(!t(o))continue;let i=o.getAttribute?.("data-reactive-tag-param");if(!i)continue;if(n.has(i.toLowerCase()))o.setAttribute("data-reactive-tags-selected","true"),o.hidden=!0,o.removeAttribute?.("data-reactive-highlighted");else if(o.hasAttribute?.("data-reactive-tags-selected")){if(o.removeAttribute("data-reactive-tags-selected"),!x(e))o.hidden=!1}}if(x(e))A(e)}function Fe(e){return e.nestedIndex=Math.max(e.nestedIndex+1,Date.now()),e.nestedIndex}function Be(e,r){let t=[e,...e.querySelectorAll?.("*")??[]];for(let n of t)for(let o of["name","id","for"]){let i=n.getAttribute?.(o);if(i&&i.includes("NEW_ROW"))n.setAttribute?.(o,i.replaceAll("NEW_ROW",String(r)))}}function Ke(e,r){if(e.nestedWarned)return;console.warn(`[phlex-reactive] nested rows: no owned [data-reactive-nested-list="${r}"] container + <template data-reactive-nested-template="${r}"> pair found in this root — the add `+"trigger did nothing. Render both inside the same reactive root (reactive_nested_list / reactive_nested_template)."),e.nestedWarned=!0}function He(e,r,t,n){if(!t)return null;let o;try{o=JSON.parse(t)}catch{return null}if(!o||typeof o!=="object")return null;let i=e.core.ownership(),s=[...r.querySelectorAll?.("input, select, textarea")??[]],a=[];for(let[c,l]of Object.entries(o)){let u=[...e.root.querySelectorAll?.(l)??[]].find(i);if(!u)continue;let d=s.find((f)=>ne(f.getAttribute?.("name"))===c);if(!d)continue;Ve(d,u),a.push(u)}if(n)for(let c of a)ze(c);return a[0]??null}function Ve(e,r){if(e.type==="checkbox")e.checked=r.type==="checkbox"?!!r.checked:N(r)!=="";else e.value=N(r);v(e)}function ze(e){if(e.type==="checkbox")e.checked=!1;else e.value="";v(e)}function Ye(e,r){if(!e.includes("%{"))return e;return e.replace(/%\{(\w+)\}/g,(t,n)=>Object.prototype.hasOwnProperty.call(r,n)?r[n]:t)}function B(e,r){let t=[...r.querySelectorAll?.('input[name$="[_destroy]"]')??[]][0];if(t)t.value="1",v(t),r.hidden=!0;else r.parentNode?.removeChild?.(r);T(e)}function T(e){if(typeof e.root?.querySelectorAll!=="function")return;let r=e.core.ownership();for(let t of[...e.root.querySelectorAll("[data-reactive-nested-json]")].filter(r))oe(e,t.getAttribute("data-reactive-nested-json"))}function Ue(e,r){let t=r.getAttribute?.("data-reactive-nested-json-field");if(!t)return null;let n=e.core.ownership();return[...e.root.querySelectorAll(t)].find(n)??null}function re(e,r){let t={},n=e.core.ownership();for(let o of[...r.querySelectorAll?.("input, select, textarea")??[]]){if(o.matches(":disabled")||o.type==="radio"&&!o.checked||!n(o))continue;let i=ne(o.getAttribute?.("name"));if(i===null||i==="_destroy")continue;t[i]=N(o)}return t}function ne(e){if(!e)return null;let r=e.match(/\[([^\][]+)\]$/);return r?r[1]:e}function N(e){if(e.type==="checkbox")return e.checked?e.value||"on":"";return e.value??""}function oe(e,r){let t=e.core.ownership(),n=[...e.root.querySelectorAll(`[data-reactive-nested-list="${r}"]`)].find(t);if(!n)return;let o=Ue(e,n);if(!o)return;let i=[];for(let a of[...n.querySelectorAll?.("[data-reactive-nested-row]")??[]]){if(!t(a)||a.hidden)continue;i.push(re(e,a))}let s=JSON.stringify(i);if(o.value===s)return;o.value=s,v(o)}function dt(e,r,t){let n=y(e,r);if(!O(n))return;if(t?.defaultPrevented)return;if(n.core.listnavOptions(t).some((s)=>s.hasAttribute?.("data-reactive-highlighted")))return;t?.preventDefault?.();let o=t?.currentTarget??t?.target;if(!o)return;if(!X(n,String(o.value??"").split(",")))return;if(o.value="",x(n))A(n)}function pt(e,r,t){let n=y(e,r);if(!O(n))return;t?.preventDefault?.();let i=(t?.currentTarget??t?.target)?.getAttribute?.("data-reactive-tag-param");if(!i)return;if(!X(n,[i]))return;let s=Le(n);if(!s)return;s.value="",A(n),s.focus?.()}function gt(e,r,t){let n=y(e,r);if(!O(n))return;t?.preventDefault?.();let i=(t?.currentTarget??t?.target)?.getAttribute?.("data-reactive-tag-param");if(!i)return;let s=j(n);if(!s)return;let a=M(s),c=a.filter((l)=>l.toLowerCase()!==i.toLowerCase());if(c.length===a.length)return;ee(n,s,c)}function ht(e,r,t){let n=y(e,r);t?.preventDefault?.();let o=t?.currentTarget??t?.target,i=o?.getAttribute?.("data-reactive-association-param");if(!i)return;if(typeof n.root?.querySelectorAll!=="function")return;let s=n.core.ownership(),a=[...n.root.querySelectorAll(`[data-reactive-nested-list="${i}"]`)].find(s),l=[...n.root.querySelectorAll(`[data-reactive-nested-template="${i}"]`)].find(s)?.content?.firstElementChild;if(!a||!l){Ke(n,i);return}let u=l.cloneNode(!0);Be(u,Fe(n)),a.appendChild(u);let d=o?.getAttribute?.("data-reactive-nested-from-param"),f=o?.getAttribute?.("data-reactive-nested-clear-param")==="true",p=He(n,u,d,f);if(d)p?.focus?.();else[...u.querySelectorAll?.("input, select, textarea")??[]][0]?.focus?.();if(a.getAttribute?.("data-reactive-nested-json")===i)oe(n,i)}function yt(e,r,t){let n=y(e,r);t?.preventDefault?.();let o=t?.currentTarget??t?.target,i=o?.closest?.("[data-reactive-nested-row]");if(!i)return;if(i.closest?.('[data-controller~="reactive"]')!==n.root)return;let s=o?.getAttribute?.("data-reactive-confirm-param"),a=o?.getAttribute?.("data-reactive-confirm-when-param"),c=s||(a?ue(n,a):null);if(!c)return B(n,i);let l=re(n,i),u=Ye(c,l);return n.core.confirm(u,{el:o,row:i,fields:l}).then((d)=>{if(d)B(n,i)})}function ie(e,r){let t=r?.target;if(!t||!e.core.owns(t))return;T(e)}var se=["gte","gt","lte","lt"],Ze=["len_eq","len_gte","len_gt","len_lte","len_lt"],ae=["checked_eq","checked_gte","checked_gt","checked_lte","checked_lt"],Qe=["digits_eq","digits_gte","digits_lt","digits_lte"];function C(e,r,t){if(!Number.isInteger(r))return console.warn(`[phlex-reactive] reactive_show ${e}: needs an integer literal, got ${JSON.stringify(r)} — skipped`),null;switch(e.slice(e.indexOf("_")+1)){case"eq":return t===r;case"gte":return t>=r;case"gt":return t>r;case"lte":return t<=r;case"lt":return t<r;default:return null}}function ce(e,r,t){let n=Number(r);if(Number.isNaN(n))return console.warn(`[phlex-reactive] reactive_show ${e}: needs a numeric literal, got ${JSON.stringify(r)} — skipped`),null;let o=t==null?"":String(t).trim(),i=o===""?NaN:Number(o);if(Number.isNaN(i))return!1;switch(e){case"gte":return i>=n;case"gt":return i>n;case"lte":return i<=n;case"lt":return i<n;default:return null}}function le(e,r){if(!e||typeof e!=="object")return null;if(typeof e.equals==="string")return r===e.equals;if(typeof e.not==="string")return r!==e.not;if(Array.isArray(e.in))return e.in.includes(r);for(let t of se)if(t in e)return ce(t,e[t],r);for(let t of Ze)if(t in e)return C(t,e[t],[...String(r??"")].length);return null}function J(e,r){if(!e||typeof e!=="object"||typeof e.field!=="string")return!1;let t=ae.find((i)=>(i in e));if(t){let i=r(e.field,!0);return C(t,e[t],Array.isArray(i)?i.length:Number(i)||0)===!0}if(typeof e.same==="string"){let i=(s)=>{let a=String(r(s)??"");return e.fold===!0?a.replace(/[A-Z]/g,(c)=>String.fromCharCode(c.charCodeAt(0)+32)):a};return i(e.field)===i(e.same)!==(e.negate===!0)}let n=Qe.filter((i)=>(i in e));if(n.length){let i=String(r(e.field)??"");if(!n.every((a)=>Number.isInteger(e[a]))||e.prefix!=null&&typeof e.prefix!=="string")return!1;return(/^[0-9]*$/.test(i)&&n.every((a)=>C(a,e[a],i.length))&&i.startsWith(e.prefix??""))!==(e.negate===!0)}let o=r(e.field)??"";return le(e,o)===!0}function w(e,r){if(!Array.isArray(e)||e.length===0)return null;return e.some((t)=>Array.isArray(t)&&t.length>0&&t.every((n)=>J(n,r)))}function Xe(e){if(!Array.isArray(e)||e.length===0)return null;let r=new Set;for(let t of e){if(!Array.isArray(t))continue;for(let n of t){if(n&&typeof n==="object"&&typeof n.field==="string")r.add(n.field);if(typeof n?.same==="string")r.add(n.same)}}return r.size>0?[...r]:null}function et(e){return e.flat().every((r)=>ae.some((t)=>(t in Object(r))))}function ue(e,r){let t=r;if(typeof r==="string")try{t=JSON.parse(r)}catch{return console.warn(`[phlex-reactive] malformed conditional confirm payload ${JSON.stringify(r)} — skipped`),null}if(!t||typeof t!=="object")return null;let{fields:n}=e.core.collectFields(),o=(s)=>n[s],i;if(typeof t.predicate==="string"){let s=de(t.predicate);if(!s)return console.warn(`[phlex-reactive] confirm predicate "${t.predicate}" is not registered — proceeding without a dialog (register it with setConfirmPredicate)`),null;i=!!s(n)}else i=w(t.groups?.any,o)===!0;return i?t.message:null}function I(e,r){let t=r.target?.closest?.("[data-reactive-editable]");return t&&e.core.owns(t)?t:null}function tt(e,r){let t=I(e,r);if(!t||r.isComposing||r.keyCode===229)return;if(r.key==="Enter"){let n=t.getAttribute("data-reactive-editable-enter");if(t.getAttribute("data-reactive-editable")==="multi"&&(n==null||r.shiftKey))return;if(r.preventDefault(),n==="submit")t.closest("form")?.requestSubmit();else if(n)e.core.applyOps(JSON.parse(n),"@root")}else if(r.key==="Escape"&&t.hasAttribute("data-reactive-editable-escape"))r.preventDefault(),t.textContent=e.core.served(t),v(t),t.blur()}function rt(e,r){let t=I(e,r),n=t?.getAttribute("data-reactive-editable")!=="multi",o=(r.clipboardData??r.dataTransfer)?.getData("text/plain");if(!t||o==null||e.core.plain()&&!(n&&/[\r\n]/.test(o)))return;if(r.preventDefault(),n)o=o.replace(/\r?\n|\r/g," ");t.focus(),document.execCommand("insertText",!1,o)}function nt(e,r){let t=I(e,r);if(t?.firstChild&&e.core.text(t)==="")t.replaceChildren()}export{ft as checkGroup,ut as confirmMessage,st as connect,at as disconnect,ht as nestedAdd,yt as nestedRemove,ct as reseed,lt as syncNestedJson,dt as tagsAdd,pt as tagsPick,gt as tagsRemove};
|
|
2
2
|
|
|
3
|
-
//# debugId=
|
|
3
|
+
//# debugId=0E6A93F98751F98F64756E2164756E21
|
|
4
4
|
//# sourceMappingURL=bindings.min.js.map
|