import { __spreadProps, __spreadValues } from "./chunk.KIILAQWQ.js"; // src/internal/form.ts var formCollections = /* @__PURE__ */ new WeakMap(); var reportValidityOverloads = /* @__PURE__ */ new WeakMap(); var checkValidityOverloads = /* @__PURE__ */ new WeakMap(); var userInteractedControls = /* @__PURE__ */ new WeakSet(); var interactions = /* @__PURE__ */ new WeakMap(); var FormControlController = class { constructor(host, options) { this.handleFormData = (event) => { const disabled = this.options.disabled(this.host); const name = this.options.name(this.host); const value = this.options.value(this.host); const isButton = this.host.tagName.toLowerCase() === "sl-button"; if (this.host.isConnected && !disabled && !isButton && typeof name === "string" && name.length > 0 && typeof value !== "undefined") { if (Array.isArray(value)) { value.forEach((val) => { event.formData.append(name, val.toString()); }); } else { event.formData.append(name, value.toString()); } } }; this.handleFormSubmit = (event) => { var _a; const disabled = this.options.disabled(this.host); const reportValidity = this.options.reportValidity; if (this.form && !this.form.noValidate) { (_a = formCollections.get(this.form)) == null ? void 0 : _a.forEach((control) => { this.setUserInteracted(control, true); }); } if (this.form && !this.form.noValidate && !disabled && !reportValidity(this.host)) { event.preventDefault(); event.stopImmediatePropagation(); } }; this.handleFormReset = () => { this.options.setValue(this.host, this.options.defaultValue(this.host)); this.setUserInteracted(this.host, false); interactions.set(this.host, []); }; this.handleInteraction = (event) => { const emittedEvents = interactions.get(this.host); if (!emittedEvents.includes(event.type)) { emittedEvents.push(event.type); } if (emittedEvents.length === this.options.assumeInteractionOn.length) { this.setUserInteracted(this.host, true); } }; this.checkFormValidity = () => { if (this.form && !this.form.noValidate) { const elements = this.form.querySelectorAll("*"); for (const element of elements) { if (typeof element.checkValidity === "function") { if (!element.checkValidity()) { return false; } } } } return true; }; this.reportFormValidity = () => { if (this.form && !this.form.noValidate) { const elements = this.form.querySelectorAll("*"); for (const element of elements) { if (typeof element.reportValidity === "function") { if (!element.reportValidity()) { return false; } } } } return true; }; (this.host = host).addController(this); this.options = __spreadValues({ form: (input) => { const formId = input.form; if (formId) { const root = input.getRootNode(); const form = root.getElementById(formId); if (form) { return form; } } return input.closest("form"); }, name: (input) => input.name, value: (input) => input.value, defaultValue: (input) => input.defaultValue, disabled: (input) => { var _a; return (_a = input.disabled) != null ? _a : false; }, reportValidity: (input) => typeof input.reportValidity === "function" ? input.reportValidity() : true, checkValidity: (input) => typeof input.checkValidity === "function" ? input.checkValidity() : true, setValue: (input, value) => input.value = value, assumeInteractionOn: ["sl-input"] }, options); } hostConnected() { const form = this.options.form(this.host); if (form) { this.attachForm(form); } interactions.set(this.host, []); this.options.assumeInteractionOn.forEach((event) => { this.host.addEventListener(event, this.handleInteraction); }); } hostDisconnected() { this.detachForm(); interactions.delete(this.host); this.options.assumeInteractionOn.forEach((event) => { this.host.removeEventListener(event, this.handleInteraction); }); } hostUpdated() { const form = this.options.form(this.host); if (!form) { this.detachForm(); } if (form && this.form !== form) { this.detachForm(); this.attachForm(form); } if (this.host.hasUpdated) { this.setValidity(this.host.validity.valid); } } attachForm(form) { if (form) { this.form = form; if (formCollections.has(this.form)) { formCollections.get(this.form).add(this.host); } else { formCollections.set(this.form, /* @__PURE__ */ new Set([this.host])); } this.form.addEventListener("formdata", this.handleFormData); this.form.addEventListener("submit", this.handleFormSubmit); this.form.addEventListener("reset", this.handleFormReset); if (!reportValidityOverloads.has(this.form)) { reportValidityOverloads.set(this.form, this.form.reportValidity); this.form.reportValidity = () => this.reportFormValidity(); } if (!checkValidityOverloads.has(this.form)) { checkValidityOverloads.set(this.form, this.form.checkValidity); this.form.checkValidity = () => this.checkFormValidity(); } } else { this.form = void 0; } } detachForm() { if (!this.form) return; const formCollection = formCollections.get(this.form); if (!formCollection) { return; } formCollection.delete(this.host); if (formCollection.size <= 0) { this.form.removeEventListener("formdata", this.handleFormData); this.form.removeEventListener("submit", this.handleFormSubmit); this.form.removeEventListener("reset", this.handleFormReset); if (reportValidityOverloads.has(this.form)) { this.form.reportValidity = reportValidityOverloads.get(this.form); reportValidityOverloads.delete(this.form); } if (checkValidityOverloads.has(this.form)) { this.form.checkValidity = checkValidityOverloads.get(this.form); checkValidityOverloads.delete(this.form); } this.form = void 0; } } setUserInteracted(el, hasInteracted) { if (hasInteracted) { userInteractedControls.add(el); } else { userInteractedControls.delete(el); } el.requestUpdate(); } doAction(type, submitter) { if (this.form) { const button = document.createElement("button"); button.type = type; button.style.position = "absolute"; button.style.width = "0"; button.style.height = "0"; button.style.clipPath = "inset(50%)"; button.style.overflow = "hidden"; button.style.whiteSpace = "nowrap"; if (submitter) { button.name = submitter.name; button.value = submitter.value; ["formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"].forEach((attr) => { if (submitter.hasAttribute(attr)) { button.setAttribute(attr, submitter.getAttribute(attr)); } }); } this.form.append(button); button.click(); button.remove(); } } /** Returns the associated `
` element, if one exists. */ getForm() { var _a; return (_a = this.form) != null ? _a : null; } /** Resets the form, restoring all the control to their default value */ reset(submitter) { this.doAction("reset", submitter); } /** Submits the form, triggering validation and form data injection. */ submit(submitter) { this.doAction("submit", submitter); } /** * Synchronously sets the form control's validity. Call this when you know the future validity but need to update * the host element immediately, i.e. before Lit updates the component in the next update. */ setValidity(isValid) { const host = this.host; const hasInteracted = Boolean(userInteractedControls.has(host)); const required = Boolean(host.required); host.toggleAttribute("data-required", required); host.toggleAttribute("data-optional", !required); host.toggleAttribute("data-invalid", !isValid); host.toggleAttribute("data-valid", isValid); host.toggleAttribute("data-user-invalid", !isValid && hasInteracted); host.toggleAttribute("data-user-valid", isValid && hasInteracted); } /** * Updates the form control's validity based on the current value of `host.validity.valid`. Call this when anything * that affects constraint validation changes so the component receives the correct validity states. */ updateValidity() { const host = this.host; this.setValidity(host.validity.valid); } /** * Dispatches a non-bubbling, cancelable custom event of type `sl-invalid`. * If the `sl-invalid` event will be cancelled then the original `invalid` * event (which may have been passed as argument) will also be cancelled. * If no original `invalid` event has been passed then the `sl-invalid` * event will be cancelled before being dispatched. */ emitInvalidEvent(originalInvalidEvent) { const slInvalidEvent = new CustomEvent("sl-invalid", { bubbles: false, composed: false, cancelable: true, detail: {} }); if (!originalInvalidEvent) { slInvalidEvent.preventDefault(); } if (!this.host.dispatchEvent(slInvalidEvent)) { originalInvalidEvent == null ? void 0 : originalInvalidEvent.preventDefault(); } } }; var validValidityState = Object.freeze({ badInput: false, customError: false, patternMismatch: false, rangeOverflow: false, rangeUnderflow: false, stepMismatch: false, tooLong: false, tooShort: false, typeMismatch: false, valid: true, valueMissing: false }); var valueMissingValidityState = Object.freeze(__spreadProps(__spreadValues({}, validValidityState), { valid: false, valueMissing: true })); var customErrorValidityState = Object.freeze(__spreadProps(__spreadValues({}, validValidityState), { valid: false, customError: true })); export { formCollections, FormControlController, validValidityState, valueMissingValidityState, customErrorValidityState };