import { Controller } from "@hotwired/stimulus"; var BackendRequest_default = class { constructor(promise, actions, updateModels) { this.isResolved = false; this.promise = promise; this.promise.then((response) => { this.isResolved = true; return response; }); this.actions = actions; this.updatedModels = updateModels; } containsOneOfActions(targetedActions) { return this.actions.filter((action) => targetedActions.includes(action)).length > 0; } areAnyModelsUpdated(targetedModels) { return this.updatedModels.filter((model) => targetedModels.includes(model)).length > 0; } }; var RequestBuilder_default = class { constructor(url, method = "post", credentials = "same-origin") { this.url = url; this.method = method; this.credentials = credentials; } buildRequest(props, actions, updated, children, updatedPropsFromParent, files) { const splitUrl = this.url.split("?"); let [url] = splitUrl; const [, queryString] = splitUrl; const params = new URLSearchParams(queryString || ""); const fetchOptions = {}; fetchOptions.credentials = this.credentials; fetchOptions.headers = { Accept: "application/vnd.live-component+html", "X-Requested-With": "XMLHttpRequest", "X-Live-Url": window.location.pathname + window.location.search }; const totalFiles = Object.entries(files).reduce((total, current) => total + current.length, 0); const hasFingerprints = Object.keys(children).length > 0; if (actions.length === 0 && totalFiles === 0 && this.method === "get" && this.willDataFitInUrl(JSON.stringify(props), JSON.stringify(updated), params, JSON.stringify(children), JSON.stringify(updatedPropsFromParent))) { params.set("props", JSON.stringify(props)); params.set("updated", JSON.stringify(updated)); if (Object.keys(updatedPropsFromParent).length > 0) params.set("propsFromParent", JSON.stringify(updatedPropsFromParent)); if (hasFingerprints) params.set("children", JSON.stringify(children)); fetchOptions.method = "GET"; } else { fetchOptions.method = "POST"; const requestData = { props, updated }; if (Object.keys(updatedPropsFromParent).length > 0) requestData.propsFromParent = updatedPropsFromParent; if (hasFingerprints) requestData.children = children; if (actions.length > 0) if (actions.length === 1) { requestData.args = actions[0].args; url += `/${encodeURIComponent(actions[0].name)}`; } else { url += "/_batch"; requestData.actions = actions; } const formData = new FormData(); formData.append("data", JSON.stringify(requestData)); for (const [key, value] of Object.entries(files)) { const length = value.length; for (let i = 0; i < length; ++i) formData.append(key, value[i]); } fetchOptions.body = formData; } const paramsString = params.toString(); return { url: `${url}${paramsString.length > 0 ? `?${paramsString}` : ""}`, fetchOptions }; } willDataFitInUrl(propsJson, updatedJson, params, childrenJson, propsFromParentJson) { return (new URLSearchParams(propsJson + updatedJson + childrenJson + propsFromParentJson).toString() + params.toString()).length < 1500; } }; var Backend_default = class { constructor(url, method = "post", credentials = "same-origin") { this.requestBuilder = new RequestBuilder_default(url, method, credentials); } makeRequest(props, actions, updated, children, updatedPropsFromParent, files) { const { url, fetchOptions } = this.requestBuilder.buildRequest(props, actions, updated, children, updatedPropsFromParent, files); return new BackendRequest_default(fetch(url, fetchOptions), actions.map((backendAction) => backendAction.name), Object.keys(updated)); } }; var BackendResponse_default = class { constructor(response) { this.response = response; } async getBody() { if (!this.body) this.body = await this.response.text(); return this.body; } getLiveUrl() { if (void 0 === this.liveUrl) this.liveUrl = this.response.headers.get("X-Live-Url"); return this.liveUrl; } }; function getElementAsTagText(element) { return element.innerHTML ? element.outerHTML.slice(0, element.outerHTML.indexOf(element.innerHTML)) : element.outerHTML; } let componentMapByElement = /* @__PURE__ */ new WeakMap(); let componentMapByComponent = /* @__PURE__ */ new Map(); const registerComponent = (component) => { componentMapByElement.set(component.element, component); componentMapByComponent.set(component, component.name); }; const unregisterComponent = (component) => { componentMapByElement.delete(component.element); componentMapByComponent.delete(component); }; const getComponent = (element) => new Promise((resolve, reject) => { let count = 0; const maxCount = 10; const interval = setInterval(() => { const component = componentMapByElement.get(element); if (component) { clearInterval(interval); resolve(component); } count++; if (count > maxCount) { clearInterval(interval); reject(/* @__PURE__ */ new Error(`Component not found for element ${getElementAsTagText(element)}`)); } }, 5); }); const findComponents = (currentComponent, onlyParents, onlyMatchName) => { const components = []; componentMapByComponent.forEach((componentName, component) => { if (onlyParents && (currentComponent === component || !component.element.contains(currentComponent.element))) return; if (onlyMatchName && componentName !== onlyMatchName) return; components.push(component); }); return components; }; const findChildren = (currentComponent) => { const children = []; componentMapByComponent.forEach((componentName, component) => { if (currentComponent === component) return; if (!currentComponent.element.contains(component.element)) return; let foundChildComponent = false; componentMapByComponent.forEach((childComponentName, childComponent) => { if (foundChildComponent) return; if (childComponent === component) return; if (childComponent.element.contains(component.element)) foundChildComponent = true; }); children.push(component); }); return children; }; const findParent = (currentComponent) => { let parentElement = currentComponent.element.parentElement; while (parentElement) { const component = componentMapByElement.get(parentElement); if (component) return component; parentElement = parentElement.parentElement; } return null; }; function parseDirectives(content) { const directives = []; if (!content) return directives; let currentActionName = ""; let currentArgumentValue = ""; let currentArguments = []; let currentModifiers = []; let state = "action"; const getLastActionName = () => { if (currentActionName) return currentActionName; if (directives.length === 0) throw new Error("Could not find any directives"); return directives[directives.length - 1].action; }; const pushInstruction = () => { directives.push({ action: currentActionName, args: currentArguments, modifiers: currentModifiers, getString: () => { return content; } }); currentActionName = ""; currentArgumentValue = ""; currentArguments = []; currentModifiers = []; state = "action"; }; const pushArgument = () => { currentArguments.push(currentArgumentValue.trim()); currentArgumentValue = ""; }; const pushModifier = () => { if (currentArguments.length > 1) throw new Error(`The modifier "${currentActionName}()" does not support multiple arguments.`); currentModifiers.push({ name: currentActionName, value: currentArguments.length > 0 ? currentArguments[0] : null }); currentActionName = ""; currentArguments = []; state = "action"; }; for (let i = 0; i < content.length; i++) { const char = content[i]; switch (state) { case "action": if (char === "(") { state = "arguments"; break; } if (char === " ") { if (currentActionName) pushInstruction(); break; } if (char === "|") { pushModifier(); break; } currentActionName += char; break; case "arguments": if (char === ")") { pushArgument(); state = "after_arguments"; break; } if (char === ",") { pushArgument(); break; } currentArgumentValue += char; break; case "after_arguments": if (char === "|") { pushModifier(); break; } if (char !== " ") throw new Error(`Missing space after ${getLastActionName()}()`); pushInstruction(); break; } } switch (state) { case "action": case "after_arguments": if (currentActionName) pushInstruction(); break; default: throw new Error(`Did you forget to add a closing ")" after "${currentActionName}"?`); } return directives; } function combineSpacedArray(parts) { const finalParts = []; parts.forEach((part) => { finalParts.push(...trimAll(part).split(" ")); }); return finalParts; } function trimAll(str) { return str.replace(/[\s]+/g, " ").trim(); } function normalizeModelName(model) { return model.replace(/\[]$/, "").split("[").map((s) => s.replace("]", "")).join("."); } function getValueFromElement(element, valueStore) { if (element instanceof HTMLInputElement) { if (element.type === "checkbox") { const modelNameData = getModelDirectiveFromElement(element, false); if (modelNameData !== null) { const modelValue = valueStore.get(modelNameData.action); if (Array.isArray(modelValue)) return getMultipleCheckboxValue(element, modelValue); if (Object(modelValue) === modelValue) return getMultipleCheckboxValue(element, Object.values(modelValue)); } if (element.hasAttribute("value")) return element.checked ? element.getAttribute("value") : null; return element.checked; } return inputValue(element); } if (element instanceof HTMLSelectElement) { if (element.multiple) return Array.from(element.selectedOptions).map((el) => el.value); return element.value; } if (element.hasAttribute("data-value")) return element.dataset.value; if ("value" in element) return element.value; if (element.hasAttribute("value")) return element.getAttribute("value"); return null; } function setValueOnElement(element, value) { if (element instanceof HTMLInputElement) { if (element.type === "file") return; if (element.type === "radio") { element.checked = element.value == value; return; } if (element.type === "checkbox") { if (Array.isArray(value)) element.checked = value.some((val) => val == element.value); else if (element.hasAttribute("value")) element.checked = element.value == value; else element.checked = value; return; } } if (element instanceof HTMLSelectElement) { const arrayWrappedValue = [].concat(value).map((value) => { return `${value}`; }); Array.from(element.options).forEach((option) => { option.selected = arrayWrappedValue.includes(option.value); }); return; } value = value === void 0 ? "" : value; element.value = value; } function getAllModelDirectiveFromElements(element) { if (!element.dataset.model) return []; const directives = parseDirectives(element.dataset.model); directives.forEach((directive) => { if (directive.args.length > 0) throw new Error(`The data-model="${element.dataset.model}" format is invalid: it does not support passing arguments to the model.`); directive.action = normalizeModelName(directive.action); }); return directives; } function getModelDirectiveFromElement(element, throwOnMissing = true) { const dataModelDirectives = getAllModelDirectiveFromElements(element); if (dataModelDirectives.length > 0) return dataModelDirectives[0]; if (element.getAttribute("name")) { const formElement = element.closest("form"); if (formElement && "model" in formElement.dataset) { const directive = parseDirectives(formElement.dataset.model || "*")[0]; if (directive.args.length > 0) throw new Error(`The data-model="${formElement.dataset.model}" format is invalid: it does not support passing arguments to the model.`); directive.action = normalizeModelName(element.getAttribute("name")); return directive; } } if (!throwOnMissing) return null; throw new Error(`Cannot determine the model name for "${getElementAsTagText(element)}": the element must either have a "data-model" (or "name" attribute living inside a