PageSourceSearch

https://meine.svp.eu/assets/@symfony/ux-live-component/live_controller-90770da447151c1b41a171769e33f581.js

js svp.eu collected 2026-09-25 02:44:34 UTC 101,433 bytes, 3,089 lines download raw bytes

1// src/live_controller.ts
2import { Controller } from "@hotwired/stimulus";
3
4// src/Backend/BackendRequest.ts
5var BackendRequest_default = class {
6  constructor(promise, actions, updateModels) {
7    this.isResolved = false;
8    this.promise = promise;
9    this.promise.then((response) => {
10      this.isResolved = true;
11      return response;
12    });
13    this.actions = actions;
14    this.updatedModels = updateModels;
15  }
16  /**
17   * Does this BackendRequest contain at least on action in targetedActions?
18   */
19  containsOneOfActions(targetedActions) {
20    return this.actions.filter((action) => targetedActions.includes(action)).length > 0;
21  }
22  /**
23   * Does this BackendRequest includes updates for any of these models?
24   */
25  areAnyModelsUpdated(targetedModels) {
26    return this.updatedModels.filter((model) => targetedModels.includes(model)).length > 0;
27  }
28};
29
30// src/Backend/RequestBuilder.ts
31var RequestBuilder_default = class {
32  constructor(url, method = "post") {
33    this.url = url;
34    this.method = method;
35  }
36  buildRequest(props, actions, updated, children, updatedPropsFromParent, files) {
37    const splitUrl = this.url.split("?");
38    let [url] = splitUrl;
39    const [, queryString] = splitUrl;
40    const params = new URLSearchParams(queryString || "");
41    const fetchOptions = {};
42    fetchOptions.headers = {
43      Accept: "application/vnd.live-component+html",
44      "X-Requested-With": "XMLHttpRequest",
45      "X-Live-Url": window.location.pathname + window.location.search
46    };
47    const totalFiles = Object.entries(files).reduce((total, current) => total + current.length, 0);
48    const hasFingerprints = Object.keys(children).length > 0;
49    if (actions.length === 0 && totalFiles === 0 && this.method === "get" && this.willDataFitInUrl(
50      JSON.stringify(props),
51      JSON.stringify(updated),
52      params,
53      JSON.stringify(children),
54      JSON.stringify(updatedPropsFromParent)
55    )) {
56      params.set("props", JSON.stringify(props));
57      params.set("updated", JSON.stringify(updated));
58      if (Object.keys(updatedPropsFromParent).length > 0) {
59        params.set("propsFromParent", JSON.stringify(updatedPropsFromParent));
60      }
61      if (hasFingerprints) {
62        params.set("children", JSON.stringify(children));
63      }
64      fetchOptions.method = "GET";
65    } else {
66      fetchOptions.method = "POST";
67      const requestData = { props, updated };
68      if (Object.keys(updatedPropsFromParent).length > 0) {
69        requestData.propsFromParent = updatedPropsFromParent;
70      }
71      if (hasFingerprints) {
72        requestData.children = children;
73      }
74      if (actions.length > 0) {
75        if (actions.length === 1) {
76          requestData.args = actions[0].args;
77          url += `/${encodeURIComponent(actions[0].name)}`;
78        } else {
79          url += "/_batch";
80          requestData.actions = actions;
81        }
82      }
83      const formData = new FormData();
84      formData.append("data", JSON.stringify(requestData));
85      for (const [key, value] of Object.entries(files)) {
86        const length = value.length;
87        for (let i = 0; i < length; ++i) {
88          formData.append(key, value[i]);
89        }
90      }
91      fetchOptions.body = formData;
92    }
93    const paramsString = params.toString();
94    return {
95      url: `${url}${paramsString.length > 0 ? `?${paramsString}` : ""}`,
96      fetchOptions
97    };
98  }
99  willDataFitInUrl(propsJson, updatedJson, params, childrenJson, propsFromParentJson) {
100    const urlEncodedJsonData = new URLSearchParams(
101      propsJson + updatedJson + childrenJson + propsFromParentJson
102    ).toString();
103    return (urlEncodedJsonData + params.toString()).length < 1500;
104  }
105};
106
107// src/Backend/Backend.ts
108var Backend_default = class {
109  constructor(url, method = "post") {
110    this.requestBuilder = new RequestBuilder_default(url, method);
111  }
112  makeRequest(props, actions, updated, children, updatedPropsFromParent, files) {
113    const { url, fetchOptions } = this.requestBuilder.buildRequest(
114      props,
115      actions,
116      updated,
117      children,
118      updatedPropsFromParent,
119      files
120    );
121    return new BackendRequest_default(
122      fetch(url, fetchOptions),
123      actions.map((backendAction) => backendAction.name),
124      Object.keys(updated)
125    );
126  }
127};
128
129// src/Backend/BackendResponse.ts
130var BackendResponse_default = class {
131  constructor(response) {
132    this.response = response;
133  }
134  async getBody() {
135    if (!this.body) {
136      this.body = await this.response.text();
137    }
138    return this.body;
139  }
140  getLiveUrl() {
141    if (void 0 === this.liveUrl) {
142      this.liveUrl = this.response.headers.get("X-Live-Url");
143    }
144    return this.liveUrl;
145  }
146};
147
148// src/Util/getElementAsTagText.ts
149function getElementAsTagText(element) {
150  return element.innerHTML ? element.outerHTML.slice(0, element.outerHTML.indexOf(element.innerHTML)) : element.outerHTML;
151}
152
153// src/ComponentRegistry.ts
154var componentMapByElement = /* @__PURE__ */ new WeakMap();
155var componentMapByComponent = /* @__PURE__ */ new Map();
156var registerComponent = (component) => {
157  componentMapByElement.set(component.element, component);
158  componentMapByComponent.set(component, component.name);
159};
160var unregisterComponent = (component) => {
161  componentMapByElement.delete(component.element);
162  componentMapByComponent.delete(component);
163};
164var getComponent = (element) => new Promise((resolve, reject) => {
165  let count = 0;
166  const maxCount = 10;
167  const interval = setInterval(() => {
168    const component = componentMapByElement.get(element);
169    if (component) {
170      clearInterval(interval);
171      resolve(component);
172    }
173    count++;
174    if (count > maxCount) {
175      clearInterval(interval);
176      reject(new Error(`Component not found for element ${getElementAsTagText(element)}`));
177    }
178  }, 5);
179});
180var findComponents = (currentComponent, onlyParents, onlyMatchName) => {
181  const components = [];
182  componentMapByComponent.forEach((componentName, component) => {
183    if (onlyParents && (currentComponent === component || !component.element.contains(currentComponent.element))) {
184      return;
185    }
186    if (onlyMatchName && componentName !== onlyMatchName) {
187      return;
188    }
189    components.push(component);
190  });
191  return components;
192};
193var findChildren = (currentComponent) => {
194  const children = [];
195  componentMapByComponent.forEach((componentName, component) => {
196    if (currentComponent === component) {
197      return;
198    }
199    if (!currentComponent.element.contains(component.element)) {
200      return;
201    }
202    let foundChildComponent = false;
203    componentMapByComponent.forEach((childComponentName, childComponent) => {
204      if (foundChildComponent) {
205        return;
206      }
207      if (childComponent === component) {
208        return;
209      }
210      if (childComponent.element.contains(component.element)) {
211        foundChildComponent = true;
212      }
213    });
214    children.push(component);
215  });
216  return children;
217};
218var findParent = (currentComponent) => {
219  let parentElement = currentComponent.element.parentElement;
220  while (parentElement) {
221    const component = componentMapByElement.get(parentElement);
222    if (component) {
223      return component;
224    }
225    parentElement = parentElement.parentElement;
226  }
227  return null;
228};
229
230// src/Directive/directives_parser.ts
231function parseDirectives(content) {
232  const directives = [];
233  if (!content) {
234    return directives;
235  }
236  let currentActionName = "";
237  let currentArgumentValue = "";
238  let currentArguments = [];
239  let currentModifiers = [];
240  let state = "action";
241  const getLastActionName = () => {
242    if (currentActionName) {
243      return currentActionName;
244    }
245    if (directives.length === 0) {
246      throw new Error("Could not find any directives");
247    }
248    return directives[directives.length - 1].action;
249  };
250  const pushInstruction = () => {
251    directives.push({
252      action: currentActionName,
253      args: currentArguments,
254      modifiers: currentModifiers,
255      getString: () => {
256        return content;
257      }
258    });
259    currentActionName = "";
260    currentArgumentValue = "";
261    currentArguments = [];
262    currentModifiers = [];
263    state = "action";
264  };
265  const pushArgument = () => {
266    currentArguments.push(currentArgumentValue.trim());
267    currentArgumentValue = "";
268  };
269  const pushModifier = () => {
270    if (currentArguments.length > 1) {
271      throw new Error(`The modifier "${currentActionName}()" does not support multiple arguments.`);
272    }
273    currentModifiers.push({
274      name: currentActionName,
275      value: currentArguments.length > 0 ? currentArguments[0] : null
276    });
277    currentActionName = "";
278    currentArguments = [];
279    state = "action";
280  };
281  for (let i = 0; i < content.length; i++) {
282    const char = content[i];
283    switch (state) {
284      case "action":
285        if (char === "(") {
286          state = "arguments";
287          break;
288        }
289        if (char === " ") {
290          if (currentActionName) {
291            pushInstruction();
292          }
293          break;
294        }
295        if (char === "|") {
296          pushModifier();
297          break;
298        }
299        currentActionName += char;
300        break;
301      case "arguments":
302        if (char === ")") {
303          pushArgument();
304          state = "after_arguments";
305          break;
306        }
307        if (char === ",") {
308          pushArgument();
309          break;
310        }
311        currentArgumentValue += char;
312        break;
313      case "after_arguments":
314        if (char === "|") {
315          pushModifier();
316          break;
317        }
318        if (char !== " ") {
319          throw new Error(`Missing space after ${getLastActionName()}()`);
320        }
321        pushInstruction();
322        break;
323    }
324  }
325  switch (state) {
326    case "action":
327    case "after_arguments":
328      if (currentActionName) {
329        pushInstruction();
330      }
331      break;
332    default:
333      throw new Error(`Did you forget to add a closing ")" after "${currentActionName}"?`);
334  }
335  return directives;
336}
337
338// src/string_utils.ts
339function combineSpacedArray(parts) {
340  const finalParts = [];
341  parts.forEach((part) => {
342    finalParts.push(...trimAll(part).split(" "));
343  });
344  return finalParts;
345}
346function trimAll(str) {
347  return str.replace(/[\s]+/g, " ").trim();
348}
349function normalizeModelName(model) {
350  return model.replace(/\[]$/, "").split("[").map((s) => s.replace("]", "")).join(".");
351}
352
353// src/dom_utils.ts
354function getValueFromElement(element, valueStore) {
355  if (element instanceof HTMLInputElement) {
356    if (element.type === "checkbox") {
357      const modelNameData = getModelDirectiveFromElement(element, false);
358      if (modelNameData !== null) {
359        const modelValue = valueStore.get(modelNameData.action);
360        if (Array.isArray(modelValue)) {
361          return getMultipleCheckboxValue(element, modelValue);
362        }
363        if (Object(modelValue) === modelValue) {
364          return getMultipleCheckboxValue(element, Object.values(modelValue));
365        }
366      }
367      if (element.hasAttribute("value")) {
368        return element.checked ? element.getAttribute("value") : null;
369      }
370      return element.checked;
371    }
372    return inputValue(element);
373  }
374  if (element instanceof HTMLSelectElement) {
375    if (element.multiple) {
376      return Array.from(element.selectedOptions).map((el) => el.value);
377    }
378    return element.value;
379  }
380  if (element.hasAttribute("data-value")) {
381    return element.dataset.value;
382  }
383  if ("value" in element) {
384    return element.value;
385  }
386  if (element.hasAttribute("value")) {
387    return element.getAttribute("value");
388  }
389  return null;
390}
391function setValueOnElement(element, value) {
392  if (element instanceof HTMLInputElement) {
393    if (element.type === "file") {
394      return;
395    }
396    if (element.type === "radio") {
397      element.checked = element.value == value;
398      return;
399    }
400    if (element.type === "checkbox") {
401      if (Array.isArray(value)) {
402        element.checked = value.some((val) => val == element.value);
403      } else if (element.hasAttribute("value")) {
404        element.checked = element.value == value;
405      } else {
406        element.checked = value;
407      }
408      return;
409    }
410  }
411  if (element instanceof HTMLSelectElement) {
412    const arrayWrappedValue = [].concat(value).map((value2) => {
413      return `${value2}`;
414    });
415    Array.from(element.options).forEach((option) => {
416      option.selected = arrayWrappedValue.includes(option.value);
417    });
418    return;
419  }
420  value = value === void 0 ? "" : value;
421  element.value = value;
422}
423function getAllModelDirectiveFromElements(element) {
424  if (!element.dataset.model) {
425    return [];
426  }
427  const directives = parseDirectives(element.dataset.model);
428  directives.forEach((directive) => {
429    if (directive.args.length > 0) {
430      throw new Error(
431        `The data-model="${element.dataset.model}" format is invalid: it does not support passing arguments to the model.`
432      );
433    }
434    directive.action = normalizeModelName(directive.action);
435  });
436  return directives;
437}
438function getModelDirectiveFromElement(element, throwOnMissing = true) {
439  const dataModelDirectives = getAllModelDirectiveFromElements(element);
440  if (dataModelDirectives.length > 0) {
441    return dataModelDirectives[0];
442  }
443  if (element.getAttribute("name")) {
444    const formElement = element.closest("form");
445    if (formElement && "model" in formElement.dataset) {
446      const directives = parseDirectives(formElement.dataset.model || "*");
447      const directive = directives[0];
448      if (directive.args.length > 0) {
449        throw new Error(
450          `The data-model="${formElement.dataset.model}" format is invalid: it does not support passing arguments to the model.`
451        );
452      }
453      directive.action = normalizeModelName(element.getAttribute("name"));
454      return directive;
455    }
456  }
457  if (!throwOnMissing) {
458    return null;
459  }
460  throw new Error(
461    `Cannot determine the model name for "${getElementAsTagText(
462      element
463    )}": the element must either have a "data-model" (or "name" attribute living inside a <form data-model="*">).`
464  );
465}
466function elementBelongsToThisComponent(element, component) {
467  if (component.element === element) {
468    return true;
469  }
470  if (!component.element.contains(element)) {
471    return false;
472  }
473  const closestLiveComponent = element.closest('[data-controller~="live"]');
474  return closestLiveComponent === component.element;
475}
476function cloneHTMLElement(element) {
477  const newElement = element.cloneNode(true);
478  if (!(newElement instanceof HTMLElement)) {
479    throw new Error("Could not clone element");
480  }
481  return newElement;
482}
483function htmlToElement(html) {
484  const template = document.createElement("template");
485  html = html.trim();
486  template.innerHTML = html;
487  if (template.content.childElementCount > 1) {
488    throw new Error(
489      `Component HTML contains ${template.content.childElementCount} elements, but only 1 root element is allowed.`
490    );
491  }
492  const child = template.content.firstElementChild;
493  if (!child) {
494    throw new Error("Child not found");
495  }
496  if (!(child instanceof HTMLElement)) {
497    throw new Error(`Created element is not an HTMLElement: ${html.trim()}`);
498  }
499  return child;
500}
501var getMultipleCheckboxValue = (element, currentValues) => {
502  const finalValues = [...currentValues];
503  const value = inputValue(element);
504  const index = currentValues.indexOf(value);
505  if (element.checked) {
506    if (index === -1) {
507      finalValues.push(value);
508    }
509    return finalValues;
510  }
511  if (index > -1) {
512    finalValues.splice(index, 1);
513  }
514  return finalValues;
515};
516var inputValue = (element) => element.dataset.value ? element.dataset.value : element.value;
517function isTextualInputElement(el) {
518  return el instanceof HTMLInputElement && ["text", "email", "password", "search", "tel", "url"].includes(el.type);
519}
520function isTextareaElement(el) {
521  return el instanceof HTMLTextAreaElement;
522}
523function isNumericalInputElement(element) {
524  return element instanceof HTMLInputElement && ["number", "range"].includes(element.type);
525}
526
527// src/HookManager.ts
528var HookManager_default = class {
529  constructor() {
530    this.hooks = /* @__PURE__ */ new Map();
531  }
532  register(hookName, callback) {
533    const hooks = this.hooks.get(hookName) || [];
534    hooks.push(callback);
535    this.hooks.set(hookName, hooks);
536  }
537  unregister(hookName, callback) {
538    const hooks = this.hooks.get(hookName) || [];
539    const index = hooks.indexOf(callback);
540    if (index === -1) {
541      return;
542    }
543    hooks.splice(index, 1);
544    this.hooks.set(hookName, hooks);
545  }
546  triggerHook(hookName, ...args) {
547    const hooks = this.hooks.get(hookName) || [];
548    hooks.forEach((callback) => callback(...args));
549  }
550};
551
vendor: 19,227 bytes, lines 552-1097
552// ../../../node_modules/.pnpm/[email protected]/node_modules/idiomorph/dist/idiomorph.esm.js
553var Idiomorph = function() {
554  "use strict";
555  let EMPTY_SET = /* @__PURE__ */ new Set();
556  let defaults = {
557    morphStyle: "outerHTML",
558    callbacks: {
559      beforeNodeAdded: noOp,
560      afterNodeAdded: noOp,
561      beforeNodeMorphed: noOp,
562      afterNodeMorphed: noOp,
563      beforeNodeRemoved: noOp,
564      afterNodeRemoved: noOp,
565      beforeAttributeUpdated: noOp
566    },
567    head: {
568      style: "merge",
569      shouldPreserve: function(elt) {
570        return elt.getAttribute("im-preserve") === "true";
571      },
572      shouldReAppend: function(elt) {
573        return elt.getAttribute("im-re-append") === "true";
574      },
575      shouldRemove: noOp,
576      afterHeadMorphed: noOp
577    }
578  };
579  function morph(oldNode, newContent, config = {}) {
580    if (oldNode instanceof Document) {
581      oldNode = oldNode.documentElement;
582    }
583    if (typeof newContent === "string") {
584      newContent = parseContent(newContent);
585    }
586    let normalizedContent = normalizeContent(newContent);
587    let ctx = createMorphContext(oldNode, normalizedContent, config);
588    return morphNormalizedContent(oldNode, normalizedContent, ctx);
589  }
590  function morphNormalizedContent(oldNode, normalizedNewContent, ctx) {
591    if (ctx.head.block) {
592      let oldHead = oldNode.querySelector("head");
593      let newHead = normalizedNewContent.querySelector("head");
594      if (oldHead && newHead) {
595        let promises = handleHeadElement(newHead, oldHead, ctx);
596        Promise.all(promises).then(function() {
597          morphNormalizedContent(oldNode, normalizedNewContent, Object.assign(ctx, {
598            head: {
599              block: false,
600              ignore: true
601            }
602          }));
603        });
604        return;
605      }
606    }
607    if (ctx.morphStyle === "innerHTML") {
608      morphChildren(normalizedNewContent, oldNode, ctx);
609      return oldNode.children;
610    } else if (ctx.morphStyle === "outerHTML" || ctx.morphStyle == null) {
611      let bestMatch = findBestNodeMatch(normalizedNewContent, oldNode, ctx);
612      let previousSibling = bestMatch?.previousSibling;
613      let nextSibling = bestMatch?.nextSibling;
614      let morphedNode = morphOldNodeTo(oldNode, bestMatch, ctx);
615      if (bestMatch) {
616        return insertSiblings(previousSibling, morphedNode, nextSibling);
617      } else {
618        return [];
619      }
620    } else {
621      throw "Do not understand how to morph style " + ctx.morphStyle;
622    }
623  }
624  function ignoreValueOfActiveElement(possibleActiveElement, ctx) {
625    return ctx.ignoreActiveValue && possibleActiveElement === document.activeElement;
626  }
627  function morphOldNodeTo(oldNode, newContent, ctx) {
628    if (ctx.ignoreActive && oldNode === document.activeElement) {
629    } else if (newContent == null) {
630      if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode;
631      oldNode.remove();
632      ctx.callbacks.afterNodeRemoved(oldNode);
633      return null;
634    } else if (!isSoftMatch(oldNode, newContent)) {
635      if (ctx.callbacks.beforeNodeRemoved(oldNode) === false) return oldNode;
636      if (ctx.callbacks.beforeNodeAdded(newContent) === false) return oldNode;
637      oldNode.parentElement.replaceChild(newContent, oldNode);
638      ctx.callbacks.afterNodeAdded(newContent);
639      ctx.callbacks.afterNodeRemoved(oldNode);
640      return newContent;
641    } else {
642      if (ctx.callbacks.beforeNodeMorphed(oldNode, newContent) === false) return oldNode;
643      if (oldNode instanceof HTMLHeadElement && ctx.head.ignore) {
644      } else if (oldNode instanceof HTMLHeadElement && ctx.head.style !== "morph") {
645        handleHeadElement(newContent, oldNode, ctx);
646      } else {
647        syncNodeFrom(newContent, oldNode, ctx);
648        if (!ignoreValueOfActiveElement(oldNode, ctx)) {
649          morphChildren(newContent, oldNode, ctx);
650        }
651      }
652      ctx.callbacks.afterNodeMorphed(oldNode, newContent);
653      return oldNode;
654    }
655  }
656  function morphChildren(newParent, oldParent, ctx) {
657    let nextNewChild = newParent.firstChild;
658    let insertionPoint = oldParent.firstChild;
659    let newChild;
660    while (nextNewChild) {
661      newChild = nextNewChild;
662      nextNewChild = newChild.nextSibling;
663      if (insertionPoint == null) {
664        if (ctx.callbacks.beforeNodeAdded(newChild) === false) return;
665        oldParent.appendChild(newChild);
666        ctx.callbacks.afterNodeAdded(newChild);
667        removeIdsFromConsideration(ctx, newChild);
668        continue;
669      }
670      if (isIdSetMatch(newChild, insertionPoint, ctx)) {
671        morphOldNodeTo(insertionPoint, newChild, ctx);
672        insertionPoint = insertionPoint.nextSibling;
673        removeIdsFromConsideration(ctx, newChild);
674        continue;
675      }
676      let idSetMatch = findIdSetMatch(newParent, oldParent, newChild, insertionPoint, ctx);
677      if (idSetMatch) {
678        insertionPoint = removeNodesBetween(insertionPoint, idSetMatch, ctx);
679        morphOldNodeTo(idSetMatch, newChild, ctx);
680        removeIdsFromConsideration(ctx, newChild);
681        continue;
682      }
683      let softMatch = findSoftMatch(newParent, oldParent, newChild, insertionPoint, ctx);
684      if (softMatch) {
685        insertionPoint = removeNodesBetween(insertionPoint, softMatch, ctx);
686        morphOldNodeTo(softMatch, newChild, ctx);
687        removeIdsFromConsideration(ctx, newChild);
688        continue;
689      }
690      if (ctx.callbacks.beforeNodeAdded(newChild) === false) return;
691      oldParent.insertBefore(newChild, insertionPoint);
692      ctx.callbacks.afterNodeAdded(newChild);
693      removeIdsFromConsideration(ctx, newChild);
694    }
695    while (insertionPoint !== null) {
696      let tempNode = insertionPoint;
697      insertionPoint = insertionPoint.nextSibling;
698      removeNode(tempNode, ctx);
699    }
700  }
701  function ignoreAttribute(attr, to, updateType, ctx) {
702    if (attr === "value" && ctx.ignoreActiveValue && to === document.activeElement) {
703      return true;
704    }
705    return ctx.callbacks.beforeAttributeUpdated(attr, to, updateType) === false;
706  }
707  function syncNodeFrom(from, to, ctx) {
708    let type = from.nodeType;
709    if (type === 1) {
710      const fromAttributes = from.attributes;
711      const toAttributes = to.attributes;
712      for (const fromAttribute of fromAttributes) {
713        if (ignoreAttribute(fromAttribute.name, to, "update", ctx)) {
714          continue;
715        }
716        if (to.getAttribute(fromAttribute.name) !== fromAttribute.value) {
717          to.setAttribute(fromAttribute.name, fromAttribute.value);
718        }
719      }
720      for (let i = toAttributes.length - 1; 0 <= i; i--) {
721        const toAttribute = toAttributes[i];
722        if (ignoreAttribute(toAttribute.name, to, "remove", ctx)) {
723          continue;
724        }
725        if (!from.hasAttribute(toAttribute.name)) {
726          to.removeAttribute(toAttribute.name);
727        }
728      }
729    }
730    if (type === 8 || type === 3) {
731      if (to.nodeValue !== from.nodeValue) {
732        to.nodeValue = from.nodeValue;
733      }
734    }
735    if (!ignoreValueOfActiveElement(to, ctx)) {
736      syncInputValue(from, to, ctx);
737    }
738  }
739  function syncBooleanAttribute(from, to, attributeName, ctx) {
740    if (from[attributeName] !== to[attributeName]) {
741      let ignoreUpdate = ignoreAttribute(attributeName, to, "update", ctx);
742      if (!ignoreUpdate) {
743        to[attributeName] = from[attributeName];
744      }
745      if (from[attributeName]) {
746        if (!ignoreUpdate) {
747          to.setAttribute(attributeName, from[attributeName]);
748        }
749      } else {
750        if (!ignoreAttribute(attributeName, to, "remove", ctx)) {
751          to.removeAttribute(attributeName);
752        }
753      }
754    }
755  }
756  function syncInputValue(from, to, ctx) {
757    if (from instanceof HTMLInputElement && to instanceof HTMLInputElement && from.type !== "file") {
758      let fromValue = from.value;
759      let toValue = to.value;
760      syncBooleanAttribute(from, to, "checked", ctx);
761      syncBooleanAttribute(from, to, "disabled", ctx);
762      if (!from.hasAttribute("value")) {
763        if (!ignoreAttribute("value", to, "remove", ctx)) {
764          to.value = "";
765          to.removeAttribute("value");
766        }
767      } else if (fromValue !== toValue) {
768        if (!ignoreAttribute("value", to, "update", ctx)) {
769          to.setAttribute("value", fromValue);
770          to.value = fromValue;
771        }
772      }
773    } else if (from instanceof HTMLOptionElement) {
774      syncBooleanAttribute(from, to, "selected", ctx);
775    } else if (from instanceof HTMLTextAreaElement && to instanceof HTMLTextAreaElement) {
776      let fromValue = from.value;
777      let toValue = to.value;
778      if (ignoreAttribute("value", to, "update", ctx)) {
779        return;
780      }
781      if (fromValue !== toValue) {
782        to.value = fromValue;
783      }
784      if (to.firstChild && to.firstChild.nodeValue !== fromValue) {
785        to.firstChild.nodeValue = fromValue;
786      }
787    }
788  }
789  function handleHeadElement(newHeadTag, currentHead, ctx) {
790    let added = [];
791    let removed = [];
792    let preserved = [];
793    let nodesToAppend = [];
794    let headMergeStyle = ctx.head.style;
795    let srcToNewHeadNodes = /* @__PURE__ */ new Map();
796    for (const newHeadChild of newHeadTag.children) {
797      srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);
798    }
799    for (const currentHeadElt of currentHead.children) {
800      let inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);
801      let isReAppended = ctx.head.shouldReAppend(currentHeadElt);
802      let isPreserved = ctx.head.shouldPreserve(currentHeadElt);
803      if (inNewContent || isPreserved) {
804        if (isReAppended) {
805          removed.push(currentHeadElt);
806        } else {
807          srcToNewHeadNodes.delete(currentHeadElt.outerHTML);
808          preserved.push(currentHeadElt);
809        }
810      } else {
811        if (headMergeStyle === "append") {
812          if (isReAppended) {
813            removed.push(currentHeadElt);
814            nodesToAppend.push(currentHeadElt);
815          }
816        } else {
817          if (ctx.head.shouldRemove(currentHeadElt) !== false) {
818            removed.push(currentHeadElt);
819          }
820        }
821      }
822    }
823    nodesToAppend.push(...srcToNewHeadNodes.values());
824    log("to append: ", nodesToAppend);
825    let promises = [];
826    for (const newNode of nodesToAppend) {
827      log("adding: ", newNode);
828      let newElt = document.createRange().createContextualFragment(newNode.outerHTML).firstChild;
829      log(newElt);
830      if (ctx.callbacks.beforeNodeAdded(newElt) !== false) {
831        if (newElt.href || newElt.src) {
832          let resolve = null;
833          let promise = new Promise(function(_resolve) {
834            resolve = _resolve;
835          });
836          newElt.addEventListener("load", function() {
837            resolve();
838          });
839          promises.push(promise);
840        }
841        currentHead.appendChild(newElt);
842        ctx.callbacks.afterNodeAdded(newElt);
843        added.push(newElt);
844      }
845    }
846    for (const removedElement of removed) {
847      if (ctx.callbacks.beforeNodeRemoved(removedElement) !== false) {
848        currentHead.removeChild(removedElement);
849        ctx.callbacks.afterNodeRemoved(removedElement);
850      }
851    }
852    ctx.head.afterHeadMorphed(currentHead, { added, kept: preserved, removed });
853    return promises;
854  }
855  function log() {
856  }
857  function noOp() {
858  }
859  function mergeDefaults(config) {
860    let finalConfig = {};
861    Object.assign(finalConfig, defaults);
862    Object.assign(finalConfig, config);
863    finalConfig.callbacks = {};
864    Object.assign(finalConfig.callbacks, defaults.callbacks);
865    Object.assign(finalConfig.callbacks, config.callbacks);
866    finalConfig.head = {};
867    Object.assign(finalConfig.head, defaults.head);
868    Object.assign(finalConfig.head, config.head);
869    return finalConfig;
870  }
871  function createMorphContext(oldNode, newContent, config) {
872    config = mergeDefaults(config);
873    return {
874      target: oldNode,
875      newContent,
876      config,
877      morphStyle: config.morphStyle,
878      ignoreActive: config.ignoreActive,
879      ignoreActiveValue: config.ignoreActiveValue,
880      idMap: createIdMap(oldNode, newContent),
881      deadIds: /* @__PURE__ */ new Set(),
882      callbacks: config.callbacks,
883      head: config.head
884    };
885  }
886  function isIdSetMatch(node1, node2, ctx) {
887    if (node1 == null || node2 == null) {
888      return false;
889    }
890    if (node1.nodeType === node2.nodeType && node1.tagName === node2.tagName) {
891      if (node1.id !== "" && node1.id === node2.id) {
892        return true;
893      } else {
894        return getIdIntersectionCount(ctx, node1, node2) > 0;
895      }
896    }
897    return false;
898  }
899  function isSoftMatch(node1, node2) {
900    if (node1 == null || node2 == null) {
901      return false;
902    }
903    return node1.nodeType === node2.nodeType && node1.tagName === node2.tagName;
904  }
905  function removeNodesBetween(startInclusive, endExclusive, ctx) {
906    while (startInclusive !== endExclusive) {
907      let tempNode = startInclusive;
908      startInclusive = startInclusive.nextSibling;
909      removeNode(tempNode, ctx);
910    }
911    removeIdsFromConsideration(ctx, endExclusive);
912    return endExclusive.nextSibling;
913  }
914  function findIdSetMatch(newContent, oldParent, newChild, insertionPoint, ctx) {
915    let newChildPotentialIdCount = getIdIntersectionCount(ctx, newChild, oldParent);
916    let potentialMatch = null;
917    if (newChildPotentialIdCount > 0) {
918      let potentialMatch2 = insertionPoint;
919      let otherMatchCount = 0;
920      while (potentialMatch2 != null) {
921        if (isIdSetMatch(newChild, potentialMatch2, ctx)) {
922          return potentialMatch2;
923        }
924        otherMatchCount += getIdIntersectionCount(ctx, potentialMatch2, newContent);
925        if (otherMatchCount > newChildPotentialIdCount) {
926          return null;
927        }
928        potentialMatch2 = potentialMatch2.nextSibling;
929      }
930    }
931    return potentialMatch;
932  }
933  function findSoftMatch(newContent, oldParent, newChild, insertionPoint, ctx) {
934    let potentialSoftMatch = insertionPoint;
935    let nextSibling = newChild.nextSibling;
936    let siblingSoftMatchCount = 0;
937    while (potentialSoftMatch != null) {
938      if (getIdIntersectionCount(ctx, potentialSoftMatch, newContent) > 0) {
939        return null;
940      }
941      if (isSoftMatch(newChild, potentialSoftMatch)) {
942        return potentialSoftMatch;
943      }
944      if (isSoftMatch(nextSibling, potentialSoftMatch)) {
945        siblingSoftMatchCount++;
946        nextSibling = nextSibling.nextSibling;
947        if (siblingSoftMatchCount >= 2) {
948          return null;
949        }
950      }
951      potentialSoftMatch = potentialSoftMatch.nextSibling;
952    }
953    return potentialSoftMatch;
954  }
955  function parseContent(newContent) {
956    let parser = new DOMParser();
957    let contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, "");
958    if (contentWithSvgsRemoved.match(/<\/html>/) || contentWithSvgsRemoved.match(/<\/head>/) || contentWithSvgsRemoved.match(/<\/body>/)) {
959      let content = parser.parseFromString(newContent, "text/html");
960      if (contentWithSvgsRemoved.match(/<\/html>/)) {
961        content.generatedByIdiomorph = true;
962        return content;
963      } else {
964        let htmlElement = content.firstChild;
965        if (htmlElement) {
966          htmlElement.generatedByIdiomorph = true;
967          return htmlElement;
968        } else {
969          return null;
970        }
971      }
972    } else {
973      let responseDoc = parser.parseFromString("<body><template>" + newContent + "</template></body>", "text/html");
974      let content = responseDoc.body.querySelector("template").content;
975      content.generatedByIdiomorph = true;
976      return content;
977    }
978  }
979  function normalizeContent(newContent) {
980    if (newContent == null) {
981      const dummyParent = document.createElement("div");
982      return dummyParent;
983    } else if (newContent.generatedByIdiomorph) {
984      return newContent;
985    } else if (newContent instanceof Node) {
986      const dummyParent = document.createElement("div");
987      dummyParent.append(newContent);
988      return dummyParent;
989    } else {
990      const dummyParent = document.createElement("div");
991      for (const elt of [...newContent]) {
992        dummyParent.append(elt);
993      }
994      return dummyParent;
995    }
996  }
997  function insertSiblings(previousSibling, morphedNode, nextSibling) {
998    let stack = [];
999    let added = [];
1000    while (previousSibling != null) {
1001      stack.push(previousSibling);
1002      previousSibling = previousSibling.previousSibling;
1003    }
1004    while (stack.length > 0) {
1005      let node = stack.pop();
1006      added.push(node);
1007      morphedNode.parentElement.insertBefore(node, morphedNode);
1008    }
1009    added.push(morphedNode);
1010    while (nextSibling != null) {
1011      stack.push(nextSibling);
1012      added.push(nextSibling);
1013      nextSibling = nextSibling.nextSibling;
1014    }
1015    while (stack.length > 0) {
1016      morphedNode.parentElement.insertBefore(stack.pop(), morphedNode.nextSibling);
1017    }
1018    return added;
1019  }
1020  function findBestNodeMatch(newContent, oldNode, ctx) {
1021    let currentElement;
1022    currentElement = newContent.firstChild;
1023    let bestElement = currentElement;
1024    let score = 0;
1025    while (currentElement) {
1026      let newScore = scoreElement(currentElement, oldNode, ctx);
1027      if (newScore > score) {
1028        bestElement = currentElement;
1029        score = newScore;
1030      }
1031      currentElement = currentElement.nextSibling;
1032    }
1033    return bestElement;
1034  }
1035  function scoreElement(node1, node2, ctx) {
1036    if (isSoftMatch(node1, node2)) {
1037      return 0.5 + getIdIntersectionCount(ctx, node1, node2);
1038    }
1039    return 0;
1040  }
1041  function removeNode(tempNode, ctx) {
1042    removeIdsFromConsideration(ctx, tempNode);
1043    if (ctx.callbacks.beforeNodeRemoved(tempNode) === false) return;
1044    tempNode.remove();
1045    ctx.callbacks.afterNodeRemoved(tempNode);
1046  }
1047  function isIdInConsideration(ctx, id) {
1048    return !ctx.deadIds.has(id);
1049  }
1050  function idIsWithinNode(ctx, id, targetNode) {
1051    let idSet = ctx.idMap.get(targetNode) || EMPTY_SET;
1052    return idSet.has(id);
1053  }
1054  function removeIdsFromConsideration(ctx, node) {
1055    let idSet = ctx.idMap.get(node) || EMPTY_SET;
1056    for (const id of idSet) {
1057      ctx.deadIds.add(id);
1058    }
1059  }
1060  function getIdIntersectionCount(ctx, node1, node2) {
1061    let sourceSet = ctx.idMap.get(node1) || EMPTY_SET;
1062    let matchCount = 0;
1063    for (const id of sourceSet) {
1064      if (isIdInConsideration(ctx, id) && idIsWithinNode(ctx, id, node2)) {
1065        ++matchCount;
1066      }
1067    }
1068    return matchCount;
1069  }
1070  function populateIdMapForNode(node, idMap) {
1071    let nodeParent = node.parentElement;
1072    let idElements = node.querySelectorAll("[id]");
1073    for (const elt of idElements) {
1074      let current = elt;
1075      while (current !== nodeParent && current != null) {
1076        let idSet = idMap.get(current);
1077        if (idSet == null) {
1078          idSet = /* @__PURE__ */ new Set();
1079          idMap.set(current, idSet);
1080        }
1081        idSet.add(elt.id);
1082        current = current.parentElement;
1083      }
1084    }
1085  }
1086  function createIdMap(oldContent, newContent) {
1087    let idMap = /* @__PURE__ */ new Map();
1088    populateIdMapForNode(oldContent, idMap);
1089    populateIdMapForNode(newContent, idMap);
1090    return idMap;
1091  }
1092  return {
1093    morph,
1094    defaults
1095  };
1096}();
1097
1098// src/normalize_attributes_for_comparison.ts
1099function normalizeAttributesForComparison(element) {
1100  const isFileInput = element instanceof HTMLInputElement && element.type === "file";
1101  if (!isFileInput) {
1102    if ("value" in element) {
1103      element.setAttribute("value", element.value);
1104    } else if (element.hasAttribute("value")) {
1105      element.setAttribute("value", "");
1106    }
1107  }
1108  Array.from(element.children).forEach((child) => {
1109    normalizeAttributesForComparison(child);
1110  });
1111}
1112
1113// src/morphdom.ts
1114var syncAttributes = (fromEl, toEl) => {
1115  for (let i = 0; i < fromEl.attributes.length; i++) {
1116    const attr = fromEl.attributes[i];
1117    toEl.setAttribute(attr.name, attr.value);
1118  }
1119};
1120function executeMorphdom(rootFromElement, rootToElement, modifiedFieldElements, getElementValue, externalMutationTracker) {
1121  const originalElementIdsToSwapAfter = [];
1122  const originalElementsToPreserve = /* @__PURE__ */ new Map();
1123  const markElementAsNeedingPostMorphSwap = (id, replaceWithClone) => {
1124    const oldElement = originalElementsToPreserve.get(id);
1125    if (!(oldElement instanceof HTMLElement)) {
1126      throw new Error(`Original element with id ${id} not found`);
1127    }
1128    originalElementIdsToSwapAfter.push(id);
1129    if (!replaceWithClone) {
1130      return null;
1131    }
1132    const clonedOldElement = cloneHTMLElement(oldElement);
1133    oldElement.replaceWith(clonedOldElement);
1134    return clonedOldElement;
1135  };
1136  rootToElement.querySelectorAll("[data-live-preserve]").forEach((newElement) => {
1137    const id = newElement.id;
1138    if (!id) {
1139      throw new Error("The data-live-preserve attribute requires an id attribute to be set on the element");
1140    }
1141    const oldElement = rootFromElement.querySelector(`#${id}`);
1142    if (!(oldElement instanceof HTMLElement)) {
1143      throw new Error(`The element with id "${id}" was not found in the original HTML`);
1144    }
1145    newElement.removeAttribute("data-live-preserve");
1146    originalElementsToPreserve.set(id, oldElement);
1147    syncAttributes(newElement, oldElement);
1148  });
1149  Idiomorph.morph(rootFromElement, rootToElement, {
1150    callbacks: {
1151      beforeNodeMorphed: (fromEl, toEl) => {
1152        if (!(fromEl instanceof Element) || !(toEl instanceof Element)) {
1153          return true;
1154        }
1155        if (fromEl === rootFromElement) {
1156          return true;
1157        }
1158        if (fromEl.id && originalElementsToPreserve.has(fromEl.id)) {
1159          if (fromEl.id === toEl.id) {
1160            return false;
1161          }
1162          const clonedFromEl = markElementAsNeedingPostMorphSwap(fromEl.id, true);
1163          if (!clonedFromEl) {
1164            throw new Error("missing clone");
1165          }
1166          Idiomorph.morph(clonedFromEl, toEl);
1167          return false;
1168        }
1169        if (fromEl instanceof HTMLElement && toEl instanceof HTMLElement) {
1170          if (typeof fromEl.__x !== "undefined") {
1171            if (!window.Alpine) {
1172              throw new Error(
1173                "Unable to access Alpine.js though the global window.Alpine variable. Please make sure Alpine.js is loaded before Symfony UX LiveComponent."
1174              );
1175            }
1176            if (typeof window.Alpine.morph !== "function") {
1177              throw new Error(
1178                "Unable to access Alpine.js morph function. Please make sure the Alpine.js Morp
1178h plugin is installed and loaded, see https://alpinejs.dev/plugins/morph for more information."
1179              );
1180            }
1181            window.Alpine.morph(fromEl.__x, toEl);
1182          }
1183          if (externalMutationTracker.wasElementAdded(fromEl)) {
1184            fromEl.insertAdjacentElement("afterend", toEl);
1185            return false;
1186          }
1187          if (modifiedFieldElements.includes(fromEl)) {
1188            setValueOnElement(toEl, getElementValue(fromEl));
1189          }
1190          if (fromEl === document.activeElement && fromEl !== document.body && null !== getModelDirectiveFromElement(fromEl, false)) {
1191            setValueOnElement(toEl, getElementValue(fromEl));
1192          }
1193          const elementChanges = externalMutationTracker.getChangedElement(fromEl);
1194          if (elementChanges) {
1195            elementChanges.applyToElement(toEl);
1196          }
1197          if (fromEl.nodeName.toUpperCase() !== "OPTION" && fromEl.isEqualNode(toEl)) {
1198            const normalizedFromEl = cloneHTMLElement(fromEl);
1199            normalizeAttributesForComparison(normalizedFromEl);
1200            const normalizedToEl = cloneHTMLElement(toEl);
1201            normalizeAttributesForComparison(normalizedToEl);
1202            if (normalizedFromEl.isEqualNode(normalizedToEl)) {
1203              return false;
1204            }
1205          }
1206        }
1207        if (fromEl.hasAttribute("data-skip-morph") || fromEl.id && fromEl.id !== toEl.id) {
1208          fromEl.innerHTML = toEl.innerHTML;
1209          return true;
1210        }
1211        if (fromEl.parentElement?.hasAttribute("data-skip-morph")) {
1212          return false;
1213        }
1214        return !fromEl.hasAttribute("data-live-ignore");
1215      },
1216      beforeNodeRemoved(node) {
1217        if (!(node instanceof HTMLElement)) {
1218          return true;
1219        }
1220        if (node.id && originalElementsToPreserve.has(node.id)) {
1221          markElementAsNeedingPostMorphSwap(node.id, false);
1222          return true;
1223        }
1224        if (externalMutationTracker.wasElementAdded(node)) {
1225          return false;
1226        }
1227        return !node.hasAttribute("data-live-ignore");
1228      }
1229    }
1230  });
1231  originalElementIdsToSwapAfter.forEach((id) => {
1232    const newElement = rootFromElement.querySelector(`#${id}`);
1233    const originalElement = originalElementsToPreserve.get(id);
1234    if (!(newElement instanceof HTMLElement) || !(originalElement instanceof HTMLElement)) {
1235      throw new Error("Missing elements.");
1236    }
1237    newElement.replaceWith(originalElement);
1238  });
1239}
1240
1241// src/Rendering/ChangingItemsTracker.ts
1242var ChangingItemsTracker_default = class {
1243  constructor() {
1244    // e.g. a Map with key "color" & value { original: 'previousValue', new: 'newValue' },
1245    this.changedItems = /* @__PURE__ */ new Map();
1246    this.removedItems = /* @__PURE__ */ new Map();
1247  }
1248  /**
1249   * A "null" previousValue means the item was NOT previously present.
1250   */
1251  setItem(itemName, newValue, previousValue) {
1252    if (this.removedItems.has(itemName)) {
1253      const removedRecord = this.removedItems.get(itemName);
1254      this.removedItems.delete(itemName);
1255      if (removedRecord.original === newValue) {
1256        return;
1257      }
1258    }
1259    if (this.changedItems.has(itemName)) {
1260      const originalRecord = this.changedItems.get(itemName);
1261      if (originalRecord.original === newValue) {
1262        this.changedItems.delete(itemName);
1263        return;
1264      }
1265      this.changedItems.set(itemName, { original: originalRecord.original, new: newValue });
1266      return;
1267    }
1268    this.changedItems.set(itemName, { original: previousValue, new: newValue });
1269  }
1270  removeItem(itemName, currentValue) {
1271    let trueOriginalValue = currentValue;
1272    if (this.changedItems.has(itemName)) {
1273      const originalRecord = this.changedItems.get(itemName);
1274      trueOriginalValue = originalRecord.original;
1275      this.changedItems.delete(itemName);
1276      if (trueOriginalValue === null) {
1277        return;
1278      }
1279    }
1280    if (!this.removedItems.has(itemName)) {
1281      this.removedItems.set(itemName, { original: trueOriginalValue });
1282    }
1283  }
1284  getChangedItems() {
1285    return Array.from(this.changedItems, ([name, { new: value }]) => ({ name, value }));
1286  }
1287  getRemovedItems() {
1288    return Array.from(this.removedItems.keys());
1289  }
1290  isEmpty() {
1291    return this.changedItems.size === 0 && this.removedItems.size === 0;
1292  }
1293};
1294
1295// src/Rendering/ElementChanges.ts
1296var ElementChanges = class {
1297  constructor() {
1298    this.addedClasses = /* @__PURE__ */ new Set();
1299    this.removedClasses = /* @__PURE__ */ new Set();
1300    this.styleChanges = new ChangingItemsTracker_default();
1301    this.attributeChanges = new ChangingItemsTracker_default();
1302  }
1303  addClass(className) {
1304    if (!this.removedClasses.delete(className)) {
1305      this.addedClasses.add(className);
1306    }
1307  }
1308  removeClass(className) {
1309    if (!this.addedClasses.delete(className)) {
1310      this.removedClasses.add(className);
1311    }
1312  }
1313  addStyle(styleName, newValue, originalValue) {
1314    this.styleChanges.setItem(styleName, newValue, originalValue);
1315  }
1316  removeStyle(styleName, originalValue) {
1317    this.styleChanges.removeItem(styleName, originalValue);
1318  }
1319  addAttribute(attributeName, newValue, originalValue) {
1320    this.attributeChanges.setItem(attributeName, newValue, originalValue);
1321  }
1322  removeAttribute(attributeName, originalValue) {
1323    this.attributeChanges.removeItem(attributeName, originalValue);
1324  }
1325  getAddedClasses() {
1326    return [...this.addedClasses];
1327  }
1328  getRemovedClasses() {
1329    return [...this.removedClasses];
1330  }
1331  getChangedStyles() {
1332    return this.styleChanges.getChangedItems();
1333  }
1334  getRemovedStyles() {
1335    return this.styleChanges.getRemovedItems();
1336  }
1337  getChangedAttributes() {
1338    return this.attributeChanges.getChangedItems();
1339  }
1340  getRemovedAttributes() {
1341    return this.attributeChanges.getRemovedItems();
1342  }
1343  applyToElement(element) {
1344    element.classList.add(...this.addedClasses);
1345    element.classList.remove(...this.removedClasses);
1346    this.styleChanges.getChangedItems().forEach((change) => {
1347      element.style.setProperty(change.name, change.value);
1348      return;
1349    });
1350    this.styleChanges.getRemovedItems().forEach((styleName) => {
1351      element.style.removeProperty(styleName);
1352    });
1353    this.attributeChanges.getChangedItems().forEach((change) => {
1354      element.setAttribute(change.name, change.value);
1355    });
1356    this.attributeChanges.getRemovedItems().forEach((attributeName) => {
1357      element.removeAttribute(attributeName);
1358    });
1359  }
1360  isEmpty() {
1361    return this.addedClasses.size === 0 && this.removedClasses.size === 0 && this.styleChanges.isEmpty() && this.attributeChanges.isEmpty();
1362  }
1363};
1364
1365// src/Rendering/ExternalMutationTracker.ts
1366var ExternalMutationTracker_default = class {
1367  constructor(element, shouldTrackChangeCallback) {
1368    this.changedElements = /* @__PURE__ */ new WeakMap();
1369    /** For testing */
1370    this.changedElementsCount = 0;
1371    this.addedElements = [];
1372    this.removedElements = [];
1373    this.isStarted = false;
1374    this.element = element;
1375    this.shouldTrackChangeCallback = shouldTrackChangeCallback;
1376    this.mutationObserver = new MutationObserver(this.onMutations.bind(this));
1377  }
1378  start() {
1379    if (this.isStarted) {
1380      return;
1381    }
1382    this.mutationObserver.observe(this.element, {
1383      childList: true,
1384      subtree: true,
1385      attributes: true,
1386      attributeOldValue: true
1387    });
1388    this.isStarted = true;
1389  }
1390  stop() {
1391    if (this.isStarted) {
1392      this.mutationObserver.disconnect();
1393      this.isStarted = false;
1394    }
1395  }
1396  getChangedElement(element) {
1397    return this.changedElements.has(element) ? this.changedElements.get(element) : null;
1398  }
1399  getAddedElements() {
1400    return this.addedElements;
1401  }
1402  wasElementAdded(element) {
1403    return this.addedElements.includes(element);
1404  }
1405  /**
1406   * Forces any pending mutations to be handled immediately, then clears the queue.
1407   */
1408  handlePendingChanges() {
1409    this.onMutations(this.mutationObserver.takeRecords());
1410  }
1411  onMutations(mutations) {
1412    const handledAttributeMutations = /* @__PURE__ */ new WeakMap();
1413    for (const mutation of mutations) {
1414      const element = mutation.target;
1415      if (!this.shouldTrackChangeCallback(element)) {
1416        continue;
1417      }
1418      if (this.isElementAddedByTranslation(element)) {
1419        continue;
1420      }
1421      let isChangeInAddedElement = false;
1422      for (const addedElement of this.addedElements) {
1423        if (addedElement.contains(element)) {
1424          isChangeInAddedElement = true;
1425          break;
1426        }
1427      }
1428      if (isChangeInAddedElement) {
1429        continue;
1430      }
1431      switch (mutation.type) {
1432        case "childList":
1433          this.handleChildListMutation(mutation);
1434          break;
1435        case "attributes":
1436          if (!handledAttributeMutations.has(element)) {
1437            handledAttributeMutations.set(element, []);
1438          }
1439          if (!handledAttributeMutations.get(element).includes(mutation.attributeName)) {
1440            this.handleAttributeMutation(mutation);
1441            handledAttributeMutations.set(element, [
1442              ...handledAttributeMutations.get(element),
1443              mutation.attributeName
1444            ]);
1445          }
1446          break;
1447      }
1448    }
1449  }
1450  handleChildListMutation(mutation) {
1451    mutation.addedNodes.forEach((node) => {
1452      if (!(node instanceof Element)) {
1453        return;
1454      }
1455      if (this.removedElements.includes(node)) {
1456        this.removedElements.splice(this.removedElements.indexOf(node), 1);
1457        return;
1458      }
1459      if (this.isElementAddedByTranslation(node)) {
1460        return;
1461      }
1462      this.addedElements.push(node);
1463    });
1464    mutation.removedNodes.forEach((node) => {
1465      if (!(node instanceof Element)) {
1466        return;
1467      }
1468      if (this.addedElements.includes(node)) {
1469        this.addedElements.splice(this.addedElements.indexOf(node), 1);
1470        return;
1471      }
1472      this.removedElements.push(node);
1473    });
1474  }
1475  handleAttributeMutation(mutation) {
1476    const element = mutation.target;
1477    if (!this.changedElements.has(element)) {
1478      this.changedElements.set(element, new ElementChanges());
1479      this.changedElementsCount++;
1480    }
1481    const changedElement = this.changedElements.get(element);
1482    switch (mutation.attributeName) {
1483      case "class":
1484        this.handleClassAttributeMutation(mutation, changedElement);
1485        break;
1486      case "style":
1487        this.handleStyleAttributeMutation(mutation, changedElement);
1488        break;
1489      default:
1490        this.handleGenericAttributeMutation(mutation, changedElement);
1491    }
1492    if (changedElement.isEmpty()) {
1493      this.changedElements.delete(element);
1494      this.changedElementsCount--;
1495    }
1496  }
1497  handleClassAttributeMutation(mutation, elementChanges) {
1498    const element = mutation.target;
1499    const previousValue = mutation.oldValue || "";
1500    const previousValues = previousValue.match(/(\S+)/gu) || [];
1501    const newValues = [].slice.call(element.classList);
1502    const addedValues = newValues.filter((value) => !previousValues.includes(value));
1503    const removedValues = previousValues.filter((value) => !newValues.includes(value));
1504    addedValues.forEach((value) => {
1505      elementChanges.addClass(value);
1506    });
1507    removedValues.forEach((value) => {
1508      elementChanges.removeClass(value);
1509    });
1510  }
1511  handleStyleAttributeMutation(mutation, elementChanges) {
1512    const element = mutation.target;
1513    const previousValue = mutation.oldValue || "";
1514    const previousStyles = this.extractStyles(previousValue);
1515    const newValue = element.getAttribute("style") || "";
1516    const newStyles = this.extractStyles(newValue);
1517    const addedOrChangedStyles = Object.keys(newStyles).filter(
1518      (key) => previousStyles[key] === void 0 || previousStyles[key] !== newStyles[key]
1519    );
1520    const removedStyles = Object.keys(previousStyles).filter((key) => !newStyles[key]);
1521    addedOrChangedStyles.forEach((style) => {
1522      elementChanges.addStyle(
1523        style,
1524        newStyles[style],
1525        previousStyles[style] === void 0 ? null : previousStyles[style]
1526      );
1527    });
1528    removedStyles.forEach((style) => {
1529      elementChanges.removeStyle(style, previousStyles[style]);
1530    });
1531  }
1532  handleGenericAttributeMutation(mutation, elementChanges) {
1533    const attributeName = mutation.attributeName;
1534    const element = mutation.target;
1535    let oldValue = mutation.oldValue;
1536    let newValue = element.getAttribute(attributeName);
1537    if (oldValue === attributeName) {
1538      oldValue = "";
1539    }
1540    if (newValue === attributeName) {
1541      newValue = "";
1542    }
1543    if (!element.hasAttribute(attributeName)) {
1544      if (oldValue === null) {
1545        return;
1546      }
1547      elementChanges.removeAttribute(attributeName, mutation.oldValue);
1548      return;
1549    }
1550    if (newValue === oldValue) {
1551      return;
1552    }
1553    elementChanges.addAttribute(attributeName, element.getAttribute(attributeName), mutation.oldValue);
1554  }
1555  extractStyles(styles) {
1556    const styleObject = {};
1557    styles.split(";").forEach((style) => {
1558      const parts = style.split(":");
1559      if (parts.length === 1) {
1560        return;
1561      }
1562      const property = parts[0].trim();
1563      styleObject[property] = parts.slice(1).join(":").trim();
1564    });
1565    return styleObject;
1566  }
1567  /**
1568   * Helps avoid tracking changes by Chrome's translation feature.
1569   *
1570   * When Chrome translates, it mutates the dom in a way that triggers MutationObserver.
1571   * This includes adding new elements wrapped in a <font> tag. This causes live
1572   * components to incorrectly think that these new elements should persist through
1573   * re-renders, causing duplicate text.
1574   */
1575  isElementAddedByTranslation(element) {
1576    return element.tagName === "FONT" && element.getAttribute("style") === "vertical-align: inherit;";
1577  }
1578};
1579
1580// src/Component/UnsyncedInputsTracker.ts
1581var UnsyncedInputsTracker_default = class {
1582  constructor(component, modelElementResolver) {
1583    this.elementEventListeners = [
1584      { event: "input", callback: (event) => this.handleInputEvent(event) }
1585    ];
1586    this.component = component;
1587    this.modelElementResolver = modelElementResolver;
1588    this.unsyncedInputs = new UnsyncedInputContainer();
1589  }
1590  activate() {
1591    this.elementEventListeners.forEach(({ event, callback }) => {
1592      this.component.element.addEventListener(event, callback);
1593    });
1594  }
1595  deactivate() {
1596    this.elementEventListeners.forEach(({ event, callback }) => {
1597      this.component.element.removeEventListener(event, callback);
1598    });
1599  }
1600  markModelAsSynced(modelName) {
1601    this.unsyncedInputs.markModelAsSynced(modelName);
1602  }
1603  handleInputEvent(event) {
1604    const target = event.target;
1605    if (!target) {
1606      return;
1607    }
1608    this.updateModelFromElement(target);
1609  }
1610  updateModelFromElement(element) {
1611    if (!elementBelongsToThisComponent(element, this.component)) {
1612      return;
1613    }
1614    if (!(element instanceof HTMLElement)) {
1615      throw new Error("Could not update model for non HTMLElement");
1616    }
1617    const modelName = this.modelElementResolver.getModelName(element);
1618    this.unsyncedInputs.add(element, modelName);
1619  }
1620  getUnsyncedInputs() {
1621    return this.unsyncedInputs.allUnsyncedInputs();
1622  }
1623  getUnsyncedModels() {
1624    return Array.from(this.unsyncedInputs.getUnsyncedModelNames());
1625  }
1626  resetUnsyncedFields() {
1627    this.unsyncedInputs.resetUnsyncedFields();
1628  }
1629};
1630var UnsyncedInputContainer = class {
1631  constructor() {
1632    this.unsyncedNonModelFields = [];
1633    this.unsyncedModelNames = [];
1634    this.unsyncedModelFields = /* @__PURE__ */ new Map();
1635  }
1636  add(element, modelName = null) {
1637    if (modelName) {
1638      this.unsyncedModelFields.set(modelName, element);
1639      if (!this.unsyncedModelNames.includes(modelName)) {
1640        this.unsyncedModelNames.push(modelName);
1641      }
1642      return;
1643    }
1644    this.unsyncedNonModelFields.push(element);
1645  }
1646  /**
1647   * Mark all fields as synced, except for those not bound to a model or whose
1648   * values are still dirty.
1649   */
1650  resetUnsyncedFields() {
1651    this.unsyncedModelFields.forEach((value, key) => {
1652      if (!this.unsyncedModelNames.includes(key)) {
1653        this.unsyncedModelFields.delete(key);
1654      }
1655    });
1656  }
1657  allUnsyncedInputs() {
1658    return [...this.unsyncedNonModelFields, ...this.unsyncedModelFields.values()];
1659  }
1660  markModelAsSynced(modelName) {
1661    const index = this.unsyncedModelNames.indexOf(modelName);
1662    if (index !== -1) {
1663      this.unsyncedModelNames.splice(index, 1);
1664    }
1665  }
1666  /**
1667   * Returns a list of models whose fields have been modified, but whose values
1668   * have not yet been set onto the data store.
1669   */
1670  getUnsyncedModelNames() {
1671    return this.unsyncedModelNames;
1672  }
1673};
1674
1675// src/data_manipulation_utils.ts
1676function getDeepData(data, propertyPath) {
1677  const { currentLevelData, finalKey } = parseDeepData(data, propertyPath);
1678  if (currentLevelData === void 0) {
1679    return void 0;
1680  }
1681  return currentLevelData[finalKey];
1682}
1683var parseDeepData = (data, propertyPath) => {
1684  const finalData = JSON.parse(JSON.stringify(data));
1685  let currentLevelData = finalData;
1686  const parts = propertyPath.split(".");
1687  for (let i = 0; i < parts.length - 1; i++) {
1688    currentLevelData = currentLevelData[parts[i]];
1689  }
1690  const finalKey = parts[parts.length - 1];
1691  return {
1692    currentLevelData,
1693    finalData,
1694    finalKey,
1695    parts
1696  };
1697};
1698
1699// src/Component/ValueStore.ts
1700var ValueStore_default = class {
1701  constructor(props) {
1702    /**
1703     * Original, read-only props that represent the original component state.
1704     *
1705     * @private
1706     */
1707    this.props = {};
1708    /**
1709     * A list of props that have been "dirty" (changed) since the last request to the server.
1710     */
1711    this.dirtyProps = {};
1712    /**
1713     * A list of dirty props that were sent to the server, but the response has
1714     * not yet been received.
1715     */
1716    this.pendingProps = {};
1717    /**
1718     * A list of props that the parent wants us to update.
1719     *
1720     * These will be sent on the next request to the server.
1721     */
1722    this.updatedPropsFromParent = {};
1723    this.props = props;
1724  }
1725  /**
1726   * Returns the props with the given name.
1727   *
1728   * This allows for non-normalized model names - e.g.
1729   * user[firstName] -> user.firstName and also will fetch
1730   * deeply (fetching the "firstName" sub-key from the "user" key).
1731   */
1732  get(name) {
1733    const normalizedName = normalizeModelName(name);
1734    if (this.dirtyProps[normalizedName] !== void 0) {
1735      return this.dirtyProps[normalizedName];
1736    }
1737    if (this.pendingProps[normalizedName] !== void 0) {
1738      return this.pendingProps[normalizedName];
1739    }
1740    if (this.props[normalizedName] !== void 0) {
1741      return this.props[normalizedName];
1742    }
1743    return getDeepData(this.props, normalizedName);
1744  }
1745  has(name) {
1746    return this.get(name) !== void 0;
1747  }
1748  /**
1749   * Sets data back onto the value store.
1750   *
1751   * The name can be in the non-normalized format.
1752   *
1753   * Returns true if the new value is different from the existing value.
1754   */
1755  set(name, value) {
1756    const normalizedName = normalizeModelName(name);
1757    if (this.get(normalizedName) === value) {
1758      return false;
1759    }
1760    this.dirtyProps[normalizedName] = value;
1761    return true;
1762  }
1763  getOriginalProps() {
1764    return { ...this.props };
1765  }
1766  getDirtyProps() {
1767    return { ...this.dirtyProps };
1768  }
1769  getUpdatedPropsFromParent() {
1770    return { ...this.updatedPropsFromParent };
1771  }
1772  /**
1773   * Called when an update request begins.
1774   */
1775  flushDirtyPropsToPending() {
1776    this.pendingProps = { ...this.dirtyProps };
1777    this.dirtyProps = {};
1778  }
1779  /**
1780   * Called when an update request finishes successfully.
1781   */
1782  reinitializeAllProps(props) {
1783    this.props = props;
1784    this.updatedPropsFromParent = {};
1785    this.pendingProps = {};
1786  }
1787  /**
1788   * Called after an update request failed.
1789   */
1790  pushPendingPropsBackToDirty() {
1791    this.dirtyProps = { ...this.pendingProps, ...this.dirtyProps };
1792    this.pendingProps = {};
1793  }
1794  /**
1795   * This is used when a parent component is rendering, and it includes
1796   * a fresh set of props that should be updated on the child component.
1797   *
1798   * The server manages returning only the props that should be updated onto
1799   * the child, so we don't need to worry about that.
1800   *
1801   * The props are stored in a different place, because the existing props
1802   * have their own checksum and these new props have *their* own checksum.
1803   * So, on the next render, both need to be sent independently.
1804   *
1805   * Returns true if any of the props are different.
1806   */
1807  storeNewPropsFromParent(props) {
1808    let changed = false;
1809    for (const [key, value] of Object.entries(props)) {
1810      const currentValue = this.get(key);
1811      if (currentValue !== value) {
1812        changed = true;
1813      }
1814    }
1815    if (changed) {
1816      this.updatedPropsFromParent = props;
1817    }
1818    return changed;
1819  }
1820};
1821
1822// src/Component/index.ts
1823var Component = class {
1824  /**
1825   * @param element The root element
1826   * @param name    The name of the component
1827   * @param props   Readonly component props
1828   * @param listeners Array of event -> action listeners
1829   * @param id      Some unique id to identify this component. Needed to be a child component
1830   * @param backend Backend instance for updating
1831   * @param elementDriver Class to get "model" name from any element.
1832   */
1833  constructor(element, name, props, listeners, id, backend, elementDriver) {
1834    /**
1835     * A fingerprint that identifies the props/input that was used on
1836     * the server to create this component, especially if it was a
1837     * child component. This is sent back to the server and can be used
1838     * to determine if any "input" to the child component changed and thus,
1839     * if the child component needs to be re-rendered.
1840     */
1841    this.fingerprint = "";
1842    this.defaultDebounce = 150;
1843    this.backendRequest = null;
1844    /** Actions that are waiting to be executed */
1845    this.pendingActions = [];
1846    /** Files that are waiting to be sent */
1847    this.pendingFiles = {};
1848    /** Is a request waiting to be made? */
1849    this.isRequestPending = false;
1850    /** Current "timeout" before the pending request should be sent. */
1851    this.requestDebounceTimeout = null;
1852    this.element = element;
1853    this.name = name;
1854    this.backend = backend;
1855    this.elementDriver = elementDriver;
1856    this.id = id;
1857    this.listeners = /* @__PURE__ */ new Map();
1858    listeners.forEach((listener) => {
1859      if (!this.listeners.has(listener.event)) {
1860        this.listeners.set(listener.event, []);
1861      }
1862      this.listeners.get(listener.event)?.push(listener.action);
1863    });
1864    this.valueStore = new ValueStore_default(props);
1865    this.unsyncedInputsTracker = new UnsyncedInputsTracker_default(this, elementDriver);
1866    this.hooks = new HookManager_default();
1867    this.resetPromise();
1868    this.externalMutationTracker = new ExternalMutationTracker_default(
1869      this.element,
1870      (element2) => elementBelongsToThisComponent(element2, this)
1871    );
1872    this.externalMutationTracker.start();
1873  }
1874  addPlugin(plugin) {
1875    plugin.attachToComponent(this);
1876  }
1877  connect() {
1878    registerComponent(this);
1879    this.hooks.triggerHook("connect", this);
1880    this.unsyncedInputsTracker.activate();
1881    this.externalMutationTracker.start();
1882  }
1883  disconnect() {
1884    unregisterComponent(this);
1885    this.hooks.triggerHook("disconnect", this);
1886    this.clearRequestDebounceTimeout();
1887    this.unsyncedInputsTracker.deactivate();
1888    this.externalMutationTracker.stop();
1889  }
1890  on(hookName, callback) {
1891    this.hooks.register(hookName, callback);
1892  }
1893  off(hookName, callback) {
1894    this.hooks.unregister(hookName, callback);
1895  }
1896  set(model, value, reRender = false, debounce = false) {
1897    const promise = this.nextRequestPromise;
1898    const modelName = normalizeModelName(model);
1899    if (!this.valueStore.has(modelName)) {
1900      throw new Error(`Invalid model name "${model}".`);
1901    }
1902    const isChanged = this.valueStore.set(modelName, value);
1903    this.hooks.triggerHook("model:set", model, value, this);
1904    this.unsyncedInputsTracker.markModelAsSynced(modelName);
1905    if (reRender && isChanged) {
1906      this.debouncedStartRequest(debounce);
1907    }
1908    return promise;
1909  }
1910  getData(model) {
1911    const modelName = normalizeModelName(model);
1912    if (!this.valueStore.has(modelName)) {
1913      throw new Error(`Invalid model "${model}".`);
1914    }
1915    return this.valueStore.get(modelName);
1916  }
1917  action(name, args = {}, debounce = false) {
1918    const promise = this.nextRequestPromise;
1919    this.pendingActions.push({
1920      name,
1921      args
1922    });
1923    this.debouncedStartRequest(debounce);
1924    return promise;
1925  }
1926  files(key, input) {
1927    this.pendingFiles[key] = input;
1928  }
1929  render() {
1930    const promise = this.nextRequestPromise;
1931    this.tryStartingRequest();
1932    return promise;
1933  }
1934  /**
1935   * Returns an array of models the user has modified, but whose model has not
1936   * yet been updated.
1937   */
1938  getUnsyncedModels() {
1939    return this.unsyncedInputsTracker.getUnsyncedModels();
1940  }
1941  emit(name, data, onlyMatchingComponentsNamed = null) {
1942    this.performEmit(name, data, false, onlyMatchingComponentsNamed);
1943  }
1944  emitUp(name, data, onlyMatchingComponentsNamed = null) {
1945    this.performEmit(name, data, true, onlyMatchingComponentsNamed);
1946  }
1947  emitSelf(name, data) {
1948    this.doEmit(name, data);
1949  }
1950  performEmit(name, data, emitUp, matchingName) {
1951    const components = findComponents(this, emitUp, matchingName);
1952    components.forEach((component) => {
1953      component.doEmit(name, data);
1954    });
1955  }
1956  doEmit(name, data) {
1957    if (!this.listeners.has(name)) {
1958      return;
1959    }
1960    const actions = this.listeners.get(name) || [];
1961    actions.forEach((action) => {
1962      this.action(action, data, 1);
1963    });
1964  }
1965  isTurboEnabled() {
1966    return typeof Turbo !== "undefined" && !this.element.closest('[data-turbo="false"]');
1967  }
1968  tryStartingRequest() {
1969    if (!this.backendRequest) {
1970      this.performRequest();
1971      return;
1972    }
1973    this.isRequestPending = true;
1974  }
1975  performRequest() {
1976    const thisPromiseResolve = this.nextRequestPromiseResolve;
1977    this.resetPromise();
1978    this.unsyncedInputsTracker.resetUnsyncedFields();
1979    const filesToSend = {};
1980    for (const [key, value] of Object.entries(this.pendingFiles)) {
1981      if (value.files) {
1982        filesToSend[key] = value.files;
1983      }
1984    }
1985    const requestConfig = {
1986      props: this.valueStore.getOriginalProps(),
1987      actions: this.pendingActions,
1988      updated: this.valueStore.getDirtyProps(),
1989      children: {},
1990      updatedPropsFromParent: this.valueStore.getUpdatedPropsFromParent(),
1991      files: filesToSend
1992    };
1993    this.hooks.triggerHook("request:started", requestConfig);
1994    this.backendRequest = this.backend.makeRequest(
1995      requestConfig.props,
1996      requestConfig.actions,
1997      requestConfig.updated,
1998      requestConfig.children,
1999      requestConfig.updatedPropsFromParent,
2000      requestConfig.files
2001    );
2002    this.hooks.triggerHook("loading.state:started", this.element, this.backendRequest);
2003    this.pendingActions = [];
2004    this.valueStore.flushDirtyPropsToPending();
2005    this.isRequestPending = false;
2006    this.backendRequest.promise.then(async (response) => {
2007      const backendResponse = new BackendResponse_default(response);
2008      const html = await backendResponse.getBody();
2009      for (const input of Object.values(this.pendingFiles)) {
2010        input.value = "";
2011      }
2012      const headers = backendResponse.response.headers;
2013      if (!headers.get("Content-Type")?.includes("application/vnd.live-component+html") && !headers.get("X-Live-Redirect")) {
2014        const controls = { displayError: true };
2015        this.valueStore.pushPendingPropsBackToDirty();
2016        this.hooks.triggerHook("response:error", backendResponse, controls);
2017        if (controls.displayError) {
2018          this.renderError(html);
2019        }
2020        this.backendRequest = null;
2021        thisPromiseResolve(backendResponse);
2022        return response;
2023      }
2024      const liveUrl = backendResponse.getLiveUrl();
2025      if (liveUrl) {
2026        history.replaceState(
2027          history.state,
2028          "",
2029          new URL(liveUrl + window.location.hash, window.location.origin)
2030        );
2031      }
2032      this.processRerender(html, backendResponse);
2033      this.backendRequest = null;
2034      thisPromiseResolve(backendResponse);
2035      if (this.isRequestPending) {
2036        this.isRequestPending = false;
2037        this.performRequest();
2038      }
2039      return response;
2040    });
2041  }
2042  processRerender(html, backendResponse) {
2043    const controls = { shouldRender: true };
2044    this.hooks.triggerHook("render:started", html, backendResponse, controls);
2045    if (!controls.shouldRender) {
2046      return;
2047    }
2048    if (backendResponse.response.headers.get("Location")) {
2049      if (this.isTurboEnabled()) {
2050        Turbo.visit(backendResponse.response.headers.get("Location"));
2051      } else {
2052        window.location.href = backendResponse.response.headers.get("Location") || "";
2053      }
2054      return;
2055    }
2056    this.hooks.triggerHook("loading.state:finished", this.element);
2057    const modifiedModelValues = {};
2058    Object.keys(this.valueStore.getDirtyProps()).forEach((modelName) => {
2059      modifiedModelValues[modelName] = this.valueStore.get(modelName);
2060    });
2061    let newElement;
2062    try {
2063      newElement = htmlToElement(html);
2064      if (!newElement.matches("[data-controller~=live]")) {
2065        throw new Error("A live component template must contain a single root controller element.");
2066      }
2067    } catch (error) {
2068      console.error(`There was a problem with the '${this.name}' component HTML returned:`, {
2069        id: this.id
2070      });
2071      throw error;
2072    }
2073    this.externalMutationTracker.handlePendingChanges();
2074    this.externalMutationTracker.stop();
2075    executeMorphdom(
2076      this.element,
2077      newElement,
2078      this.unsyncedInputsTracker.getUnsyncedInputs(),
2079      (element) => getValueFromElement(element, this.valueStore),
2080      this.externalMutationTracker
2081    );
2082    this.externalMutationTracker.start();
2083    const newProps = this.elementDriver.getComponentProps();
2084    this.valueStore.reinitializeAllProps(newProps);
2085    const eventsToEmit = this.elementDriver.getEventsToEmit();
2086    const browserEventsToDispatch = this.elementDriver.getBrowserEventsToDispatch();
2087    Object.keys(modifiedModelValues).forEach((modelName) => {
2088      this.valueStore.set(modelName, modifiedModelValues[modelName]);
2089    });
2090    eventsToEmit.forEach(({ event, data, target, componentName }) => {
2091      if (target === "up") {
2092        this.emitUp(event, data, componentName);
2093        return;
2094      }
2095      if (target === "self") {
2096        this.emitSelf(event, data);
2097        return;
2098      }
2099      this.emit(event, data, componentName);
2100    });
2101    browserEventsToDispatch.forEach(({ event, payload }) => {
2102      this.element.dispatchEvent(
2103        new CustomEvent(event, {
2104          detail: payload,
2105          bubbles: true
2106        })
2107      );
2108    });
2109    this.hooks.triggerHook("render:finished", this);
2110  }
2111  calculateDebounce(debounce) {
2112    if (debounce === true) {
2113      return this.defaultDebounce;
2114    }
2115    if (debounce === false) {
2116      return 0;
2117    }
2118    return debounce;
2119  }
2120  clearRequestDebounceTimeout() {
2121    if (this.requestDebounceTimeout) {
2122      clearTimeout(this.requestDebounceTimeout);
2123      this.requestDebounceTimeout = null;
2124    }
2125  }
2126  debouncedStartRequest(debounce) {
2127    this.clearRequestDebounceTimeout();
2128    this.requestDebounceTimeout = window.setTimeout(() => {
2129      this.render();
2130    }, this.calculateDebounce(debounce));
2131  }
2132  // inspired by Livewire!
2133  renderError(html) {
2134    let modal = document.getElementById("live-component-error");
2135    if (modal) {
2136      modal.innerHTML = "";
2137    } else {
2138      modal = document.createElement("div");
2139      modal.id = "live-component-error";
2140      modal.style.padding = "50px";
2141      modal.style.backgroundColor = "rgba(0, 0, 0, .5)";
2142      modal.style.zIndex = "100000";
2143      modal.style.position = "fixed";
2144      modal.style.top = "0px";
2145      modal.style.bottom = "0px";
2146      modal.style.left = "0px";
2147      modal.style.right = "0px";
2148      modal.style.display = "flex";
2149      modal.style.flexDirection = "column";
2150    }
2151    const iframe = document.createElement("iframe");
2152    iframe.style.borderRadius = "5px";
2153    iframe.style.flexGrow = "1";
2154    modal.appendChild(iframe);
2155    document.body.prepend(modal);
2156    document.body.style.overflow = "hidden";
2157    if (iframe.contentWindow) {
2158      iframe.contentWindow.document.open();
2159      iframe.contentWindow.document.write(html);
2160      iframe.contentWindow.document.close();
2161    }
2162    const closeModal = (modal2) => {
2163      if (modal2) {
2164        modal2.outerHTML = "";
2165      }
2166      document.body.style.overflow = "visible";
2167    };
2168    modal.addEventListener("click", () => closeModal(modal));
2169    modal.setAttribute("tabindex", "0");
2170    modal.addEventListener("keydown", (e) => {
2171      if (e.key === "Escape") {
2172        closeModal(modal);
2173      }
2174    });
2175    modal.focus();
2176  }
2177  resetPromise() {
2178    this.nextRequestPromise = new Promise((resolve) => {
2179      this.nextRequestPromiseResolve = resolve;
2180    });
2181  }
2182  /**
2183   * Called on a child component after the parent component render has requested
2184   * that the child component update its props & re-render if necessary.
2185   */
2186  _updateFromParentProps(props) {
2187    const isChanged = this.valueStore.storeNewPropsFromParent(props);
2188    if (isChanged) {
2189      this.render();
2190    }
2191  }
2192};
2193function proxifyComponent(component) {
2194  return new Proxy(component, {
2195    get(component2, prop) {
2196      if (prop in component2 || typeof prop !== "string") {
2197        if (typeof component2[prop] === "function") {
2198          const callable = component2[prop];
2199          return (...args) => {
2200            return callable.apply(component2, args);
2201          };
2202        }
2203        return Reflect.get(component2, prop);
2204      }
2205      if (component2.valueStore.has(prop)) {
2206        return component2.getData(prop);
2207      }
2208      return (args) => {
2209        return component2.action.apply(component2, [prop, args]);
2210      };
2211    },
2212    set(target, property, value) {
2213      if (property in target) {
2214        target[property] = value;
2215        return true;
2216      }
2217      target.set(property, value);
2218      return true;
2219    }
2220  });
2221}
2222
2223// src/Component/ElementDriver.ts
2224var StimulusElementDriver = class {
2225  constructor(controller) {
2226    this.controller = controller;
2227  }
2228  getModelName(element) {
2229    const modelDirective = getModelDirectiveFromElement(element, false);
2230    if (!modelDirective) {
2231      return null;
2232    }
2233    return modelDirective.action;
2234  }
2235  getComponentProps() {
2236    return this.controller.propsValue;
2237  }
2238  getEventsToEmit() {
2239    return this.controller.eventsToEmitValue;
2240  }
2241  getBrowserEventsToDispatch() {
2242    return this.controller.eventsToDispatchValue;
2243  }
2244};
2245
2246// src/Directive/get_model_binding.ts
2247function get_model_binding_default(modelDirective) {
2248  let shouldRender = true;
2249  let targetEventName = null;
2250  let debounce = false;
2251  let minLength = null;
2252  let maxLength = null;
2253  let minValue = null;
2254  let maxValue = null;
2255  modelDirective.modifiers.forEach((modifier) => {
2256    switch (modifier.name) {
2257      case "on":
2258        if (!modifier.value) {
2259          throw new Error(
2260            `The "on" modifier in ${modelDirective.getString()} requires a value - e.g. on(change).`
2261          );
2262        }
2263        if (!["input", "change"].includes(modifier.value)) {
2264          throw new Error(
2265            `The "on" modifier in ${modelDirective.getString()} only accepts the arguments "input" or "change".`
2266          );
2267        }
2268        targetEventName = modifier.value;
2269        break;
2270      case "norender":
2271        shouldRender = false;
2272        break;
2273      case "debounce":
2274        debounce = modifier.value ? Number.parseInt(modifier.value) : true;
2275        break;
2276      case "min_length":
2277        minLength = modifier.value ? Number.parseInt(modifier.value) : null;
2278        break;
2279      case "max_length":
2280        maxLength = modifier.value ? Number.parseInt(modifier.value) : null;
2281        break;
2282      case "min_value":
2283        minValue = modifier.value ? Number.parseFloat(modifier.value) : null;
2284        break;
2285      case "max_value":
2286        maxValue = modifier.value ? Number.parseFloat(modifier.value) : null;
2287        break;
2288      default:
2289        throw new Error(`Unknown modifier "${modifier.name}" in data-model="${modelDirective.getString()}".`);
2290    }
2291  });
2292  const [modelName, innerModelName] = modelDirective.action.split(":");
2293  return {
2294    modelName,
2295    innerModelName: innerModelName || null,
2296    shouldRender,
2297    debounce,
2298    targetEventName,
2299    minLength,
2300    maxLength,
2301    minValue,
2302    maxValue
2303  };
2304}
2305
2306// src/Component/plugins/ChildComponentPlugin.ts
2307var ChildComponentPlugin_default = class {
2308  constructor(component) {
2309    this.parentModelBindings = [];
2310    this.component = component;
2311    const modelDirectives = getAllModelDirectiveFromElements(this.component.element);
2312    this.parentModelBindings = modelDirectives.map(get_model_binding_default);
2313  }
2314  attachToComponent(component) {
2315    component.on("request:started", (requestData) => {
2316      requestData.children = this.getChildrenFingerprints();
2317    });
2318    component.on("model:set", (model, value) => {
2319      this.notifyParentModelChange(model, value);
2320    });
2321  }
2322  getChildrenFingerprints() {
2323    const fingerprints = {};
2324    this.getChildren().forEach((child) => {
2325      if (!child.id) {
2326        throw new Error("missing id");
2327      }
2328      fingerprints[child.id] = {
2329        fingerprint: child.fingerprint,
2330        tag: child.element.tagName.toLowerCase()
2331      };
2332    });
2333    return fingerprints;
2334  }
2335  /**
2336   * Notifies parent of a model change if desired.
2337   *
2338   * This makes the child "behave" like it's a normal `<input>` element,
2339   * where, when its value changes, the parent is notified.
2340   */
2341  notifyParentModelChange(modelName, value) {
2342    const parentComponent = findParent(this.component);
2343    if (!parentComponent) {
2344      return;
2345    }
2346    this.parentModelBindings.forEach((modelBinding) => {
2347      const childModelName = modelBinding.innerModelName || "value";
2348      if (childModelName !== modelName) {
2349        return;
2350      }
2351      parentComponent.set(modelBinding.modelName, value, modelBinding.shouldRender, modelBinding.debounce);
2352    });
2353  }
2354  getChildren() {
2355    return findChildren(this.component);
2356  }
2357};
2358
2359// src/Component/plugins/LazyPlugin.ts
2360var LazyPlugin_default = class {
2361  constructor() {
2362    this.intersectionObserver = null;
2363  }
2364  attachToComponent(component) {
2365    if ("lazy" !== component.element.attributes.getNamedItem("loading")?.value) {
2366      return;
2367    }
2368    component.on("connect", () => {
2369      this.getObserver().observe(component.element);
2370    });
2371    component.on("disconnect", () => {
2372      this.intersectionObserver?.unobserve(component.element);
2373    });
2374  }
2375  getObserver() {
2376    if (!this.intersectionObserver) {
2377      this.intersectionObserver = new IntersectionObserver((entries, observer) => {
2378        entries.forEach((entry) => {
2379          if (entry.isIntersecting) {
2380            entry.target.dispatchEvent(new CustomEvent("live:appear"));
2381            observer.unobserve(entry.target);
2382          }
2383        });
2384      });
2385    }
2386    return this.intersectionObserver;
2387  }
2388};
2389
2390// src/Component/plugins/LoadingPlugin.ts
2391var LoadingPlugin_default = class {
2392  attachToComponent(component) {
2393    component.on("loading.state:started", (element, request) => {
2394      this.startLoading(component, element, request);
2395    });
2396    component.on("loading.state:finished", (element) => {
2397      this.finishLoading(component, element);
2398    });
2399    this.finishLoading(component, component.element);
2400  }
2401  startLoading(component, targetElement, backendRequest) {
2402    this.handleLoadingToggle(component, true, targetElement, backendRequest);
2403  }
2404  finishLoading(component, targetElement) {
2405    this.handleLoadingToggle(component, false, targetElement, null);
2406  }
2407  handleLoadingToggle(component, isLoading, targetElement, backendRequest) {
2408    if (isLoading) {
2409      this.addAttributes(targetElement, ["busy"]);
2410    } else {
2411      this.removeAttributes(targetElement, ["busy"]);
2412    }
2413    this.getLoadingDirectives(component, targetElement).forEach(({ element, directives }) => {
2414      if (isLoading) {
2415        this.addAttributes(element, ["data-live-is-loading"]);
2416      } else {
2417        this.removeAttributes(element, ["data-live-is-loading"]);
2418      }
2419      directives.forEach((directive) => {
2420        this.handleLoadingDirective(element, isLoading, directive, backendRequest);
2421      });
2422    });
2423  }
2424  handleLoadingDirective(element, isLoading, directive, backendRequest) {
2425    const finalAction = parseLoadingAction(directive.action, isLoading);
2426    const targetedActions = [];
2427    const targetedModels = [];
2428    let delay = 0;
2429    const validModifiers = /* @__PURE__ */ new Map();
2430    validModifiers.set("delay", (modifier) => {
2431      if (!isLoading) {
2432        return;
2433      }
2434      delay = modifier.value ? Number.parseInt(modifier.value) : 200;
2435    });
2436    validModifiers.set("action", (modifier) => {
2437      if (!modifier.value) {
2438        throw new Error(
2439          `The "action" in data-loading must have an action name - e.g. action(foo). It's missing for "${directive.getString()}"`
2440        );
2441      }
2442      targetedActions.push(modifier.value);
2443    });
2444    validModifiers.set("model", (modifier) => {
2445      if (!modifier.value) {
2446        throw new Error(
2447          `The "model" in data-loading must have an action name - e.g. model(foo). It's missing for "${directive.getString()}"`
2448        );
2449      }
2450      targetedModels.push(modifier.value);
2451    });
2452    directive.modifiers.forEach((modifier) => {
2453      if (validModifiers.has(modifier.name)) {
2454        const callable = validModifiers.get(modifier.name) ?? (() => {
2455        });
2456        callable(modifier);
2457        return;
2458      }
2459      throw new Error(
2460        `Unknown modifier "${modifier.name}" used in data-loading="${directive.getString()}". Available modifiers are: ${Array.from(validModifiers.keys()).join(", ")}.`
2461      );
2462    });
2463    if (isLoading && targetedActions.length > 0 && backendRequest && !backendRequest.containsOneOfActions(targetedActions)) {
2464      return;
2465    }
2466    if (isLoading && targetedModels.length > 0 && backendRequest && !backendRequest.areAnyModelsUpdated(targetedModels)) {
2467      return;
2468    }
2469    let loadingDirective;
2470    switch (finalAction) {
2471      case "show":
2472        loadingDirective = () => this.showElement(element);
2473        break;
2474      case "hide":
2475        loadingDirective = () => this.hideElement(element);
2476        break;
2477      case "addClass":
2478        loadingDirective = () => this.addClass(element, directive.args);
2479        break;
2480      case "removeClass":
2481        loadingDirective = () => this.removeClass(element, directive.args);
2482        break;
2483      case "addAttribute":
2484        loadingDirective = () => this.addAttributes(element, directive.args);
2485        break;
2486      case "removeAttribute":
2487        loadingDirective = () => this.removeAttributes(element, directive.args);
2488        break;
2489      default:
2490        throw new Error(`Unknown data-loading action "${finalAction}"`);
2491    }
2492    if (delay) {
2493      window.setTimeout(() => {
2494        if (backendRequest && !backendRequest.isResolved) {
2495          loadingDirective();
2496        }
2497      }, delay);
2498      return;
2499    }
2500    loadingDirective();
2501  }
2502  getLoadingDirectives(component, element) {
2503    const loadingDirectives = [];
2504    let matchingElements = [...Array.from(element.querySelectorAll("[data-loading]"))];
2505    matchingElements = matchingElements.filter((elt) => elementBelongsToThisComponent(elt, component));
2506    if (element.hasAttribute("data-loading")) {
2507      matchingElements = [element, ...matchingElements];
2508    }
2509    matchingElements.forEach((element2) => {
2510      if (!(element2 instanceof HTMLElement) && !(element2 instanceof SVGElement)) {
2511        throw new Error("Invalid Element Type");
2512      }
2513      const directives = parseDirectives(element2.dataset.loading || "show");
2514      loadingDirectives.push({
2515        element: element2,
2516        directives
2517      });
2518    });
2519    return loadingDirectives;
2520  }
2521  showElement(element) {
2522    element.style.display = "revert";
2523  }
2524  hideElement(element) {
2525    element.style.display = "none";
2526  }
2527  addClass(element, classes) {
2528    element.classList.add(...combineSpacedArray(classes));
2529  }
2530  removeClass(element, classes) {
2531    element.classList.remove(...combineSpacedArray(classes));
2532    if (element.classList.length === 0) {
2533      element.removeAttribute("class");
2534    }
2535  }
2536  addAttributes(element, attributes) {
2537    attributes.forEach((attribute) => {
2538      element.setAttribute(attribute, "");
2539    });
2540  }
2541  removeAttributes(element, attributes) {
2542    attributes.forEach((attribute) => {
2543      element.removeAttribute(attribute);
2544    });
2545  }
2546};
2547var parseLoadingAction = (action, isLoading) => {
2548  switch (action) {
2549    case "show":
2550      return isLoading ? "show" : "hide";
2551    case "hide":
2552      return isLoading ? "hide" : "show";
2553    case "addClass":
2554      return isLoading ? "addClass" : "removeClass";
2555    case "removeClass":
2556      return isLoading ? "removeClass" : "addClass";
2557    case "addAttribute":
2558      return isLoading ? "addAttribute" : "removeAttribute";
2559    case "removeAttribute":
2560      return isLoading ? "removeAttribute" : "addAttribute";
2561  }
2562  throw new Error(`Unknown data-loading action "${action}"`);
2563};
2564
2565// src/Component/plugins/PageUnloadingPlugin.ts
2566var PageUnloadingPlugin_default = class {
2567  constructor() {
2568    this.isConnected = false;
2569  }
2570  attachToComponent(component) {
2571    component.on("render:started", (html, response, controls) => {
2572      if (!this.isConnected) {
2573        controls.shouldRender = false;
2574      }
2575    });
2576    component.on("connect", () => {
2577      this.isConnected = true;
2578    });
2579    component.on("disconnect", () => {
2580      this.isConnected = false;
2581    });
2582  }
2583};
2584
2585// src/PollingDirector.ts
2586var PollingDirector_default = class {
2587  constructor(component) {
2588    this.isPollingActive = true;
2589    this.pollingIntervals = [];
2590    this.component = component;
2591  }
2592  addPoll(actionName, duration) {
2593    this.polls.push({ actionName, duration });
2594    if (this.isPollingActive) {
2595      this.initiatePoll(actionName, duration);
2596    }
2597  }
2598  startAllPolling() {
2599    if (this.isPollingActive) {
2600      return;
2601    }
2602    this.isPollingActive = true;
2603    this.polls.forEach(({ actionName, duration }) => {
2604      this.initiatePoll(actionName, duration);
2605    });
2606  }
2607  stopAllPolling() {
2608    this.isPollingActive = false;
2609    this.pollingIntervals.forEach((interval) => {
2610      clearInterval(interval);
2611    });
2612  }
2613  clearPolling() {
2614    this.stopAllPolling();
2615    this.polls = [];
2616    this.startAllPolling();
2617  }
2618  initiatePoll(actionName, duration) {
2619    let callback;
2620    if (actionName === "$render") {
2621      callback = () => {
2622        this.component.render();
2623      };
2624    } else {
2625      callback = () => {
2626        this.component.action(actionName, {}, 0);
2627      };
2628    }
2629    const timer = window.setInterval(() => {
2630      callback();
2631    }, duration);
2632    this.pollingIntervals.push(timer);
2633  }
2634};
2635
2636// src/Component/plugins/PollingPlugin.ts
2637var PollingPlugin_default = class {
2638  attachToComponent(component) {
2639    this.element = component.element;
2640    this.pollingDirector = new PollingDirector_default(component);
2641    this.initializePolling();
2642    component.on("connect", () => {
2643      this.pollingDirector.startAllPolling();
2644    });
2645    component.on("disconnect", () => {
2646      this.pollingDirector.stopAllPolling();
2647    });
2648    component.on("render:finished", () => {
2649      this.initializePolling();
2650    });
2651  }
2652  addPoll(actionName, duration) {
2653    this.pollingDirector.addPoll(actionName, duration);
2654  }
2655  clearPolling() {
2656    this.pollingDirector.clearPolling();
2657  }
2658  initializePolling() {
2659    this.clearPolling();
2660    if (this.element.dataset.poll === void 0) {
2661      return;
2662    }
2663    const rawPollConfig = this.element.dataset.poll;
2664    const directives = parseDirectives(rawPollConfig || "$render");
2665    directives.forEach((directive) => {
2666      let duration = 2e3;
2667      directive.modifiers.forEach((modifier) => {
2668        switch (modifier.name) {
2669          case "delay":
2670            if (modifier.value) {
2671              duration = Number.parseInt(modifier.value);
2672            }
2673            break;
2674          default:
2675            console.warn(`Unknown modifier "${modifier.name}" in data-poll "${rawPollConfig}".`);
2676        }
2677      });
2678      this.addPoll(directive.action, duration);
2679    });
2680  }
2681};
2682
2683// src/Component/plugins/SetValueOntoModelFieldsPlugin.ts
2684var SetValueOntoModelFieldsPlugin_default = class {
2685  attachToComponent(component) {
2686    this.synchronizeValueOfModelFields(component);
2687    component.on("render:finished", () => {
2688      this.synchronizeValueOfModelFields(component);
2689    });
2690  }
2691  /**
2692   * Sets the "value" of all model fields to the component data.
2693   *
2694   * This is called when the component initializes and after re-render.
2695   * Take the following element:
2696   *
2697   *      <input data-model="firstName">
2698   *
2699   * This method will set the "value" of that element to the value of
2700   * the "firstName" model.
2701   */
2702  synchronizeValueOfModelFields(component) {
2703    component.element.querySelectorAll("[data-model]").forEach((element) => {
2704      if (!(element instanceof HTMLElement)) {
2705        throw new Error("Invalid element using data-model.");
2706      }
2707      if (element instanceof HTMLFormElement) {
2708        return;
2709      }
2710      if (!elementBelongsToThisComponent(element, component)) {
2711        return;
2712      }
2713      const modelDirective = getModelDirectiveFromElement(element);
2714      if (!modelDirective) {
2715        return;
2716      }
2717      const modelName = modelDirective.action;
2718      if (component.getUnsyncedModels().includes(modelName)) {
2719        return;
2720      }
2721      if (component.valueStore.has(modelName)) {
2722        setValueOnElement(element, component.valueStore.get(modelName));
2723      }
2724      if (element instanceof HTMLSelectElement && !element.multiple) {
2725        component.valueStore.set(modelName, getValueFromElement(element, component.valueStore));
2726      }
2727    });
2728  }
2729};
2730
2731// src/Component/plugins/ValidatedFieldsPlugin.ts
2732var ValidatedFieldsPlugin_default = class {
2733  attachToComponent(component) {
2734    component.on("model:set", (modelName) => {
2735      this.handleModelSet(modelName, component.valueStore);
2736    });
2737  }
2738  handleModelSet(modelName, valueStore) {
2739    if (valueStore.has("validatedFields")) {
2740      const validatedFields = [...valueStore.get("validatedFields")];
2741      if (!validatedFields.includes(modelName)) {
2742        validatedFields.push(modelName);
2743      }
2744      valueStore.set("validatedFields", validatedFields);
2745    }
2746  }
2747};
2748
2749// src/live_controller.ts
2750var _LiveControllerDefault = class _LiveControllerDefault extends Controller {
2751  constructor() {
2752    super(...arguments);
2753    this.pendingActionTriggerModelElement = null;
2754    this.elementEventListeners = [
2755      { event: "input", callback: (event) => this.handleInputEvent(event) },
2756      { event: "change", callback: (event) => this.handleChangeEvent(event) }
2757    ];
2758    this.pendingFiles = {};
2759  }
2760  initialize() {
2761    this.mutationObserver = new MutationObserver(this.onMutations.bind(this));
2762    this.createComponent();
2763  }
2764  connect() {
2765    this.connectComponent();
2766    this.mutationObserver.observe(this.element, {
2767      attributes: true
2768    });
2769  }
2770  disconnect() {
2771    this.disconnectComponent();
2772    this.mutationObserver.disconnect();
2773  }
2774  /**
2775   * Called to update one piece of the model.
2776   *
2777   *      <button data-action="live#update" data-model="foo" data-value="5">
2778   */
2779  update(event) {
2780    if (event.type === "input" || event.type === "change") {
2781      throw new Error(
2782        `Since LiveComponents 2.3, you no longer need data-action="live#update" on form elements. Found on element: ${getElementAsTagText(
2783          event.currentTarget
2784        )}`
2785      );
2786    }
2787    this.updateModelFromElementEvent(event.currentTarget, null);
2788  }
2789  action(event) {
2790    const params = event.params;
2791    if (!params.action) {
2792      throw new Error(
2793        `No action name provided on element: ${getElementAsTagText(
2794          event.currentTarget
2795        )}. Did you forget to add the "data-live-action-param" attribute?`
2796      );
2797    }
2798    const rawAction = params.action;
2799    const actionArgs = { ...params };
2800    delete actionArgs.action;
2801    const directives = parseDirectives(rawAction);
2802    let debounce = false;
2803    directives.forEach((directive) => {
2804      let pendingFiles = {};
2805      const validModifiers = /* @__PURE__ */ new Map();
2806      validModifiers.set("stop", () => {
2807        event.stopPropagation();
2808      });
2809      validModifiers.set("self", () => {
2810        if (event.target !== event.currentTarget) {
2811          return;
2812        }
2813      });
2814      validModifiers.set("debounce", (modifier) => {
2815        debounce = modifier.value ? Number.parseInt(modifier.value) : true;
2816      });
2817      validModifiers.set("files", (modifier) => {
2818        if (!modifier.value) {
2819          pendingFiles = this.pendingFiles;
2820        } else if (this.pendingFiles[modifier.value]) {
2821          pendingFiles[modifier.value] = this.pendingFiles[modifier.value];
2822        }
2823      });
2824      directive.modifiers.forEach((modifier) => {
2825        if (validModifiers.has(modifier.name)) {
2826          const callable = validModifiers.get(modifier.name) ?? (() => {
2827          });
2828          callable(modifier);
2829          return;
2830        }
2831        console.warn(
2832          `Unknown modifier ${modifier.name} in action "${rawAction}". Available modifiers are: ${Array.from(
2833            validModifiers.keys()
2834          ).join(", ")}.`
2835        );
2836      });
2837      for (const [key, input] of Object.entries(pendingFiles)) {
2838        if (input.files) {
2839          this.component.files(key, input);
2840        }
2841        delete this.pendingFiles[key];
2842      }
2843      this.component.action(directive.action, actionArgs, debounce);
2844      if (getModelDirectiveFromElement(event.currentTarget, false)) {
2845        this.pendingActionTriggerModelElement = event.currentTarget;
2846      }
2847    });
2848  }
2849  $render() {
2850    return this.component.render();
2851  }
2852  emit(event) {
2853    this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
2854      this.component.emit(name, data, nameMatch);
2855    });
2856  }
2857  emitUp(event) {
2858    this.getEmitDirectives(event).forEach(({ name, data, nameMatch }) => {
2859      this.component.emitUp(name, data, nameMatch);
2860    });
2861  }
2862  emitSelf(event) {
2863    this.getEmitDirectives(event).forEach(({ name, data }) => {
2864      this.component.emitSelf(name, data);
2865    });
2866  }
2867  /**
2868   * Update a model value.
2869   *
2870   * @param {string} model The model to update
2871   * @param {any} value The new value
2872   * @param {boolean} shouldRender Whether a re-render should be triggered
2873   * @param {number|boolean} debounce
2874   */
2875  $updateModel(model, value, shouldRender = true, debounce = true) {
2876    return this.component.set(model, value, shouldRender, debounce);
2877  }
2878  propsUpdatedFromParentValueChanged() {
2879    this.component._updateFromParentProps(this.propsUpdatedFromParentValue);
2880  }
2881  fingerprintValueChanged() {
2882    this.component.fingerprint = this.fingerprintValue;
2883  }
2884  getEmitDirectives(event) {
2885    const params = event.params;
2886    if (!params.event) {
2887      throw new Error(
2888        `No event name provided on element: ${getElementAsTagText(
2889          event.currentTarget
2890        )}. Did you forget to add the "data-live-event-param" attribute?`
2891      );
2892    }
2893    const eventInfo = params.event;
2894    const eventArgs = { ...params };
2895    delete eventArgs.event;
2896    const directives = parseDirectives(eventInfo);
2897    const emits = [];
2898    directives.forEach((directive) => {
2899      let nameMatch = null;
2900      directive.modifiers.forEach((modifier) => {
2901        switch (modifier.name) {
2902          case "name":
2903            nameMatch = modifier.value;
2904            break;
2905          default:
2906            throw new Error(`Unknown modifier ${modifier.name} in event "${eventInfo}".`);
2907        }
2908      });
2909      emits.push({
2910        name: directive.action,
2911        data: eventArgs,
2912        nameMatch
2913      });
2914    });
2915    return emits;
2916  }
2917  createComponent() {
2918    const id = this.element.id || null;
2919    this.component = new Component(
2920      this.element,
2921      this.nameValue,
2922      this.propsValue,
2923      this.listenersValue,
2924      id,
2925      _LiveControllerDefault.backendFactory(this),
2926      new StimulusElementDriver(this)
2927    );
2928    this.proxiedComponent = proxifyComponent(this.component);
2929    Object.defineProperty(this.element, "__component", {
2930      value: this.proxiedComponent,
2931      writable: true
2932    });
2933    if (this.hasDebounceValue) {
2934      this.component.defaultDebounce = this.debounceValue;
2935    }
2936    const plugins = [
2937      new LoadingPlugin_default(),
2938      new LazyPlugin_default(),
2939      new ValidatedFieldsPlugin_default(),
2940      new PageUnloadingPlugin_default(),
2941      new PollingPlugin_default(),
2942      new SetValueOntoModelFieldsPlugin_default(),
2943      new ChildComponentPlugin_default(this.component)
2944    ];
2945    plugins.forEach((plugin) => {
2946      this.component.addPlugin(plugin);
2947    });
2948  }
2949  connectComponent() {
2950    this.component.connect();
2951    this.mutationObserver.observe(this.element, {
2952      attributes: true
2953    });
2954    this.elementEventListeners.forEach(({ event, callback }) => {
2955      this.component.element.addEventListener(event, callback);
2956    });
2957    this.dispatchEvent("connect");
2958  }
2959  disconnectComponent() {
2960    this.component.disconnect();
2961    this.elementEventListeners.forEach(({ event, callback }) => {
2962      this.component.element.removeEventListener(event, callback);
2963    });
2964    this.dispatchEvent("disconnect");
2965  }
2966  handleInputEvent(event) {
2967    const target = event.target;
2968    if (!target) {
2969      return;
2970    }
2971    this.updateModelFromElementEvent(target, "input");
2972  }
2973  handleChangeEvent(event) {
2974    const target = event.target;
2975    if (!target) {
2976      return;
2977    }
2978    this.updateModelFromElementEvent(target, "change");
2979  }
2980  /**
2981   * Sets a model given an element and some event.
2982   *
2983   * This parses the "data-model" from the element and takes
2984   * into account modifiers like "debounce", "norender" and "on()".
2985   *
2986   * This is used, for example, the grab the new value from an input
2987   * on "change" and set that new value onto the model.
2988   *
2989   * It's also used to, on click, set the value from a button
2990   * with data-model="" and data-value"".
2991   *
2992   * @param element
2993   * @param eventName If specified (e.g. "input" or "change"), the model may
2994   *                  skip updating if the on() modifier is passed (e.g. on(change)).
2995   *                  If not passed, the model will always be updated.
2996   */
2997  updateModelFromElementEvent(element, eventName) {
2998    if (!elementBelongsToThisComponent(element, this.component)) {
2999      return;
3000    }
3001    if (!(element instanceof HTMLElement)) {
3002      throw new Error("Could not update model for non HTMLElement");
3003    }
3004    if (element instanceof HTMLInputElement && element.type === "file") {
3005      const key = element.name;
3006      if (element.files?.length) {
3007        this.pendingFiles[key] = element;
3008      } else if (this.pendingFiles[key]) {
3009        delete this.pendingFiles[key];
3010      }
3011    }
3012    const modelDirective = getModelDirectiveFromElement(element, false);
3013    if (!modelDirective) {
3014      return;
3015    }
3016    const modelBinding = get_model_binding_default(modelDirective);
3017    if (!modelBinding.targetEventName) {
3018      modelBinding.targetEventName = "input";
3019    }
3020    if (this.pendingActionTriggerModelElement === element) {
3021      modelBinding.shouldRender = false;
3022    }
3023    if (eventName === "change" && modelBinding.targetEventName === "input") {
3024      modelBinding.targetEventName = "change";
3025    }
3026    if (eventName && modelBinding.targetEventName !== eventName) {
3027      return;
3028    }
3029    if (false === modelBinding.debounce) {
3030      if (modelBinding.targetEventName === "input") {
3031        modelBinding.debounce = true;
3032      } else {
3033        modelBinding.debounce = 0;
3034      }
3035    }
3036    const finalValue = getValueFromElement(element, this.component.valueStore);
3037    if (isTextualInputElement(element) || isTextareaElement(element)) {
3038      if (modelBinding.minLength !== null && typeof finalValue === "string" && finalValue.length < modelBinding.minLength) {
3039        return;
3040      }
3041      if (modelBinding.maxLength !== null && typeof finalValue === "string" && finalValue.length > modelBinding.maxLength) {
3042        return;
3043      }
3044    }
3045    if (isNumericalInputElement(element)) {
3046      const numericValue = Number(finalValue);
3047      if (modelBinding.minValue !== null && numericValue < modelBinding.minValue) {
3048        return;
3049      }
3050      if (modelBinding.maxValue !== null && numericValue > modelBinding.maxValue) {
3051        return;
3052      }
3053    }
3054    this.component.set(modelBinding.modelName, finalValue, modelBinding.shouldRender, modelBinding.debounce);
3055  }
3056  dispatchEvent(name, detail = {}, canBubble = true, cancelable = false) {
3057    detail.controller = this;
3058    detail.component = this.proxiedComponent;
3059    this.dispatch(name, { detail, prefix: "live", cancelable, bubbles: canBubble });
3060  }
3061  onMutations(mutations) {
3062    mutations.forEach((mutation) => {
3063      if (mutation.type === "attributes" && mutation.attributeName === "id" && this.element.id !== this.component.id) {
3064        this.disconnectComponent();
3065        this.createComponent();
3066        this.connectComponent();
3067      }
3068    });
3069  }
3070};
3071_LiveControllerDefault.values = {
3072  name: String,
3073  url: String,
3074  props: { type: Object, default: {} },
3075  propsUpdatedFromParent: { type: Object, default: {} },
3076  listeners: { type: Array, default: [] },
3077  eventsToEmit: { type: Array, default: [] },
3078  eventsToDispatch: { type: Array, default: [] },
3079  debounce: { type: Number, default: 150 },
3080  fingerprint: { type: String, default: "" },
3081  requestMethod: { type: String, default: "post" }
3082};
3083_LiveControllerDefault.backendFactory = (controller) => new Backend_default(controller.urlValue, controller.requestMethodValue);
3084var LiveControllerDefault = _LiveControllerDefault;
3085export {
3086  Component,
3087  LiveControllerDefault as default,
3088  getComponent
3089};

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.