import { createContext } from "../shared/createContext.js"; import { useForwardExpose } from "../shared/useForwardExpose.js"; import { Primitive } from "../Primitive/Primitive.js"; import { computed, createBlock, defineComponent, getCurrentInstance, nextTick, openBlock, ref, renderSlot, unref, watch, withCtx } from "vue"; //#region src/Form/FormRoot.vue?vue&type=script&setup=true&lang.ts const [injectFormRootContext, provideFormRootContext] = /*#__PURE__*/ createContext("FormRoot"); var FormRoot_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ __name: "FormRoot", props: { errors: { type: Object, required: false }, validationMode: { type: String, required: false, default: "onSubmit" }, asChild: { type: Boolean, required: false }, as: { type: null, required: false, default: "form" } }, emits: ["submit", "formSubmit"], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emit = __emit; const instance = getCurrentInstance(); function validate(fieldName) { const targets = fieldName ? Array.from(fields).filter((field) => field.name.value === fieldName) : Array.from(fields); return targets.map((field) => field.validate()).every(Boolean); } __expose({ validate }); useForwardExpose(); const serverErrors = computed(() => props.errors ?? {}); const validationMode = computed(() => props.validationMode); const submitCount = ref(0); const fields = /* @__PURE__ */ new Set(); function registerField(field) { fields.add(field); return () => { fields.delete(field); }; } function getValues() { const values = {}; fields.forEach((field) => { if (field.name.value) values[field.name.value] = field.getValue(); }); return values; } /** * Focuses the control of the first invalid field in document order, since * registration order can diverge from it (fields mounted later, reordered * lists). Returns whether any field is invalid. */ function focusFirstInvalid() { let hasInvalid = false; let first; fields.forEach((field) => { if (!field.invalid.value) return; hasInvalid = true; const element = field.getControlElement(); if (element && (!first || first.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_PRECEDING)) first = element; }); if (first) { first.focus(); if (first instanceof HTMLInputElement) first.select(); } return hasInvalid; } let awaitingServerErrors = false; watch(serverErrors, async () => { if (!awaitingServerErrors) return; awaitingServerErrors = false; await nextTick(); focusFirstInvalid(); }); function handleSubmit(event) { submitCount.value++; validate(); if (focusFirstInvalid()) { event.preventDefault(); return; } awaitingServerErrors = true; emit("submit", event); if (instance?.vnode.props?.onFormSubmit) { event.preventDefault(); emit("formSubmit", getValues(), event); } } function handleReset() { fields.forEach((field) => field.resetField()); } provideFormRootContext({ serverErrors, validationMode, submitCount, getValues, registerField }); return (_ctx, _cache) => { return openBlock(), createBlock(unref(Primitive), { as: __props.as, "as-child": __props.asChild, novalidate: "", onSubmit: handleSubmit, onReset: handleReset }, { default: withCtx(() => [renderSlot(_ctx.$slots, "default")]), _: 3 }, 8, ["as", "as-child"]); }; } }); //#endregion //#region src/Form/FormRoot.vue var FormRoot_default = FormRoot_vue_vue_type_script_setup_true_lang_default; //#endregion export { FormRoot_default, injectFormRootContext }; //# sourceMappingURL=FormRoot.js.map