trellis
Version:
Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications
77 lines (75 loc) • 2.23 kB
JavaScript
import {
createFormCore,
formSchemaFrom
} from "../../chunk-25WAHQHF.js";
import "../../chunk-2ESYSVXG.js";
// src/forms/vanilla/index.ts
function createVanillaForm(schema, initialValues) {
const core = createFormCore(formSchemaFrom(schema), initialValues ?? {});
const form = {
get state() {
return core.state;
},
actions: core.actions,
field: core.field,
subscribe: (listener) => core.subscribe(() => listener(core.state))
};
return form;
}
function bindFormToDOM(form, formElement, fieldSelectors, onSubmit, options = {}) {
const errorAttribute = options.errorAttribute ?? "data-error-for";
const handleSubmit = (e) => {
e.preventDefault();
void (async () => {
const result = await form.actions.validate();
if (result.valid) {
await onSubmit?.(form.state.values);
}
})();
};
formElement.addEventListener("submit", handleSubmit);
const fieldElements = {};
const removers = [];
for (const [name, selector] of Object.entries(fieldSelectors)) {
const el = formElement.querySelector(
selector
);
if (!el) continue;
fieldElements[name] = el;
const onInput = () => {
form.actions.setValue(name, el.value);
};
const onBlur = () => {
form.actions.setTouched(name, true);
};
el.addEventListener("input", onInput);
el.addEventListener("blur", onBlur);
removers.push(() => {
el.removeEventListener("input", onInput);
el.removeEventListener("blur", onBlur);
});
}
const unsubscribe = form.subscribe((state) => {
for (const [name, el] of Object.entries(fieldElements)) {
if (document.activeElement !== el) {
el.value = state.values[name] !== void 0 ? String(state.values[name]) : "";
}
const errorEl = formElement.querySelector(
`[${errorAttribute}="${name}"]`
);
if (errorEl) {
errorEl.textContent = state.errors[name] ?? "";
errorEl.style.display = state.errors[name] ? "block" : "none";
}
}
});
return () => {
formElement.removeEventListener("submit", handleSubmit);
removers.forEach((remove) => remove());
unsubscribe();
};
}
export {
bindFormToDOM,
createVanillaForm
};