PageSourceSearch

https://cdn.lekker.de/website2/assets/@symfony/ux-live-component/live_controller-L12cPdP.js

js lekker.de collected 2026-09-24 09:01:03 UTC 84,742 bytes, 2,342 lines download raw bytes

1import { Controller } from "@hotwired/stimulus";
2var BackendRequest_default = class {
3	constructor(promise, actions, updateModels) {
4		this.isResolved = false;
5		this.promise = promise;
6		this.promise.then((response) => {
7			this.isResolved = true;
8			return response;
9		});
10		this.actions = actions;
11		this.updatedModels = updateModels;
12	}
13	containsOneOfActions(targetedActions) {
14		return this.actions.filter((action) => targetedActions.includes(action)).length > 0;
15	}
16	areAnyModelsUpdated(targetedModels) {
17		return this.updatedModels.filter((model) => targetedModels.includes(model)).length > 0;
18	}
19};
20var RequestBuilder_default = class {
21	constructor(url, method = "post", credentials = "same-origin") {
22		this.url = url;
23		this.method = method;
24		this.credentials = credentials;
25	}
26	buildRequest(props, actions, updated, children, updatedPropsFromParent, files) {
27		const splitUrl = this.url.split("?");
28		let [url] = splitUrl;
29		const [, queryString] = splitUrl;
30		const params = new URLSearchParams(queryString || "");
31		const fetchOptions = {};
32		fetchOptions.credentials = this.credentials;
33		fetchOptions.headers = {
34			Accept: "application/vnd.live-component+html",
35			"X-Requested-With": "XMLHttpRequest",
36			"X-Live-Url": window.location.pathname + window.location.search
37		};
38		const totalFiles = Object.entries(files).reduce((total, current) => total + current.length, 0);
39		const hasFingerprints = Object.keys(children).length > 0;
40		if (actions.length === 0 && totalFiles === 0 && this.method === "get" && this.willDataFitInUrl(JSON.stringify(props), JSON.stringify(updated), params, JSON.stringify(children), JSON.stringify(updatedPropsFromParent))) {
41			params.set("props", JSON.stringify(props));
42			params.set("updated", JSON.stringify(updated));
43			if (Object.keys(updatedPropsFromParent).length > 0) params.set("propsFromParent", JSON.stringify(updatedPropsFromParent));
44			if (hasFingerprints) params.set("children", JSON.stringify(children));
45			fetchOptions.method = "GET";
46		} else {
47			fetchOptions.method = "POST";
48			const requestData = {
49				props,
50				updated
51			};
52			if (Object.keys(updatedPropsFromParent).length > 0) requestData.propsFromParent = updatedPropsFromParent;
53			if (hasFingerprints) requestData.children = children;
54			if (actions.length > 0) if (actions.length === 1) {
55				requestData.args = actions[0].args;
56				url += `/${encodeURIComponent(actions[0].name)}`;
57			} else {
58				url += "/_batch";
59				requestData.actions = actions;
60			}
61			const formData = new FormData();
62			formData.append("data", JSON.stringify(requestData));
63			for (const [key, value] of Object.entries(files)) {
64				const length = value.length;
65				for (let i = 0; i < length; ++i) formData.append(key, value[i]);
66			}
67			fetchOptions.body = formData;
68		}
69		const paramsString = params.toString();
70		return {
71			url: `${url}${paramsString.length > 0 ? `?${paramsString}` : ""}`,
72			fetchOptions
73		};
74	}
75	willDataFitInUrl(propsJson, updatedJson, params, childrenJson, propsFromParentJson) {
76		return (new URLSearchParams(propsJson + updatedJson + childrenJson + propsFromParentJson).toString() + params.toString()).length < 1500;
77	}
78};
79var Backend_default = class {
80	constructor(url, method = "post", credentials = "same-origin") {
81		this.requestBuilder = new RequestBuilder_default(url, method, credentials);
82	}
83	makeRequest(props, actions, updated, children, updatedPropsFromParent, files) {
84		const { url, fetchOptions } = this.requestBuilder.buildRequest(props, actions, updated, children, updatedPropsFromParent, files);
85		return new BackendRequest_default(fetch(url, fetchOptions), actions.map((backendAction) => backendAction.name), Object.keys(updated));
86	}
87};
88var BackendResponse_default = class {
89	constructor(response) {
90		this.response = response;
91	}
92	async getBody() {
93		if (!this.body) this.body = await this.response.text();
94		return this.body;
95	}
96	getLiveUrl() {
97		if (void 0 === this.liveUrl) this.liveUrl = this.response.headers.get("X-Live-Url");
98		return this.liveUrl;
99	}
100};
101function getElementAsTagText(element) {
102	return element.innerHTML ? element.outerHTML.slice(0, element.outerHTML.indexOf(element.innerHTML)) : element.outerHTML;
103}
104let componentMapByElement = /* @__PURE__ */ new WeakMap();
105let componentMapByComponent = /* @__PURE__ */ new Map();
106const registerComponent = (component) => {
107	componentMapByElement.set(component.element, component);
108	componentMapByComponent.set(component, component.name);
109};
110const unregisterComponent = (component) => {
111	componentMapByElement.delete(component.element);
112	componentMapByComponent.delete(component);
113};
114const getComponent = (element) => new Promise((resolve, reject) => {
115	let count = 0;
116	const maxCount = 10;
117	const interval = setInterval(() => {
118		const component = componentMapByElement.get(element);
119		if (component) {
120			clearInterval(interval);
121			resolve(component);
122		}
123		count++;
124		if (count > maxCount) {
125			clearInterval(interval);
126			reject(/* @__PURE__ */ new Error(`Component not found for element ${getElementAsTagText(element)}`));
127		}
128	}, 5);
129});
130const findComponents = (currentComponent, onlyParents, onlyMatchName) => {
131	const components = [];
132	componentMapByComponent.forEach((componentName, component) => {
133		if (onlyParents && (currentComponent === component || !component.element.contains(currentComponent.element))) return;
134		if (onlyMatchName && componentName !== onlyMatchName) return;
135		components.push(component);
136	});
137	return components;
138};
139const findChildren = (currentComponent) => {
140	const children = [];
141	componentMapByComponent.forEach((componentName, component) => {
142		if (currentComponent === component) return;
143		if (!currentComponent.element.contains(component.element)) return;
144		let foundChildComponent = false;
145		componentMapByComponent.forEach((childComponentName, childComponent) => {
146			if (foundChildComponent) return;
147			if (childComponent === component) return;
148			if (childComponent.element.contains(component.element)) foundChildComponent = true;
149		});
150		children.push(component);
151	});
152	return children;
153};
154const findParent = (currentComponent) => {
155	let parentElement = currentComponent.element.parentElement;
156	while (parentElement) {
157		const component = componentMapByElement.get(parentElement);
158		if (component) return component;
159		parentElement = parentElement.parentElement;
160	}
161	return null;
162};
163function parseDirectives(content) {
164	const directives = [];
165	if (!content) return directives;
166	let currentActionName = "";
167	let currentArgumentValue = "";
168	let currentArguments = [];
169	let currentModifiers = [];
170	let state = "action";
171	const getLastActionName = () => {
172		if (currentActionName) return currentActionName;
173		if (directives.length === 0) throw new Error("Could not find any directives");
174		return directives[directives.length - 1].action;
175	};
176	const pushInstruction = () => {
177		directives.push({
178			action: currentActionName,
179			args: currentArguments,
180			modifiers: currentModifiers,
181			getString: () => {
182				return content;
183			}
184		});
185		currentActionName = "";
186		currentArgumentValue = "";
187		currentArguments = [];
188		currentModifiers = [];
189		state = "action";
190	};
191	const pushArgument = () => {
192		currentArguments.push(currentArgumentValue.trim());
193		currentArgumentValue = "";
194	};
195	const pushModifier = () => {
196		if (currentArguments.length > 1) throw new Error(`The modifier "${currentActionName}()" does not support multiple arguments.`);
197		currentModifiers.push({
198			name: currentActionName,
199			value: currentArguments.length > 0 ? currentArguments[0] : null
200		});
201		currentActionName = "";
202		currentArguments = [];
203		state = "action";
204	};
205	for (let i = 0; i < content.length; i++) {
206		const char = content[i];
207		switch (state) {
208			case "action":
209				if (char === "(") {
210					state = "arguments";
211					break;
212				}
213				if (char === " ") {
214					if (currentActionName) pushInstruction();
215					break;
216				}
217				if (char === "|") {
218					pushModifier();
219					break;
220				}
221				currentActionName += char;
222				break;
223			case "arguments":
224				if (char === ")") {
225					pushArgument();
226					state = "after_arguments";
227					break;
228				}
229				if (char === ",") {
230					pushArgument();
231					break;
232				}
233				currentArgumentValue += char;
234				break;
235			case "after_arguments":
236				if (char === "|") {
237					pushModifier();
238					break;
239				}
240				if (char !== " ") throw new Error(`Missing space after ${getLastActionName()}()`);
241				pushInstruction();
242				break;
243		}
244	}
245	switch (state) {
246		case "action":
247		case "after_arguments":
248			if (currentActionName) pushInstruction();
249			break;
250		default: throw new Error(`Did you forget to add a closing ")" after "${currentActionName}"?`);
251	}
252	return directives;
253}
254function combineSpacedArray(parts) {
255	const finalParts = [];
256	parts.forEach((part) => {
257		finalParts.push(...trimAll(part).split(" "));
258	});
259	return finalParts;
260}
261function trimAll(str) {
262	return str.replace(/[\s]+/g, " ").trim();
263}
264function normalizeModelName(model) {
265	return model.replace(/\[]$/, "").split("[").map((s) => s.replace("]", "")).join(".");
266}
267function getValueFromElement(element, valueStore) {
268	if (element instanceof HTMLInputElement) {
269		if (element.type === "checkbox") {
270			const modelNameData = getModelDirectiveFromElement(element, false);
271			if (modelNameData !== null) {
272				const modelValue = valueStore.get(modelNameData.action);
273				if (Array.isArray(modelValue)) return getMultipleCheckboxValue(element, modelValue);
274				if (Object(modelValue) === modelValue) return getMultipleCheckboxValue(element, Object.values(modelValue));
275			}
276			if (element.hasAttribute("value")) return element.checked ? element.getAttribute("value") : null;
277			return element.checked;
278		}
279		return inputValue(element);
280	}
281	if (element instanceof HTMLSelectElement) {
282		if (element.multiple) return Array.from(element.selectedOptions).map((el) => el.value);
283		return element.value;
284	}
285	if (element.hasAttribute("data-value")) return element.dataset.value;
286	if ("value" in element) return element.value;
287	if (element.hasAttribute("value")) return element.getAttribute("value");
288	return null;
289}
290function setValueOnElement(element, value) {
291	if (element instanceof HTMLInputElement) {
292		if (element.type === "file") return;
293		if (element.type === "radio") {
294			element.checked = element.value == value;
295			return;
296		}
297		if (element.type === "checkbox") {
298			if (Array.isArray(value)) element.checked = value.some((val) 
298=> val == element.value);
299			else if (element.hasAttribute("value")) element.checked = element.value == value;
300			else element.checked = value;
301			return;
302		}
303	}
304	if (element instanceof HTMLSelectElement) {
305		const arrayWrappedValue = [].concat(value).map((value) => {
306			return `${value}`;
307		});
308		Array.from(element.options).forEach((option) => {
309			option.selected = arrayWrappedValue.includes(option.value);
310		});
311		return;
312	}
313	value = value === void 0 ? "" : value;
314	element.value = value;
315}
316function getAllModelDirectiveFromElements(element) {
317	if (!element.dataset.model) return [];
318	const directives = parseDirectives(element.dataset.model);
319	directives.forEach((directive) => {
320		if (directive.args.length > 0) throw new Error(`The data-model="${element.dataset.model}" format is invalid: it does not support passing arguments to the model.`);
321		directive.action = normalizeModelName(directive.action);
322	});
323	return directives;
324}
325function getModelDirectiveFromElement(element, throwOnMissing = true) {
326	const dataModelDirectives = getAllModelDirectiveFromElements(element);
327	if (dataModelDirectives.length > 0) return dataModelDirectives[0];
328	if (element.getAttribute("name")) {
329		const formElement = element.closest("form");
330		if (formElement && "model" in formElement.dataset) {
331			const directive = parseDirectives(formElement.dataset.model || "*")[0];
332			if (directive.args.length > 0) throw new Error(`The data-model="${formElement.dataset.model}" format is invalid: it does not support passing arguments to the model.`);
333			directive.action = normalizeModelName(element.getAttribute("name"));
334			return directive;
335		}
336	}
337	if (!throwOnMissing) return null;
338	throw new Error(`Cannot determine the model name for "${getElementAsTagText(element)}": the element must either have a "data-model" (or "name" attribute living inside a <form data-model="*">).`);
339}
340function elementBelongsToThisComponent(element, component) {
341	if (component.element === element) return true;
342	if (!component.element.contains(element)) return false;
343	return element.closest("[data-controller~=\"live\"]") === component.element;
344}
345function cloneHTMLElement(element) {
346	const newElement = element.cloneNode(true);
347	if (!(newElement instanceof HTMLElement)) throw new Error("Could not clone element");
348	return newElement;
349}
350function htmlToElement(html) {
351	const template = document.createElement("template");
352	html = html.trim();
353	template.innerHTML = html;
354	if (template.content.childElementCount > 1) throw new Error(`Component HTML contains ${template.content.childElementCount} elements, but only 1 root element is allowed.`);
355	const child = template.content.firstElementChild;
356	if (!child) throw new Error("Child not found");
357	if (!(child instanceof HTMLElement)) throw new Error(`Created element is not an HTMLElement: ${html.trim()}`);
358	return child;
359}
360const getMultipleCheckboxValue = (element, currentValues) => {
361	const finalValues = [...currentValues];
362	const value = inputValue(element);
363	const index = currentValues.indexOf(value);
364	if (element.checked) {
365		if (index === -1) finalValues.push(value);
366		return finalValues;
367	}
368	if (index > -1) finalValues.splice(index, 1);
369	return finalValues;
370};
371const inputValue = (element) => element.dataset.value ? element.dataset.value : element.value;
372function isTextualInputElement(el) {
373	return el instanceof HTMLInputElement && [
374		"text",
375		"email",
376		"password",
377		"search",
378		"tel",
379		"url"
380	].includes(el.type);
381}
382function isTextareaElement(el) {
383	return el instanceof HTMLTextAreaElement;
384}
385function isNumericalInputElement(element) {
386	return element instanceof HTMLInputElement && ["number", "range"].includes(element.type);
387}
388var HookManager_default = class {
389	constructor() {
390		this.hooks = /* @__PURE__ */ new Map();
391	}
392	register(hookName, callback) {
393		const hooks = this.hooks.get(hookName) || [];
394		hooks.push(callback);
395		this.hooks.set(hookName, hooks);
396	}
397	unregister(hookName, callback) {
398		const hooks = this.hooks.get(hookName) || [];
399		const index = hooks.indexOf(callback);
400		if (index === -1) return;
401		hooks.splice(index, 1);
402		this.hooks.set(hookName, hooks);
403	}
404	triggerHook(hookName, ...args) {
405		(this.hooks.get(hookName) || []).forEach((callback) => {
406			callback(...args);
407		});
408	}
409};
410var Idiomorph = (function() {
411	"use strict";
412	let EMPTY_SET = /* @__PURE__ */ new Set();
413	let defaults = {
414		morphStyle: "outerHTML",
415		callbacks: {
416			beforeNodeAdded: noOp,
417			afterNodeAdded: noOp,
418			beforeNodeMorphed: noOp,
419			afterNodeMorphed: noOp,
420			beforeNodeRemoved: noOp,
421			afterNodeRemoved: noOp,
422			beforeAttributeUpdated: noOp
423		},
424		head: {
425			style: "merge",
426			shouldPreserve: function(elt) {
427				return elt.getAttribute("im-preserve") === "true";
428			},
429			shouldReAppend: function(elt) {
430				return elt.getAttribute("im-re-append") === "true";
431			},
432			shouldRemove: noOp,
433			afterHeadMorphed: noOp
434		}
435	};
436	function morph(oldNode, newContent, config = {}) {
437		if (oldNode instanceof Document) oldNode = oldNode.documentElement;
438		if (typeof newContent === "string") newContent = parseContent(newContent);
439		let normalizedContent = normalizeContent(newContent);
440		let ctx = createMorphContext(oldNode, normalizedContent, config);
441		return morphNormalizedContent(oldNode, normalizedContent, ctx);
442	}
443	function morphNormalizedContent(oldNode, normalizedNewContent, ctx) {
444		if (ctx.head.block) {
445			let oldHead = oldNode.querySelector("head");
446			let newHead = normalizedNewContent.querySelector("head");
447			if (oldHead && newHead) {
448				let promises = handleHeadElement(newHead, oldHead, ctx);
449				Promise.all(promises).then(function() {
450					morphNormalizedContent(oldNode, normalizedNewContent, Object.assign(ctx, { head: {
451						block: false,
452						ignore: true
453					} }));
454				});
455				return;
456			}
457		}
458		if (ctx.morphStyle === "innerHTML") {
459			morphChildren(normalizedNewContent, oldNode, ctx);
460			return oldNode.children;
461		} else if (ctx.morphStyle === "outerHTML" || ctx.morphStyle == null) {
462			let bestMatch = findBestNodeMatch(normalizedNewContent, oldNode, ctx);
463			let previousSibling = bestMatch?.previousSibling;
464			let nextSibling = bestMatch?.nextSibling;
465			let morphedNode = morphOldNodeTo(oldNode, bestMatch, ctx);
466			if (bestMatch) return insertSiblings(previousSibling, morphedNode, nextSibling);
467			else return [];
468		} else throw "Do not understand how to morph style " + ctx.morphStyle;
469	}
470	function ignoreValueOfActiveElement(possibleActiveElement, ctx) {
471		return ctx.ignoreActiveValue && possibleActiveElement === document.activeElement;
472	}
473	function morphOldNodeTo(oldNode, newContent, ctx) {
474		if (ctx.ignoreActive && oldNode === document.activeElement) {} else if (newContent == null) {
475			if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode;
476			oldNode.remove();
477			ctx.callbacks.afterNodeRemoved(oldNode);
478			return null;
479		} else if (!isSoftMatch(oldNode, newContent)) {
480			if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode;
481			if (ctx.callbacks.beforeNodeAdded(newContent) === false) return oldNode;
482			oldNode.parentElement.replaceChild(newContent, oldNode);
483			ctx.callbacks.afterNodeAdded(newContent);
484			ctx.callbacks.afterNodeRemoved(oldNode);
485			return newContent;
486		} else {
487			if (ctx.callbacks.beforeNodeMorphed(oldNode, newContent) === false) return oldNode;
488			if (oldNode instanceof HTMLHeadElement && ctx.head.ignore) {} else if (oldNode instanceof HTMLHeadElement && ctx.head.style !== "morph") handleHeadElement(newContent, oldNode, ctx);
489			else {
490				syncNodeFrom(newContent, oldNode, ctx);
491				if (!ignoreValueOfActiveElement(oldNode, ctx)) morphChildren(newContent, oldNode, ctx);
492			}
493			ctx.callbacks.afterNodeMorphed(oldNode, newContent);
494			return oldNode;
495		}
496	}
497	function morphChildren(newParent, oldParent, ctx) {
498		let nextNewChild = newParent.firstChild;
499		let insertionPoint = oldParent.firstChild;
500		let newChild;
501		while (nextNewChild) {
502			newChild = nextNewChild;
503			nextNewChild = newChild.nextSibling;
504			if (insertionPoint == null) {
505				if (ctx.callbacks.beforeNodeAdded(newChild) === false) return;
506				oldParent.appendChild(newChild);
507				ctx.callbacks.afterNodeAdded(newChild);
508				removeIdsFromConsideration(ctx, newChild);
509				continue;
510			}
511			if (isIdSetMatch(newChild, insertionPoint, ctx)) {
512				morphOldNodeTo(insertionPoint, newChild, ctx);
513				insertionPoint = insertionPoint.nextSibling;
514				removeIdsFromConsideration(ctx, newChild);
515				continue;
516			}
517			let idSetMatch = findIdSetMatch(newParent, oldParent, newChild, insertionPoint, ctx);
518			if (idSetMatch) {
519				insertionPoint = removeNodesBetween(insertionPoint, idSetMatch, ctx);
520				morphOldNodeTo(idSetMatch, newChild, ctx);
521				removeIdsFromConsideration(ctx, newChild);
522				continue;
523			}
524			let softMatch = findSoftMatch(newParent, oldParent, newChild, insertionPoint, ctx);
525			if (softMatch) {
526				insertionPoint = removeNodesBetween(insertionPoint, softMatch, ctx);
527				morphOldNodeTo(softMatch, newChild, ctx);
528				removeIdsFromConsideration(ctx, newChild);
529				continue;
530			}
531			if (ctx.callbacks.beforeNodeAdded(newChild) === false) return;
532			oldParent.insertBefore(newChild, insertionPoint);
533			ctx.callbacks.afterNodeAdded(newChild);
534			removeIdsFromConsideration(ctx, newChild);
535		}
536		while (insertionPoint !== null) {
537			let tempNode = insertionPoint;
538			insertionPoint = insertionPoint.nextSibling;
539			removeNode(tempNode, ctx);
540		}
541	}
542	function ignoreAttribute(attr, to, updateType, ctx) {
543		if (attr === "value" && ctx.ignoreActiveValue && to === document.activeElement) return true;
544		return ctx.callbacks.beforeAttributeUpdated(attr, to, updateType) === false;
545	}
546	function syncNodeFrom(from, to, ctx) {
547		let type = from.nodeType;
548		if (type === 1) {
549			const fromAttributes = from.attributes;
550			const toAttributes = to.attributes;
551			for (const fromAttribute of fromAttributes) {
552				if (ignoreAttribute(fromAttribute.name, to, "update", ctx)) continue;
553				if (to.getAttribute(fromAttribute.name) !== fromAttribute.value) to.setAttribute(fromAttribute.name, fromAttribute.value);
554			}
555			for (let i = toAttributes.length - 1; 0 <= i; i--) {
556				const toAttribute = toAttributes[i];
557				if (ignoreAttribute(toAttribute.name, to, "remove", ctx)) continue;
558				if (!from.hasAttribute(toAttribute.name)) to.removeAttribute(toAttribute.name);
559			}
560		}
561		if (type === 8 || type === 3) {
562			if (to.nodeValue !== from.nodeValue) to.nodeValue = from.nodeValue;
563		}
564		if (!ignoreValueOfActiveElement(to, ctx)) syncInputValue(from, to, ctx);
565	}
566	function syncBooleanAttribute(from, to, attributeName, ctx) {
567		if (from[attributeName] !== to[attributeName]) {
568			let ignoreUpdate = ignoreAttribute(attributeName, to, "update", ctx);
569			if (!ignoreUpdate) to[attributeName] = from[attributeName];
570			if (from[attributeName]) {
571				if (!ignoreUpdate) to.setAttribute(attributeName, from[attributeName]);
572			} else if (!ignoreAttribute(attributeName, to, "remove", ctx)) to.removeAttribute(attributeName);
573		}
574	}
575	function syncInputValue(from, to, ctx) {
576		if (from instanceof HTMLInputElement && to instanceof HTMLInputElement && from.type !== "file") {
577			let fromValue = from.value;
578			let toValue = to.value;
579			syncBooleanAttribute(from, to, "checked", ctx);
580			syncBooleanAttribute(from, to, "disabled", ctx);
581			if (!from.hasAttribute("value")) {
582				if (!ignoreAttribute("value", to, "remove", ctx)) {
583					to.value = "";
584					to.removeAttribute("value");
585				}
586			} else if (fromValue !== toValue) {
587				if (!ignoreAttribute("value", to, "update", ctx)) {
588					to.setAttribute("value", fromValue);
589					to.value = fromValue;
590				}
591			}
592		} else if (from instanceof HTMLOptionElement) syncBooleanAttribute(from, to, "selected", ctx);
593		else if (from instanceof HTMLTextAreaElement && to instanceof HTMLTextAreaElement) {
594			let fromValue = from.value;
595			let toValue = to.value;
596			if (ignoreAttribute("value", to, "update", ctx)) return;
597			if (fromValue !== toValue) to.value = fromValue;
598			if (to.firstChild && to.firstChild.nodeValue !== fromValue) to.firstChild.nodeValue = fromValue;
599		}
600	}
601	function handleHeadElement(newHeadTag, currentHead, ctx) {
602		let added = [];
603		let removed = [];
604		let preserved = [];
605		let nodesToAppend = [];
606		let headMergeStyle = ctx.head.style;
607		let srcToNewHeadNodes = /* @__PURE__ */ new Map();
608		for (const newHeadChild of newHeadTag.children) srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);
609		for (const currentHeadElt of currentHead.children) {
610			let inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);
611			let isReAppended = ctx.head.shouldReAppend(currentHeadElt);
612			let isPreserved = ctx.head.shouldPreserve(currentHeadElt);
613			if (inNewContent || isPreserved) if (isReAppended) removed.push(currentHeadElt);
614			else {
615				srcToNewHeadNodes.delete(currentHeadElt.outerHTML);
616				preserved.push(currentHeadElt);
617			}
618			else if (headMergeStyle === "append") {
619				if (isReAppended) {
620					removed.push(currentHeadElt);
621					nodesToAppend.push(currentHeadElt);
622				}
623			} else if (ctx.head.shouldRemove(currentHeadElt) !== false) removed.push(currentHeadElt);
624		}
625		nodesToAppend.push(...srcToNewHeadNodes.values());
626		log("to append: ", nodesToAppend);
627		let promises = [];
628		for (const newNode of nodesToAppend) {
629			log("adding: ", newNode);
630			let newElt = document.createRange().createContextualFragment(newNode.outerHTML).firstChild;
631			log(newElt);
632			if (ctx.callbacks.beforeNodeAdded(newElt) !== false) {
633				if (newElt.href || newElt.src) {
634					let resolve = null;
635					let promise = new Promise(function(_resolve) {
636						resolve = _resolve;
637					});
638					newElt.addEventListener("load", function() {
639						resolve();
640					});
641					promises.push(promise);
642				}
643				currentHead.appendChild(newElt);
644				ctx.callbacks.afterNodeAdded(newElt);
645				added.push(newElt);
646			}
647		}
648		for (const removedElement of removed) if (ctx.callbacks.beforeNodeRemoved(removedElement) !== false) {
649			currentHead.removeChild(removedElement);
650			ctx.callbacks.afterNodeRemoved(removedElement);
651		}
652		ctx.head.afterHeadMorphed(currentHead, {
653			added,
654			kept: preserved,
655			removed
656		});
657		return promises;
658	}
659	function log() {}
660	function noOp() {}
661	function mergeDefaults(config) {
662		let finalConfig = {};
663		Object.assign(finalConfig, defaults);
664		Object.assign(finalConfig, config);
665		finalConfig.callbacks = {};
666		Object.assign(finalConfig.callbacks, defaults.callbacks);
667		Object.assign(finalConfig.callbacks, config.callbacks);
668		finalConfig.head = {};
669		Object.assign(finalConfig.head, defaults.head);
670		Object.assign(finalConfig.head, config.head);
671		return finalConfig;
672	}
673	function createMorphContext(oldNode, newContent, config) {
674		config = mergeDefaults(config);
675		return {
676			target: oldNode,
677			newContent,
678			config,
679			morphStyle: config.morphStyle,
680			ignoreActive: config.ignoreActive,
681			ignoreActiveValue: config.ignoreActiveValue,
682			idMap: createIdMap(oldNode, newContent),
683			deadIds: /* @__PURE__ */ new Set(),
684			callbacks: config.callbacks,
685			head: config.head
686		};
687	}
688	function isIdSetMatch(node1, node2, ctx) {
689		if (node1 == null || node2 == null) return false;
690		if (node1.nodeType === node2.nodeType && node1.tagName === node2.tagName) if (node1.id !== "" && node1.id === node2.id) return true;
691		else return getIdIntersectionCount(ctx, node1, node2) > 0;
692		return false;
693	}
694	function isSoftMatch(node1, node2) {
695		if (node1 == null || node2 == null) return false;
696		return node1.nodeType === node2.nodeType && node1.tagName === node2.tagName;
697	}
698	function removeNodesBetween(startInclusive, endExclusive, ctx) {
699		while (startInclusive !== endExclusive) {
700			let tempNode = startInclusive;
701			startInclusive = startInclusive.nextSibling;
702			removeNode(tempNode, ctx);
703		}
704		removeIdsFromConsideration(ctx, endExclusive);
705		return endExclusive.nextSibling;
706	}
707	function findIdSetMatch(newContent, oldParent, newChild, insertionPoint, ctx) {
708		let newChildPotentialIdCount = getIdIntersectionCount(ctx, newChild, oldParent);
709		let potentialMatch = null;
710		if (newChildPotentialIdCount > 0) {
711			let potentialMatch = insertionPoint;
712			let otherMatchCount = 0;
713			while (potentialMatch != null) {
714				if (isIdSetMatch(newChild, potentialMatch, ctx)) return potentialMatch;
715				otherMatchCount += getIdIntersectionCount(ctx, potentialMatch, newContent);
716				if (otherMatchCount > newChildPotentialIdCount) return null;
717				potentialMatch = potentialMatch.nextSibling;
718			}
719		}
720		return potentialMatch;
721	}
722	function findSoftMatch(newContent, oldParent, newChild, insertionPoint, ctx) {
723		let potentialSoftMatch = insertionPoint;
724		let nextSibling = newChild.nextSibling;
725		let siblingSoftMatchCount = 0;
726		while (potentialSoftMatch != null) {
727			if (getIdIntersectionCount(ctx, potentialSoftMatch, newContent) > 0) return null;
728			if (isSoftMatch(newChild, potentialSoftMatch)) return potentialSoftMatch;
729			if (isSoftMatch(nextSibling, potentialSoftMatch)) {
730				siblingSoftMatchCount++;
731				nextSibling = nextSibling.nextSibling;
732				if (siblingSoftMatchCount >= 2) return null;
733			}
734			potentialSoftMatch = potentialSoftMatch.nextSibling;
735		}
736		return potentialSoftMatch;
737	}
738	function parseContent(newContent) {
739		let parser = new DOMParser();
740		let contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, "");
741		if (contentWithSvgsRemoved.match(/<\/html>/) || contentWithSvgsRemoved.match(/<\/head>/) || contentWithSvgsRemoved.match(/<\/body>/)) {
742			let content = parser.parseFromString(newContent, "text/html");
743			if (contentWithSvgsRemoved.match(/<\/html>/)) {
744				content.generatedByIdiomorph = true;
745				return content;
746			} else {
747				let htmlElement = content.firstChild;
748				if (htmlElement) {
749					htmlElement.generatedByIdiomorph = true;
750					return htmlElement;
751				} else return null;
752			}
753		} else {
754			let content = parser.parseFromString("<body><template>" + newContent + "</template></body>", "text/html").body.querySelector("template").content;
755			content.generatedByIdiomorph = true;
756			return content;
757		}
758	}
759	function normalizeContent(newContent) {
760		if (newContent == null) return document.createElement("div");
761		else if (newContent.generatedByIdiomorph) return newContent;
762		else if (newContent instanceof Node) {
763			const dummyParent = document.createElement("div");
764			dummyParent.append(newContent);
765			return dummyParent;
766		} else {
767			const dummyParent = document.createElement("div");
768			for (const elt of [...newContent]) dummyParent.append(elt);
769			return dummyParent;
770		}
771	}
772	function insertSiblings(previousSibling, morphedNode, nextSibling) {
773		let stack = [];
774		let added = [];
775		while (previousSibling != null) {
776			stack.push(previousSibling);
777			previousSibling = previousSibling.previousSibling;
778		}
779		while (stack.length > 0) {
780			let node = stack.pop();
781			added.push(node);
782			morphedNode.parentElement.insertBefore(node, morphedNode);
783		}
784		added.push(morphedNode);
785		while (nextSibling != null) {
786			stack.push(nextSibling);
787			added.push(nextSibling);
788			nextSibling = nextSibling.nextSibling;
789		}
790		while (stack.length > 0) morphedNode.parentElement.insertBefore(stack.pop(), morphedNode.nextSibling);
791		return added;
792	}
793	function findBestNodeMatch(newContent, oldNode, ctx) {
794		let currentElement;
795		currentElement = newContent.firstChild;
796		let bestElement = currentElement;
797		let score = 0;
798		while (currentElement) {
799			let newScore = scoreElement(currentElement, oldNode, ctx);
800			if (newScore > score) {
801				bestElement = currentElement;
802				score = newScore;
803			}
804			currentElement = currentElement.nextSibling;
805		}
806		return bestElement;
807	}
808	function scoreElement(node1, node2, ctx) {
809		if (isSoftMatch(node1, node2)) return .5 + getIdIntersectionCount(ctx, node1, node2);
810		return 0;
811	}
812	function removeNode(tempNode, ctx) {
813		removeIdsFromConsideration(ctx, tempNode);
814		if (ctx.callbacks.beforeNodeRemoved(tempNode) === false) return;
815		tempNode.remove();
816		ctx.callbacks.afterNodeRemoved(tempNode);
817	}
818	function isIdInConsideration(ctx, id) {
819		return !ctx.deadIds.has(id);
820	}
821	function idIsWithinNode(ctx, id, targetNode) {
822		return (ctx.idMap.get(targetNode) || EMPTY_SET).has(id);
823	}
824	function removeIdsFromConsideration(ctx, node) {
825		let idSet = ctx.idMap.get(node) || EMPTY_SET;
826		for (const id of idSet) ctx.deadIds.add(id);
827	}
828	function getIdIntersectionCount(ctx, node1, node2) {
829		let sourceSet = ctx.idMap.get(node1) || EMPTY_SET;
830		let matchCount = 0;
831		for (const id of sourceSet) if (isIdInConsideration(ctx, id) && idIsWithinNode(ctx, id, node2)) ++matchCount;
832		return matchCount;
833	}
834	function populateIdMapForNode(node, idMap) {
835		let nodeParent = node.parentElement;
836		let idElements = node.querySelectorAll("[id]");
837		for (const elt of idElements) {
838			let current = elt;
839			while (current !== nodeParent && current != null) {
840				let idSet = idMap.get(current);
841				if (idSet == null) {
842					idSet = /* @__PURE__ */ new Set();
843					idMap.set(current, idSet);
844				}
845				idSet.add(elt.id);
846				current = current.parentElement;
847			}
848		}
849	}
850	function createIdMap(oldContent, newContent) {
851		let idMap = /* @__PURE__ */ new Map();
852		populateIdMapForNode(oldContent, idMap);
853		populateIdMapForNode(newContent, idMap);
854		return idMap;
855	}
856	return {
857		morph,
858		defaults
859	};
860})();
861function normalizeAttributesForComparison(element) {
862	if (!(element instanceof HTMLInputElement && element.type === "file")) {
863		if ("value" in element) element.setAttribute("value", element.value);
864		else if (element.hasAttribute("value")) element.setAttribute("value", "");
865	}
866	Array.from(element.children).forEach((child) => {
867		normalizeAttributesForComparison(child);
868	});
869}
870const syncAttributes = (fromEl, toEl) => {
871	for (let i = 0; i < fromEl.attributes.length; i++) {
872		const attr = fromEl.attributes[i];
873		toEl.setAttribute(attr.name, attr.value);
874	}
875};
876function executeMorphdom(rootFromElement, rootToElement, modifiedFieldElements, getElementValue, externalMutationTracker) {
877	const originalElementIdsToSwapAfter = [];
878	const originalElementsToPreserve = /* @__PURE__ */ new Map();
879	const markElementAsNeedingPostMorphSwap = (id, replaceWithClone) => {
880		const oldElement = originalElementsToPreserve.get(id);
881		if (!(oldElement instanceof HTMLElement)) throw new Error(`Original element with id ${id} not found`);
882		originalElementIdsToSwapAfter.push(id);
883		if (!replaceWithClone) return null;
884		const clonedOldElement = cloneHTMLElement(oldElement);
885		oldElement.replaceWith(clonedOldElement);
886		return clonedOldElement;
887	};
888	rootToElement.querySelectorAll("[data-live-preserve]").forEach((newElement) => {
889		const id = newElement.id;
890		if (!id) throw new Error("The data-live-preserve attribute requires an id attribute to be set on the element");
891		const oldElement = rootFromElement.querySelector(`#${id}`);
892		if (!(oldElement instanceof HTMLElement)) throw new Error(`The element with id "${id}" was not found in the original HTML`);
893		newElement.removeAttribute("data-live-preserve");
894		originalElementsToPreserve.set(id, oldElement);
895		syncAttributes(newElement, oldElement);
896	});
897	Idiomorph.morph(rootFromElement, rootToElement, { callbacks: {
898		beforeNodeMorphed: (fromEl, toEl) => {
899			if (!(fromEl instanceof Element) || !(toEl instanceof Element)) return true;
900			if (fromEl === rootFromElement) return true;
901			if (fromEl.id && originalElementsToPreserve.has(fromEl.id)) {
902				if (fromEl.id === toEl.id) return false;
903				const clonedFromEl = markElementAsNeedingPostMorphSwap(fromEl.id, true);
904				if (!clonedFromEl) throw new Error("missing clone");
905				Idiomorph.morph(clonedFromEl, toEl);
906				return false;
907			}
908			if (fromEl instanceof HTMLElement && toEl instanceof HTMLElement) {
909				if (typeof fromEl.__x !== "undefined") {
910					if (!window.Alpine) throw new Error("Unable to access Alpine.js though the global window.Alpine variable. Please make sure Alpine.js is loaded before Symfony UX LiveComponent.");
911					if (typeof window.Alpine.morph !== "function") throw new Error("Unable to access Alpine.js morph function. Please make sure the Alpine.js Morp
911h plugin is installed and loaded, see https://alpinejs.dev/plugins/morph for more information.");
912					window.Alpine.morph(fromEl.__x, toEl);
913				}
914				if (externalMutationTracker.wasElementAdded(fromEl)) {
915					fromEl.insertAdjacentElement("afterend", toEl);
916					return false;
917				}
918				if (modifiedFieldElements.includes(fromEl)) setValueOnElement(toEl, getElementValue(fromEl));
919				if (fromEl === document.activeElement && fromEl !== document.body && null !== getModelDirectiveFromElement(fromEl, false)) setValueOnElement(toEl, getElementValue(fromEl));
920				const elementChanges = externalMutationTracker.getChangedElement(fromEl);
921				if (elementChanges) elementChanges.applyToElement(toEl);
922				if (fromEl.nodeName.toUpperCase() !== "OPTION" && fromEl.isEqualNode(toEl)) {
923					const normalizedFromEl = cloneHTMLElement(fromEl);
924					normalizeAttributesForComparison(normalizedFromEl);
925					const normalizedToEl = cloneHTMLElement(toEl);
926					normalizeAttributesForComparison(normalizedToEl);
927					if (normalizedFromEl.isEqualNode(normalizedToEl)) return false;
928				}
929			}
930			if (fromEl.hasAttribute("data-skip-morph") || fromEl.id && fromEl.id !== toEl.id) {
931				fromEl.innerHTML = toEl.innerHTML;
932				return true;
933			}
934			if (fromEl.parentElement?.hasAttribute("data-skip-morph")) return false;
935			return !fromEl.hasAttribute("data-live-ignore");
936		},
937		beforeNodeRemoved(node) {
938			if (!(node instanceof HTMLElement)) return true;
939			if (node.id && originalElementsToPreserve.has(node.id)) {
940				markElementAsNeedingPostMorphSwap(node.id, false);
941				return true;
942			}
943			if (externalMutationTracker.wasElementAdded(node)) return false;
944			return !node.hasAttribute("data-live-ignore");
945		}
946	} });
947	originalElementIdsToSwapAfter.forEach((id) => {
948		const newElement = rootFromElement.querySelector(`#${id}`);
949		const originalElement = originalElementsToPreserve.get(id);
950		if (!(newElement instanceof HTMLElement) || !(originalElement instanceof HTMLElement)) throw new Error("Missing elements.");
951		newElement.replaceWith(originalElement);
952	});
953}
954var ChangingItemsTracker_default = class {
955	constructor() {
956		this.changedItems = /* @__PURE__ */ new Map();
957		this.removedItems = /* @__PURE__ */ new Map();
958	}
959	setItem(itemName, newValue, previousValue) {
960		if (this.removedItems.has(itemName)) {
961			const removedRecord = this.removedItems.get(itemName);
962			this.removedItems.delete(itemName);
963			if (removedRecord.original === newValue) return;
964		}
965		if (this.changedItems.has(itemName)) {
966			const originalRecord = this.changedItems.get(itemName);
967			if (originalRecord.original === newValue) {
968				this.changedItems.delete(itemName);
969				return;
970			}
971			this.changedItems.set(itemName, {
972				original: originalRecord.original,
973				new: newValue
974			});
975			return;
976		}
977		this.changedItems.set(itemName, {
978			original: previousValue,
979			new: newValue
980		});
981	}
982	removeItem(itemName, currentValue) {
983		let trueOriginalValue = currentValue;
984		if (this.changedItems.has(itemName)) {
985			trueOriginalValue = this.changedItems.get(itemName).original;
986			this.changedItems.delete(itemName);
987			if (trueOriginalValue === null) return;
988		}
989		if (!this.removedItems.has(itemName)) this.removedItems.set(itemName, { original: trueOriginalValue });
990	}
991	getChangedItems() {
992		return Array.from(this.changedItems, ([name, { new: value }]) => ({
993			name,
994			value
995		}));
996	}
997	getRemovedItems() {
998		return Array.from(this.removedItems.keys());
999	}
1000	isEmpty() {
1001		return this.changedItems.size === 0 && this.removedItems.size === 0;
1002	}
1003};
1004var ElementChanges = class {
1005	constructor() {
1006		this.addedClasses = /* @__PURE__ */ new Set();
1007		this.removedClasses = /* @__PURE__ */ new Set();
1008		this.styleChanges = new ChangingItemsTracker_default();
1009		this.attributeChanges = new ChangingItemsTracker_default();
1010	}
1011	addClass(className) {
1012		if (!this.removedClasses.delete(className)) this.addedClasses.add(className);
1013	}
1014	removeClass(className) {
1015		if (!this.addedClasses.delete(className)) this.removedClasses.add(className);
1016	}
1017	addStyle(styleName, newValue, originalValue) {
1018		this.styleChanges.setItem(styleName, newValue, originalValue);
1019	}
1020	removeStyle(styleName, originalValue) {
1021		this.styleChanges.removeItem(styleName, originalValue);
1022	}
1023	addAttribute(attributeName, newValue, originalValue) {
1024		this.attributeChanges.setItem(attributeName, newValue, originalValue);
1025	}
1026	removeAttribute(attributeName, originalValue) {
1027		this.attributeChanges.removeItem(attributeName, originalValue);
1028	}
1029	getAddedClasses() {
1030		return [...this.addedClasses];
1031	}
1032	getRemovedClasses() {
1033		return [...this.removedClasses];
1034	}
1035	getChangedStyles() {
1036		return this.styleChanges.getChangedItems();
1037	}
1038	getRemovedStyles() {
1039		return this.styleChanges.getRemovedItems();
1040	}
1041	getChangedAttributes() {
1042		return this.attributeChanges.getChangedItems();
1043	}
1044	getRemovedAttributes() {
1045		return this.attributeChanges.getRemovedItems();
1046	}
1047	applyToElement(element) {
1048		element.classList.add(...this.addedClasses);
1049		element.classList.remove(...this.removedClasses);
1050		this.styleChanges.getChangedItems().forEach((change) => {
1051			if (/!\s*important/i.test(change.value)) element.style.setProperty(change.name, change.value.replace(/!\s*important/i, "").trim(), "important");
1052			else element.style.setProperty(change.name, change.value);
1053		});
1054		this.styleChanges.getRemovedItems().forEach((styleName) => {
1055			element.style.removeProperty(styleName);
1056		});
1057		this.attributeChanges.getChangedItems().forEach((change) => {
1058			element.setAttribute(change.name, change.value);
1059		});
1060		this.attributeChanges.getRemovedItems().forEach((attributeName) => {
1061			element.removeAttribute(attributeName);
1062		});
1063	}
1064	isEmpty() {
1065		return this.addedClasses.size === 0 && this.removedClasses.size === 0 && this.styleChanges.isEmpty() && this.attributeChanges.isEmpty();
1066	}
1067};
1068var ExternalMutationTracker_default = class {
1069	constructor(element, shouldTrackChangeCallback) {
1070		this.changedElements = /* @__PURE__ */ new WeakMap();
1071		this.changedElementsCount = 0;
1072		this.addedElements = [];
1073		this.removedElements = [];
1074		this.isStarted = false;
1075		this.element = element;
1076		this.shouldTrackChangeCallback = shouldTrackChangeCallback;
1077		this.mutationObserver = new MutationObserver(this.onMutations.bind(this));
1078	}
1079	start() {
1080		if (this.isStarted) return;
1081		this.mutationObserver.observe(this.element, {
1082			childList: true,
1083			subtree: true,
1084			attributes: true,
1085			attributeOldValue: true
1086		});
1087		this.isStarted = true;
1088	}
1089	stop() {
1090		if (this.isStarted) {
1091			this.mutationObserver.disconnect();
1092			this.isStarted = false;
1093		}
1094	}
1095	getChangedElement(element) {
1096		return this.changedElements.has(element) ? this.changedElements.get(element) : null;
1097	}
1098	getAddedElements() {
1099		return this.addedElements;
1100	}
1101	wasElementAdded(element) {
1102		return this.addedElements.includes(element);
1103	}
1104	handlePendingChanges() {
1105		this.onMutations(this.mutationObserver.takeRecords());
1106	}
1107	onMutations(mutations) {
1108		const handledAttributeMutations = /* @__PURE__ */ new WeakMap();
1109		for (const mutation of mutations) {
1110			const element = mutation.target;
1111			if (!this.shouldTrackChangeCallback(element)) continue;
1112			if (this.isElementAddedByTranslation(element)) continue;
1113			let isChangeInAddedElement = false;
1114			for (const addedElement of this.addedElements) if (addedElement.contains(element)) {
1115				isChangeInAddedElement = true;
1116				break;
1117			}
1118			if (isChangeInAddedElement) continue;
1119			switch (mutation.type) {
1120				case "childList":
1121					this.handleChildListMutation(mutation);
1122					break;
1123				case "attributes":
1124					if (!handledAttributeMutations.has(element)) handledAttributeMutations.set(element, []);
1125					if (!handledAttributeMutations.get(element).includes(mutation.attributeName)) {
1126						this.handleAttributeMutation(mutation);
1127						handledAttributeMutations.set(element, [...handledAttributeMutations.get(element), mutation.attributeName]);
1128					}
1129					break;
1130			}
1131		}
1132	}
1133	handleChildListMutation(mutation) {
1134		mutation.addedNodes.forEach((node) => {
1135			if (!(node instanceof Element)) return;
1136			if (this.removedElements.includes(node)) {
1137				this.removedElements.splice(this.removedElements.indexOf(node), 1);
1138				return;
1139			}
1140			if (this.isElementAddedByTranslation(node)) return;
1141			this.addedElements.push(node);
1142		});
1143		mutation.removedNodes.forEach((node) => {
1144			if (!(node instanceof Element)) return;
1145			if (this.addedElements.includes(node)) {
1146				this.addedElements.splice(this.addedElements.indexOf(node), 1);
1147				return;
1148			}
1149			this.removedElements.push(node);
1150		});
1151	}
1152	handleAttributeMutation(mutation) {
1153		const element = mutation.target;
1154		if (!this.changedElements.has(element)) {
1155			this.changedElements.set(element, new ElementChanges());
1156			this.changedElementsCount++;
1157		}
1158		const changedElement = this.changedElements.get(element);
1159		switch (mutation.attributeName) {
1160			case "class":
1161				this.handleClassAttributeMutation(mutation, changedElement);
1162				break;
1163			case "style":
1164				this.handleStyleAttributeMutation(mutation, changedElement);
1165				break;
1166			default: this.handleGenericAttributeMutation(mutation, changedElement);
1167		}
1168		if (changedElement.isEmpty()) {
1169			this.changedElements.delete(element);
1170			this.changedElementsCount--;
1171		}
1172	}
1173	handleClassAttributeMutation(mutation, elementChanges) {
1174		const element = mutation.target;
1175		const previousValues = (mutation.oldValue || "").match(/(\S+)/gu) || [];
1176		const newValues = [].slice.call(element.classList);
1177		const addedValues = newValues.filter((value) => !previousValues.includes(value));
1178		const removedValues = previousValues.filter((value) => !newValues.includes(value));
1179		addedValues.forEach((value) => {
1180			elementChanges.addClass(value);
1181		});
1182		removedValues.forEach((value) => {
1183			elementChanges.removeClass(value);
1184		});
1185	}
1186	handleStyleAttributeMutation(mutation, elementChanges) {
1187		const element = mutation.target;
1188		const previousValue = mutation.oldValue || "";
1189		const previousStyles = this.extractStyles(previousValue);
1190		const newValue = element.getAttribute("style") || "";
1191		const newStyles = this.extractStyles(newValue);
1192		const addedOrChangedStyles = Object.keys(newStyles).filter((key) => previousStyles[key] === void 0 || previousStyles[key] !== newStyles[key]);
1193		const removedStyles = Object.keys(previousStyles).filter((key) => !newStyles[key]);
1194		addedOrChangedStyles.forEach((style) => {
1195			elementChanges.addStyle(style, newStyles[style], previousStyles[style] === void 0 ? null : previousStyles[style]);
1196		});
1197		removedStyles.forEach((style) => {
1198			elementChanges.removeStyle(style, previousStyles[style]);
1199		});
1200	}
1201	handleGenericAttributeMutation(mutation, elementChanges) {
1202		const attributeName = mutation.attributeName;
1203		const element = mutation.target;
1204		let oldValue = mutation.oldValue;
1205		let newValue = element.getAttribute(attributeName);
1206		if (oldValue === attributeName) oldValue = "";
1207		if (newValue === attributeName) newValue = "";
1208		if (!element.hasAttribute(attributeName)) {
1209			if (oldValue === null) return;
1210			elementChanges.removeAttribute(attributeName, mutation.oldValue);
1211			return;
1212		}
1213		if (newValue === oldValue) return;
1214		elementChanges.addAttribute(attributeName, element.getAttribute(attributeName), mutation.oldValue);
1215	}
1216	extractStyles(styles) {
1217		const styleObject = {};
1218		styles.split(";").forEach((style) => {
1219			const parts = style.split(":");
1220			if (parts.length === 1) return;
1221			const property = parts[0].trim();
1222			styleObject[property] = parts.slice(1).join(":").trim();
1223		});
1224		return styleObject;
1225	}
1226	isElementAddedByTranslation(element) {
1227		return element.tagName === "FONT" && element.getAttribute("style") === "vertical-align: inherit;";
1228	}
1229};
1230var UnsyncedInputsTracker_default = class {
1231	constructor(component, modelElementResolver) {
1232		this.elementEventListeners = [{
1233			event: "input",
1234			callback: (event) => this.handleInputEvent(event)
1235		}];
1236		this.component = component;
1237		this.modelElementResolver = modelElementResolver;
1238		this.unsyncedInputs = new UnsyncedInputContainer();
1239	}
1240	activate() {
1241		this.elementEventListeners.forEach(({ event, callback }) => {
1242			this.component.element.addEventListener(event, callback);
1243		});
1244	}
1245	deactivate() {
1246		this.elementEventListeners.forEach(({ event, callback }) => {
1247			this.component.element.removeEventListener(event, callback);
1248		});
1249	}
1250	markModelAsSynced(modelName) {
1251		this.unsyncedInputs.markModelAsSynced(modelName);
1252	}
1253	handleInputEvent(event) {
1254		const target = event.target;
1255		if (!target) return;
1256		this.updateModelFromElement(target);
1257	}
1258	updateModelFromElement(element) {
1259		if (!elementBelongsToThisComponent(element, this.component)) return;
1260		if (!(element instanceof HTMLElement)) throw new Error("Could not update model for non HTMLElement");
1261		const modelName = this.modelElementResolver.getModelName(element);
1262		this.unsyncedInputs.add(element, modelName);
1263	}
1264	getUnsyncedInputs() {
1265		return this.unsyncedInputs.allUnsyncedInputs();
1266	}
1267	getUnsyncedModels() {
1268		return Array.from(this.unsyncedInputs.getUnsyncedModelNames());
1269	}
1270	resetUnsyncedFields() {
1271		this.unsyncedInputs.resetUnsyncedFields();
1272	}
1273};
1274var UnsyncedInputContainer = class {
1275	constructor() {
1276		this.unsyncedNonModelFields = [];
1277		this.unsyncedModelNames = [];
1278		this.unsyncedModelFields = /* @__PURE__ */ new Map();
1279	}
1280	add(element, modelName = null) {
1281		if (modelName) {
1282			this.unsyncedModelFields.set(modelName, element);
1283			if (!this.unsyncedModelNames.includes(modelName)) this.unsyncedModelNames.push(modelName);
1284			return;
1285		}
1286		this.unsyncedNonModelFields.push(element);
1287	}
1288	resetUnsyncedFields() {
1289		this.unsyncedModelFields.forEach((value, key) => {
1290			if (!this.unsyncedModelNames.includes(key)) this.unsyncedModelFields.delete(key);
1291		});
1292	}
1293	allUnsyncedInputs() {
1294		return [...this.unsyncedNonModelFields, ...this.unsyncedModelFields.values()];
1295	}
1296	markModelAsSynced(modelName) {
1297		const index = this.unsyncedModelNames.indexOf(modelName);
1298		if (index !== -1) this.unsyncedModelNames.splice(index, 1);
1299	}
1300	getUnsyncedModelNames() {
1301		return this.unsyncedModelNames;
1302	}
1303};
1304function getDeepData(data, propertyPath) {
1305	const { currentLevelData, finalKey } = parseDeepData(data, propertyPath);
1306	if (currentLevelData === void 0) return;
1307	return currentLevelData[finalKey];
1308}
1309const parseDeepData = (data, propertyPath) => {
1310	const finalData = JSON.parse(JSON.stringify(data));
1311	let currentLevelData = finalData;
1312	const parts = propertyPath.split(".");
1313	for (let i = 0; i < parts.length - 1; i++) currentLevelData = currentLevelData[parts[i]];
1314	const finalKey = parts[parts.length - 1];
1315	return {
1316		currentLevelData,
1317		finalData,
1318		finalKey,
1319		parts
1320	};
1321};
1322var ValueStore_default = class {
1323	constructor(props) {
1324		this.props = {};
1325		this.dirtyProps = {};
1326		this.pendingProps = {};
1327		this.updatedPropsFromParent = {};
1328		this.props = props;
1329	}
1330	get(name) {
1331		const normalizedName = normalizeModelName(name);
1332		if (this.dirtyProps[normalizedName] !== void 0) return this.dirtyProps[normalizedName];
1333		if (this.pendingProps[normalizedName] !== void 0) return this.pendingProps[normalizedName];
1334		if (this.props[normalizedName] !== void 0) return this.props[normalizedName];
1335		return getDeepData(this.props, normalizedName);
1336	}
1337	has(name) {
1338		return this.get(name) !== void 0;
1339	}
1340	set(name, value) {
1341		const normalizedName = normalizeModelName(name);
1342		if (this.get(normalizedName) === value) return false;
1343		this.dirtyProps[normalizedName] = value;
1344		return true;
1345	}
1346	getOriginalProps() {
1347		return { ...this.props };
1348	}
1349	getDirtyProps() {
1350		return { ...this.dirtyProps };
1351	}
1352	getUpdatedPropsFromParent() {
1353		return { ...this.updatedPropsFromParent };
1354	}
1355	flushDirtyPropsToPending() {
1356		this.pendingProps = { ...this.dirtyProps };
1357		this.dirtyProps = {};
1358	}
1359	reinitializeAllProps(props) {
1360		this.props = props;
1361		this.updatedPropsFromParent = {};
1362		this.pendingProps = {};
1363	}
1364	pushPendingPropsBackToDirty() {
1365		this.dirtyProps = {
1366			...this.pendingProps,
1367			...this.dirtyProps
1368		};
1369		this.pendingProps = {};
1370	}
1371	storeNewPropsFromParent(props) {
1372		let changed = false;
1373		for (const [key, value] of Object.entries(props)) if (this.get(key) !== value) changed = true;
1374		if (changed) this.updatedPropsFromParent = props;
1375		return changed;
1376	}
1377};
1378var Component = class {
1379	constructor(element, name, props, listeners, id, backend, elementDriver) {
1380		this.fingerprint = "";
1381		this.defaultDebounce = 150;
1382		this.backendRequest = null;
1383		this.pendingActions = [];
1384		this.pendingFiles = {};
1385		this.isRequestPending = false;
1386		this.requestDebounceTimeout = null;
1387		this.element = element;
1388		this.name = name;
1389		this.backend = backend;
1390		this.elementDriver = elementDriver;
1391		this.id = id;
1392		this.listeners = /* @__PURE__ */ new Map();
1393		listeners.forEach((listener) => {
1394			if (!this.listeners.has(listener.event)) this.listeners.set(listener.event, []);
1395			this.listeners.get(listener.event)?.push(listener.action);
1396		});
1397		this.valueStore = new ValueStore_default(props);
1398		this.unsyncedInputsTracker = new UnsyncedInputsTracker_default(this, elementDriver);
1399		this.hooks = new HookManager_default();
1400		this.resetPromise();
1401		this.externalMutationTracker = new ExternalMutationTracker_default(this.element, (element) => elementBelongsToThisComponent(element, this));
1402		this.externalMutationTracker.start();
1403	}
1404	addPlugin(plugin) {
1405		plugin.attachToComponent(this);
1406	}
1407	connect() {
1408		registerComponent(this);
1409		this.hooks.triggerHook("connect", this);
1410		this.unsyncedInputsTracker.activate();
1411		this.externalMutationTracker.start();
1412	}
1413	disconnect() {
1414		unregisterComponent(this);
1415		this.hooks.triggerHook("disconnect", this);
1416		this.clearRequestDebounceTimeout();
1417		this.unsyncedInputsTracker.deactivate();
1418		this.externalMutationTracker.stop();
1419	}
1420	on(hookName, callback) {
1421		this.hooks.register(hookName, callback);
1422	}
1423	off(hookName, callback) {
1424		this.hooks.unregister(hookName, callback);
1425	}
1426	set(model, value, reRender = false, debounce = false) {
1427		const promise = this.nextRequestPromise;
1428		const modelName = normalizeModelName(model);
1429		if (!this.valueStore.has(modelName)) throw new Error(`Invalid model name "${model}".`);
1430		const isChanged = this.valueStore.set(modelName, value);
1431		this.hooks.triggerHook("model:set", model, value, this);
1432		this.unsyncedInputsTracker.markModelAsSynced(modelName);
1433		if (reRender && isChanged) this.debouncedStartRequest(debounce);
1434		return promise;
1435	}
1436	getData(model) {
1437		const modelName = normalizeModelName(model);
1438		if (!this.valueStore.has(modelName)) throw new Error(`Invalid model "${model}".`);
1439		return this.valueStore.get(modelName);
1440	}
1441	action(name, args = {}, debounce = false) {
1442		const promise = this.nextRequestPromise;
1443		this.pendingActions.push({
1444			name,
1445			args
1446		});
1447		this.debouncedStartRequest(debounce);
1448		return promise;
1449	}
1450	files(key, input) {
1451		this.pendingFiles[key] = input;
1452	}
1453	render() {
1454		const promise = this.nextRequestPromise;
1455		this.tryStartingRequest();
1456		return promise;
1457	}
1458	getUnsyncedModels() {
1459		return this.unsyncedInputsTracker.getUnsyncedModels();
1460	}
1461	emit(name, data, onlyMatchingComponentsNamed = null) {
1462		this.performEmit(name, data, false, onlyMatchingComponentsNamed);
1463	}
1464	emitUp(name, data, onlyMatchingComponentsNamed = null) {
1465		this.performEmit(name, data, true, onlyMatchingComponentsNamed);
1466	}
1467	emitSelf(name, data) {
1468		this.doEmit(name, data);
1469	}
1470	performEmit(name, data, emitUp, matchingName) {
1471		findComponents(this, emitUp, matchingName).forEach((component) => {
1472			component.doEmit(name, data);
1473		});
1474	}
1475	doEmit(name, data) {
1476		if (!this.listeners.has(name)) return;
1477		(this.listeners.get(name) || []).forEach((action) => {
1478			this.action(action, data, 1);
1479		});
1480	}
1481	isTurboEnabled() {
1482		return typeof Turbo !== "undefined" && !this.element.closest("[data-turbo=\"false\"]");
1483	}
1484	tryStartingRequest() {
1485		if (!this.backendRequest) {
1486			this.performRequest();
1487			return;
1488		}
1489		this.isRequestPending = true;
1490	}
1491	performRequest() {
1492		const thisPromiseResolve = this.nextRequestPromiseResolve;
1493		this.resetPromise();
1494		this.unsyncedInputsTracker.resetUnsyncedFields();
1495		const filesToSend = {};
1496		for (const [key, value] of Object.entries(this.pendingFiles)) if (value.files) filesToSend[key] = value.files;
1497		const actionsToSend = this.pendingActions.slice(0, 50);
1498		const remainingActions = this.pendingActions.slice(50);
1499		const requestConfig = {
1500			props: this.valueStore.getOriginalProps(),
1501			actions: actionsToSend,
1502			updated: this.valueStore.getDirtyProps(),
1503			children: {},
1504			updatedPropsFromParent: this.valueStore.getUpdatedPropsFromParent(),
1505			files: filesToSend
1506		};
1507		this.hooks.triggerHook("request:started", requestConfig);
1508		this.backendRequest = this.backend.makeRequest(requestConfig.props, requestConfig.actions, requestConfig.updated, requestConfig.children, requestConfig.updatedPropsFromParent, requestConfig.files);
1509		this.hooks.triggerHook("loading.state:started", this.element, this.backendRequest);
1510		this.pendingActions = remainingActions;
1511		this.valueStore.flushDirtyPropsToPending();
1512		this.isRequestPending = remainingActions.length > 0;
1513		this.backendRequest.promise.then(async (response) => {
1514			const backendResponse = new BackendResponse_default(response);
1515			const html = await backendResponse.getBody();
1516			for (const input of Object.values(this.pendingFiles)) input.value = "";
1517			const headers = backendResponse.response.headers;
1518			if (!headers.get("Content-Type")?.includes("application/vnd.live-component+html") && !headers.get("X-Live-Redirect")) {
1519				const controls = { displayError: true };
1520				this.valueStore.pushPendingPropsBackToDirty();
1521				this.hooks.triggerHook("response:error", backendResponse, controls);
1522				if (controls.displayError) this.renderError(html);
1523				this.backendRequest = null;
1524				thisPromiseResolve(backendResponse);
1525				return response;
1526			}
1527			const liveUrl = backendResponse.getLiveUrl();
1528			if (liveUrl) history.replaceState(history.state, "", new URL(liveUrl + window.location.hash, window.location.origin));
1529			this.processRerender(html, backendResponse);
1530			this.backendRequest = null;
1531			thisPromiseResolve(backendResponse);
1532			if (this.isRequestPending) {
1533				this.isRequestPending = false;
1534				this.performRequest();
1535			}
1536			return response;
1537		});
1538	}
1539	processRerender(html, backendResponse) {
1540		const controls = { shouldRender: true };
1541		this.hooks.triggerHook("render:started", html, backendResponse, controls);
1542		if (!controls.shouldRender) return;
1543		if (backendResponse.response.headers.get("Location")) {
1544			if (this.isTurboEnabled()) Turbo.visit(backendResponse.response.headers.get("Location"));
1545			else window.location.href = backendResponse.response.headers.get("Location") || "";
1546			return;
1547		}
1548		this.hooks.triggerHook("loading.state:finished", this.element);
1549		const modifiedModelValues = {};
1550		Object.keys(this.valueStore.getDirtyProps()).forEach((modelName) => {
1551			modifiedModelValues[modelName] = this.valueStore.get(modelName);
1552		});
1553		let newElement;
1554		try {
1555			newElement = htmlToElement(html);
1556			if (!newElement.matches("[data-controller~=live]")) throw new Error("A live component template must contain a single root controller element.");
1557		} catch (error) {
1558			console.error(`There was a problem with the '${this.name}' component HTML returned:`, { id: this.id });
1559			throw error;
1560		}
1561		this.externalMutationTracker.handlePendingChanges();
1562		this.externalMutationTracker.stop();
1563		executeMorphdom(this.element, newElement, this.unsyncedInputsTracker.getUnsyncedInputs(), (element) => getValueFromElement(element, this.valueStore), this.externalMutationTracker);
1564		this.externalMutationTracker.start();
1565		const newProps = this.elementDriver.getComponentProps();
1566		this.valueStore.reinitializeAllProps(newProps);
1567		const eventsToEmit = this.elementDriver.getEventsToEmit();
1568		const browserEventsToDispatch = this.elementDriver.getBrowserEventsToDispatch();
1569		Object.keys(modifiedModelValues).forEach((modelName) => {
1570			this.valueStore.set(modelName, modifiedModelValues[modelName]);
1571		});
1572		eventsToEmit.forEach(({ event, data, target, componentName }) => {
1573			if (target === "up") {
1574				this.emitUp(event, data, componentName);
1575				return;
1576			}
1577			if (target === "self") {
1578				this.emitSelf(event, data);
1579				return;
1580			}
1581			this.emit(event, data, componentName);
1582		});
1583		browserEventsToDispatch.forEach(({ event, payload }) => {
1584			this.element.dispatchEvent(new CustomEvent(event, {
1585				detail: payload,
1586				bubbles: true
1587			}));
1588		});
1589		this.hooks.triggerHook("render:finished", this);
1590	}
1591	calculateDebounce(debounce) {
1592		if (debounce === true) return this.defaultDebounce;
1593		if (debounce === false) return 0;
1594		return debounce;
1595	}
1596	clearRequestDebounceTimeout() {
1597		if (this.requestDebounceTimeout) {
1598			clearTimeout(this.requestDebounceTimeout);
1599			this.requestDebounceTimeout = null;
1600		}
1601	}
1602	debouncedStartRequest(debounce) {
1603		this.clearRequestDebounceTimeout();
1604		this.requestDebounceTimeout = window.setTimeout(() => {
1605			this.render();
1606		}, this.calculateDebounce(debounce));
1607	}
1608	renderError(html) {
1609		let modal = document.getElementById("live-component-error");
1610		if (modal) modal.innerHTML = "";
1611		else {
1612			modal = document.createElement("div");
1613			modal.id = "live-component-error";
1614			modal.style.padding = "50px";
1615			modal.style.backgroundColor = "rgba(0, 0, 0, .5)";
1616			modal.style.zIndex = "100000";
1617			modal.style.position = "fixed";
1618			modal.style.top = "0px";
1619			modal.style.bottom = "0px";
1620			modal.style.left = "0px";
1621			modal.style.right = "0px";
1622			modal.style.display = "flex";
1623			modal.style.flexDirection = "column";
1624		}
1625		const iframe = document.createElement("iframe");
1626		iframe.style.borderRadius = "5px";
1627		iframe.style.flexGrow = "1";
1628		modal.appendChild(iframe);
1629		document.body.prepend(modal);
1630		document.body.style.overflow = "hidden";
1631		if (iframe.contentWindow) {
1632			iframe.contentWindow.document.open();
1633			iframe.contentWindow.document.write(html);
1634			iframe.contentWindow.document.close();
1635		}
1636		const closeModal = (modal) => {
1637			if (modal) modal.outerHTML = "";
1638			document.body.style.overflow = "visible";
1639		};
1640		modal.addEventListener("click", () => closeModal(modal));
1641		modal.setAttribute("tabindex", "0");
1642		modal.addEventListener("keydown", (e) => {
1643			if (e.key === "Escape") closeModal(modal);
1644		});
1645		modal.focus();
1646	}
1647	resetPromise() {
1648		this.nextRequestPromise = new Promise((resolve) => {
1649			this.nextRequestPromiseResolve = resolve;
1650		});
1651	}
1652	_updateFromParentProps(props) {
1653		if (this.valueStore.storeNewPropsFromParent(props)) this.render();
1654	}
1655};
1656function proxifyComponent(component) {
1657	return new Proxy(component, {
1658		get(component, prop) {
1659			if (prop in component || typeof prop !== "string") {
1660				if (typeof component[prop] === "function") {
1661					const callable = component[prop];
1662					return (...args) => {
1663						return callable.apply(component, args);
1664					};
1665				}
1666				return Reflect.get(component, prop);
1667			}
1668			if (component.valueStore.has(prop)) return component.getData(prop);
1669			return (args) => {
1670				return component.action.apply(component, [prop, args]);
1671			};
1672		},
1673		set(target, property, value) {
1674			if (property in target) {
1675				target[property] = value;
1676				return true;
1677			}
1678			target.set(property, value);
1679			return true;
1680		}
1681	});
1682}
1683var StimulusElementDriver = class {
1684	constructor(controller) {
1685		this.controller = controller;
1686	}
1687	getModelName(element) {
1688		const modelDirective = getModelDirectiveFromElement(element, false);
1689		if (!modelDirective) return null;
1690		return modelDirective.action;
1691	}
1692	getComponentProps() {
1693		return this.controller.propsValue;
1694	}
1695	getEventsToEmit() {
1696		return this.controller.eventsToEmitValue;
1697	}
1698	getBrowserEventsToDispatch() {
1699		return this.controller.eventsToDispatchValue;
1700	}
1701};
1702function get_model_binding_default(modelDirective) {
1703	let shouldRender = true;
1704	let targetEventName = null;
1705	let debounce = false;
1706	let minLength = null;
1707	let maxLength = null;
1708	let minValue = null;
1709	let maxValue = null;
1710	modelDirective.modifiers.forEach((modifier) => {
1711		switch (modifier.name) {
1712			case "on":
1713				if (!modifier.value) throw new Error(`The "on" modifier in ${modelDirective.getString()} requires a value - e.g. on(change).`);
1714				if (!["input", "change"].includes(modifier.value)) throw new Error(`The "on" modifier in ${modelDirective.getString()} only accepts the arguments "input" or "change".`);
1715				targetEventName = modifier.value;
1716				break;
1717			case "norender":
1718				shouldRender = false;
1719				break;
1720			case "debounce":
1721				debounce = modifier.value ? Number.parseInt(modifier.value) : true;
1722				break;
1723			case "min_length":
1724				minLength = modifier.value ? Number.parseInt(modifier.value) : null;
1725				break;
1726			case "max_length":
1727				maxLength = modifier.value ? Number.parseInt(modifier.value) : null;
1728				break;
1729			case "min_value":
1730				minValue = modifier.value ? Number.parseFloat(modifier.value) : null;
1731				break;
1732			case "max_value":
1733				maxValue = modifier.value ? Number.parseFloat(modifier.value) : null;
1734				break;
1735			default: throw new Error(`Unknown modifier "${modifier.name}" in data-model="${modelDirective.getString()}".`);
1736		}
1737	});
1738	const [modelName, innerModelName] = modelDirective.action.split(":");
1739	return {
1740		modelName,
1741		innerModelName: innerModelName || null,
1742		shouldRender,
1743		debounce,
1744		targetEventName,
1745		minLength,
1746		maxLength,
1747		minValue,
1748		maxValue
1749	};
1750}
1751var ChildComponentPlugin_default = class {
1752	constructor(component) {
1753		this.parentModelBindings = [];
1754		this.component = component;
1755		this.parentModelBindings = getAllModelDirectiveFromElements(this.component.element).map(get_model_binding_default);
1756	}
1757	attachToComponent(component) {
1758		component.on("request:started", (requestData) => {
1759			requestData.children = this.getChildrenFingerprints();
1760		});
1761		component.on("model:set", (model, value) => {
1762			this.notifyParentModelChange(model, value);
1763		});
1764	}
1765	getChildrenFingerprints() {
1766		const fingerprints = {};
1767		this.getChildren().forEach((child) => {
1768			if (!child.id) throw new Error("missing id");
1769			fingerprints[child.id] = {
1770				fingerprint: child.fingerprint,
1771				tag: child.element.tagName.toLowerCase()
1772			};
1773		});
1774		return fingerprints;
1775	}
1776	notifyParentModelChange(modelName, value) {
1777		const parentComponent = findParent(this.component);
1778		if (!parentComponent) return;
1779		this.parentModelBindings.forEach((modelBinding) => {
1780			if ((modelBinding.innerModelName || "value") !== modelName) return;
1781			parentComponent.set(modelBinding.modelName, value, modelBinding.shouldRender, modelBinding.debounce);
1782		});
1783	}
1784	getChildren() {
1785		return findChildren(this.component);
1786	}
1787};
1788var LazyPlugin_default = class {
1789	constructor() {
1790		this.intersectionObserver = null;
1791	}
1792	attachToComponent(component) {
1793		if ("lazy" !== component.element.attributes.getNamedItem("loading")?.value) return;
1794		component.on("connect", () => {
1795			this.getObserver().observe(component.element);
1796		});
1797		component.on("disconnect", () => {
1798			this.intersectionObserver?.unobserve(component.element);
1799		});
1800	}
1801	getObserver() {
1802		if (!this.intersectionObserver) this.intersectionObserver = new IntersectionObserver((entries, observer) => {
1803			entries.forEach((entry) => {
1804				if (entry.isIntersecting) {
1805					entry.target.dispatchEvent(new CustomEvent("live:appear"));
1806					observer.unobserve(entry.target);
1807				}
1808			});
1809		});
1810		return this.intersectionObserver;
1811	}
1812};
1813var LoadingPlugin_default = class {
1814	attachToComponent(component) {
1815		component.on("loading.state:started", (element, request) => {
1816			this.startLoading(component, element, request);
1817		});
1818		component.on("loading.state:finished", (element) => {
1819			this.finishLoading(component, element);
1820		});
1821		this.finishLoading(component, component.element);
1822	}
1823	startLoading(component, targetElement, backendRequest) {
1824		this.handleLoadingToggle(component, true, targetElement, backendRequest);
1825	}
1826	finishLoading(component, targetElement) {
1827		this.handleLoadingToggle(component, false, targetElement, null);
1828	}
1829	handleLoadingToggle(component, isLoading, targetElement, backendRequest) {
1830		if (isLoading) this.addAttributes(targetElement, ["busy"]);
1831		else this.removeAttributes(targetElement, ["busy"]);
1832		this.getLoadingDirectives(component, targetElement).forEach(({ element, directives }) => {
1833			if (isLoading) this.addAttributes(element, ["data-live-is-loading"]);
1834			else this.removeAttributes(element, ["data-live-is-loading"]);
1835			directives.forEach((directive) => {
1836				this.handleLoadingDirective(element, isLoading, directive, backendRequest);
1837			});
1838		});
1839	}
1840	handleLoadingDirective(element, isLoading, directive, backendRequest) {
1841		const finalAction = parseLoadingAction(directive.action, isLoading);
1842		const targetedActions = [];
1843		const targetedModels = [];
1844		let delay = 0;
1845		const validModifiers = /* @__PURE__ */ new Map();
1846		validModifiers.set("delay", (modifier) => {
1847			if (!isLoading) return;
1848			delay = modifier.value ? Number.parseInt(modifier.value) : 200;
1849		});
1850		validModifiers.set("action", (modifier) => {
1851			if (!modifier.value) throw new Error(`The "action" in data-loading must have an action name - e.g. action(foo). It's missing for "${directive.getString()}"`);
1852			targetedActions.push(modifier.value);
1853		});
1854		validModifiers.set("model", (modifier) => {
1855			if (!modifier.value) throw new Error(`The "model" in data-loading must have an action name - e.g. model(foo). It's missing for "${directive.getString()}"`);
1856			targetedModels.push(modifier.value);
1857		});
1858		directive.modifiers.forEach((modifier) => {
1859			if (validModifiers.has(modifier.name)) {
1860				(validModifiers.get(modifier.name) ?? (() => {}))(modifier);
1861				return;
1862			}
1863			throw new Error(`Unknown modifier "${modifier.name}" used in data-loading="${directive.getString()}". Available modifiers are: ${Array.from(validModifiers.keys()).join(", ")}.`);
1864		});
1865		if (isLoading && targetedActions.length > 0 && backendRequest && !backendRequest.containsOneOfActions(targetedActions)) return;
1866		if (isLoading && targetedModels.length > 0 && backendRequest && !backendRequest.areAnyModelsUpdated(targetedModels)) return;
1867		let loadingDirective;
1868		switch (finalAction) {
1869			case "show":
1870				loadingDirective = () => this.showElement(element);
1871				break;
1872			case "hide":
1873				loadingDirective = () => this.hideElement(element);
1874				break;
1875			case "addClass":
1876				loadingDirective = () => this.addClass(element, directive.args);
1877				break;
1878			case "removeClass":
1879				loadingDirective = () => this.removeClass(element, directive.args);
1880				break;
1881			case "addAttribute":
1882				loadingDirective = () => this.addAttributes(element, directive.args);
1883				break;
1884			case "removeAttribute":
1885				loadingDirective = () => this.removeAttributes(element, directive.args);
1886				break;
1887			default: throw new Error(`Unknown data-loading action "${finalAction}"`);
1888		}
1889		if (delay) {
1890			window.setTimeout(() => {
1891				if (backendRequest && !backendRequest.isResolved) loadingDirective();
1892			}, delay);
1893			return;
1894		}
1895		loadingDirective();
1896	}
1897	getLoadingDirectives(component, element) {
1898		const loadingDirectives = [];
1899		let matchingElements = Array.from(element.querySelectorAll("[data-loading]"));
1900		matchingElements = matchingElements.filter((elt) => elementBelongsToThisComponent(elt, component));
1901		if (element.hasAttribute("data-loading")) matchingElements = [element, ...matchingElements];
1902		matchingElements.forEach((element) => {
1903			if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) throw new Error("Invalid Element Type");
1904			const directives = parseDirectives(element.dataset.loading || "show");
1905			loadingDirectives.push({
1906				element,
1907				directives
1908			});
1909		});
1910		return loadingDirectives;
1911	}
1912	showElement(element) {
1913		element.style.display = "revert";
1914	}
1915	hideElement(element) {
1916		element.style.display = "none";
1917	}
1918	addClass(element, classes) {
1919		element.classList.add(...combineSpacedArray(classes));
1920	}
1921	removeClass(element, classes) {
1922		element.classList.remove(...combineSpacedArray(classes));
1923		if (element.classList.length === 0) element.removeAttribute("class");
1924	}
1925	addAttributes(element, attributes) {
1926		attributes.forEach((attribute) => {
1927			element.setAttribute(attribute, "");
1928		});
1929	}
1930	removeAttributes(element, attributes) {
1931		attributes.forEach((attribute) => {
1932			element.removeAttribute(attribute);
1933		});
1934	}
1935};
1936const parseLoadingAction = (action, isLoading) => {
1937	switch (action) {
1938		case "show": return isLoading ? "show" : "hide";
1939		case "hide": return isLoading ? "hide" : "show";
1940		case "addClass": return isLoading ? "addClass" : "removeClass";
1941		case "removeClass": return isLoading ? "removeClass" : "addClass";
1942		case "addAttribute": return isLoading ? "addAttribute" : "removeAttribute";
1943		case "removeAttribute": return isLoading ? "removeAttribute" : "addAttribute";
1944	}
1945	throw new Error(`Unknown data-loading action "${action}"`);
1946};
1947var PageUnloadingPlugin_default = class {
1948	constructor() {
1949		this.isConnected = false;
1950	}
1951	attachToComponent(component) {
1952		component.on("render:started", (html, response, controls) => {
1953			if (!this.isConnected) controls.shouldRender = false;
1954		});
1955		component.on("connect", () => {
1956			this.isConnected = true;
1957		});
1958		component.on("disconnect", () => {
1959			this.isConnected = false;
1960		});
1961	}
1962};
1963var PollingDirector_default = class {
1964	constructor(component) {
1965		this.isPollingActive = true;
1966		this.pollingIntervals = [];
1967		this.component = component;
1968	}
1969	addPoll(actionName, duration) {
1970		this.polls.push({
1971			actionName,
1972			duration
1973		});
1974		if (this.isPollingActive) this.initiatePoll(actionName, duration);
1975	}
1976	startAllPolling() {
1977		if (this.isPollingActive) return;
1978		this.isPollingActive = true;
1979		this.polls.forEach(({ actionName, duration }) => {
1980			this.initiatePoll(actionName, duration);
1981		});
1982	}
1983	stopAllPolling() {
1984		this.isPollingActive = false;
1985		this.pollingIntervals.forEach((interval) => {
1986			clearInterval(interval);
1987		});
1988	}
1989	clearPolling() {
1990		this.stopAllPolling();
1991		this.polls = [];
1992		this.startAllPolling();
1993	}
1994	initiatePoll(actionName, duration) {
1995		let callback;
1996		if (actionName === "$render") callback = () => {
1997			this.component.render();
1998		};
1999		else callback = () => {
2000			this.component.action(actionName, {}, 0);
2001		};
2002		const timer = window.setInterval(() => {
2003			callback();
2004		}, duration);
2005		this.pollingIntervals.push(timer);
2006	}
2007};
2008var PollingPlugin_default = class {
2009	attachToComponent(component) {
2010		this.element = component.element;
2011		this.pollingDirector = new PollingDirector_default(component);
2012		this.initializePolling();
2013		component.on("connect", () => {
2014			this.pollingDirector.startAllPolling();
2015		});
2016		component.on("disconnect", () => {
2017			this.pollingDirector.stopAllPolling();
2018		});
2019		component.on("render:finished", () => {
2020			this.initializePolling();
2021		});
2022	}
2023	addPoll(actionName, duration) {
2024		this.pollingDirector.addPoll(actionName, duration);
2025	}
2026	clearPolling() {
2027		this.pollingDirector.clearPolling();
2028	}
2029	initializePolling() {
2030		this.clearPolling();
2031		if (this.element.dataset.poll === void 0) return;
2032		const rawPollConfig = this.element.dataset.poll;
2033		parseDirectives(rawPollConfig || "$render").forEach((directive) => {
2034			let duration = 2e3;
2035			directive.modifiers.forEach((modifier) => {
2036				switch (modifier.name) {
2037					case "delay":
2038						if (modifier.value) duration = Number.parseInt(modifier.value);
2039						break;
2040					default: console.warn(`Unknown modifier "${modifier.name}" in data-poll "${rawPollConfig}".`);
2041				}
2042			});
2043			this.addPoll(directive.action, duration);
2044		});
2045	}
2046};
2047var SetValueOntoModelFieldsPlugin_default = class {
2048	attachToComponent(component) {
2049		this.synchronizeValueOfModelFields(component);
2050		component.on("render:finished", () => {
2051			this.synchronizeValueOfModelFields(component);
2052		});
2053	}
2054	synchronizeValueOfModelFields(component) {
2055		component.element.querySelectorAll("[data-model]").forEach((element) => {
2056			if (!(element instanceof HTMLElement)) throw new Error("Invalid element using data-model.");
2057			if (element instanceof HTMLFormElement) return;
2058			if (!elementBelongsToThisComponent(element, component)) return;
2059			const modelDirective = getModelDirectiveFromElement(element);
2060			if (!modelDirective) return;
2061			const modelName = modelDirective.action;
2062			if (component.getUnsyncedModels().includes(modelName)) return;
2063			if (component.valueStore.has(modelName)) setValueOnElement(element, component.valueStore.get(modelName));
2064			if (element instanceof HTMLSelectElement && !element.multiple) component.valueStore.set(modelName, getValueFromElement(element, component.valueStore));
2065		});
2066	}
2067};
2068var ValidatedFieldsPlugin_default = class {
2069	attachToComponent(component) {
2070		component.on("model:set", (modelName) => {
2071			this.handleModelSet(modelName, component.valueStore);
2072		});
2073	}
2074	handleModelSet(modelName, valueStore) {
2075		if (valueStore.has("validatedFields")) {
2076			const validatedFields = [...valueStore.get("validatedFields")];
2077			if (!validatedFields.includes(modelName)) validatedFields.push(modelName);
2078			valueStore.set("validatedFields", validatedFields);
2079		}
2080	}
2081};
2082var LiveControllerDefault = class LiveControllerDefault extends Controller {
2083	constructor(..._args) {
2084		super(..._args);
2085		this.pendingActionTriggerModelElement = null;
2086		this.elementEventListeners = [{
2087			event: "input",
2088			callback: (event) => this.handleInputEvent(event)
2089		}, {
2090			event: "change",
2091			callback: (event) => this.handleChangeEvent(event)
2092		}];
2093		this.pendingFiles = {};
2094	}
2095	initialize() {
2096		this.mutationObserver = new MutationObserver(this.onMutations.bind(this));
2097		this.createComponent();
2098	}
2099	connect() {
2100		this.connectComponent();
2101		this.mutationObserver.observe(this.element, { attributes: true });
2102	}
2103	disconnect() {
2104		this.disconnectComponent();
2105		this.mutationObserver.disconnect();
2106	}
2107	update(event) {
2108		if (event.type === "input" || event.type === "change") throw new Error(`Since LiveComponents 2.3, you no longer need data-action="live#update" on form elements. Found on element: ${getElementAsTagText(event.currentTarget)}`);
2109		this.updateModelFromElementEvent(event.currentTarget, null);
2110	}
2111	action(event) {
2112		const params = event.params;
2113		if (!params.action) throw new Error(`No action name provided on element: ${getElementAsTagText(event.currentTarget)}. Did you forget to add the "data-live-action-param" attribute?`);
2114		const rawAction = params.action;
2115		const actionArgs = { ...params };
2116		delete actionArgs.action;
2117		const directives = parseDirectives(rawAction);
2118		let debounce = false;
2119		directives.forEach((directive) => {
2120			let pendingFiles = {};
2121			const validModifiers = /* @__PURE__ */ new Map();
2122			validModifiers.set("stop", () => {
2123				event.stopPropagation();
2124			});
2125			validModifiers.set("self", () => {
2126				if (event.target !== event.currentTarget) return;
2127			});
2128			validModifiers.set("debounce", (modifier) => {
2129				debounce = modifier.value ? Number.parseInt(modifier.value) : true;
2130			});
2131			validModifiers.set("files", (modifier) => {
2132				if (!modifier.value) pendingFiles = this.pendingFiles;
2133				else if (this.pendingFiles[modifier.value]) pendingFiles[modifier.value] = this.pendingFiles[modifier.value];
2134			});
2135			directive.modifiers.forEach((modifier) => {
2136				if (validModifiers.has(modifier.name)) {
2137					(validModifiers.get(modifier.name) ?? (() => {}))(modifier);
2138					return;
2139				}
2140				console.warn(`Unknown modifier ${modifier.name} in action "${rawAction}". Available modifiers are: ${Array.from(validModifiers.keys()).join(", ")}.`);
2141			});
2142			for (const [key, input] of Object.entries(pendingFiles)) {
2143				if (input.files) this.component.files(key, input);
2144				delete this.pendingFiles[key];
2145			}
2146			this.component.action(directive.action, actionArgs, debounce);
2147			if (getModelDirectiveFromElement(event.currentTarget, false)) this.pendingActionTriggerModelElement = event.currentTarget;
2148		});
2149	}
2150	$render() {
2151		return this.component.render();
2152	}
2153	emit(event) {
2154		this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
2155			this.component.emit(name, data, nameMatch);
2156		});
2157	}
2158	emitUp(event) {
2159		this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
2160			this.component.emitUp(name, data, nameMatch);
2161		});
2162	}
2163	emitSelf(event) {
2164		this.getEmitDirectives(event).forEach(({ name, data }) => {
2165			this.component.emitSelf(name, data);
2166		});
2167	}
2168	$updateModel(model, value, shouldRender = true, debounce = true) {
2169		return this.component.set(model, value, shouldRender, debounce);
2170	}
2171	propsUpdatedFromParentValueChanged() {
2172		this.component._updateFromParentProps(this.propsUpdatedFromParentValue);
2173	}
2174	fingerprintValueChanged() {
2175		this.component.fingerprint = this.fingerprintValue;
2176	}
2177	getEmitDirectives(event) {
2178		const params = event.params;
2179		if (!params.event) throw new Error(`No event name provided on element: ${getElementAsTagText(event.currentTarget)}. Did you forget to add the "data-live-event-param" attribute?`);
2180		const eventInfo = params.event;
2181		const eventArgs = { ...params };
2182		delete eventArgs.event;
2183		const directives = parseDirectives(eventInfo);
2184		const emits = [];
2185		directives.forEach((directive) => {
2186			let nameMatch = null;
2187			directive.modifiers.forEach((modifier) => {
2188				switch (modifier.name) {
2189					case "name":
2190						nameMatch = modifier.value;
2191						break;
2192					default: throw new Error(`Unknown modifier ${modifier.name} in event "${eventInfo}".`);
2193				}
2194			});
2195			emits.push({
2196				name: directive.action,
2197				data: eventArgs,
2198				nameMatch
2199			});
2200		});
2201		return emits;
2202	}
2203	createComponent() {
2204		const id = this.element.id || null;
2205		this.component = new Component(this.element, this.nameValue, this.propsValue, this.listenersValue, id, LiveControllerDefault.backendFactory(this), new StimulusElementDriver(this));
2206		this.proxiedComponent = proxifyComponent(this.component);
2207		Object.defineProperty(this.element, "__component", {
2208			value: this.proxiedComponent,
2209			writable: true
2210		});
2211		if (this.hasDebounceValue) this.component.defaultDebounce = this.debounceValue;
2212		[
2213			new LoadingPlugin_default(),
2214			new LazyPlugin_default(),
2215			new ValidatedFieldsPlugin_default(),
2216			new PageUnloadingPlugin_default(),
2217			new PollingPlugin_default(),
2218			new SetValueOntoModelFieldsPlugin_default(),
2219			new ChildComponentPlugin_default(this.component)
2220		].forEach((plugin) => {
2221			this.component.addPlugin(plugin);
2222		});
2223	}
2224	connectComponent() {
2225		this.component.connect();
2226		this.mutationObserver.observe(this.element, { attributes: true });
2227		this.elementEventListeners.forEach(({ event, callback }) => {
2228			this.component.element.addEventListener(event, callback);
2229		});
2230		this.dispatchEvent("connect");
2231	}
2232	disconnectComponent() {
2233		this.component.disconnect();
2234		this.elementEventListeners.forEach(({ event, callback }) => {
2235			this.component.element.removeEventListener(event, callback);
2236		});
2237		this.dispatchEvent("disconnect");
2238	}
2239	handleInputEvent(event) {
2240		const target = event.target;
2241		if (!target) return;
2242		this.updateModelFromElementEvent(target, "input");
2243	}
2244	handleChangeEvent(event) {
2245		const target = event.target;
2246		if (!target) return;
2247		this.updateModelFromElementEvent(target, "change");
2248	}
2249	updateModelFromElementEvent(element, eventName) {
2250		if (!elementBelongsToThisComponent(element, this.component)) return;
2251		if (!(element instanceof HTMLElement)) throw new Error("Could not update model for non HTMLElement");
2252		if (element instanceof HTMLInputElement && element.type === "file") {
2253			const key = element.name;
2254			if (element.files?.length) this.pendingFiles[key] = element;
2255			else if (this.pendingFiles[key]) delete this.pendingFiles[key];
2256		}
2257		const modelDirective = getModelDirectiveFromElement(element, false);
2258		if (!modelDirective) return;
2259		const modelBinding = get_model_binding_default(modelDirective);
2260		if (!modelBinding.targetEventName) modelBinding.targetEventName = "input";
2261		if (this.pendingActionTriggerModelElement === element) modelBinding.shouldRender = false;
2262		if (eventName === "change" && modelBinding.targetEventName === "input") modelBinding.targetEventName = "change";
2263		if (eventName && modelBinding.targetEventName !== eventName) return;
2264		if (false === modelBinding.debounce) if (modelBinding.targetEventName === "input") modelBinding.debounce = true;
2265		else modelBinding.debounce = 0;
2266		const finalValue = getValueFromElement(element, this.component.valueStore);
2267		const finalValueIsEmpty = finalValue === "" || finalValue === null || finalValue === void 0;
2268		if (isTextualInputElement(element) || isTextareaElement(element)) {
2269			if (!finalValueIsEmpty && modelBinding.minLength !== null && typeof finalValue === "string" && finalValue.length < modelBinding.minLength) return;
2270			if (!finalValueIsEmpty && modelBinding.maxLength !== null && typeof finalValue === "string" && finalValue.length > modelBinding.maxLength) return;
2271		}
2272		if (isNumericalInputElement(element)) {
2273			if (!finalValueIsEmpty) {
2274				const numericValue = Number(finalValue);
2275				if (modelBinding.minValue !== null && numericValue < modelBinding.minValue) return;
2276				if (modelBinding.maxValue !== null && numericValue > modelBinding.maxValue) return;
2277			}
2278		}
2279		this.component.set(modelBinding.modelName, finalValue, modelBinding.shouldRender, modelBinding.debounce);
2280	}
2281	dispatchEvent(name, detail = {}, canBubble = true, cancelable = false) {
2282		detail.controller = this;
2283		detail.component = this.proxiedComponent;
2284		this.dispatch(name, {
2285			detail,
2286			prefix: "live",
2287			cancelable,
2288			bubbles: canBubble
2289		});
2290	}
2291	onMutations(mutations) {
2292		mutations.forEach((mutation) => {
2293			if (mutation.type === "attributes" && mutation.attributeName === "id" && this.element.id !== this.component.id) {
2294				this.disconnectComponent();
2295				this.createComponent();
2296				this.connectComponent();
2297			}
2298		});
2299	}
2300};
2301LiveControllerDefault.values = {
2302	name: String,
2303	url: String,
2304	props: {
2305		type: Object,
2306		default: {}
2307	},
2308	propsUpdatedFromParent: {
2309		type: Object,
2310		default: {}
2311	},
2312	listeners: {
2313		type: Array,
2314		default: []
2315	},
2316	eventsToEmit: {
2317		type: Array,
2318		default: []
2319	},
2320	eventsToDispatch: {
2321		type: Array,
2322		default: []
2323	},
2324	debounce: {
2325		type: Number,
2326		default: 150
2327	},
2328	fingerprint: {
2329		type: String,
2330		default: ""
2331	},
2332	requestMethod: {
2333		type: String,
2334		default: "post"
2335	},
2336	fetchCredentials: {
2337		type: String,
2338		default: "same-origin"
2339	}
2340};
2341LiveControllerDefault.backendFactory = (controller) => new Backend_default(controller.urlValue, controller.requestMethodValue, controller.fetchCredentialsValue);
2342export { Component, LiveControllerDefault as default, getComponent };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.