303 lines
10 KiB
JavaScript
303 lines
10 KiB
JavaScript
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 `<form>` 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
|
|
};
|