@livetemplate/client 0.8.12 → 0.8.14
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.
- package/dist/dom/directives.d.ts +7 -5
- package/dist/dom/directives.d.ts.map +1 -1
- package/dist/dom/directives.js +31 -17
- package/dist/dom/directives.js.map +1 -1
- package/dist/dom/event-delegation.d.ts +5 -3
- package/dist/dom/event-delegation.d.ts.map +1 -1
- package/dist/dom/event-delegation.js +92 -189
- package/dist/dom/event-delegation.js.map +1 -1
- package/dist/dom/link-interceptor.d.ts +1 -1
- package/dist/dom/link-interceptor.js +3 -3
- package/dist/dom/link-interceptor.js.map +1 -1
- package/dist/dom/reactive-attributes.d.ts +15 -20
- package/dist/dom/reactive-attributes.d.ts.map +1 -1
- package/dist/dom/reactive-attributes.js +78 -81
- package/dist/dom/reactive-attributes.js.map +1 -1
- package/dist/livetemplate-client.browser.js +4 -4
- package/dist/livetemplate-client.browser.js.map +4 -4
- package/dist/livetemplate-client.d.ts +0 -2
- package/dist/livetemplate-client.d.ts.map +1 -1
- package/dist/livetemplate-client.js +3 -12
- package/dist/livetemplate-client.js.map +1 -1
- package/dist/state/change-auto-wirer.js +2 -2
- package/dist/state/change-auto-wirer.js.map +1 -1
- package/dist/state/form-lifecycle-manager.d.ts +1 -3
- package/dist/state/form-lifecycle-manager.d.ts.map +1 -1
- package/dist/state/form-lifecycle-manager.js +6 -6
- package/dist/state/form-lifecycle-manager.js.map +1 -1
- package/dist/tests/change-auto-wirer.test.js +4 -4
- package/dist/tests/change-auto-wirer.test.js.map +1 -1
- package/dist/tests/directives.test.js +33 -33
- package/dist/tests/directives.test.js.map +1 -1
- package/dist/tests/event-delegation.test.js +66 -9
- package/dist/tests/event-delegation.test.js.map +1 -1
- package/dist/tests/form-lifecycle-manager.test.js +27 -28
- package/dist/tests/form-lifecycle-manager.test.js.map +1 -1
- package/dist/tests/reactive-attributes.test.js +60 -84
- package/dist/tests/reactive-attributes.test.js.map +1 -1
- package/dist/utils/lvt-selector.d.ts +3 -0
- package/dist/utils/lvt-selector.d.ts.map +1 -0
- package/dist/utils/lvt-selector.js +13 -0
- package/dist/utils/lvt-selector.js.map +1 -0
- package/package.json +1 -1
- package/dist/dom/modal-manager.d.ts +0 -11
- package/dist/dom/modal-manager.d.ts.map +0 -1
- package/dist/dom/modal-manager.js +0 -62
- package/dist/dom/modal-manager.js.map +0 -1
- package/dist/tests/modal-manager.test.d.ts +0 -2
- package/dist/tests/modal-manager.test.d.ts.map +0 -1
- package/dist/tests/modal-manager.test.js +0 -80
- package/dist/tests/modal-manager.test.js.map +0 -1
- package/dist/utils/confirm.d.ts +0 -12
- package/dist/utils/confirm.d.ts.map +0 -1
- package/dist/utils/confirm.js +0 -35
- package/dist/utils/confirm.js.map +0 -1
package/dist/dom/directives.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Apply scroll directives on elements with lvt-scroll attributes.
|
|
3
|
-
*/
|
|
4
1
|
export declare function handleScrollDirectives(rootElement: Element): void;
|
|
5
2
|
/**
|
|
6
|
-
* Apply highlight directives to elements with lvt-highlight attributes.
|
|
3
|
+
* Apply highlight directives to elements with lvt-fx:highlight attributes.
|
|
4
|
+
* Configuration read from CSS custom properties:
|
|
5
|
+
* --lvt-highlight-duration: <ms> (default: 500)
|
|
6
|
+
* --lvt-highlight-color: <color> (default: #ffc107)
|
|
7
7
|
*/
|
|
8
8
|
export declare function handleHighlightDirectives(rootElement: Element): void;
|
|
9
9
|
/**
|
|
10
|
-
* Apply animation directives to elements with lvt-animate attributes.
|
|
10
|
+
* Apply animation directives to elements with lvt-fx:animate attributes.
|
|
11
|
+
* Configuration read from CSS custom properties:
|
|
12
|
+
* --lvt-animate-duration: <ms> (default: 300)
|
|
11
13
|
*/
|
|
12
14
|
export declare function handleAnimateDirectives(rootElement: Element): void;
|
|
13
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":"AAQA,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAuDjE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA6BpE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA0ElE;AAkBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA4BhE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAW7C"}
|
package/dist/dom/directives.js
CHANGED
|
@@ -6,16 +6,23 @@ exports.handleAnimateDirectives = handleAnimateDirectives;
|
|
|
6
6
|
exports.handleToastDirectives = handleToastDirectives;
|
|
7
7
|
exports.setupToastClickOutside = setupToastClickOutside;
|
|
8
8
|
/**
|
|
9
|
-
* Apply scroll directives on elements with lvt-scroll attributes.
|
|
9
|
+
* Apply scroll directives on elements with lvt-fx:scroll attributes.
|
|
10
|
+
* Configuration read from CSS custom properties:
|
|
11
|
+
* --lvt-scroll-behavior: auto | smooth (default: auto)
|
|
12
|
+
* --lvt-scroll-threshold: <number> (default: 100)
|
|
10
13
|
*/
|
|
14
|
+
const VALID_SCROLL_BEHAVIORS = new Set(["auto", "smooth", "instant"]);
|
|
11
15
|
function handleScrollDirectives(rootElement) {
|
|
12
|
-
const scrollElements = rootElement.querySelectorAll("[lvt-scroll]");
|
|
16
|
+
const scrollElements = rootElement.querySelectorAll("[lvt-fx\\:scroll]");
|
|
13
17
|
scrollElements.forEach((element) => {
|
|
14
18
|
const htmlElement = element;
|
|
15
|
-
const mode = htmlElement.getAttribute("lvt-scroll");
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
+
const mode = htmlElement.getAttribute("lvt-fx:scroll");
|
|
20
|
+
const computed = getComputedStyle(htmlElement);
|
|
21
|
+
const rawBehavior = computed.getPropertyValue("--lvt-scroll-behavior").trim();
|
|
22
|
+
const behavior = VALID_SCROLL_BEHAVIORS.has(rawBehavior)
|
|
23
|
+
? rawBehavior
|
|
24
|
+
: "auto";
|
|
25
|
+
const threshold = parseInt(computed.getPropertyValue("--lvt-scroll-threshold").trim() || "100", 10);
|
|
19
26
|
if (!mode)
|
|
20
27
|
return;
|
|
21
28
|
switch (mode) {
|
|
@@ -47,19 +54,23 @@ function handleScrollDirectives(rootElement) {
|
|
|
47
54
|
case "preserve":
|
|
48
55
|
break;
|
|
49
56
|
default:
|
|
50
|
-
console.warn(`Unknown lvt-scroll mode: ${mode}`);
|
|
57
|
+
console.warn(`Unknown lvt-fx:scroll mode: ${mode}`);
|
|
51
58
|
}
|
|
52
59
|
});
|
|
53
60
|
}
|
|
54
61
|
/**
|
|
55
|
-
* Apply highlight directives to elements with lvt-highlight attributes.
|
|
62
|
+
* Apply highlight directives to elements with lvt-fx:highlight attributes.
|
|
63
|
+
* Configuration read from CSS custom properties:
|
|
64
|
+
* --lvt-highlight-duration: <ms> (default: 500)
|
|
65
|
+
* --lvt-highlight-color: <color> (default: #ffc107)
|
|
56
66
|
*/
|
|
57
67
|
function handleHighlightDirectives(rootElement) {
|
|
58
|
-
const highlightElements = rootElement.querySelectorAll("[lvt-highlight]");
|
|
68
|
+
const highlightElements = rootElement.querySelectorAll("[lvt-fx\\:highlight]");
|
|
59
69
|
highlightElements.forEach((element) => {
|
|
60
|
-
const mode = element.getAttribute("lvt-highlight");
|
|
61
|
-
const
|
|
62
|
-
const
|
|
70
|
+
const mode = element.getAttribute("lvt-fx:highlight");
|
|
71
|
+
const computed = getComputedStyle(element);
|
|
72
|
+
const duration = parseInt(computed.getPropertyValue("--lvt-highlight-duration").trim() || "500", 10);
|
|
73
|
+
const color = computed.getPropertyValue("--lvt-highlight-color").trim() || "#ffc107";
|
|
63
74
|
if (!mode)
|
|
64
75
|
return;
|
|
65
76
|
const htmlElement = element;
|
|
@@ -76,13 +87,16 @@ function handleHighlightDirectives(rootElement) {
|
|
|
76
87
|
});
|
|
77
88
|
}
|
|
78
89
|
/**
|
|
79
|
-
* Apply animation directives to elements with lvt-animate attributes.
|
|
90
|
+
* Apply animation directives to elements with lvt-fx:animate attributes.
|
|
91
|
+
* Configuration read from CSS custom properties:
|
|
92
|
+
* --lvt-animate-duration: <ms> (default: 300)
|
|
80
93
|
*/
|
|
81
94
|
function handleAnimateDirectives(rootElement) {
|
|
82
|
-
const animateElements = rootElement.querySelectorAll("[lvt-animate]");
|
|
95
|
+
const animateElements = rootElement.querySelectorAll("[lvt-fx\\:animate]");
|
|
83
96
|
animateElements.forEach((element) => {
|
|
84
|
-
const animation = element.getAttribute("lvt-animate");
|
|
85
|
-
const
|
|
97
|
+
const animation = element.getAttribute("lvt-fx:animate");
|
|
98
|
+
const computed = getComputedStyle(element);
|
|
99
|
+
const duration = parseInt(computed.getPropertyValue("--lvt-animate-duration").trim() || "300", 10);
|
|
86
100
|
if (!animation)
|
|
87
101
|
return;
|
|
88
102
|
const htmlElement = element;
|
|
@@ -98,7 +112,7 @@ function handleAnimateDirectives(rootElement) {
|
|
|
98
112
|
htmlElement.style.animation = `lvt-scale-in var(--lvt-animate-duration) ease-out`;
|
|
99
113
|
break;
|
|
100
114
|
default:
|
|
101
|
-
console.warn(`Unknown lvt-animate mode: ${animation}`);
|
|
115
|
+
console.warn(`Unknown lvt-fx:animate mode: ${animation}`);
|
|
102
116
|
}
|
|
103
117
|
htmlElement.addEventListener("animationend", () => {
|
|
104
118
|
htmlElement.style.animation = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"directives.js","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,6 @@ export interface EventDelegationContext {
|
|
|
5
5
|
parseValue(value: string): any;
|
|
6
6
|
send(message: any): void;
|
|
7
7
|
setActiveSubmission(form: HTMLFormElement | null, button: HTMLButtonElement | null, originalButtonText: string | null): void;
|
|
8
|
-
openModal(modalId: string): void;
|
|
9
|
-
closeModal(modalId: string): void;
|
|
10
8
|
getWebSocketReadyState(): number | undefined;
|
|
11
9
|
triggerPendingUploads(uploadName: string): void;
|
|
12
10
|
}
|
|
@@ -20,8 +18,12 @@ export declare class EventDelegator {
|
|
|
20
18
|
private extractButtonData;
|
|
21
19
|
setupEventDelegation(): void;
|
|
22
20
|
setupWindowEventDelegation(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Sets up click-away detection for lvt-el:*:on:click-away attributes.
|
|
23
|
+
* Instead of routing to a server action, click-away triggers client-side
|
|
24
|
+
* DOM manipulation via executeAction from reactive-attributes.
|
|
25
|
+
*/
|
|
23
26
|
setupClickAwayDelegation(): void;
|
|
24
|
-
setupModalDelegation(): void;
|
|
25
27
|
/**
|
|
26
28
|
* Sets up focus trapping for elements with lvt-focus-trap attribute.
|
|
27
29
|
* Focus is trapped within the element, cycling through focusable elements
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-delegation.d.ts","sourceRoot":"","sources":["../../dom/event-delegation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-delegation.d.ts","sourceRoot":"","sources":["../../dom/event-delegation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAa9C,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,IAAI,OAAO,GAAG,IAAI,CAAC;IACpC,sBAAsB,IAAI,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;IAC/B,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,mBAAmB,CACjB,IAAI,EAAE,eAAe,GAAG,IAAI,EAC5B,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAChC,IAAI,CAAC;IACR,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAAC;IAC7C,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACjD;AAED;;GAEG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,MAAM;IAGjC,OAAO,CAAC,iBAAiB;IAYzB,oBAAoB,IAAI,IAAI;IA+Y5B,0BAA0B,IAAI,IAAI;IA8FlC;;;;OAIG;IACH,wBAAwB,IAAI,IAAI;IAuChC;;;;OAIG;IACH,wBAAwB,IAAI,IAAI;IAmGhC;;;;OAIG;IACH,wBAAwB,IAAI,IAAI;CA0GjC"}
|
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EventDelegator = void 0;
|
|
4
4
|
const rate_limit_1 = require("../utils/rate-limit");
|
|
5
|
-
const
|
|
5
|
+
const lvt_selector_1 = require("../utils/lvt-selector");
|
|
6
|
+
const reactive_attributes_1 = require("./reactive-attributes");
|
|
7
|
+
// Methods supported by click-away, derived from ReactiveAction values
|
|
8
|
+
const CLICK_AWAY_METHOD_MAP = {
|
|
9
|
+
reset: "reset",
|
|
10
|
+
addclass: "addClass",
|
|
11
|
+
removeclass: "removeClass",
|
|
12
|
+
toggleclass: "toggleClass",
|
|
13
|
+
setattr: "setAttr",
|
|
14
|
+
toggleattr: "toggleAttr",
|
|
15
|
+
};
|
|
16
|
+
const CLICK_AWAY_METHODS = Object.keys(CLICK_AWAY_METHOD_MAP);
|
|
6
17
|
/**
|
|
7
18
|
* Handles all DOM event delegation concerns for LiveTemplateClient.
|
|
8
19
|
*/
|
|
@@ -75,7 +86,7 @@ class EventDelegator {
|
|
|
75
86
|
}
|
|
76
87
|
if (!inWrapper)
|
|
77
88
|
return;
|
|
78
|
-
const attrName = `lvt
|
|
89
|
+
const attrName = `lvt-on:${eventType}`;
|
|
79
90
|
element = target;
|
|
80
91
|
while (element && element !== currentWrapper.parentElement) {
|
|
81
92
|
let action = element.getAttribute(attrName);
|
|
@@ -92,7 +103,7 @@ class EventDelegator {
|
|
|
92
103
|
// Orphan button detection (Tier 1: formless standalone buttons).
|
|
93
104
|
// A <button name="action"> outside any form triggers the named action directly.
|
|
94
105
|
// Resolution order for click events:
|
|
95
|
-
// 1. lvt-click attribute (Tier 2 — already checked above)
|
|
106
|
+
// 1. lvt-on:click attribute (Tier 2 — already checked above)
|
|
96
107
|
// 2. Orphan button name (Tier 1 — checked here)
|
|
97
108
|
if (!action && eventType === "click") {
|
|
98
109
|
const btn = element instanceof HTMLButtonElement ? element : null;
|
|
@@ -107,22 +118,35 @@ class EventDelegator {
|
|
|
107
118
|
isOrphanButton = true;
|
|
108
119
|
}
|
|
109
120
|
}
|
|
110
|
-
// Auto-intercept forms
|
|
111
|
-
//
|
|
112
|
-
// 1.
|
|
113
|
-
// 2.
|
|
114
|
-
// 3.
|
|
121
|
+
// Auto-intercept forms (progressive complexity).
|
|
122
|
+
// Action resolution order:
|
|
123
|
+
// 1. lvt-form:action attribute (explicit routing)
|
|
124
|
+
// 2. submitter.name (button name = action)
|
|
125
|
+
// 3. form.name (form name = action)
|
|
126
|
+
// 4. "submit" (server defaults to Submit())
|
|
127
|
+
//
|
|
128
|
+
// Note: lvt-action hidden field is a server-side progressive
|
|
129
|
+
// enhancement fallback (no-JS POST). The client does not read it;
|
|
130
|
+
// the server extracts it from form data directly.
|
|
115
131
|
if (!action && eventType === "submit" && element instanceof HTMLFormElement) {
|
|
116
|
-
if (!element.hasAttribute("lvt-no-intercept")) {
|
|
132
|
+
if (!element.hasAttribute("lvt-form:no-intercept")) {
|
|
133
|
+
// Check for explicit routing attribute first.
|
|
134
|
+
// Empty string ("") falls through to submitter/form name resolution.
|
|
135
|
+
const explicitAction = element.getAttribute("lvt-form:action");
|
|
117
136
|
const submitter = e.submitter;
|
|
118
|
-
if (
|
|
119
|
-
action =
|
|
120
|
-
}
|
|
121
|
-
else if (element.name) {
|
|
122
|
-
action = element.name;
|
|
137
|
+
if (explicitAction) {
|
|
138
|
+
action = explicitAction;
|
|
123
139
|
}
|
|
124
140
|
else {
|
|
125
|
-
|
|
141
|
+
if (submitter instanceof HTMLButtonElement && submitter.name) {
|
|
142
|
+
action = submitter.name;
|
|
143
|
+
}
|
|
144
|
+
else if (element.name) {
|
|
145
|
+
action = element.name;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
action = "submit";
|
|
149
|
+
}
|
|
126
150
|
}
|
|
127
151
|
actionElement = element;
|
|
128
152
|
if (submitter) {
|
|
@@ -136,22 +160,6 @@ class EventDelegator {
|
|
|
136
160
|
}
|
|
137
161
|
}
|
|
138
162
|
}
|
|
139
|
-
if (!action && (eventType === "change" || eventType === "input" || eventType === "search")) {
|
|
140
|
-
// For input/search events, also check lvt-change on the element itself
|
|
141
|
-
// This handles: typing (input), clearing via X button (search/input), blur (change)
|
|
142
|
-
if ((eventType === "input" || eventType === "search") && element.hasAttribute("lvt-change")) {
|
|
143
|
-
action = element.getAttribute("lvt-change");
|
|
144
|
-
actionElement = element;
|
|
145
|
-
}
|
|
146
|
-
// Check for form-level lvt-change
|
|
147
|
-
if (!action) {
|
|
148
|
-
const formElement = element.closest("form");
|
|
149
|
-
if (formElement && formElement.hasAttribute("lvt-change")) {
|
|
150
|
-
action = formElement.getAttribute("lvt-change");
|
|
151
|
-
actionElement = formElement;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
163
|
if (action != null && actionElement) {
|
|
156
164
|
if (eventType === "submit") {
|
|
157
165
|
window.__lvtActionFound = action;
|
|
@@ -176,11 +184,6 @@ class EventDelegator {
|
|
|
176
184
|
eventType,
|
|
177
185
|
targetElement,
|
|
178
186
|
});
|
|
179
|
-
// Handle lvt-confirm for any action
|
|
180
|
-
if (!(0, confirm_1.checkLvtConfirm)(targetElement)) {
|
|
181
|
-
this.logger.debug("Action cancelled by user:", action);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
187
|
const message = { action, data: {} };
|
|
185
188
|
if (targetElement instanceof HTMLFormElement) {
|
|
186
189
|
this.logger.debug("Processing form element");
|
|
@@ -192,12 +195,17 @@ class EventDelegator {
|
|
|
192
195
|
});
|
|
193
196
|
// Get password field names to skip parseValue for them
|
|
194
197
|
const passwordFields = new Set(Array.from(targetElement.querySelectorAll('input[type="password"][name]')).map((el) => el.name));
|
|
195
|
-
//
|
|
196
|
-
//
|
|
198
|
+
// Exclude the submitter button's name from form data.
|
|
199
|
+
// The submitter's name is used as the action routing key in the
|
|
200
|
+
// button-name path — including it in data would be redundant.
|
|
201
|
+
// When lvt-form:action overrides routing, the button name is still
|
|
202
|
+
// excluded to avoid noisy payloads (the button is a UI control,
|
|
203
|
+
// not domain data). Button value and data-* attrs are collected below.
|
|
204
|
+
// "action" is NOT excluded — it's a normal data field.
|
|
197
205
|
const submitterForData = targetElement.__lvtSubmitter;
|
|
198
|
-
const actionFieldName = submitterForData?.name
|
|
206
|
+
const actionFieldName = submitterForData?.name;
|
|
199
207
|
formData.forEach((value, key) => {
|
|
200
|
-
if (
|
|
208
|
+
if (actionFieldName && key === actionFieldName)
|
|
201
209
|
return;
|
|
202
210
|
if (checkboxNames.has(key)) {
|
|
203
211
|
message.data[key] = true;
|
|
@@ -238,29 +246,28 @@ class EventDelegator {
|
|
|
238
246
|
if (isOrphanButton) {
|
|
239
247
|
this.extractButtonData(actionElement, message.data);
|
|
240
248
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
});
|
|
249
|
+
// Extract standard data-* attributes from the action element.
|
|
250
|
+
// Exclude data-key (list reconciliation) and data-lvt-id (internal framework ID)
|
|
251
|
+
// since these are LiveTemplate internals, not user-provided action data.
|
|
252
|
+
if (!(targetElement instanceof HTMLFormElement) && !isOrphanButton) {
|
|
253
|
+
Array.from(actionElement.attributes).forEach((attr) => {
|
|
254
|
+
if (attr.name.startsWith("data-") && attr.name !== "data-key" && attr.name !== "data-lvt-id") {
|
|
255
|
+
const key = attr.name.slice(5);
|
|
256
|
+
message.data[key] = this.context.parseValue(attr.value);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
253
260
|
if (eventType === "submit" &&
|
|
254
261
|
targetElement instanceof HTMLFormElement) {
|
|
255
262
|
const submitEvent = e;
|
|
256
263
|
const submitButton = submitEvent.submitter;
|
|
257
264
|
let originalButtonText = null;
|
|
258
265
|
if (submitButton &&
|
|
259
|
-
submitButton.hasAttribute("lvt-disable-with")) {
|
|
266
|
+
submitButton.hasAttribute("lvt-form:disable-with")) {
|
|
260
267
|
originalButtonText = submitButton.textContent;
|
|
261
268
|
submitButton.disabled = true;
|
|
262
269
|
submitButton.textContent =
|
|
263
|
-
submitButton.getAttribute("lvt-disable-with");
|
|
270
|
+
submitButton.getAttribute("lvt-form:disable-with");
|
|
264
271
|
this.logger.debug("Disabled submit button");
|
|
265
272
|
}
|
|
266
273
|
this.context.setActiveSubmission(targetElement, submitButton || null, originalButtonText);
|
|
@@ -289,8 +296,8 @@ class EventDelegator {
|
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
298
|
};
|
|
292
|
-
const throttleValue = actionElement.getAttribute("lvt-throttle");
|
|
293
|
-
const debounceValue = actionElement.getAttribute("lvt-debounce");
|
|
299
|
+
const throttleValue = actionElement.getAttribute("lvt-mod:throttle");
|
|
300
|
+
const debounceValue = actionElement.getAttribute("lvt-mod:debounce");
|
|
294
301
|
// Skip rate limiting for "search" event (clear button click) - it's a discrete action
|
|
295
302
|
const shouldRateLimit = (throttleValue || debounceValue) && eventType !== "search";
|
|
296
303
|
if (shouldRateLimit) {
|
|
@@ -372,8 +379,8 @@ class EventDelegator {
|
|
|
372
379
|
const currentWrapper = this.context.getWrapperElement();
|
|
373
380
|
if (!currentWrapper)
|
|
374
381
|
return;
|
|
375
|
-
const attrName = `lvt-window
|
|
376
|
-
const elements = currentWrapper.querySelectorAll(
|
|
382
|
+
const attrName = `lvt-on:window:${eventType}`;
|
|
383
|
+
const elements = currentWrapper.querySelectorAll((0, lvt_selector_1.lvtSelector)(attrName));
|
|
377
384
|
elements.forEach((element) => {
|
|
378
385
|
const action = element.getAttribute(attrName);
|
|
379
386
|
if (!action)
|
|
@@ -387,20 +394,15 @@ class EventDelegator {
|
|
|
387
394
|
}
|
|
388
395
|
}
|
|
389
396
|
const message = { action, data: {} };
|
|
397
|
+
// Extract standard data-* attributes from element
|
|
390
398
|
Array.from(element.attributes).forEach((attr) => {
|
|
391
|
-
if (attr.name.startsWith("
|
|
392
|
-
const key = attr.name.
|
|
393
|
-
message.data[key] = this.context.parseValue(attr.value);
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
Array.from(element.attributes).forEach((attr) => {
|
|
397
|
-
if (attr.name.startsWith("lvt-value-")) {
|
|
398
|
-
const key = attr.name.replace("lvt-value-", "");
|
|
399
|
+
if (attr.name.startsWith("data-") && attr.name !== "data-key" && attr.name !== "data-lvt-id") {
|
|
400
|
+
const key = attr.name.slice(5);
|
|
399
401
|
message.data[key] = this.context.parseValue(attr.value);
|
|
400
402
|
}
|
|
401
403
|
});
|
|
402
|
-
const throttleValue = element.getAttribute("lvt-throttle");
|
|
403
|
-
const debounceValue = element.getAttribute("lvt-debounce");
|
|
404
|
+
const throttleValue = element.getAttribute("lvt-mod:throttle");
|
|
405
|
+
const debounceValue = element.getAttribute("lvt-mod:debounce");
|
|
404
406
|
const handleAction = () => this.context.send(message);
|
|
405
407
|
if (throttleValue || debounceValue) {
|
|
406
408
|
if (!rateLimitedHandlers.has(element)) {
|
|
@@ -435,6 +437,11 @@ class EventDelegator {
|
|
|
435
437
|
window.addEventListener(eventType, listener);
|
|
436
438
|
});
|
|
437
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* Sets up click-away detection for lvt-el:*:on:click-away attributes.
|
|
442
|
+
* Instead of routing to a server action, click-away triggers client-side
|
|
443
|
+
* DOM manipulation via executeAction from reactive-attributes.
|
|
444
|
+
*/
|
|
438
445
|
setupClickAwayDelegation() {
|
|
439
446
|
const wrapperElement = this.context.getWrapperElement();
|
|
440
447
|
if (!wrapperElement)
|
|
@@ -450,133 +457,29 @@ class EventDelegator {
|
|
|
450
457
|
if (!currentWrapper)
|
|
451
458
|
return;
|
|
452
459
|
const target = e.target;
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
460
|
+
const clickAwaySelector = CLICK_AWAY_METHODS
|
|
461
|
+
.map(m => (0, lvt_selector_1.lvtSelector)(`lvt-el:${m}:on:click-away`))
|
|
462
|
+
.join(", ");
|
|
463
|
+
const clickAwayElements = currentWrapper.querySelectorAll(clickAwaySelector);
|
|
464
|
+
clickAwayElements.forEach((element) => {
|
|
465
|
+
if (element.contains(target))
|
|
466
|
+
return; // Click was inside, not away
|
|
467
|
+
Array.from(element.attributes).forEach((attr) => {
|
|
468
|
+
if (!attr.name.includes(":on:click-away"))
|
|
458
469
|
return;
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (attr.name.startsWith("lvt-value-")) {
|
|
468
|
-
const key = attr.name.replace("lvt-value-", "");
|
|
469
|
-
message.data[key] = this.context.parseValue(attr.value);
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
this.context.send(message);
|
|
473
|
-
}
|
|
470
|
+
const match = attr.name.match(/^lvt-el:(\w+):on:click-away$/);
|
|
471
|
+
if (!match)
|
|
472
|
+
return;
|
|
473
|
+
const method = CLICK_AWAY_METHOD_MAP[match[1].toLowerCase()];
|
|
474
|
+
if (!method)
|
|
475
|
+
return;
|
|
476
|
+
(0, reactive_attributes_1.executeAction)(element, method, attr.value);
|
|
477
|
+
});
|
|
474
478
|
});
|
|
475
479
|
};
|
|
476
480
|
document[listenerKey] = listener;
|
|
477
481
|
document.addEventListener("click", listener);
|
|
478
482
|
}
|
|
479
|
-
setupModalDelegation() {
|
|
480
|
-
const wrapperElement = this.context.getWrapperElement();
|
|
481
|
-
if (!wrapperElement)
|
|
482
|
-
return;
|
|
483
|
-
const wrapperId = wrapperElement.getAttribute("data-lvt-id");
|
|
484
|
-
const openListenerKey = `__lvt_modal_open_${wrapperId}`;
|
|
485
|
-
const existingOpenListener = document[openListenerKey];
|
|
486
|
-
if (existingOpenListener) {
|
|
487
|
-
document.removeEventListener("click", existingOpenListener);
|
|
488
|
-
}
|
|
489
|
-
const openListener = (e) => {
|
|
490
|
-
const currentWrapper = this.context.getWrapperElement();
|
|
491
|
-
if (!currentWrapper)
|
|
492
|
-
return;
|
|
493
|
-
const target = e.target?.closest("[lvt-modal-open]");
|
|
494
|
-
if (!target || !currentWrapper.contains(target))
|
|
495
|
-
return;
|
|
496
|
-
const modalId = target.getAttribute("lvt-modal-open");
|
|
497
|
-
if (!modalId)
|
|
498
|
-
return;
|
|
499
|
-
e.preventDefault();
|
|
500
|
-
this.context.openModal(modalId);
|
|
501
|
-
};
|
|
502
|
-
document[openListenerKey] = openListener;
|
|
503
|
-
document.addEventListener("click", openListener);
|
|
504
|
-
const closeListenerKey = `__lvt_modal_close_${wrapperId}`;
|
|
505
|
-
const existingCloseListener = document[closeListenerKey];
|
|
506
|
-
if (existingCloseListener) {
|
|
507
|
-
document.removeEventListener("click", existingCloseListener);
|
|
508
|
-
}
|
|
509
|
-
// Close listener is intentionally NOT scoped to wrapper (unlike openListener).
|
|
510
|
-
// Close buttons may be inside modals rendered in portals outside the wrapper.
|
|
511
|
-
// Instead, we verify the target modal exists by ID.
|
|
512
|
-
const closeListener = (e) => {
|
|
513
|
-
const target = e.target?.closest("[lvt-modal-close]");
|
|
514
|
-
if (!target)
|
|
515
|
-
return;
|
|
516
|
-
const modalId = target.getAttribute("lvt-modal-close");
|
|
517
|
-
if (!modalId)
|
|
518
|
-
return;
|
|
519
|
-
// Verify the modal exists before attempting to close
|
|
520
|
-
const modal = document.getElementById(modalId);
|
|
521
|
-
if (!modal)
|
|
522
|
-
return;
|
|
523
|
-
e.preventDefault();
|
|
524
|
-
this.context.closeModal(modalId);
|
|
525
|
-
};
|
|
526
|
-
document[closeListenerKey] = closeListener;
|
|
527
|
-
document.addEventListener("click", closeListener);
|
|
528
|
-
const backdropListenerKey = `__lvt_modal_backdrop_${wrapperId}`;
|
|
529
|
-
const existingBackdropListener = document[backdropListenerKey];
|
|
530
|
-
if (existingBackdropListener) {
|
|
531
|
-
document.removeEventListener("click", existingBackdropListener);
|
|
532
|
-
}
|
|
533
|
-
// Helper to close modal, dispatching action if data-modal-close-action is set
|
|
534
|
-
const closeModalWithAction = (modal, modalId) => {
|
|
535
|
-
const closeAction = modal.getAttribute("data-modal-close-action");
|
|
536
|
-
if (closeAction) {
|
|
537
|
-
this.context.send({ action: closeAction, data: {} });
|
|
538
|
-
}
|
|
539
|
-
else {
|
|
540
|
-
this.context.closeModal(modalId);
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
const backdropListener = (e) => {
|
|
544
|
-
const target = e.target;
|
|
545
|
-
// Only trigger if clicked directly on the backdrop element itself
|
|
546
|
-
if (!target.hasAttribute("data-modal-backdrop"))
|
|
547
|
-
return;
|
|
548
|
-
const modalId = target.getAttribute("data-modal-id");
|
|
549
|
-
if (!modalId)
|
|
550
|
-
return;
|
|
551
|
-
const modal = document.getElementById(modalId);
|
|
552
|
-
if (!modal)
|
|
553
|
-
return;
|
|
554
|
-
closeModalWithAction(modal, modalId);
|
|
555
|
-
};
|
|
556
|
-
document[backdropListenerKey] = backdropListener;
|
|
557
|
-
document.addEventListener("click", backdropListener);
|
|
558
|
-
const escapeListenerKey = `__lvt_modal_escape_${wrapperId}`;
|
|
559
|
-
const existingEscapeListener = document[escapeListenerKey];
|
|
560
|
-
if (existingEscapeListener) {
|
|
561
|
-
document.removeEventListener("keydown", existingEscapeListener);
|
|
562
|
-
}
|
|
563
|
-
const escapeListener = (e) => {
|
|
564
|
-
if (e.key !== "Escape")
|
|
565
|
-
return;
|
|
566
|
-
const currentWrapper = this.context.getWrapperElement();
|
|
567
|
-
if (!currentWrapper)
|
|
568
|
-
return;
|
|
569
|
-
const openModals = currentWrapper.querySelectorAll('[role="dialog"]:not([hidden])');
|
|
570
|
-
if (openModals.length > 0) {
|
|
571
|
-
const lastModal = openModals[openModals.length - 1];
|
|
572
|
-
if (lastModal.id) {
|
|
573
|
-
closeModalWithAction(lastModal, lastModal.id);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
document[escapeListenerKey] = escapeListener;
|
|
578
|
-
document.addEventListener("keydown", escapeListener);
|
|
579
|
-
}
|
|
580
483
|
/**
|
|
581
484
|
* Sets up focus trapping for elements with lvt-focus-trap attribute.
|
|
582
485
|
* Focus is trapped within the element, cycling through focusable elements
|