@samline/forms 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/browser/index.ts","../../src/api/append.ts","../../src/api/add-cleanup.ts","../../src/api/auto-submit.ts","../../src/api/clear-errors.ts","../../src/core/format-helpers.ts","../../src/core/formatter-loader.ts","../../src/api/format.ts","../../src/api/destroy.ts","../../src/api/disable-auto-submit.ts","../../src/core/serialize.ts","../../src/api/get-data.ts","../../src/api/get-field.ts","../../src/core/state.ts","../../src/api/get-state.ts","../../src/core/dom.ts","../../src/api/get-value.ts","../../src/api/observe.ts","../../src/api/on-submit.ts","../../src/api/prefill.ts","../../src/api/reset.ts","../../src/api/validate.ts","../../src/api/revalidate.ts","../../src/api/set-errors.ts","../../src/api/set-options.ts","../../src/api/set-value.ts","../../src/api/subscribe.ts","../../src/api/unwatch.ts","../../src/api/watch.ts","../../src/core/validation.ts","../../src/core/controller.ts","../../src/api/form.ts","../../src/browser/registry.ts","../../src/browser/global.ts"],"sourcesContent":["export {\n available,\n default,\n destroyForm,\n form,\n newForm\n} from './global'\nexport type { FormsApi, FormsAvailable, NewFormInput } from './registry'\n","// api/append.ts\n// Appends DOM content to the bound form. If a class is provided, removes\n// any existing node with that class first to avoid duplicates.\n// Returns the created node or null when no element is bound.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { AppendContentOptions } from '../core/types'\n\nexport const createAppend =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n ({ tag, content, class: className, atStart = false }: AppendContentOptions) => {\n if (!state.element || state.isDestroyed) return null\n\n helpers.clearFieldCache()\n\n if (className) {\n const classSelector = className.trim().split(/\\s+/)[0]\n const existing = classSelector\n ? state.element.getElementsByClassName(classSelector)[0]\n : null\n existing?.remove()\n }\n\n const node = document.createElement(tag)\n if (className) node.className = className\n node.innerHTML = content\n\n if (atStart && state.element.firstChild) {\n state.element.insertBefore(node, state.element.firstChild)\n } else {\n state.element.appendChild(node)\n }\n\n return node\n }\n","// api/add-cleanup.ts\n// Registers controller-owned teardown work and returns an unregister function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormCleanup } from '../core/types'\n\nexport const createAddCleanup =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (cleanup: FormCleanup): (() => void) => {\n if (state.isDestroyed) {\n cleanup()\n return () => undefined\n }\n\n const registration = () => cleanup()\n state.cleanups.add(registration)\n let active = true\n return () => {\n if (!active) return\n active = false\n state.cleanups.delete(registration)\n }\n }\n","// api/auto-submit.ts\n// Enables native auto-submit. Pass `true` to enable, `false` to disable,\n// or an { debounce } object to delay.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createAutoSubmit =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (next: boolean | { debounce?: number } = true) => {\n if (state.isDestroyed) return state.api!\n state.autoSubmitEnabled = next !== false\n if (!state.autoSubmitEnabled && state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n state.autoSubmitDebounce =\n typeof next === 'object' && next ? next.debounce ?? 0 : 0\n helpers.notifySubscribers()\n return state.api!\n }\n","// api/clear-errors.ts\n// Clears manual errors. With no args, clears every manual error. With a\n// list, clears only those fields.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createClearErrors =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields?: string[]) => {\n if (state.isDestroyed) return state.api!\n if (!fields) {\n state.manualErrors = {}\n helpers.syncVisualState()\n helpers.notifySubscribers()\n return state.api!\n }\n\n for (const field of fields) {\n delete state.manualErrors[field]\n }\n helpers.syncVisualState(fields)\n helpers.notifySubscribers()\n return state.api!\n }\n","// Low-level helpers used by `api/format.ts`:\n// - DOM cursor tracking equivalent to cleave.js' `getNextCursorPosition`\n// (so typing/backspacing inside formatted inputs keeps the caret\n// in a sensible place, even when delimiters are inserted or removed).\n// - `postDelimiterBackspace` contract: after a deletion, the caret\n// is pulled backwards past any leading delimiter so the user never\n// ends up parked with a format character on the caret's left.\n// - Hidden-mirror lookup & creation: each formatted input gets a\n// hidden sibling (`type=\"hidden\"`) that holds the backend-ready\n// `raw` value under the **canonical** field name (the one the\n// developer wrote in the HTML and the one the backend reads).\n// The visible input is renamed to `<field>_displayed` on the\n// first `format()` call. Both names are first-class in the\n// controller's API — see `docs/api/format.md` for the contract.\n//\n// The helpers here are pure DOM utilities — they do not know about the\n// controller state.\n\nimport type { FormFieldElement } from './types'\n\n/**\n * Marks a hidden input as the raw mirror of a formatted field.\n * Presence of this attribute is how `format()` distinguishes\n * mirrors it owns (created at `format()` time) from mirrors the\n * developer pre-authored in the HTML (which survive `destroy()`).\n */\nexport const FORMATTER_RAW_ATTRIBUTE = 'data-formatter-raw-for'\n\n// Resolve a field by name. Returns the first matching element or `null`.\nexport const getFormatterField = (\n form: HTMLFormElement,\n name: string\n): HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null => {\n const selector = `[name=\"${cssEscape(name)}\"]`\n const node = form.querySelector(selector)\n if (\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement\n ) {\n return node\n }\n return null\n}\n\n// Minimal CSS.escape polyfill for selectors that may contain special\n// characters (`[1].phone`, `email[primary]`, etc.).\nconst cssEscape = (value: string): string => {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value)\n }\n return value.replace(/([!\"#$%&'()*+,./:;<=>?@\\[\\\\\\]^`{|}~])/g, '\\\\$1')\n}\n\n// Find the visible (non-hidden) input that owns the formatted pair for\n// `fieldName`. Looks up by the display name (defaults to\n// `<fieldName>_displayed`, or whatever the developer passed in\n// `FieldFormatConfig.displayField`). Returns `null` when no visible\n// field matches.\nexport const findVisibleField = (\n form: HTMLFormElement,\n displayName: string\n): HTMLInputElement | HTMLTextAreaElement | null => {\n const node = form.querySelector(\n `[name=\"${cssEscape(displayName)}\"]:not([type=\"hidden\"])`\n )\n if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) {\n return node\n }\n return null\n}\n\n// Find the hidden input that mirrors `raw` for the given canonical\n// field name. Returns the existing element or `null`.\n//\n// The canonical name is the one the developer wrote in the HTML\n// (e.g. `phone`) and the one the backend reads. The hidden input\n// is named `phone` and carries the raw value. It is identified\n// either by the `data-formatter-raw-for` attribute (set when the\n// controller creates the mirror) or by a pre-authored hidden with\n// the same name (no attribute — owned externally, preserved on\n// `destroy()`).\nexport const findHiddenMirror = (\n form: HTMLFormElement,\n fieldName: string\n): HTMLInputElement | null => {\n const byAttr = form.querySelector<HTMLInputElement>(\n `[${FORMATTER_RAW_ATTRIBUTE}=\"${cssEscape(fieldName)}\"]`\n )\n if (byAttr) return byAttr\n\n const byName = form.querySelector<HTMLInputElement>(\n `input[type=\"hidden\"][name=\"${cssEscape(fieldName)}\"]`\n )\n if (byName) return byName\n\n return null\n}\n\n// Create a hidden input that will mirror the raw value of `fieldName`.\n// Idempotent: if a mirror already exists it is returned as-is. The\n// mirror is named with the canonical `fieldName` (not a derived\n// suffix) so the value the backend reads sits at the developer's\n// natural name. The `data-formatter-raw-for` attribute is set so\n// `destroy()` can identify the mirror as owned and remove it.\nexport const ensureHiddenMirror = (\n form: HTMLFormElement,\n fieldName: string\n): HTMLInputElement => {\n const existing = findHiddenMirror(form, fieldName)\n if (existing) return existing\n\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = fieldName\n input.setAttribute('aria-hidden', 'true')\n input.tabIndex = -1\n input.setAttribute(FORMATTER_RAW_ATTRIBUTE, fieldName)\n form.appendChild(input)\n return input\n}\n\n// Rename a visible input from its current `name` to `displayName`.\n// Idempotent: if the input already has `displayName` it is left\n// alone. Used by `format()` to migrate the developer's authored\n// `<input name=\"phone\">` to `<input name=\"phone_displayed\">` so\n// the canonical `name` slot is free for the hidden raw mirror.\nexport const renameVisibleField = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n displayName: string\n): void => {\n if (visible.name === displayName) return\n visible.name = displayName\n}\n\n// Restore a visible input to `originalName`. Called by the format\n// registry on `destroy()` to put the DOM back the way the developer\n// authored it (modulo the value, which the developer controls).\nexport const restoreVisibleName = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n originalName: string\n): void => {\n visible.name = originalName\n}\n\n// Remove every hidden mirror owned by `format()`. Mirrors created by\n// this controller carry the `data-formatter-raw-for` attribute;\n// mirrors that existed before are left untouched.\nexport const removeOwnedHiddenMirrors = (form: HTMLFormElement): void => {\n form\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n}\n\n// Write `formatted` into the visible field and `raw` into the hidden\n// mirror, preserving the cursor as best as possible.\n//\n// Returns the new caret position so callers can debug or run additional\n// assertions. The function avoids triggering `MutationObserver` cascades\n// for the hidden mirror by setting `.value` directly (the controller's\n// own delegated handler ignores hidden inputs via `isFieldElement`).\n//\n// `inputType` is the optional `InputEvent.inputType` value (e.g.\n// `'insertText'`, `'deleteContentBackward'`, `'deleteWordBackward'`).\n// When it indicates a deletion, this helper mirrors cleave.js'\n// `postDelimiterBackspace` contract: after the caret is re-anchored in\n// the freshly formatted value, walk backwards while the character\n// immediately to the left of the caret is a format character (delimiter,\n// prefix/suffix symbol, …) and decrement the caret. That keeps the\n// caret from \"jumping\" past a delimiter that disappeared when the user\n// deleted the digit sitting right next to it.\nexport const applyFormattedValue = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n mirror: HTMLInputElement | null,\n formatted: string,\n raw: string,\n inputType?: string\n): number => {\n // Capture the caret in the **raw** input the user just typed — this\n // is what cleave's `getNextCursorPosition` does. Using the formatted\n // previous value would lose information when the user edits in the\n // middle of a masked field (deletion adjacent to delimiters, etc.).\n const rawInput = visible.value\n const caret = clamp(\n visible.selectionStart ?? rawInput.length,\n 0,\n rawInput.length\n )\n\n if (mirror && mirror.value !== raw) mirror.value = raw\n\n if (rawInput === formatted) {\n // The formatter did not change the visible value — usually because\n // the user is editing at the tail of a fully-formatted string. Even\n // so, a backspace can leave the caret sitting with a delimiter on\n // its left (because the digit right after the delimiter just\n // disappeared). Apply the postDelimiterBackspace scan in this path\n // too so the contract holds for both branches.\n const newCaret = pullCaretPastLeadingDelimiter(caret, formatted, inputType)\n if (newCaret !== caret) restoreCursor(visible, newCaret)\n return newCaret\n }\n\n visible.value = formatted\n\n const newCaret = pullCaretPastLeadingDelimiter(\n computeCursorPosition(caret, rawInput, formatted),\n formatted,\n inputType\n )\n restoreCursor(visible, newCaret)\n return newCaret\n}\n\n// Mirrors cleave.js' `postDelimiterBackspace` contract. After a\n// deletion (`inputType` starts with `'delete'`) we never want the\n// caret to sit with a format character immediately on its left; if it\n// would, pull it backwards until it does (or until we hit index 0).\n// No-op when `inputType` is missing or does not indicate a deletion.\nconst pullCaretPastLeadingDelimiter = (\n caret: number,\n value: string,\n inputType: string | undefined\n): number => {\n if (!inputType || !inputType.startsWith('delete')) return caret\n\n let cursor = caret\n while (cursor > 0 && isFormatChar(value[cursor - 1]!)) {\n cursor -= 1\n }\n return cursor\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, value))\n\n// `computeCursorPosition` is a cleave-style implementation:\n// - count \"non-format\" characters (digits / letters) between the caret\n// and the start of the **raw input the user just typed**, then\n// locate that same logical index in the new formatted value\n// (jumping over inserted delimiters).\n// - when the caret is at (or past) the end of the raw input, place\n// it at the end of the formatted value.\n//\n// The algorithm intentionally avoids any cleave-zen dependency so this\n// file is pure DOM arithmetic.\nexport const computeCursorPosition = (\n caretPos: number,\n rawInput: string,\n newValue: string\n): number => {\n if (newValue.length === 0) return 0\n\n // Caret at (or past) the end of the raw input — place at new end.\n if (caretPos >= rawInput.length) return newValue.length\n\n // Caret within the raw input: count non-format characters to its\n // LEFT (i.e. how many real characters are before the caret) and\n // find that same count in the new formatted value.\n const targetNonFormat = countNonFormat(rawInput.slice(0, caretPos))\n\n if (targetNonFormat === 0) {\n // Skip leading delimiters / prefix symbols (`$`, `+`, …) so the\n // caret lands at the first real character of the new value.\n let i = 0\n while (i < newValue.length && isFormatChar(newValue[i]!)) i += 1\n return i\n }\n\n let seen = 0\n for (let i = 0; i < newValue.length; i += 1) {\n if (!isFormatChar(newValue[i]!)) {\n seen += 1\n if (seen === targetNonFormat) {\n return Math.min(i + 1, newValue.length)\n }\n }\n }\n\n return newValue.length\n}\n\nconst countNonFormat = (value: string): number => {\n let count = 0\n for (const char of value) {\n if (!isFormatChar(char)) count += 1\n }\n return count\n}\n\n// \"Format characters\" are delimiters, prefix symbols, and other\n// non-alphanumeric separators that the formatter may insert or remove.\n// We deliberately keep this conservative — anything that is not a digit\n// or ASCII letter counts as a format character.\nexport const isFormatChar = (char: string): boolean => {\n if (!char) return false\n if (char >= '0' && char <= '9') return false\n if ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z')) return false\n return true\n}\n\nconst restoreCursor = (\n field: HTMLInputElement | HTMLTextAreaElement,\n position: number\n): void => {\n // Moving the selection of a control the user is not editing is never\n // wanted, and Safari focuses an input when its selection is set.\n if (field.ownerDocument.activeElement !== field) return\n\n const max = field.value.length\n const safe = clamp(position, 0, max)\n\n const apply = () => {\n try {\n field.setSelectionRange(safe, safe)\n } catch {\n // Some input types (number, email) throw on setSelectionRange.\n // Ignore — the caret just stays where the browser put it.\n }\n }\n\n // Android keyboard fix: defer one frame so the IME catches up before\n // we re-position the caret. Mirrors cleave.js' `isAndroid` branch.\n if (typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent)) {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(apply)\n } else {\n setTimeout(apply, 1)\n }\n return\n }\n\n apply()\n}\n\n// `getFormatterField` re-exported above is the canonical entry point,\n// but it is intentionally restricted to controller-owned fields. This\n// looser helper accepts a wider set of inputs for test fixtures.\nexport const isFormatterFieldElement = (node: Element): node is FormFieldElement =>\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement","// Lazy singleton loader for the optional `@samline/formatter` peer.\n// The formatter is imported dynamically so the package stays usable\n// even when the peer is not installed: callers receive `null` and a\n// single console.error explaining the missing dependency.\n//\n// The first failure is cached so the warning is printed exactly once\n// per process, not on every `format(...)` call.\n\nexport interface FormatterModule {\n format: (\n value: unknown,\n formatType: string,\n options?: Record<string, unknown>\n ) => { formatted: string; raw: string; type: string }\n FORMAT_TYPES?: readonly string[]\n isFormatType?: (value: unknown) => boolean\n regex?: Record<string, { pattern: RegExp; errorMessage: string }>\n}\n\ntype LoaderState =\n | { status: 'pending'; promise: Promise<FormatterModule | null> }\n | { status: 'resolved'; module: FormatterModule | null }\n\nlet state: LoaderState | null = null\n\nconst MISSING_MESSAGE =\n '[samline/forms] The `format()` and `formatAll()` methods require the ' +\n '@samline/formatter package. Install it with: npm i @samline/formatter ' +\n '(or pnpm/bun/yarn equivalent).'\n\nlet warned = false\n\nconst warnOnce = () => {\n if (warned) return\n warned = true\n console.error(MISSING_MESSAGE)\n}\n\nexport const loadFormatter = (): Promise<FormatterModule | null> => {\n if (state && state.status === 'resolved') {\n if (!state.module) warnOnce()\n return Promise.resolve(state.module)\n }\n\n if (state && state.status === 'pending') {\n return state.promise\n }\n\n const promise = (async () => {\n try {\n // Dynamic import keeps the optional peer out of the eager build graph.\n // The consumer's bundler is responsible for resolving the peer at\n // build time — `tsup` treats `@samline/formatter` as `external` so it\n // does not try to pre-bundle it. Do NOT re-add `/* @vite-ignore */`\n // here: in production it leaves the bare specifier as a literal in\n // the bundle, browsers cannot resolve it, and the formatter silently\n // never loads (the catch below masks the failure).\n const mod = (await import('@samline/formatter')) as FormatterModule\n state = { status: 'resolved', module: mod }\n return mod\n } catch {\n warnOnce()\n state = { status: 'resolved', module: null }\n return null\n }\n })()\n\n state = { status: 'pending', promise }\n return promise\n}\n\n// Test-only helper: reset the cached loader so unit tests can swap the\n// dynamic import between \"installed\" and \"missing\" scenarios.\nexport const __resetFormatterLoaderForTests = (): void => {\n state = null\n warned = false\n}\n\n// Test-only helper: inject a formatter implementation directly,\n// bypassing the dynamic import. Pass `null` to simulate the\n// \"peer not installed\" branch.\nexport const __setFormatterModuleForTests = (\n module: FormatterModule | null\n): void => {\n state = { status: 'resolved', module }\n}\n\nexport const __setFormatterPromiseForTests = (\n promise: Promise<FormatterModule | null>\n): void => {\n state = { status: 'pending', promise }\n}\n","import type { FieldFormatConfig, FormController, FormFieldElement } from '../core/types'\nimport {\n applyFormattedValue,\n ensureHiddenMirror,\n findHiddenMirror,\n findVisibleField,\n FORMATTER_RAW_ATTRIBUTE,\n renameVisibleField,\n restoreVisibleName\n} from '../core/format-helpers'\nimport { loadFormatter } from '../core/formatter-loader'\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\ntype FormatEntry = {\n canonicalName: string\n displayName: string\n visible: HTMLInputElement | HTMLTextAreaElement\n mirror: HTMLInputElement\n mirrorIsOwned: boolean\n defaultVisible: string | null\n defaultRaw: string | null\n /** Bound after the formatter peer resolves. */\n handler: ((event: Event) => void) | null\n}\n\nconst UNBOUND: ((event: Event) => void) | null = null\n\nconst registry = new WeakMap<FormControllerState, Map<string, FormatEntry>>()\n\nconst getRegistry = (state: FormControllerState): Map<string, FormatEntry> => {\n let bucket = registry.get(state)\n if (!bucket) {\n bucket = new Map<string, FormatEntry>()\n registry.set(state, bucket)\n }\n return bucket\n}\n\nconst resolveFieldNames = (config: FieldFormatConfig): string[] =>\n Array.isArray(config.field) ? config.field : [config.field]\n\nconst addListener = (\n state: FormControllerState,\n target: EventTarget,\n type: string,\n handler: EventListener,\n useCapture?: boolean\n): void => {\n if (useCapture) {\n target.addEventListener(type, handler, { capture: true })\n } else {\n target.addEventListener(type, handler)\n }\n const entry: {\n element: EventTarget\n type: string\n handler: EventListener\n capture?: boolean\n } = { element: target, type, handler }\n if (useCapture !== undefined) entry.capture = useCapture\n state.listeners.push(entry)\n}\n\nconst readInputType = (event: Event): string | undefined => {\n const candidate = event as Partial<InputEvent>\n return typeof candidate.inputType === 'string' ? candidate.inputType : undefined\n}\n\n// Canonical mirrors use auto detection; visible input is always display-order.\nconst buildAutoInterpretedOptions = (\n formatOptions: Record<string, unknown> | undefined\n): Record<string, unknown> => ({\n ...(formatOptions ?? {}),\n interpretInputAs: 'auto'\n})\n\nconst buildDisplayInterpretedOptions = (\n formatOptions: Record<string, unknown> | undefined\n): Record<string, unknown> => ({\n ...(formatOptions ?? {}),\n interpretInputAs: 'display'\n})\n\nconst shouldForceAutoInterpretation = (\n formatOptions: Record<string, unknown> | undefined\n): boolean => formatOptions?.interpretInputAs === undefined\n\nconst buildHandler = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n mirror: HTMLInputElement,\n formatFn: NonNullable<Awaited<ReturnType<typeof loadFormatter>>>['format'],\n formatType: FieldFormatConfig['type'],\n formatOptions: Record<string, unknown> | undefined\n): ((event: Event) => void) => {\n const handler = (event: Event) => {\n if (!visible.isConnected || !mirror.isConnected) return\n\n const isVisible = event.target === visible\n const isMirror = event.target === mirror\n if (!isVisible && !isMirror) return\n\n const rawInput = isMirror ? mirror.value : visible.value\n const inputType = readInputType(event)\n const sourceOptions = shouldForceAutoInterpretation(formatOptions)\n ? isMirror\n ? buildAutoInterpretedOptions(formatOptions)\n : buildDisplayInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatFn(rawInput, formatType, sourceOptions)\n\n if (!formatted && !raw) {\n visible.value = ''\n if (mirror.value !== '') mirror.value = ''\n return\n }\n\n applyFormattedValue(visible, mirror, formatted, raw, inputType)\n }\n return handler\n}\n\n// Phase one mutates the DOM synchronously; phase two binds only this call's entries.\nconst applyFormat = async (\n state: FormControllerState,\n helpers: FormControllerHelpers,\n config: FieldFormatConfig\n): Promise<void> => {\n if (!state.element || !state.api) return\n if (Array.isArray(config.field) && config.displayField) {\n console.error(\n '[samline/forms] `displayField` can only be used when `field` is a string.'\n )\n return\n }\n\n const formatType = config.type\n const formatOptions = config.options\n const fieldNames = resolveFieldNames(config)\n const bucket = getRegistry(state)\n\n const phase1Entries: FormatEntry[] = []\n\n // Phase 1: establish the visible/canonical pair synchronously.\n for (const fieldName of fieldNames) {\n const displayName = config.displayField ?? `${fieldName}_displayed`\n\n // Accept either a canonical visible field or a pre-authored display field.\n const canonicalFields = helpers.getFieldsByName(fieldName) as FormFieldElement[]\n const candidates = canonicalFields.filter(\n (f): f is HTMLInputElement | HTMLTextAreaElement =>\n (f instanceof HTMLInputElement && f.type !== 'hidden') ||\n f instanceof HTMLTextAreaElement\n )\n let visible: HTMLInputElement | HTMLTextAreaElement | null = candidates[0] ?? null\n if (!visible) {\n visible = findVisibleField(state.element, displayName)\n }\n if (!visible) continue\n\n const existing = bucket.get(fieldName)\n\n let mirror = findHiddenMirror(state.element, fieldName)\n const mirrorIsOwned = !mirror\n if (!mirror) mirror = ensureHiddenMirror(state.element, fieldName)\n\n renameVisibleField(visible, displayName)\n\n if (existing) {\n existing.displayName = displayName\n existing.mirrorIsOwned = mirrorIsOwned\n state.formattedFields.set(fieldName, {\n config,\n displayName,\n mirrorIsOwned\n })\n phase1Entries.push(existing)\n } else {\n const entry: FormatEntry = {\n canonicalName: fieldName,\n displayName,\n visible,\n mirror,\n mirrorIsOwned,\n defaultVisible: null,\n defaultRaw: null,\n handler: UNBOUND\n }\n bucket.set(fieldName, entry)\n state.formattedFields.set(fieldName, {\n config,\n displayName,\n mirrorIsOwned\n })\n phase1Entries.push(entry)\n }\n }\n\n // Phase 2: load the peer, bind listeners, and normalize initial values.\n const formatter = await loadFormatter()\n if (state.isDestroyed) {\n rollbackPhase1(phase1Entries, bucket, state.formattedFields)\n return\n }\n if (!formatter) {\n rollbackPhase1(phase1Entries, bucket, state.formattedFields)\n return\n }\n\n for (const entry of phase1Entries) {\n if (entry.handler !== UNBOUND) {\n // Reformat without duplicating the existing capture listener.\n const current = entry.visible.value\n if (current !== '') {\n const rebindOptions = shouldForceAutoInterpretation(formatOptions)\n ? buildDisplayInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatter.format(current, formatType, rebindOptions)\n applyFormattedValue(entry.visible, entry.mirror, formatted, raw)\n }\n continue\n }\n\n const handler = buildHandler(\n entry.visible,\n entry.mirror,\n formatter.format,\n formatType,\n formatOptions\n )\n addListener(state, state.element, 'input', handler, true)\n entry.handler = handler\n\n const initial = entry.visible.value\n if (initial !== '') {\n // Initial values may be canonical server data; preserve explicit modes.\n const initialOptions = shouldForceAutoInterpretation(formatOptions)\n ? buildAutoInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatter.format(initial, formatType, initialOptions)\n applyFormattedValue(entry.visible, entry.mirror, formatted, raw)\n } else if (entry.mirrorIsOwned && entry.mirror.value !== '') {\n entry.mirror.value = ''\n }\n entry.defaultVisible = entry.visible.value\n entry.defaultRaw = entry.mirror.value\n }\n}\n\nexport const resetFormattedFields = (state: FormControllerState): void => {\n const bucket = registry.get(state)\n if (!bucket) return\n for (const entry of bucket.values()) {\n if (entry.defaultVisible !== null) entry.visible.value = entry.defaultVisible\n if (entry.defaultRaw !== null) entry.mirror.value = entry.defaultRaw\n }\n}\n\n// Restore only entries touched by the current call when peer loading fails.\nconst rollbackPhase1 = (\n entries: FormatEntry[],\n bucket: Map<string, FormatEntry>,\n registry: FormControllerState['formattedFields']\n): void => {\n for (const entry of entries) {\n if (entry.visible.isConnected) {\n restoreVisibleName(entry.visible, entry.canonicalName)\n }\n if (entry.mirrorIsOwned && entry.mirror.isConnected) {\n entry.mirror.remove()\n }\n bucket.delete(entry.canonicalName)\n registry.delete(entry.canonicalName)\n }\n}\n\nexport const createFormat =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (config: FieldFormatConfig): FormController => {\n if (state.isDestroyed) return state.api!\n if (!state.element) return state.api!\n\n void applyFormat(state, helpers, config)\n\n return state.api!\n }\n\nexport const createFormatAll = createFormat\n\nexport const resolveCanonicalForName = (\n state: FormControllerState,\n name: string\n): string | null => {\n const bucket = registry.get(state)\n if (!bucket) return null\n for (const [canonical, entry] of bucket) {\n if (canonical === name || entry.displayName === name) return canonical\n }\n return null\n}\n\nexport const resolveDisplayNameForName = (\n state: FormControllerState,\n name: string\n): string => {\n const bucket = registry.get(state)\n if (!bucket) return name\n for (const [canonical, entry] of bucket) {\n if (canonical === name) return entry.displayName\n if (entry.displayName === name) return entry.displayName\n }\n return name\n}\n\nexport const cleanupFormatRegistry = (state: FormControllerState): void => {\n if (!state.element) {\n registry.delete(state)\n return\n }\n\n const bucket = registry.get(state)\n if (!bucket) {\n state.element\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n return\n }\n\n for (const [fieldName, entry] of bucket) {\n if (entry.handler !== UNBOUND) {\n state.element.removeEventListener('input', entry.handler, true)\n }\n if (entry.visible.isConnected) {\n restoreVisibleName(entry.visible, fieldName)\n }\n if (entry.mirrorIsOwned && entry.mirror.isConnected) {\n entry.mirror.remove()\n }\n bucket.delete(fieldName)\n state.formattedFields.delete(fieldName)\n }\n\n // Remove any orphaned mirrors defensively.\n state.element\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n}\n","// api/destroy.ts\n// Tears down the controller: removes DOM listeners, disconnects the\n// mutation observer, clears caches, and resets internal state.\n// Safe to call multiple times.\n\nimport { cleanupFormatRegistry } from './format'\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createDestroy =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n () => {\n if (state.isDestroyed) return\n\n state.isDestroyed = true\n for (const listener of state.listeners) {\n const options: EventListenerOptions | undefined = listener.capture\n ? { capture: true }\n : undefined\n if (options) {\n listener.element.removeEventListener(listener.type, listener.handler, options)\n } else {\n listener.element.removeEventListener(listener.type, listener.handler)\n }\n }\n state.listeners.length = 0\n\n if (state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n\n state.mutationObserver?.disconnect()\n state.mutationObserver = null\n\n const cleanups = Array.from(state.cleanups).reverse()\n state.cleanups.clear()\n for (const cleanup of cleanups) {\n try {\n cleanup()\n } catch (error) {\n console.error('[forms] cleanup failed', error)\n }\n }\n\n state.watchedFields.clear()\n state.groupWatchers.clear()\n state.subscribers.clear()\n state.submitHandlers.clear()\n state.fieldCache.clear()\n state.manualErrors = {}\n state.validationErrors = {}\n state.validationGroupErrors = {}\n state.validationElementErrors.clear()\n state.pendingSubmitCount = 0\n\n // Detach format listeners and drop the hidden raw mirrors that\n // `format()` created for this controller. Mirrors that pre-existed\n // in the DOM (i.e. not owned by us) are preserved.\n cleanupFormatRegistry(state)\n }\n","// api/disable-auto-submit.ts\n// Disables autoSubmit and cancels any pending debounce timer.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createDisableAutoSubmit =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n () => {\n state.autoSubmitEnabled = false\n if (state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n helpers.notifySubscribers()\n return state.api!\n }\n","// Pure serialization helpers for HTMLFormElement.\n// No DOM mutation, no controller state — safe to tree-shake into any bundle.\n\nimport type { SerializedFormResult, SerializedFormValue } from './types'\n\nconst isEmptyFile = (value: FormDataEntryValue): value is File =>\n value instanceof File && value.size === 0 && value.name === ''\n\nconst appendValue = (\n data: Record<string, SerializedFormValue>,\n key: string,\n value: FormDataEntryValue\n): void => {\n if (!Object.prototype.hasOwnProperty.call(data, key)) {\n Object.defineProperty(data, key, {\n value,\n writable: true,\n enumerable: true,\n configurable: true\n })\n return\n }\n const current = data[key] as SerializedFormValue\n if (Array.isArray(current)) {\n current.push(value)\n return\n }\n data[key] = [current, value]\n}\n\nexport const parseFormData = (\n formElement: HTMLFormElement,\n submitter?: HTMLElement | null\n): SerializedFormResult => {\n const raw = submitter\n ? new FormData(formElement, submitter)\n : new FormData(formElement)\n const formData = new FormData()\n const data: Record<string, SerializedFormValue> = {}\n\n raw.forEach((value, key) => {\n if (isEmptyFile(value)) return\n formData.append(key, value)\n appendValue(data, key, value)\n })\n\n return { data, formData }\n}\n","// api/get-data.ts\n// Returns the form serialized as both a plain object and a fresh\n// FormData instance. Empty file inputs are filtered out.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { SerializedFormResult } from '../core/types'\nimport { parseFormData } from '../core/serialize'\n\nexport const createGetData =\n (_state: FormControllerState, _helpers: FormControllerHelpers) =>\n (): SerializedFormResult => {\n if (!_state.element) return { data: {}, formData: new FormData() }\n return parseFormData(_state.element)\n }\n","// api/get-field.ts\n// Returns the underlying DOM field(s) for a given name:\n// - null when no field matches\n// - a single element when there's exactly one\n// - an array when there are multiple (radios, checkbox groups)\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldElement } from '../core/types'\n\nexport const createGetField =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string): FormFieldElement | FormFieldElement[] | null => {\n const fields = helpers.getFieldsByName(name)\n if (fields.length === 0) return null\n return fields.length === 1 ? fields[0]! : fields\n }\n","// Shared mutable state for the controller plus the small pure helpers used\n// by both core utilities and the api method factories.\n\nimport type {\n FieldFormatConfig,\n FormController,\n FormControllerOptions,\n FormCleanup,\n FormErrors,\n FormFieldElement,\n FormFieldWatcher,\n FormFieldsWatcher,\n FormStateListener,\n FormStateSnapshot,\n FormValues,\n ValidationResult,\n ValidationSchema,\n VisualAttributes\n} from './types'\n\nexport interface FormControllerState {\n element: HTMLFormElement | null\n options: FormControllerOptions\n attributes: Required<VisualAttributes>\n validators: ValidationSchema\n watchedFields: Map<string, Set<FormFieldWatcher>>\n // Watchers registered with a list of fields. `fields` is deduplicated\n // and keeps the order the caller passed.\n groupWatchers: Set<{ fields: string[]; callback: FormFieldsWatcher }>\n subscribers: Set<FormStateListener>\n submitHandlers: Set<{\n callback: import('./types').FormSubmitHandler\n preventDefault: boolean\n }>\n fieldCache: Map<string, FormFieldElement[]>\n manualErrors: FormErrors\n validationErrors: FormErrors\n validationGroupErrors: FormErrors\n validationElementErrors: Map<string, Map<FormFieldElement, string[]>>\n isValidated: boolean\n autoSubmitEnabled: boolean\n autoSubmitDebounce: number\n submitCount: number\n pendingSubmitCount: number\n autoSubmitTimer: ReturnType<typeof setTimeout> | null\n /** True while an automatic `requestSubmit()` is dispatching `submit`. */\n isAutoSubmitting: boolean\n /** Batches several programmatic writes (`prefill`) into one auto-submit. */\n autoSubmitSuspended: boolean\n /** True while `reset()` runs the native reset it already handles. */\n isResetting: boolean\n isDestroyed: boolean\n listeners: Array<{\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n /**\n * `true` when the listener was registered with `capture: true`.\n * Required for matching `removeEventListener` on teardown —\n * the spec treats capture and bubble as distinct registrations.\n */\n capture?: boolean\n }>\n mutationObserver: MutationObserver | null\n cleanups: Set<FormCleanup>\n // Tracks every field that `format()` is currently formatting, so\n // re-bindings are idempotent and `destroy()` can clean up the\n // associated listeners + hidden raw mirror. Keyed by the canonical\n // field name (the one the developer wrote in the HTML and the one\n // the backend reads). `displayName` is the visible input's name\n // (defaults to `${canonical}_displayed`).\n formattedFields: Map<\n string,\n {\n config: FieldFormatConfig\n displayName: string\n mirrorIsOwned: boolean\n }\n >\n // Back-reference to the assembled public controller. Populated by the\n // controller orchestrator after the api method factories are wired.\n api: FormController | null\n}\n\n// Internal helpers bound by the controller orchestrator and consumed by\n// the api method factories. Kept here so api/*.ts only depends on the\n// shape, not on the orchestrator implementation.\nexport interface FormControllerHelpers {\n notifySubscribers: () => void\n clearFieldCache: () => void\n getFieldsByName: (name: string) => FormFieldElement[]\n getTrackedFieldNames: () => string[]\n getValues: () => FormValues\n getMergedErrors: () => FormErrors\n syncVisualState: (names?: string[]) => void\n validateNames: (names?: string[]) => ValidationResult\n emitFieldWatchers: (name: string) => void\n scheduleAutoSubmit: () => void\n applyReset: () => void\n commitOwnMutations: (selects: HTMLSelectElement[]) => void\n}\n\nexport const createEmptyFormState = (): FormStateSnapshot => ({\n values: {},\n errors: {},\n filledFields: [],\n isValid: true,\n isValidated: false,\n autoSubmit: false,\n isSubmitting: false,\n submitCount: 0\n})\n\nexport const cloneErrors = (errors: FormErrors): FormErrors =>\n Object.fromEntries(\n Object.entries(errors).map(([field, messages]) => [field, [...messages]])\n )\n\nexport const mergeErrors = (left: FormErrors, right: FormErrors): FormErrors => {\n const merged: FormErrors = { ...left }\n for (const [field, messages] of Object.entries(right)) {\n merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages]\n }\n return merged\n}\n","// api/get-state.ts\n// Builds a snapshot of values, errors, filled fields and submission\n// metadata. Pure read — does not mutate controller state.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormStateSnapshot } from '../core/types'\nimport { cloneErrors, createEmptyFormState } from '../core/state'\n\nexport const createGetState =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (): FormStateSnapshot => {\n const values = helpers.getValues()\n const errors = cloneErrors(helpers.getMergedErrors())\n const filledFields = Object.keys(values).filter(name => {\n const value = values[name]\n if (Array.isArray(value)) return value.length > 0\n if (typeof value === 'string') return value.trim().length > 0\n return value !== undefined\n })\n\n return {\n ...createEmptyFormState(),\n values,\n errors,\n filledFields,\n isValid: Object.keys(errors).length === 0,\n isValidated: state.isValidated,\n autoSubmit: state.autoSubmitEnabled,\n isSubmitting: state.pendingSubmitCount > 0,\n submitCount: state.submitCount\n }\n }\n","// Low-level DOM helpers used by the controller orchestrator and by api\n// methods that need direct DOM access. Pure: no controller state.\n\nimport type { FormFieldElement, FormFieldValue, FormTarget } from './types'\n\nconst isFormFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\n// Convention: a name ending with \"[]\" signals multi-value inputs (the\n// de facto HTML form pattern used by PHP, Rails, Express, Spring, etc.\n// to collect repeated inputs as an array on the server). The `[]`\n// suffix is the only signal the controller uses; bare names keep the\n// original first-value semantics.\nconst isArraySyntax = (field: FormFieldElement): boolean =>\n typeof field.name === 'string' && field.name.endsWith('[]')\n\nexport const resolveFormElement = (target: FormTarget): HTMLFormElement | null => {\n if (!target) return null\n if (target instanceof HTMLFormElement) return target\n if (typeof target === 'string') {\n const node = document.getElementById(target)\n return node instanceof HTMLFormElement ? node : null\n }\n if ('current' in target) {\n return target.current instanceof HTMLFormElement ? target.current : null\n }\n return null\n}\n\nexport const getNamedFields = (form: HTMLFormElement): FormFieldElement[] =>\n Array.from(form.elements).filter(\n (element): element is FormFieldElement =>\n isFormFieldElement(element) && Boolean(element.name)\n )\n\nexport const queryNamedFields = (\n form: HTMLFormElement,\n name: string\n): FormFieldElement[] => getNamedFields(form).filter(field => field.name === name)\n\nexport const isFieldElement = (value: Element): value is FormFieldElement =>\n isFormFieldElement(value)\n\nexport const isFieldFilled = (field: FormFieldElement): boolean => {\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox' || field.type === 'radio') return field.checked\n if (field.type === 'file') return Boolean(field.files && field.files.length > 0)\n return field.value.trim() !== ''\n }\n return field.value !== ''\n}\n\nexport const applyBooleanAttribute = (\n field: FormFieldElement,\n attribute: string,\n enabled: boolean\n): void => {\n if (enabled) {\n field.setAttribute(attribute, '')\n } else {\n field.removeAttribute(attribute)\n }\n}\n\nexport const readFieldValue = (fields: FormFieldElement[]): FormFieldValue => {\n if (fields.length === 0) return undefined\n const first = fields[0]\n if (!first) return undefined\n\n // Multi-value inputs: name=\"foo[]\". Only treat the group as an array\n // when there is more than one matching input — a single input with a\n // `[]` suffix still returns a plain string, matching the non-array\n // semantics and avoiding a one-element array that callers would\n // have to flatten.\n if (isArraySyntax(first) && fields.length > 1) {\n if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {\n return fields.map(f => f.value)\n }\n\n if (first instanceof HTMLInputElement) {\n if (first.type === 'radio') {\n // Radio groups stay single-valued even with the `[]` suffix —\n // they semantically mean \"one of these\". Find the checked one.\n const checked = fields.find(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n return checked?.value ?? ''\n }\n\n if (first.type === 'checkbox') {\n // Always return an array of checked values (no single-value\n // collapse) so `Array.isArray(value)` validators stay correct.\n return fields\n .filter(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n .map(f => f.value)\n }\n\n if (first.type === 'file') {\n // Concatenate every selected file across all matching inputs.\n return fields.flatMap(f =>\n f instanceof HTMLInputElement && f.files ? Array.from(f.files) : []\n )\n }\n }\n\n // text / email / password / number / hidden — one string per input.\n return fields.map(f => f.value)\n }\n\n if (first instanceof HTMLSelectElement && first.multiple) {\n return Array.from(first.selectedOptions, option => option.value)\n }\n\n if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {\n return first.value\n }\n\n if (first instanceof HTMLInputElement) {\n if (first.type === 'radio') {\n const checked = fields.find(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n return checked?.value ?? ''\n }\n\n if (first.type === 'checkbox') {\n const values = fields\n .filter(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n .map(f => f.value)\n return values.length > 1 ? values : (values[0] ?? '')\n }\n\n if (first.type === 'file') {\n return first.files ? Array.from(first.files) : []\n }\n }\n\n return first.value\n}\n\nexport const writeFieldValue = (fields: FormFieldElement[], value: unknown): void => {\n const normalizedArray = Array.isArray(value)\n ? value.map(item => String(item))\n : null\n const normalizedValue = value === undefined || value === null ? '' : String(value)\n\n // For `name=\"foo[]\"` fields receiving an array, distribute one element\n // per input. Surplus inputs (more inputs than array elements) are\n // cleared to ''; surplus array elements (more elements than inputs)\n // are dropped — there's no input to write to. The distribution only\n // applies to text-like inputs; checkbox / radio / file keep their\n // own special semantics.\n const distributeArray =\n fields.length > 0 &&\n fields[0] !== undefined &&\n isArraySyntax(fields[0]) &&\n normalizedArray !== null\n\n for (let index = 0; index < fields.length; index++) {\n const field = fields[index]\n if (!field) continue\n\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox') {\n field.checked = normalizedArray\n ? normalizedArray.includes(field.value)\n : normalizedValue === field.value\n continue\n }\n if (field.type === 'radio') {\n field.checked = field.value === normalizedValue\n continue\n }\n if (field.type === 'file') {\n if (Array.isArray(value) && value.length === 0) field.value = ''\n continue\n }\n if (distributeArray && normalizedArray) {\n field.value = normalizedArray[index] ?? ''\n continue\n }\n field.value = normalizedValue\n continue\n }\n\n if (field instanceof HTMLSelectElement && field.multiple) {\n const selectedValues = normalizedArray ?? [normalizedValue]\n for (const option of field.options) {\n option.selected = selectedValues.includes(option.value)\n }\n continue\n }\n\n if (distributeArray && normalizedArray) {\n field.value = normalizedArray[index] ?? ''\n continue\n }\n\n field.value = normalizedValue\n }\n}\n\nexport const clearAttributes = (form: HTMLFormElement, attributes: string[]): void => {\n for (const attribute of attributes) {\n getNamedFields(form).forEach(field => field.removeAttribute(attribute))\n }\n}\n\nexport const submitForm = (form: HTMLFormElement): void => {\n if (typeof form.requestSubmit === 'function') {\n form.requestSubmit()\n return\n }\n const submitButton = form.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) as HTMLButtonElement | HTMLInputElement | null\n if (submitButton) {\n submitButton.click()\n return\n }\n form.submit()\n}\n","// api/get-value.ts\n// Returns the current value of a field, with normalization for checkboxes,\n// radios, files, and multi-value inputs.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldValue } from '../core/types'\nimport { readFieldValue } from '../core/dom'\n\nexport const createGetValue =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string): FormFieldValue => readFieldValue(helpers.getFieldsByName(name))\n","// api/observe.ts\n// Registers a callback that runs on mount and whenever the field changes.\n// Accepts one field name or a list of names. Returns an unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldsWatcher, FormFieldWatcher } from '../core/types'\n\nconst observeField = (state: FormControllerState, field: string, callback: FormFieldWatcher) => {\n const callbacks = state.watchedFields.get(field) ?? new Set<FormFieldWatcher>()\n callbacks.add(callback)\n state.watchedFields.set(field, callbacks)\n\n if (state.element) {\n callback(state.api!.getValue(field), state.api!.getField(field), state.element, state.api!.getState())\n }\n\n return () => {\n const current = state.watchedFields.get(field)\n current?.delete(callback)\n if (current && current.size === 0) {\n state.watchedFields.delete(field)\n }\n }\n}\n\nconst observeFields = (\n state: FormControllerState,\n fields: string[],\n callback: FormFieldsWatcher\n) => {\n const names = Array.from(new Set(fields))\n if (names.length === 0) return () => undefined\n const entry = { fields: names, callback }\n state.groupWatchers.add(entry)\n\n if (state.element) {\n const values = Object.fromEntries(names.map(name => [name, state.api!.getValue(name)]))\n callback(values, null, state.element, state.api!.getState())\n }\n\n return () => {\n state.groupWatchers.delete(entry)\n }\n}\n\nexport const createObserve = (state: FormControllerState, _helpers: FormControllerHelpers) => {\n function observe(field: string, callback: FormFieldWatcher): () => void\n function observe(fields: string[], callback: FormFieldsWatcher): () => void\n function observe(field: string | string[], callback: FormFieldWatcher | FormFieldsWatcher) {\n if (state.isDestroyed) return () => undefined\n return Array.isArray(field)\n ? observeFields(state, field, callback as FormFieldsWatcher)\n : observeField(state, field, callback as FormFieldWatcher)\n }\n return observe\n}\n","// api/on-submit.ts\n// Registers a submit handler. preventDefault=true intercepts valid submits,\n// which is the right choice for AJAX/fetch flows. Invalid submits are\n// always prevented regardless of the flag.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormSubmitHandler } from '../core/types'\n\nexport const createOnSubmit =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (callback: FormSubmitHandler, preventDefault = true) => {\n if (state.isDestroyed) return state.api!\n state.submitHandlers.add({ callback, preventDefault })\n return state.api!\n }\n","// api/prefill.ts\n// Reads window.location.search and writes matching values into the form.\n// Pass a field name to scope prefill to a single field. Repeated keys\n// (`?tags[]=a&tags[]=b`) are written together as one array.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createPrefill =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fieldName?: string) => {\n if (!state.element || state.isDestroyed) return state.api!\n\n const params = new URLSearchParams(window.location.search)\n const keys = Array.from(new Set(params.keys())).filter(\n key => !fieldName || fieldName === key\n )\n if (keys.length === 0) return state.api!\n\n // Every written field still runs the delegated pipeline (watchers,\n // validation, visual state); auto-submit waits for the whole batch.\n state.autoSubmitSuspended = true\n try {\n for (const key of keys) {\n const values = params.getAll(key)\n state.api!.setValue(key, values.length > 1 ? values : values[0])\n }\n } finally {\n state.autoSubmitSuspended = false\n }\n helpers.scheduleAutoSubmit()\n return state.api!\n }\n","// api/reset.ts\n// Resets the native form, clears manual and validation errors, strips\n// css-filled/css-error attributes, re-emits field watchers and notifies\n// subscribers. Native reset buttons run the same state pass.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createReset =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n () => {\n if (!state.element || state.isDestroyed) return state.api!\n\n state.isResetting = true\n try {\n state.element.reset()\n } finally {\n state.isResetting = false\n }\n helpers.applyReset()\n return state.api!\n }\n","// api/validate.ts\n// Runs validation. Marks the form as validated, syncs visual state, and\n// returns the validation result for callers that want it.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { ValidationResult } from '../core/types'\n\nexport const createValidate =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields?: string[]): ValidationResult => {\n // A destroyed controller owns no errors; never repaint the form again.\n if (state.isDestroyed) return { isValid: true, errors: {} }\n state.isValidated = true\n // validateNames synchronizes visual state for the same field set.\n return helpers.validateNames(fields)\n }\n","// api/revalidate.ts\n// Alias of validate(); kept separate for readability at call sites that\n// want to express \"re-run validation now\".\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport { createValidate } from './validate'\n\nexport const createRevalidate = createValidate\n","// api/set-errors.ts\n// Sets manual errors. Accepts an array of field names (each gets a\n// generic message) or a FormErrors map with per-field messages.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormErrors } from '../core/types'\nimport { cloneErrors } from '../core/state'\n\nexport const createSetErrors =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields: string[] | FormErrors) => {\n if (state.isDestroyed) return state.api!\n if (Array.isArray(fields)) {\n state.manualErrors = {\n ...state.manualErrors,\n ...Object.fromEntries(fields.map(field => [field, ['Invalid value.']]))\n }\n } else {\n state.manualErrors = {\n ...state.manualErrors,\n ...cloneErrors(fields)\n }\n }\n\n helpers.syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields))\n helpers.notifySubscribers()\n return state.api!\n }\n","// api/set-options.ts\n// Replaces the <option>/<optgroup> children of every <select> with the\n// given name. Labels are written as text, never as HTML. The previous\n// selection survives when its value is still listed (unless the caller\n// marks options as `selected` or passes `keepValue: false`). The change\n// pipeline (validation, watchers, subscribers, auto-submit) runs through\n// one `input` event, and only when a selected value actually changed.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { SelectOption, SelectOptionInput, SetOptionsConfig } from '../core/types'\n\nconst isGroup = (\n entry: SelectOptionInput\n): entry is Extract<SelectOptionInput, { options: unknown }> =>\n typeof entry === 'object' &&\n entry !== null &&\n Array.isArray((entry as { options?: unknown }).options)\n\nconst createOption = (entry: string | number | SelectOption): HTMLOptionElement => {\n const option = document.createElement('option')\n if (typeof entry === 'object') {\n option.value = String(entry.value)\n option.textContent = entry.label ?? String(entry.value)\n option.disabled = Boolean(entry.disabled)\n if (entry.selected) option.defaultSelected = true\n } else {\n option.value = String(entry)\n option.textContent = String(entry)\n }\n return option\n}\n\nconst buildNodes = (options: SelectOptionInput[]) => {\n const nodes: Array<HTMLOptionElement | HTMLOptGroupElement> = []\n let hasExplicitSelection = false\n const track = (option: HTMLOptionElement) => {\n if (option.defaultSelected) hasExplicitSelection = true\n return option\n }\n\n for (const entry of options) {\n if (entry === null || entry === undefined) continue\n if (isGroup(entry)) {\n const group = document.createElement('optgroup')\n group.label = entry.label\n group.disabled = Boolean(entry.disabled)\n for (const child of entry.options) {\n if (child === null || child === undefined) continue\n group.appendChild(track(createOption(child)))\n }\n nodes.push(group)\n continue\n }\n nodes.push(track(createOption(entry)))\n }\n\n return { nodes, hasExplicitSelection }\n}\n\nconst selectedValues = (select: HTMLSelectElement): string[] =>\n Array.from(select.selectedOptions, option => option.value)\n\nconst restoreSelection = (select: HTMLSelectElement, previous: string[]) => {\n if (previous.length === 0) return\n const options = Array.from(select.options)\n if (select.multiple) {\n for (const option of options) option.selected = previous.includes(option.value)\n return\n }\n const match = options.find(option => option.value === previous[0])\n if (match) match.selected = true\n}\n\nconst sameValues = (left: string[], right: string[]) =>\n left.length === right.length && left.every((value, index) => value === right[index])\n\nexport const createSetOptions =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string, options: SelectOptionInput[], config: SetOptionsConfig = {}) => {\n if (!state.element || state.isDestroyed) return state.api!\n const selects = helpers\n .getFieldsByName(name)\n .filter((field): field is HTMLSelectElement => field instanceof HTMLSelectElement)\n if (selects.length === 0) return state.api!\n\n const keepValue = config.keepValue ?? true\n const changed: HTMLSelectElement[] = []\n\n for (const select of selects) {\n const previous = selectedValues(select)\n const { nodes, hasExplicitSelection } = buildNodes(options)\n select.replaceChildren(...nodes)\n if (keepValue && !hasExplicitSelection) restoreSelection(select, previous)\n if (!sameValues(previous, selectedValues(select))) changed.push(select)\n }\n\n // The option swap is handled here; the mutation observer must not\n // process it a second time.\n helpers.commitOwnMutations(selects)\n\n changed[0]?.dispatchEvent(new Event('input', { bubbles: true }))\n return state.api!\n }\n","// api/set-value.ts\n// Writes a value into a field and dispatches the correct DOM event so\n// listeners, validators, and visual state run as if a user typed.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport { writeFieldValue } from '../core/dom'\n\nexport const createSetValue =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string, value: unknown) => {\n if (state.isDestroyed) return state.api!\n const fields = helpers.getFieldsByName(name)\n if (fields.length === 0) return state.api!\n\n writeFieldValue(fields, value)\n const firstField = fields[0]\n if (!firstField) return state.api!\n\n firstField.dispatchEvent(new Event('input', { bubbles: true }))\n return state.api!\n }\n","// api/subscribe.ts\n// Subscribes to global form state. Listener fires once immediately with\n// the current snapshot, then on every state mutation. Returns an\n// unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormStateListener } from '../core/types'\n\nexport const createSubscribe =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (listener: FormStateListener) => {\n if (state.isDestroyed) return () => undefined\n state.subscribers.add(listener)\n listener(state.api!.getState())\n return () => {\n state.subscribers.delete(listener)\n }\n }\n","// api/unwatch.ts\n// Removes watched callbacks. With no args, clears every watcher. With only\n// a field, removes all callbacks for that field. With field + callback,\n// removes just that callback. A list of fields targets watchers registered\n// with that same list (order and duplicates do not matter).\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormController, FormFieldsWatcher, FormFieldWatcher } from '../core/types'\n\nconst sameFields = (left: string[], right: Set<string>) =>\n left.length === right.size && left.every(name => right.has(name))\n\nexport const createUnwatch = (state: FormControllerState, _helpers: FormControllerHelpers) => {\n function unwatch(field?: string, callback?: FormFieldWatcher): FormController\n function unwatch(fields: string[], callback?: FormFieldsWatcher): FormController\n function unwatch(\n field?: string | string[],\n callback?: FormFieldWatcher | FormFieldsWatcher\n ): FormController {\n if (field === undefined || field === '') {\n state.watchedFields.clear()\n state.groupWatchers.clear()\n return state.api!\n }\n\n if (Array.isArray(field)) {\n const names = new Set(field)\n for (const entry of Array.from(state.groupWatchers)) {\n if (!sameFields(entry.fields, names)) continue\n if (callback && entry.callback !== callback) continue\n state.groupWatchers.delete(entry)\n }\n return state.api!\n }\n\n if (!callback) {\n state.watchedFields.delete(field)\n return state.api!\n }\n\n const callbacks = state.watchedFields.get(field)\n callbacks?.delete(callback as FormFieldWatcher)\n if (callbacks && callbacks.size === 0) {\n state.watchedFields.delete(field)\n }\n return state.api!\n }\n return unwatch\n}\n","// api/watch.ts\n// Chainable alias over `observe`. Use this when you want a fluent setup\n// without holding the returned unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormController, FormFieldsWatcher, FormFieldWatcher } from '../core/types'\nimport { createObserve } from './observe'\n\nexport const createWatch = (state: FormControllerState, helpers: FormControllerHelpers) => {\n const observe = createObserve(state, helpers)\n function watch(field: string, callback: FormFieldWatcher): FormController\n function watch(fields: string[], callback: FormFieldsWatcher): FormController\n function watch(field: string | string[], callback: FormFieldWatcher | FormFieldsWatcher) {\n if (Array.isArray(field)) observe(field, callback as FormFieldsWatcher)\n else observe(field, callback as FormFieldWatcher)\n return state.api!\n }\n return watch\n}\n","// Pure validation routines. No DOM, no controller state.\n\nimport type {\n FieldValidationContext,\n FieldValidationRules,\n FormErrors,\n FormFieldValue,\n FormValues,\n RuleConfig,\n ValueValidationRules,\n ValidationResult,\n ValidationSchema\n} from './types'\n\nconst resolveRule = <T>(rule: RuleConfig<T> | undefined) => {\n if (rule === undefined) {\n return { value: undefined as T | undefined, message: undefined as string | undefined }\n }\n if (typeof rule === 'object' && rule !== null && 'value' in rule) {\n return { value: rule.value, message: rule.message }\n }\n return { value: rule, message: undefined as string | undefined }\n}\n\nconst hasValue = (value: FormFieldValue): boolean => {\n if (Array.isArray(value)) return value.length > 0\n if (typeof value === 'string') return value.trim().length > 0\n return value !== undefined\n}\n\nconst getValueLength = (value: FormFieldValue): number => {\n if (Array.isArray(value)) return value.length\n if (typeof value === 'string') return value.length\n return 0\n}\n\nconst toPatternTarget = (value: FormFieldValue): string => {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n return value\n .map(entry => (typeof entry === 'string' ? entry : entry.name))\n .join(',')\n }\n return ''\n}\n\nconst valuesAreEqual = (left: FormFieldValue, right: FormFieldValue): boolean => {\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((entry, index) => entry === right[index])\n }\n return left === right\n}\n\nconst DECIMAL_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)$/\n\nconst parseStrictNumber = (value: FormFieldValue): number | undefined => {\n if (typeof value !== 'string') return undefined\n const candidate = value.trim()\n if (!DECIMAL_PATTERN.test(candidate)) return undefined\n const number = Number(candidate)\n return Number.isFinite(number) ? number : undefined\n}\n\nexport interface FieldValidationItem {\n value: FormFieldValue\n element?: import('./types').FormFieldElement\n}\n\nexport interface DetailedValidationResult {\n groupErrors: string[]\n itemErrors: Array<{\n index: number\n element?: import('./types').FormFieldElement\n messages: string[]\n }>\n}\n\nconst validateValue = (\n field: string,\n value: FormFieldValue,\n rules: ValueValidationRules,\n values: FormValues,\n contextOverrides: Partial<Pick<FieldValidationContext, 'element' | 'index'>> = {}\n): string[] => {\n const errors: string[] = []\n const context: FieldValidationContext = {\n field,\n value,\n values,\n ...contextOverrides\n }\n const required = resolveRule(rules.required)\n const minLength = resolveRule(rules.minLength)\n const maxLength = resolveRule(rules.maxLength)\n const pattern = resolveRule(rules.pattern)\n const numeric = resolveRule(rules.numeric)\n const min = resolveRule(rules.min)\n const max = resolveRule(rules.max)\n\n if (required.value && !hasValue(value)) {\n errors.push(required.message ?? 'This field is required.')\n }\n if (minLength.value !== undefined && getValueLength(value) < minLength.value) {\n errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`)\n }\n if (maxLength.value !== undefined && getValueLength(value) > maxLength.value) {\n errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`)\n }\n if (pattern.value && hasValue(value)) {\n pattern.value.lastIndex = 0\n const matches = pattern.value.test(toPatternTarget(value))\n pattern.value.lastIndex = 0\n if (!matches) {\n errors.push(pattern.message ?? 'Value does not match the required pattern.')\n }\n }\n\n if (hasValue(value) && (numeric.value || min.value !== undefined || max.value !== undefined)) {\n const number = parseStrictNumber(value)\n if (number === undefined) {\n errors.push(numeric.message ?? 'Value must be a number.')\n } else {\n if (min.value !== undefined && number < min.value) {\n errors.push(min.message ?? `Minimum value is ${min.value}.`)\n }\n if (max.value !== undefined && number > max.value) {\n errors.push(max.message ?? `Maximum value is ${max.value}.`)\n }\n }\n }\n\n const custom = rules.validate\n ? Array.isArray(rules.validate)\n ? rules.validate\n : [rules.validate]\n : []\n\n for (const validator of custom) {\n const result = validator(context)\n if (typeof result === 'string' && result.length > 0) errors.push(result)\n if (result === false) errors.push('Validation failed.')\n }\n\n return errors\n}\n\nexport const validateFieldValueDetailed = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues,\n items?: FieldValidationItem[]\n): DetailedValidationResult => {\n const groupErrors = validateValue(field, value, rules, values)\n const sameAs = resolveRule(rules.sameAs)\n\n if (sameAs.value !== undefined) {\n const otherValue = values[sameAs.value]\n if (hasValue(value) && hasValue(otherValue) && !valuesAreEqual(value, otherValue)) {\n groupErrors.push(sameAs.message ?? `Value must match ${sameAs.value}.`)\n }\n }\n\n const itemErrors: DetailedValidationResult['itemErrors'] = []\n if (rules.each) {\n const sourceItems: FieldValidationItem[] =\n items ??\n (Array.isArray(value)\n ? value.map(entry => ({\n value: typeof entry === 'string' ? entry : ([entry] as File[])\n }))\n : [{ value }])\n\n sourceItems.forEach((item, index) => {\n const overrides: Partial<Pick<FieldValidationContext, 'element' | 'index'>> = {\n index\n }\n if (item.element) overrides.element = item.element\n const messages = validateValue(field, item.value, rules.each!, values, overrides)\n if (messages.length === 0) return\n const error: DetailedValidationResult['itemErrors'][number] = {\n index,\n messages\n }\n if (item.element) error.element = item.element\n itemErrors.push(error)\n })\n }\n\n return { groupErrors, itemErrors }\n}\n\nexport const validateFieldValue = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues\n): string[] => {\n const result = validateFieldValueDetailed(field, value, rules, values)\n return [...result.groupErrors, ...result.itemErrors.flatMap(item => item.messages)]\n}\n\nexport const validateValues = (\n values: FormValues,\n schema: ValidationSchema\n): ValidationResult => {\n const errors: FormErrors = {}\n for (const [field, rules] of Object.entries(schema)) {\n const messages = validateFieldValue(field, values[field], rules, values)\n if (messages.length > 0) errors[field] = messages\n }\n return {\n isValid: Object.keys(errors).length === 0,\n errors\n }\n}\n","// Core orchestrator. Wires shared state, internal helpers and the public\n// api method factories into a single FormController instance.\n//\n// Internal event handlers and DOM wiring live here. Every public method\n// lives in `../api/<method>.ts` as an isolated factory.\n\nimport { createAppend } from '../api/append'\nimport { createAddCleanup } from '../api/add-cleanup'\nimport { createAutoSubmit } from '../api/auto-submit'\nimport { createClearErrors } from '../api/clear-errors'\nimport { createDestroy } from '../api/destroy'\nimport { createDisableAutoSubmit } from '../api/disable-auto-submit'\nimport {\n createFormat,\n createFormatAll,\n resolveCanonicalForName,\n resolveDisplayNameForName,\n resetFormattedFields\n} from '../api/format'\nimport { createGetData } from '../api/get-data'\nimport { createGetField } from '../api/get-field'\nimport { createGetState } from '../api/get-state'\nimport { createGetValue } from '../api/get-value'\nimport { createObserve } from '../api/observe'\nimport { createOnSubmit } from '../api/on-submit'\nimport { createPrefill } from '../api/prefill'\nimport { createReset } from '../api/reset'\nimport { createRevalidate } from '../api/revalidate'\nimport { createSetErrors } from '../api/set-errors'\nimport { createSetOptions } from '../api/set-options'\nimport { createSetValue } from '../api/set-value'\nimport { createSubscribe } from '../api/subscribe'\nimport { createUnwatch } from '../api/unwatch'\nimport { createValidate } from '../api/validate'\nimport { createWatch } from '../api/watch'\nimport { validateFieldValueDetailed } from '../core/validation'\nimport { parseFormData } from './serialize'\nimport {\n applyBooleanAttribute,\n clearAttributes,\n getNamedFields,\n isFieldElement,\n isFieldFilled,\n queryNamedFields,\n readFieldValue,\n resolveFormElement,\n submitForm,\n writeFieldValue\n} from './dom'\nimport { cloneErrors, mergeErrors } from './state'\nimport type {\n FormController,\n FormControllerOptions,\n FormFieldElement,\n FormFieldValue,\n FormTarget,\n ValidationResult,\n VisualAttributes\n} from './types'\nimport type { FormControllerHelpers, FormControllerState } from './state'\n\nconst DEFAULT_ATTRIBUTES: Required<VisualAttributes> = {\n filled: 'css-filled',\n error: 'css-error'\n}\n\nconst DEFAULT_OPTIONS = {\n autoValidate: true,\n clearErrorsOnSubmit: true,\n clearManualErrorsOnChange: true\n} satisfies Pick<\n FormControllerOptions,\n 'autoValidate' | 'clearErrorsOnSubmit' | 'clearManualErrorsOnChange'\n>\n\nexport const createFormController = (\n target: FormTarget,\n options: FormControllerOptions = {}\n): FormController => {\n const element = resolveFormElement(target)\n const attributes = { ...DEFAULT_ATTRIBUTES, ...options.attributes }\n const normalizedOptions: FormControllerOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n attributes\n }\n\n const state: FormControllerState = {\n element,\n options: normalizedOptions,\n attributes,\n validators: normalizedOptions.validators ?? {},\n watchedFields: new Map(),\n groupWatchers: new Set(),\n subscribers: new Set(),\n submitHandlers: new Set(),\n fieldCache: new Map(),\n manualErrors: {},\n validationErrors: {},\n validationGroupErrors: {},\n validationElementErrors: new Map(),\n isValidated: Boolean(normalizedOptions.autoValidate),\n autoSubmitEnabled: false,\n autoSubmitDebounce: 0,\n submitCount: 0,\n pendingSubmitCount: 0,\n autoSubmitTimer: null,\n isAutoSubmitting: false,\n autoSubmitSuspended: false,\n isResetting: false,\n isDestroyed: false,\n listeners: [],\n mutationObserver: null,\n cleanups: new Set(),\n formattedFields: new Map(),\n api: null\n }\n\n // Reverse cross-field references once so source changes can revalidate\n // dependent fields without installing per-field listeners.\n const validationDependents = new Map<string, Set<string>>()\n for (const [field, rules] of Object.entries(state.validators)) {\n const sources = new Set<string>()\n const sameAs = rules.sameAs\n if (sameAs !== undefined) {\n sources.add(typeof sameAs === 'string' ? sameAs : sameAs.value)\n }\n if (typeof rules.dependsOn === 'string') sources.add(rules.dependsOn)\n else rules.dependsOn?.forEach(source => sources.add(source))\n\n for (const source of sources) {\n const dependents = validationDependents.get(source) ?? new Set<string>()\n dependents.add(field)\n validationDependents.set(source, dependents)\n }\n }\n\n // ------- Internal helpers (no DOM wiring of their own) -----------------\n\n const notifySubscribers = () => {\n if (!state.api) return\n const snapshot = state.api.getState()\n state.subscribers.forEach(listener => listener(snapshot))\n }\n\n const addListener = (\n node: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject,\n capture?: boolean\n ) => {\n if (capture) {\n node.addEventListener(type, handler, { capture: true })\n } else {\n node.addEventListener(type, handler)\n }\n // `exactOptionalPropertyTypes: true` rejects explicit `undefined`\n // values for optional properties; only attach `capture` when it\n // actually has a value.\n const entry: {\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n capture?: boolean\n } = { element: node, type, handler }\n if (capture !== undefined) entry.capture = capture\n state.listeners.push(entry)\n }\n\n const clearFieldCache = () => state.fieldCache.clear()\n\n const getFieldsByName = (name: string): FormFieldElement[] => {\n if (!state.element) return []\n const fields = queryNamedFields(state.element, name)\n state.fieldCache.set(name, fields)\n return fields\n }\n\n // Group every named control in one pass over `form.elements`. Reading\n // all values field-by-field would rescan the collection once per name.\n const indexFieldsByName = (): Map<string, FormFieldElement[]> => {\n const index = new Map<string, FormFieldElement[]>()\n if (!state.element) return index\n for (const field of getNamedFields(state.element)) {\n const bucket = index.get(field.name)\n if (bucket) bucket.push(field)\n else index.set(field.name, [field])\n }\n return index\n }\n\n const getTrackedFieldNames = (index = indexFieldsByName()): string[] => {\n if (!state.element) return Object.keys(state.validators)\n const names = new Set<string>(Object.keys(state.validators))\n for (const name of index.keys()) names.add(name)\n // The formatted registry keeps the canonical name as the bucket\n // key. The display name (e.g. `phone_displayed`) is also a\n // tracked field because the developer can `watch`/`getValue` it\n // and `getData()` exposes it in the serialized payload.\n for (const [canonical, entry] of state.formattedFields) {\n names.add(canonical)\n if (entry.displayName && entry.displayName !== canonical) {\n names.add(entry.displayName)\n }\n }\n return Array.from(names)\n }\n\n const getValues = () => {\n const values: Record<string, FormFieldValue> = {}\n const index = indexFieldsByName()\n for (const name of getTrackedFieldNames(index)) {\n values[name] = readFieldValue(index.get(name) ?? [])\n }\n return values\n }\n\n const getMergedErrors = () => mergeErrors(state.validationErrors, state.manualErrors)\n\n const syncVisualState = (names?: string[]) => {\n if (!state.element) return\n\n // Resolve every input name to its display name so visual\n // attributes (`css-filled`, `css-error`) land on the visible\n // input, never on the hidden raw mirror. After `format()` runs\n // the canonical name (`phone`) is held by the hidden, which\n // lives at the end of the form, outside any label wrapper —\n // so writing the attribute there is invisible to the project\n // CSS that targets `:has([css-error])` on a parent label. The\n // visual attribute contract is documented in\n // `api/format.ts:resolveDisplayNameForName` and in\n // `docs/css-styling.md`.\n //\n // Errors are still keyed by canonical name (the backend's\n // view of the field); reverse-resolve so the lookup works\n // whether the caller passed canonical, display, or both.\n const sourceNames = names ?? getTrackedFieldNames()\n for (const name of sourceNames) {\n const displayName = resolveDisplayNameForName(state, name)\n const canonical = resolveCanonicalForName(state, name) ?? name\n const fields = getFieldsByName(displayName)\n const hasGroupError = Boolean(\n state.validationGroupErrors[canonical]?.length || state.manualErrors[canonical]?.length\n )\n const elementErrors = state.validationElementErrors.get(canonical)\n fields.forEach(field => {\n const hasError = hasGroupError || Boolean(elementErrors?.get(field)?.length)\n applyBooleanAttribute(field, attributes.filled, isFieldFilled(field))\n applyBooleanAttribute(field, attributes.error, hasError)\n if (hasError) field.setAttribute('aria-invalid', 'true')\n else field.removeAttribute('aria-invalid')\n })\n }\n }\n\n // readFieldValue/writeFieldValue are exported from core/dom for direct\n // callers; referenced here so the linter keeps them as part of the\n // controlled API surface.\n void readFieldValue\n void writeFieldValue\n\n const validateNames = (names?: string[]): ValidationResult => {\n const targetNames = names ?? Object.keys(state.validators)\n const values = getValues()\n const nextValidationErrors = names ? cloneErrors(state.validationErrors) : {}\n const nextGroupErrors = names ? cloneErrors(state.validationGroupErrors) : {}\n const nextElementErrors = names\n ? new Map(state.validationElementErrors)\n : new Map<string, Map<FormFieldElement, string[]>>()\n\n for (const name of targetNames) {\n const rules = state.validators[name]\n if (!rules) {\n delete nextValidationErrors[name]\n delete nextGroupErrors[name]\n nextElementErrors.delete(name)\n continue\n }\n const fields = getFieldsByName(name)\n const displayFields = getFieldsByName(resolveDisplayNameForName(state, name))\n const items = fields.map((field, index) => ({\n value: readFieldValue([field]),\n element: displayFields[index] ?? field\n }))\n const result = validateFieldValueDetailed(name, values[name], rules, values, items)\n const messages = [...result.groupErrors, ...result.itemErrors.flatMap(item => item.messages)]\n if (messages.length > 0) nextValidationErrors[name] = messages\n else delete nextValidationErrors[name]\n\n if (result.groupErrors.length > 0) nextGroupErrors[name] = result.groupErrors\n else delete nextGroupErrors[name]\n\n const perElement = new Map<FormFieldElement, string[]>()\n result.itemErrors.forEach(item => {\n if (item.element) perElement.set(item.element, item.messages)\n })\n if (perElement.size > 0) nextElementErrors.set(name, perElement)\n else nextElementErrors.delete(name)\n }\n\n state.validationErrors = nextValidationErrors\n state.validationGroupErrors = nextGroupErrors\n state.validationElementErrors = nextElementErrors\n syncVisualState(names)\n\n return {\n isValid: Object.keys(getMergedErrors()).length === 0,\n errors: cloneErrors(getMergedErrors())\n }\n }\n\n const getAffectedValidationNames = (name: string): string[] => {\n const affected: string[] = []\n const pending = [name]\n const visited = new Set<string>()\n\n for (let index = 0; index < pending.length; index += 1) {\n const current = pending[index]!\n if (visited.has(current)) continue\n visited.add(current)\n affected.push(current)\n\n for (const dependent of validationDependents.get(current) ?? []) {\n if (!visited.has(dependent)) pending.push(dependent)\n }\n }\n\n return affected\n }\n\n const emitSingleWatchers = (name: string) => {\n if (!state.element || !state.api) return\n const callbacks = state.watchedFields.get(name)\n if (!callbacks || callbacks.size === 0) return\n const value = state.api.getValue(name)\n const fieldElement = state.api.getField(name)\n const snapshot = state.api.getState()\n callbacks.forEach(callback => callback(value, fieldElement, state.element!, snapshot))\n }\n\n // Calls every multi-field watcher that lists one of `names`, once, with\n // the first matching name as `changed`. `null` calls every one of them\n // with `changed: null` (reset).\n const emitGroupWatchers = (names: string[] | null) => {\n if (!state.element || !state.api || state.groupWatchers.size === 0) return\n let snapshot: ReturnType<FormController['getState']> | undefined\n for (const entry of Array.from(state.groupWatchers)) {\n const changed = names ? names.find(name => entry.fields.includes(name)) : null\n if (changed === undefined) continue\n snapshot ??= state.api.getState()\n const values = Object.fromEntries(\n entry.fields.map(field => [field, state.api!.getValue(field)])\n )\n entry.callback(values, changed, state.element, snapshot)\n }\n }\n\n const emitFieldWatchers = (name: string) => {\n emitSingleWatchers(name)\n emitGroupWatchers([name])\n }\n\n // `requestSubmit()` dispatches `submit` synchronously, so the flag tells\n // the submit handler that no user asked to submit. An invalid automatic\n // submission must not move focus away from the field being edited.\n const runAutoSubmit = () => {\n state.autoSubmitTimer = null\n if (!state.element || state.isDestroyed || !state.autoSubmitEnabled) return\n state.isAutoSubmitting = true\n try {\n submitForm(state.element)\n } finally {\n state.isAutoSubmitting = false\n }\n }\n\n const scheduleAutoSubmit = () => {\n if (!state.element || !state.autoSubmitEnabled || state.autoSubmitSuspended) return\n if (state.autoSubmitTimer) clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n if (state.autoSubmitDebounce > 0) {\n state.autoSubmitTimer = setTimeout(runAutoSubmit, state.autoSubmitDebounce)\n return\n }\n runAutoSubmit()\n }\n\n // Last selection seen for every <select>, so option-list mutations made\n // outside the controller fire watchers only when the selection changed.\n const selectSnapshots = new WeakMap<HTMLSelectElement, string>()\n\n const readSelectSnapshot = (select: HTMLSelectElement) =>\n Array.from(select.selectedOptions, option => option.value).join('\\u0000')\n\n const snapshotSelect = (select: HTMLSelectElement) => {\n selectSnapshots.set(select, readSelectSnapshot(select))\n }\n\n const snapshotAllSelects = () => {\n if (!state.element) return\n for (const field of getNamedFields(state.element)) {\n if (field instanceof HTMLSelectElement) snapshotSelect(field)\n }\n }\n\n const emitAllFieldWatchers = () => {\n for (const name of Array.from(state.watchedFields.keys())) emitSingleWatchers(name)\n emitGroupWatchers(null)\n }\n\n // Shared by `reset()` and native reset buttons: values are already back\n // to their defaults, so clear every error and resynchronize the DOM.\n const applyReset = () => {\n if (!state.element || state.isDestroyed) return\n clearFieldCache()\n resetFormattedFields(state)\n state.manualErrors = {}\n state.validationErrors = {}\n state.validationGroupErrors = {}\n state.validationElementErrors.clear()\n clearAttributes(state.element, [attributes.error, attributes.filled, 'aria-invalid'])\n syncVisualState()\n snapshotAllSelects()\n emitAllFieldWatchers()\n notifySubscribers()\n }\n\n const helpers: FormControllerHelpers = {\n notifySubscribers,\n clearFieldCache,\n getFieldsByName,\n getTrackedFieldNames: () => getTrackedFieldNames(),\n getValues,\n getMergedErrors,\n syncVisualState,\n validateNames,\n emitFieldWatchers,\n scheduleAutoSubmit,\n applyReset,\n commitOwnMutations: selects => commitOwnMutations(selects)\n }\n\n // ------- DOM event wiring ---------------------------------------------\n\n const handleDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) return\n const name = target.name\n if (!name) return\n\n clearFieldCache()\n if (target instanceof HTMLSelectElement) snapshotSelect(target)\n\n // A formatted field is exposed under two names: the canonical\n // (e.g. `phone`, on the hidden raw mirror) and the display\n // (`phone_displayed`, on the visible). Resolve whichever side\n // fired this event to the canonical so the controller's\n // validation + error-clearing path runs once on the field the\n // backend actually reads. The display name is the visible's\n // name — `syncVisualState` targets it so visual attributes\n // (`css-filled`, `css-error`) land on the element the user\n // sees, not on the hidden. Project CSS commonly uses\n // `:has([css-filled])` on a parent label to animate the\n // label; that selector only matches when the visible (inside\n // the label) carries the attribute, never the hidden.\n const canonical = resolveCanonicalForName(state, name) ?? name\n const displayName = resolveDisplayNameForName(state, name)\n\n if (normalizedOptions.clearManualErrorsOnChange) {\n delete state.manualErrors[canonical]\n }\n\n syncVisualState([displayName])\n\n const affectedValidationNames = getAffectedValidationNames(canonical)\n if (\n state.isValidated &&\n affectedValidationNames.some(field => state.validators[field] !== undefined)\n ) {\n validateNames(affectedValidationNames)\n }\n\n emitSingleWatchers(canonical)\n if (canonical !== name) emitSingleWatchers(name)\n emitGroupWatchers(canonical !== name ? [canonical, name] : [canonical])\n notifySubscribers()\n scheduleAutoSubmit()\n }\n\n const handleExternalDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) return\n if (target.form !== state.element || state.element?.contains(target)) return\n handleDelegatedEvent(event)\n }\n\n const isFocusable = (candidate: FormFieldElement) => {\n if (!candidate.isConnected || candidate.disabled || candidate.hidden) return false\n return !(candidate instanceof HTMLInputElement && candidate.type === 'hidden')\n }\n\n // Focus the invalid control that comes first in the document, not the\n // first rule declared in the schema, so keyboard users land where the\n // form visually starts failing.\n const focusFirstInvalidField = (errors: Record<string, string[]>) => {\n const candidates: FormFieldElement[] = []\n for (const name of Object.keys(errors)) {\n const fields = getFieldsByName(resolveDisplayNameForName(state, name)).filter(isFocusable)\n const elementErrors = state.validationElementErrors.get(name)\n const field = fields.find(candidate => elementErrors?.has(candidate)) ?? fields[0]\n if (field) candidates.push(field)\n }\n candidates.sort((left, right) =>\n left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1\n )\n candidates[0]?.focus()\n }\n\n const handleSubmitEvent = (event: Event) => {\n if (!state.element || state.isDestroyed || !state.api) return\n\n if (normalizedOptions.clearErrorsOnSubmit) state.manualErrors = {}\n\n const validation = state.api.validate()\n const handlers = Array.from(state.submitHandlers)\n const shouldPrevent = validation.isValid\n ? handlers.some(handler => handler.preventDefault)\n : true\n\n if (shouldPrevent) event.preventDefault()\n\n state.submitCount += 1\n notifySubscribers()\n\n if (!validation.isValid) {\n if (!state.isAutoSubmitting) focusFirstInvalidField(validation.errors)\n return\n }\n\n const candidate = event as Event & { submitter?: unknown }\n const submitter = candidate.submitter instanceof HTMLElement\n ? candidate.submitter\n : null\n const { data, formData } = parseFormData(state.element, submitter)\n const snapshot = state.api.getState()\n const pending: Promise<void>[] = []\n let synchronousError: unknown\n let hasSynchronousError = false\n try {\n for (const handler of handlers) {\n const result = handler.callback(state.element!, data, formData, snapshot)\n if (result && typeof result.then === 'function') {\n pending.push(\n Promise.resolve(result).catch(error => {\n console.error('[forms] submit handler failed', error)\n })\n )\n }\n }\n } catch (error) {\n synchronousError = error\n hasSynchronousError = true\n }\n\n if (pending.length > 0) {\n state.pendingSubmitCount += 1\n notifySubscribers()\n void Promise.allSettled(pending).then(() => {\n state.pendingSubmitCount = Math.max(0, state.pendingSubmitCount - 1)\n if (!state.isDestroyed) notifySubscribers()\n })\n }\n\n if (hasSynchronousError) throw synchronousError\n }\n\n // The `reset` event fires before the browser restores default values,\n // and a user-initiated reset runs microtasks between the two steps, so\n // the state pass waits for the next task. `reset()` handles itself.\n const handleResetEvent = (event: Event) => {\n if (state.isResetting) return\n const timer = setTimeout(() => {\n state.cleanups.delete(cancel)\n if (!event.defaultPrevented) applyReset()\n }, 0)\n const cancel = () => clearTimeout(timer)\n state.cleanups.add(cancel)\n }\n\n const touchesFields = (node: Node) =>\n node instanceof Element &&\n (isFieldElement(node) || node.querySelector('input, select, textarea') !== null)\n\n // Error messages or other markup rendered into the form by a subscriber\n // must not re-enter validation; that would notify the same subscriber\n // again and loop. Only control additions/removals and renames count.\n const isStructural = (record: MutationRecord) =>\n record.type === 'attributes' ||\n Array.from(record.addedNodes).some(touchesFields) ||\n Array.from(record.removedNodes).some(touchesFields)\n\n const isOptionNode = (node: Node) =>\n node instanceof HTMLOptionElement || node instanceof HTMLOptGroupElement\n\n // The <select> whose option list a childList record changed, if any.\n const optionListOwner = (record: MutationRecord): HTMLSelectElement | null => {\n if (record.type !== 'childList') return null\n const touchesOptions =\n Array.from(record.addedNodes).some(isOptionNode) ||\n Array.from(record.removedNodes).some(isOptionNode)\n if (!touchesOptions) return null\n const target = record.target\n if (target instanceof HTMLSelectElement) return target\n if (\n target instanceof HTMLOptGroupElement &&\n target.parentElement instanceof HTMLSelectElement\n ) {\n return target.parentElement\n }\n return null\n }\n\n const handleMutations = (records: MutationRecord[]) => {\n if (state.isDestroyed) return\n const structural = records.some(isStructural)\n const changedNames = new Set<string>()\n\n for (const record of records) {\n const select = optionListOwner(record)\n if (!select || !select.name) continue\n const next = readSelectSnapshot(select)\n if (selectSnapshots.get(select) !== next) changedNames.add(select.name)\n selectSnapshots.set(select, next)\n }\n\n if (!structural && changedNames.size === 0) return\n clearFieldCache()\n\n if (structural) {\n snapshotAllSelects()\n if (state.isValidated) validateNames()\n else syncVisualState()\n } else {\n const affected = new Set<string>()\n for (const name of changedNames) {\n for (const field of getAffectedValidationNames(name)) affected.add(field)\n }\n const names = Array.from(affected)\n syncVisualState(Array.from(changedNames))\n if (state.isValidated && names.some(field => state.validators[field] !== undefined)) {\n validateNames(names)\n }\n }\n\n for (const name of changedNames) emitFieldWatchers(name)\n notifySubscribers()\n }\n\n // Called by api methods that rewrite option lists themselves: drop the\n // records those writes produced, keep processing everything else.\n const commitOwnMutations = (selects: HTMLSelectElement[]) => {\n selects.forEach(snapshotSelect)\n const pending = state.mutationObserver?.takeRecords() ?? []\n const foreign = pending.filter(\n record => !selects.some(select => select.contains(record.target))\n )\n if (foreign.length > 0) handleMutations(foreign)\n }\n\n const startMutationObserver = () => {\n if (!state.element || typeof MutationObserver === 'undefined') return\n\n state.mutationObserver = new MutationObserver(handleMutations)\n\n state.mutationObserver.observe(state.element, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['name', 'type']\n })\n }\n\n // ------- Public api composition --------------------------------------\n\n const api: FormController = {\n get element() {\n return state.element\n },\n get f() {\n return state.element\n },\n get options() {\n return state.options\n },\n onSubmit: createOnSubmit(state, helpers),\n addCleanup: createAddCleanup(state, helpers),\n watch: createWatch(state, helpers),\n observe: createObserve(state, helpers),\n unwatch: createUnwatch(state, helpers),\n subscribe: createSubscribe(state, helpers),\n prefill: createPrefill(state, helpers),\n append: createAppend(state, helpers),\n setErrors: createSetErrors(state, helpers),\n clearErrors: createClearErrors(state, helpers),\n setValue: createSetValue(state, helpers),\n setOptions: createSetOptions(state, helpers),\n getValue: createGetValue(state, helpers),\n getField: createGetField(state, helpers),\n validate: createValidate(state, helpers),\n revalidate: createRevalidate(state, helpers),\n reset: createReset(state, helpers),\n autoSubmit: createAutoSubmit(state, helpers),\n disableAutoSubmit: createDisableAutoSubmit(state, helpers),\n getData: createGetData(state, helpers),\n getState: createGetState(state, helpers),\n format: createFormat(state, helpers),\n formatAll: createFormatAll(state, helpers),\n destroy: createDestroy(state, helpers)\n }\n\n state.api = api\n\n // ------- Lifecycle hooks ---------------------------------------------\n\n if (state.element) {\n addListener(state.element, 'input', handleDelegatedEvent)\n addListener(document, 'input', handleExternalDelegatedEvent)\n addListener(state.element, 'submit', handleSubmitEvent)\n addListener(state.element, 'reset', handleResetEvent)\n snapshotAllSelects()\n startMutationObserver()\n }\n\n if (normalizedOptions.autoSubmit) {\n api.autoSubmit(normalizedOptions.autoSubmit)\n }\n\n if (normalizedOptions.formats) {\n for (const config of Object.values(normalizedOptions.formats)) {\n api.format(config)\n }\n }\n\n if (state.isValidated) validateNames()\n else syncVisualState()\n\n return api\n}\n","// api/form.ts\n// Public entry point: the `form(target, options)` factory.\n// Thin wrapper around the core orchestrator for ergonomic imports.\n\nimport { createFormController } from '../core/controller'\nimport type { FormControllerOptions, FormTarget } from '../core/types'\n\nexport const form = (\n target: FormTarget,\n options: FormControllerOptions = {}\n) => createFormController(target, options)\n","// Vanilla mirror of the browser IIFE registry helpers.\n// Module-level singleton: the same shape as `window.Forms`, but\n// importable from any bundler. Consumers can spread it into their own\n// globals (`{ ...browser, regex }`) or use it directly.\n//\n// The IIFE bundle (`./global.ts`) consumes this same object — single\n// source of truth for the registry helpers.\n\nimport { form } from '../api/form'\nimport type {\n FormController,\n FormControllerOptions,\n FormTarget\n} from '../core/types'\n\nexport interface NewFormInput {\n id: string\n options?: FormControllerOptions\n}\n\nexport interface FormsAvailable {\n [id: string]: FormController\n}\n\nexport interface FormsApi {\n form: (\n target: FormTarget,\n options?: FormControllerOptions\n ) => FormController\n newForm: (input: NewFormInput) => FormController | undefined\n destroyForm: (id: string) => void\n available: FormsAvailable\n}\n\nconst available: FormsAvailable = {}\n\nconst newForm = (input: NewFormInput): FormController | undefined => {\n const { id, options } = input\n if (!id) {\n console.error('Form ID is required')\n return\n }\n available[id]?.destroy()\n const controller = form(id, { ...options })\n available[id] = controller\n return controller\n}\n\nconst destroyForm = (id: string): void => {\n if (!id) {\n console.error('Form ID is required')\n return\n }\n const controller = available[id]\n if (controller) {\n controller.destroy()\n delete available[id]\n } else {\n console.warn(`Form with ID ${id} not found`)\n }\n}\n\nexport const browser: FormsApi = {\n form,\n newForm,\n destroyForm,\n available\n}\n","// Browser entrypoint. Exposes a minimal surface as a single global\n// accessible via `window.Forms` (or `globalThis.Forms`).\n//\n// Public shape:\n// - Forms.form(target, options)\n// - Forms.newForm({ id, options })\n// - Forms.destroyForm(id)\n// - Forms.available (registry keyed by form id)\n//\n// The IIFE bundle consumes the same `browser` singleton as the vanilla\n// entrypoint — single source of truth for the registry helpers.\n\nimport { browser } from './registry'\nimport type { FormsApi } from './registry'\n\nconst Forms: FormsApi = browser\n\nexport const form = Forms.form\nexport const newForm = Forms.newForm\nexport const destroyForm = Forms.destroyForm\nexport const available = Forms.available\n\ndeclare global {\n interface Window {\n Forms: FormsApi\n }\n}\n\nif (typeof globalThis !== 'undefined') {\n ;(globalThis as typeof globalThis & { Forms: FormsApi }).Forms = Forms\n}\n\nexport default Forms\n"],"mappings":"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","names":["available","destroyForm","form","newForm","state","state","state","state","form","newCaret","state","registry","state","state","state","state","form","selectedValues","state","state","state","state","state","state","state","state","state","state","state","state","state","addListener","target","form","newForm","destroyForm","available"]}
1
+ {"version":3,"sources":["../../src/browser/index.ts","../../src/api/append.ts","../../src/api/add-cleanup.ts","../../src/api/auto-submit.ts","../../src/api/clear-errors.ts","../../src/core/format-helpers.ts","../../src/core/formatter-loader.ts","../../src/api/format.ts","../../src/api/destroy.ts","../../src/api/disable-auto-submit.ts","../../src/core/serialize.ts","../../src/api/get-data.ts","../../src/api/get-field.ts","../../src/core/state.ts","../../src/api/get-state.ts","../../src/core/dom.ts","../../src/api/get-value.ts","../../src/api/observe.ts","../../src/api/on-submit.ts","../../src/api/prefill.ts","../../src/api/reset.ts","../../src/api/validate.ts","../../src/api/revalidate.ts","../../src/api/set-errors.ts","../../src/api/set-options.ts","../../src/api/set-value.ts","../../src/api/subscribe.ts","../../src/api/unwatch.ts","../../src/api/watch.ts","../../src/core/validation.ts","../../src/core/controller.ts","../../src/api/form.ts","../../src/browser/registry.ts","../../src/browser/global.ts"],"sourcesContent":["export {\n available,\n default,\n destroyForm,\n form,\n newForm\n} from './global'\nexport type { FormsApi, FormsAvailable, NewFormInput } from './registry'\n","// api/append.ts\n// Appends DOM content to the bound form. If a class is provided, removes\n// any existing node with that class first to avoid duplicates.\n// Returns the created node or null when no element is bound.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { AppendContentOptions } from '../core/types'\n\nexport const createAppend =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n ({ tag, content, class: className, atStart = false }: AppendContentOptions) => {\n if (!state.element || state.isDestroyed) return null\n\n helpers.clearFieldCache()\n\n if (className) {\n const classSelector = className.trim().split(/\\s+/)[0]\n const existing = classSelector\n ? state.element.getElementsByClassName(classSelector)[0]\n : null\n existing?.remove()\n }\n\n const node = document.createElement(tag)\n if (className) node.className = className\n node.innerHTML = content\n\n if (atStart && state.element.firstChild) {\n state.element.insertBefore(node, state.element.firstChild)\n } else {\n state.element.appendChild(node)\n }\n\n return node\n }\n","// api/add-cleanup.ts\n// Registers controller-owned teardown work and returns an unregister function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormCleanup } from '../core/types'\n\nexport const createAddCleanup =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (cleanup: FormCleanup): (() => void) => {\n if (state.isDestroyed) {\n cleanup()\n return () => undefined\n }\n\n const registration = () => cleanup()\n state.cleanups.add(registration)\n let active = true\n return () => {\n if (!active) return\n active = false\n state.cleanups.delete(registration)\n }\n }\n","// api/auto-submit.ts\n// Enables native auto-submit. Pass `true` to enable, `false` to disable,\n// or an { debounce } object to delay.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createAutoSubmit =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (next: boolean | { debounce?: number } = true) => {\n if (state.isDestroyed) return state.api!\n state.autoSubmitEnabled = next !== false\n if (!state.autoSubmitEnabled && state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n state.autoSubmitDebounce =\n typeof next === 'object' && next ? next.debounce ?? 0 : 0\n helpers.notifySubscribers()\n return state.api!\n }\n","// api/clear-errors.ts\n// Clears manual errors. With no args, clears every manual error. With a\n// list, clears only those fields.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createClearErrors =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields?: string[]) => {\n if (state.isDestroyed) return state.api!\n if (!fields) {\n state.manualErrors = {}\n helpers.syncVisualState()\n helpers.notifySubscribers()\n return state.api!\n }\n\n for (const field of fields) {\n delete state.manualErrors[field]\n }\n helpers.syncVisualState(fields)\n helpers.notifySubscribers()\n return state.api!\n }\n","// Low-level helpers used by `api/format.ts`:\n// - DOM cursor tracking equivalent to cleave.js' `getNextCursorPosition`\n// (so typing/backspacing inside formatted inputs keeps the caret\n// in a sensible place, even when delimiters are inserted or removed).\n// - `postDelimiterBackspace` contract: after a deletion, the caret\n// is pulled backwards past any leading delimiter so the user never\n// ends up parked with a format character on the caret's left.\n// - Hidden-mirror lookup & creation: each formatted input gets a\n// hidden sibling (`type=\"hidden\"`) that holds the backend-ready\n// `raw` value under the **canonical** field name (the one the\n// developer wrote in the HTML and the one the backend reads).\n// The visible input is renamed to `<field>_displayed` on the\n// first `format()` call. Both names are first-class in the\n// controller's API — see `docs/api/format.md` for the contract.\n//\n// The helpers here are pure DOM utilities — they do not know about the\n// controller state.\n\nimport type { FormFieldElement } from './types'\n\n/**\n * Marks a hidden input as the raw mirror of a formatted field.\n * Presence of this attribute is how `format()` distinguishes\n * mirrors it owns (created at `format()` time) from mirrors the\n * developer pre-authored in the HTML (which survive `destroy()`).\n */\nexport const FORMATTER_RAW_ATTRIBUTE = 'data-formatter-raw-for'\n\n// Resolve a field by name. Returns the first matching element or `null`.\nexport const getFormatterField = (\n form: HTMLFormElement,\n name: string\n): HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null => {\n const selector = `[name=\"${cssEscape(name)}\"]`\n const node = form.querySelector(selector)\n if (\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement\n ) {\n return node\n }\n return null\n}\n\n// Minimal CSS.escape polyfill for selectors that may contain special\n// characters (`[1].phone`, `email[primary]`, etc.).\nconst cssEscape = (value: string): string => {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value)\n }\n return value.replace(/([!\"#$%&'()*+,./:;<=>?@\\[\\\\\\]^`{|}~])/g, '\\\\$1')\n}\n\n// Find the visible (non-hidden) input that owns the formatted pair for\n// `fieldName`. Looks up by the display name (defaults to\n// `<fieldName>_displayed`, or whatever the developer passed in\n// `FieldFormatConfig.displayField`). Returns `null` when no visible\n// field matches.\nexport const findVisibleField = (\n form: HTMLFormElement,\n displayName: string\n): HTMLInputElement | HTMLTextAreaElement | null => {\n const node = form.querySelector(\n `[name=\"${cssEscape(displayName)}\"]:not([type=\"hidden\"])`\n )\n if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) {\n return node\n }\n return null\n}\n\n// Find the hidden input that mirrors `raw` for the given canonical\n// field name. Returns the existing element or `null`.\n//\n// The canonical name is the one the developer wrote in the HTML\n// (e.g. `phone`) and the one the backend reads. The hidden input\n// is named `phone` and carries the raw value. It is identified\n// either by the `data-formatter-raw-for` attribute (set when the\n// controller creates the mirror) or by a pre-authored hidden with\n// the same name (no attribute — owned externally, preserved on\n// `destroy()`).\nexport const findHiddenMirror = (\n form: HTMLFormElement,\n fieldName: string\n): HTMLInputElement | null => {\n const byAttr = form.querySelector<HTMLInputElement>(\n `[${FORMATTER_RAW_ATTRIBUTE}=\"${cssEscape(fieldName)}\"]`\n )\n if (byAttr) return byAttr\n\n const byName = form.querySelector<HTMLInputElement>(\n `input[type=\"hidden\"][name=\"${cssEscape(fieldName)}\"]`\n )\n if (byName) return byName\n\n return null\n}\n\n// Create a hidden input that will mirror the raw value of `fieldName`.\n// Idempotent: if a mirror already exists it is returned as-is. The\n// mirror is named with the canonical `fieldName` (not a derived\n// suffix) so the value the backend reads sits at the developer's\n// natural name. The `data-formatter-raw-for` attribute is set so\n// `destroy()` can identify the mirror as owned and remove it.\nexport const ensureHiddenMirror = (\n form: HTMLFormElement,\n fieldName: string\n): HTMLInputElement => {\n const existing = findHiddenMirror(form, fieldName)\n if (existing) return existing\n\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = fieldName\n input.setAttribute('aria-hidden', 'true')\n input.tabIndex = -1\n input.setAttribute(FORMATTER_RAW_ATTRIBUTE, fieldName)\n form.appendChild(input)\n return input\n}\n\n// Rename a visible input from its current `name` to `displayName`.\n// Idempotent: if the input already has `displayName` it is left\n// alone. Used by `format()` to migrate the developer's authored\n// `<input name=\"phone\">` to `<input name=\"phone_displayed\">` so\n// the canonical `name` slot is free for the hidden raw mirror.\nexport const renameVisibleField = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n displayName: string\n): void => {\n if (visible.name === displayName) return\n visible.name = displayName\n}\n\n// Restore a visible input to `originalName`. Called by the format\n// registry on `destroy()` to put the DOM back the way the developer\n// authored it (modulo the value, which the developer controls).\nexport const restoreVisibleName = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n originalName: string\n): void => {\n visible.name = originalName\n}\n\n// Remove every hidden mirror owned by `format()`. Mirrors created by\n// this controller carry the `data-formatter-raw-for` attribute;\n// mirrors that existed before are left untouched.\nexport const removeOwnedHiddenMirrors = (form: HTMLFormElement): void => {\n form\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n}\n\n// Write `formatted` into the visible field and `raw` into the hidden\n// mirror, preserving the cursor as best as possible.\n//\n// Returns the new caret position so callers can debug or run additional\n// assertions. The function avoids triggering `MutationObserver` cascades\n// for the hidden mirror by setting `.value` directly (the controller's\n// own delegated handler ignores hidden inputs via `isFieldElement`).\n//\n// `inputType` is the optional `InputEvent.inputType` value (e.g.\n// `'insertText'`, `'deleteContentBackward'`, `'deleteWordBackward'`).\n// When it indicates a deletion, this helper mirrors cleave.js'\n// `postDelimiterBackspace` contract: after the caret is re-anchored in\n// the freshly formatted value, walk backwards while the character\n// immediately to the left of the caret is a format character (delimiter,\n// prefix/suffix symbol, …) and decrement the caret. That keeps the\n// caret from \"jumping\" past a delimiter that disappeared when the user\n// deleted the digit sitting right next to it.\nexport const applyFormattedValue = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n mirror: HTMLInputElement | null,\n formatted: string,\n raw: string,\n inputType?: string\n): number => {\n // Capture the caret in the **raw** input the user just typed — this\n // is what cleave's `getNextCursorPosition` does. Using the formatted\n // previous value would lose information when the user edits in the\n // middle of a masked field (deletion adjacent to delimiters, etc.).\n const rawInput = visible.value\n const caret = clamp(\n visible.selectionStart ?? rawInput.length,\n 0,\n rawInput.length\n )\n\n if (mirror && mirror.value !== raw) mirror.value = raw\n\n if (rawInput === formatted) {\n // The formatter did not change the visible value — usually because\n // the user is editing at the tail of a fully-formatted string. Even\n // so, a backspace can leave the caret sitting with a delimiter on\n // its left (because the digit right after the delimiter just\n // disappeared). Apply the postDelimiterBackspace scan in this path\n // too so the contract holds for both branches.\n const newCaret = pullCaretPastLeadingDelimiter(caret, formatted, inputType)\n if (newCaret !== caret) restoreCursor(visible, newCaret)\n return newCaret\n }\n\n visible.value = formatted\n\n const newCaret = pullCaretPastLeadingDelimiter(\n computeCursorPosition(caret, rawInput, formatted),\n formatted,\n inputType\n )\n restoreCursor(visible, newCaret)\n return newCaret\n}\n\n// Mirrors cleave.js' `postDelimiterBackspace` contract. After a\n// deletion (`inputType` starts with `'delete'`) we never want the\n// caret to sit with a format character immediately on its left; if it\n// would, pull it backwards until it does (or until we hit index 0).\n// No-op when `inputType` is missing or does not indicate a deletion.\nconst pullCaretPastLeadingDelimiter = (\n caret: number,\n value: string,\n inputType: string | undefined\n): number => {\n if (!inputType || !inputType.startsWith('delete')) return caret\n\n let cursor = caret\n while (cursor > 0 && isFormatChar(value[cursor - 1]!)) {\n cursor -= 1\n }\n return cursor\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, value))\n\n// `computeCursorPosition` is a cleave-style implementation:\n// - count \"non-format\" characters (digits / letters) between the caret\n// and the start of the **raw input the user just typed**, then\n// locate that same logical index in the new formatted value\n// (jumping over inserted delimiters).\n// - when the caret is at (or past) the end of the raw input, place\n// it at the end of the formatted value.\n//\n// The algorithm intentionally avoids any cleave-zen dependency so this\n// file is pure DOM arithmetic.\nexport const computeCursorPosition = (\n caretPos: number,\n rawInput: string,\n newValue: string\n): number => {\n if (newValue.length === 0) return 0\n\n // Caret at (or past) the end of the raw input — place at new end.\n if (caretPos >= rawInput.length) return newValue.length\n\n // Caret within the raw input: count non-format characters to its\n // LEFT (i.e. how many real characters are before the caret) and\n // find that same count in the new formatted value.\n const targetNonFormat = countNonFormat(rawInput.slice(0, caretPos))\n\n if (targetNonFormat === 0) {\n // Skip leading delimiters / prefix symbols (`$`, `+`, …) so the\n // caret lands at the first real character of the new value.\n let i = 0\n while (i < newValue.length && isFormatChar(newValue[i]!)) i += 1\n return i\n }\n\n let seen = 0\n for (let i = 0; i < newValue.length; i += 1) {\n if (!isFormatChar(newValue[i]!)) {\n seen += 1\n if (seen === targetNonFormat) {\n return Math.min(i + 1, newValue.length)\n }\n }\n }\n\n return newValue.length\n}\n\nconst countNonFormat = (value: string): number => {\n let count = 0\n for (const char of value) {\n if (!isFormatChar(char)) count += 1\n }\n return count\n}\n\n// \"Format characters\" are delimiters, prefix symbols, and other\n// non-alphanumeric separators that the formatter may insert or remove.\n// We deliberately keep this conservative — anything that is not a digit\n// or ASCII letter counts as a format character.\nexport const isFormatChar = (char: string): boolean => {\n if (!char) return false\n if (char >= '0' && char <= '9') return false\n if ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z')) return false\n return true\n}\n\nconst restoreCursor = (\n field: HTMLInputElement | HTMLTextAreaElement,\n position: number\n): void => {\n // Moving the selection of a control the user is not editing is never\n // wanted, and Safari focuses an input when its selection is set.\n if (field.ownerDocument.activeElement !== field) return\n\n const max = field.value.length\n const safe = clamp(position, 0, max)\n\n const apply = () => {\n try {\n field.setSelectionRange(safe, safe)\n } catch {\n // Some input types (number, email) throw on setSelectionRange.\n // Ignore — the caret just stays where the browser put it.\n }\n }\n\n // Android keyboard fix: defer one frame so the IME catches up before\n // we re-position the caret. Mirrors cleave.js' `isAndroid` branch.\n if (typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent)) {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(apply)\n } else {\n setTimeout(apply, 1)\n }\n return\n }\n\n apply()\n}\n\n// `getFormatterField` re-exported above is the canonical entry point,\n// but it is intentionally restricted to controller-owned fields. This\n// looser helper accepts a wider set of inputs for test fixtures.\nexport const isFormatterFieldElement = (node: Element): node is FormFieldElement =>\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement","// Lazy singleton loader for the optional `@samline/formatter` peer.\n// The formatter is imported dynamically so the package stays usable\n// even when the peer is not installed: callers receive `null` and a\n// single console.error explaining the missing dependency.\n//\n// The first failure is cached so the warning is printed exactly once\n// per process, not on every `format(...)` call.\n\nexport interface FormatterModule {\n format: (\n value: unknown,\n formatType: string,\n options?: Record<string, unknown>\n ) => { formatted: string; raw: string; type: string }\n FORMAT_TYPES?: readonly string[]\n isFormatType?: (value: unknown) => boolean\n regex?: Record<string, { pattern: RegExp; errorMessage: string }>\n /** Present since @samline/formatter 3.0.0, where phones are opt-in. */\n isPhoneRegistered?: () => boolean\n}\n\ninterface PhoneModule {\n registerPhone: () => void\n}\n\nexport interface LoadFormatterOptions {\n /** Also make sure phone formatting is registered (formatter >= 3.0.0). */\n phone?: boolean\n}\n\ntype LoaderState =\n | { status: 'pending'; promise: Promise<FormatterModule | null> }\n | { status: 'resolved'; module: FormatterModule | null }\n\nlet state: LoaderState | null = null\n\nconst MISSING_MESSAGE =\n '[samline/forms] The `format()` and `formatAll()` methods require the ' +\n '@samline/formatter package. Install it with: npm i @samline/formatter ' +\n '(or pnpm/bun/yarn equivalent).'\n\nlet warned = false\nlet phonePromise: Promise<boolean> | null = null\n\nconst PHONE_MESSAGE =\n '[samline/forms] Phone formatting needs `@samline/formatter/phone` ' +\n '(@samline/formatter >= 3.0.0 makes phones opt-in) and it could not be loaded.'\n\nconst warnOnce = () => {\n if (warned) return\n warned = true\n console.error(MISSING_MESSAGE)\n}\n\n// Formatter 3 makes phones opt-in to keep libphonenumber-js (~140 KB) out of\n// forms that never format a phone. Forms registers it on demand, the first\n// time a phone field is formatted, so consumers do not have to. The subpath is\n// a separate dynamic import: bundlers split it into its own lazy chunk.\nconst ensurePhone = (formatter: FormatterModule): Promise<boolean> => {\n // Formatter 2.x always includes phones.\n if (typeof formatter.isPhoneRegistered !== 'function') return Promise.resolve(true)\n if (formatter.isPhoneRegistered()) return Promise.resolve(true)\n if (!phonePromise) {\n phonePromise = (async () => {\n try {\n const mod = (await import('@samline/formatter/phone')) as PhoneModule\n mod.registerPhone()\n return true\n } catch {\n console.error(PHONE_MESSAGE)\n phonePromise = null\n return false\n }\n })()\n }\n return phonePromise\n}\n\nexport const loadFormatter = async (\n options: LoadFormatterOptions = {}\n): Promise<FormatterModule | null> => {\n const formatter = await loadFormatterModule()\n if (!formatter || !options.phone) return formatter\n return (await ensurePhone(formatter)) ? formatter : null\n}\n\nconst loadFormatterModule = (): Promise<FormatterModule | null> => {\n if (state && state.status === 'resolved') {\n if (!state.module) warnOnce()\n return Promise.resolve(state.module)\n }\n\n if (state && state.status === 'pending') {\n return state.promise\n }\n\n const promise = (async () => {\n try {\n // Dynamic import keeps the optional peer out of the eager build graph.\n // The consumer's bundler is responsible for resolving the peer at\n // build time — `tsup` treats `@samline/formatter` as `external` so it\n // does not try to pre-bundle it. Do NOT re-add `/* @vite-ignore */`\n // here: in production it leaves the bare specifier as a literal in\n // the bundle, browsers cannot resolve it, and the formatter silently\n // never loads (the catch below masks the failure).\n const mod = (await import('@samline/formatter')) as FormatterModule\n state = { status: 'resolved', module: mod }\n return mod\n } catch {\n warnOnce()\n state = { status: 'resolved', module: null }\n return null\n }\n })()\n\n state = { status: 'pending', promise }\n return promise\n}\n\n// Test-only helper: reset the cached loader so unit tests can swap the\n// dynamic import between \"installed\" and \"missing\" scenarios.\nexport const __resetFormatterLoaderForTests = (): void => {\n state = null\n warned = false\n phonePromise = null\n}\n\n// Test-only helper: inject a formatter implementation directly,\n// bypassing the dynamic import. Pass `null` to simulate the\n// \"peer not installed\" branch.\nexport const __setFormatterModuleForTests = (\n module: FormatterModule | null\n): void => {\n state = { status: 'resolved', module }\n}\n\nexport const __setFormatterPromiseForTests = (\n promise: Promise<FormatterModule | null>\n): void => {\n state = { status: 'pending', promise }\n}\n","import type { FieldFormatConfig, FormController, FormFieldElement } from '../core/types'\nimport {\n applyFormattedValue,\n ensureHiddenMirror,\n findHiddenMirror,\n findVisibleField,\n FORMATTER_RAW_ATTRIBUTE,\n renameVisibleField,\n restoreVisibleName\n} from '../core/format-helpers'\nimport { loadFormatter } from '../core/formatter-loader'\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\ntype FormatEntry = {\n canonicalName: string\n displayName: string\n visible: HTMLInputElement | HTMLTextAreaElement\n mirror: HTMLInputElement\n mirrorIsOwned: boolean\n defaultVisible: string | null\n defaultRaw: string | null\n /** Bound after the formatter peer resolves. */\n handler: ((event: Event) => void) | null\n}\n\nconst UNBOUND: ((event: Event) => void) | null = null\n\nconst registry = new WeakMap<FormControllerState, Map<string, FormatEntry>>()\n\nconst getRegistry = (state: FormControllerState): Map<string, FormatEntry> => {\n let bucket = registry.get(state)\n if (!bucket) {\n bucket = new Map<string, FormatEntry>()\n registry.set(state, bucket)\n }\n return bucket\n}\n\nconst resolveFieldNames = (config: FieldFormatConfig): string[] =>\n Array.isArray(config.field) ? config.field : [config.field]\n\nconst addListener = (\n state: FormControllerState,\n target: EventTarget,\n type: string,\n handler: EventListener,\n useCapture?: boolean\n): void => {\n if (useCapture) {\n target.addEventListener(type, handler, { capture: true })\n } else {\n target.addEventListener(type, handler)\n }\n const entry: {\n element: EventTarget\n type: string\n handler: EventListener\n capture?: boolean\n } = { element: target, type, handler }\n if (useCapture !== undefined) entry.capture = useCapture\n state.listeners.push(entry)\n}\n\nconst readInputType = (event: Event): string | undefined => {\n const candidate = event as Partial<InputEvent>\n return typeof candidate.inputType === 'string' ? candidate.inputType : undefined\n}\n\n// Canonical mirrors use auto detection; visible input is always display-order.\nconst buildAutoInterpretedOptions = (\n formatOptions: Record<string, unknown> | undefined\n): Record<string, unknown> => ({\n ...(formatOptions ?? {}),\n interpretInputAs: 'auto'\n})\n\nconst buildDisplayInterpretedOptions = (\n formatOptions: Record<string, unknown> | undefined\n): Record<string, unknown> => ({\n ...(formatOptions ?? {}),\n interpretInputAs: 'display'\n})\n\nconst shouldForceAutoInterpretation = (\n formatOptions: Record<string, unknown> | undefined\n): boolean => formatOptions?.interpretInputAs === undefined\n\nconst buildHandler = (\n visible: HTMLInputElement | HTMLTextAreaElement,\n mirror: HTMLInputElement,\n formatFn: NonNullable<Awaited<ReturnType<typeof loadFormatter>>>['format'],\n formatType: FieldFormatConfig['type'],\n formatOptions: Record<string, unknown> | undefined\n): ((event: Event) => void) => {\n const handler = (event: Event) => {\n if (!visible.isConnected || !mirror.isConnected) return\n\n const isVisible = event.target === visible\n const isMirror = event.target === mirror\n if (!isVisible && !isMirror) return\n\n const rawInput = isMirror ? mirror.value : visible.value\n const inputType = readInputType(event)\n const sourceOptions = shouldForceAutoInterpretation(formatOptions)\n ? isMirror\n ? buildAutoInterpretedOptions(formatOptions)\n : buildDisplayInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatFn(rawInput, formatType, sourceOptions)\n\n if (!formatted && !raw) {\n visible.value = ''\n if (mirror.value !== '') mirror.value = ''\n return\n }\n\n applyFormattedValue(visible, mirror, formatted, raw, inputType)\n }\n return handler\n}\n\n// Phase one mutates the DOM synchronously; phase two binds only this call's entries.\nconst applyFormat = async (\n state: FormControllerState,\n helpers: FormControllerHelpers,\n config: FieldFormatConfig\n): Promise<void> => {\n if (!state.element || !state.api) return\n if (Array.isArray(config.field) && config.displayField) {\n console.error(\n '[samline/forms] `displayField` can only be used when `field` is a string.'\n )\n return\n }\n\n const formatType = config.type\n const formatOptions = config.options\n const fieldNames = resolveFieldNames(config)\n const bucket = getRegistry(state)\n\n const phase1Entries: FormatEntry[] = []\n\n // Phase 1: establish the visible/canonical pair synchronously.\n for (const fieldName of fieldNames) {\n const displayName = config.displayField ?? `${fieldName}_displayed`\n\n // Accept either a canonical visible field or a pre-authored display field.\n const canonicalFields = helpers.getFieldsByName(fieldName) as FormFieldElement[]\n const candidates = canonicalFields.filter(\n (f): f is HTMLInputElement | HTMLTextAreaElement =>\n (f instanceof HTMLInputElement && f.type !== 'hidden') ||\n f instanceof HTMLTextAreaElement\n )\n let visible: HTMLInputElement | HTMLTextAreaElement | null = candidates[0] ?? null\n if (!visible) {\n visible = findVisibleField(state.element, displayName)\n }\n if (!visible) continue\n\n const existing = bucket.get(fieldName)\n\n let mirror = findHiddenMirror(state.element, fieldName)\n const mirrorIsOwned = !mirror\n if (!mirror) mirror = ensureHiddenMirror(state.element, fieldName)\n\n renameVisibleField(visible, displayName)\n\n if (existing) {\n existing.displayName = displayName\n existing.mirrorIsOwned = mirrorIsOwned\n state.formattedFields.set(fieldName, {\n config,\n displayName,\n mirrorIsOwned\n })\n phase1Entries.push(existing)\n } else {\n const entry: FormatEntry = {\n canonicalName: fieldName,\n displayName,\n visible,\n mirror,\n mirrorIsOwned,\n defaultVisible: null,\n defaultRaw: null,\n handler: UNBOUND\n }\n bucket.set(fieldName, entry)\n state.formattedFields.set(fieldName, {\n config,\n displayName,\n mirrorIsOwned\n })\n phase1Entries.push(entry)\n }\n }\n\n // Phase 2: load the peer, bind listeners, and normalize initial values.\n const formatter = await loadFormatter({ phone: formatType === 'phone' })\n if (state.isDestroyed) {\n rollbackPhase1(phase1Entries, bucket, state.formattedFields)\n return\n }\n if (!formatter) {\n rollbackPhase1(phase1Entries, bucket, state.formattedFields)\n return\n }\n\n for (const entry of phase1Entries) {\n if (entry.handler !== UNBOUND) {\n // Reformat without duplicating the existing capture listener.\n const current = entry.visible.value\n if (current !== '') {\n const rebindOptions = shouldForceAutoInterpretation(formatOptions)\n ? buildDisplayInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatter.format(current, formatType, rebindOptions)\n applyFormattedValue(entry.visible, entry.mirror, formatted, raw)\n }\n continue\n }\n\n const handler = buildHandler(\n entry.visible,\n entry.mirror,\n formatter.format,\n formatType,\n formatOptions\n )\n addListener(state, state.element, 'input', handler, true)\n entry.handler = handler\n\n const initial = entry.visible.value\n if (initial !== '') {\n // Initial values may be canonical server data; preserve explicit modes.\n const initialOptions = shouldForceAutoInterpretation(formatOptions)\n ? buildAutoInterpretedOptions(formatOptions)\n : formatOptions\n const { formatted, raw } = formatter.format(initial, formatType, initialOptions)\n applyFormattedValue(entry.visible, entry.mirror, formatted, raw)\n } else if (entry.mirrorIsOwned && entry.mirror.value !== '') {\n entry.mirror.value = ''\n }\n entry.defaultVisible = entry.visible.value\n entry.defaultRaw = entry.mirror.value\n }\n}\n\nexport const resetFormattedFields = (state: FormControllerState): void => {\n const bucket = registry.get(state)\n if (!bucket) return\n for (const entry of bucket.values()) {\n if (entry.defaultVisible !== null) entry.visible.value = entry.defaultVisible\n if (entry.defaultRaw !== null) entry.mirror.value = entry.defaultRaw\n }\n}\n\n// Restore only entries touched by the current call when peer loading fails.\nconst rollbackPhase1 = (\n entries: FormatEntry[],\n bucket: Map<string, FormatEntry>,\n registry: FormControllerState['formattedFields']\n): void => {\n for (const entry of entries) {\n if (entry.visible.isConnected) {\n restoreVisibleName(entry.visible, entry.canonicalName)\n }\n if (entry.mirrorIsOwned && entry.mirror.isConnected) {\n entry.mirror.remove()\n }\n bucket.delete(entry.canonicalName)\n registry.delete(entry.canonicalName)\n }\n}\n\nexport const createFormat =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (config: FieldFormatConfig): FormController => {\n if (state.isDestroyed) return state.api!\n if (!state.element) return state.api!\n\n void applyFormat(state, helpers, config)\n\n return state.api!\n }\n\nexport const createFormatAll = createFormat\n\nexport const resolveCanonicalForName = (\n state: FormControllerState,\n name: string\n): string | null => {\n const bucket = registry.get(state)\n if (!bucket) return null\n for (const [canonical, entry] of bucket) {\n if (canonical === name || entry.displayName === name) return canonical\n }\n return null\n}\n\nexport const resolveDisplayNameForName = (\n state: FormControllerState,\n name: string\n): string => {\n const bucket = registry.get(state)\n if (!bucket) return name\n for (const [canonical, entry] of bucket) {\n if (canonical === name) return entry.displayName\n if (entry.displayName === name) return entry.displayName\n }\n return name\n}\n\nexport const cleanupFormatRegistry = (state: FormControllerState): void => {\n if (!state.element) {\n registry.delete(state)\n return\n }\n\n const bucket = registry.get(state)\n if (!bucket) {\n state.element\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n return\n }\n\n for (const [fieldName, entry] of bucket) {\n if (entry.handler !== UNBOUND) {\n state.element.removeEventListener('input', entry.handler, true)\n }\n if (entry.visible.isConnected) {\n restoreVisibleName(entry.visible, fieldName)\n }\n if (entry.mirrorIsOwned && entry.mirror.isConnected) {\n entry.mirror.remove()\n }\n bucket.delete(fieldName)\n state.formattedFields.delete(fieldName)\n }\n\n // Remove any orphaned mirrors defensively.\n state.element\n .querySelectorAll<HTMLInputElement>(`[${FORMATTER_RAW_ATTRIBUTE}]`)\n .forEach(node => node.remove())\n}\n","// api/destroy.ts\n// Tears down the controller: removes DOM listeners, disconnects the\n// mutation observer, clears caches, and resets internal state.\n// Safe to call multiple times.\n\nimport { cleanupFormatRegistry } from './format'\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createDestroy =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n () => {\n if (state.isDestroyed) return\n\n state.isDestroyed = true\n for (const listener of state.listeners) {\n const options: EventListenerOptions | undefined = listener.capture\n ? { capture: true }\n : undefined\n if (options) {\n listener.element.removeEventListener(listener.type, listener.handler, options)\n } else {\n listener.element.removeEventListener(listener.type, listener.handler)\n }\n }\n state.listeners.length = 0\n\n if (state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n\n state.mutationObserver?.disconnect()\n state.mutationObserver = null\n\n const cleanups = Array.from(state.cleanups).reverse()\n state.cleanups.clear()\n for (const cleanup of cleanups) {\n try {\n cleanup()\n } catch (error) {\n console.error('[forms] cleanup failed', error)\n }\n }\n\n state.watchedFields.clear()\n state.groupWatchers.clear()\n state.subscribers.clear()\n state.submitHandlers.clear()\n state.fieldCache.clear()\n state.manualErrors = {}\n state.validationErrors = {}\n state.validationGroupErrors = {}\n state.validationElementErrors.clear()\n state.pendingSubmitCount = 0\n\n // Detach format listeners and drop the hidden raw mirrors that\n // `format()` created for this controller. Mirrors that pre-existed\n // in the DOM (i.e. not owned by us) are preserved.\n cleanupFormatRegistry(state)\n }\n","// api/disable-auto-submit.ts\n// Disables autoSubmit and cancels any pending debounce timer.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createDisableAutoSubmit =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n () => {\n state.autoSubmitEnabled = false\n if (state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n helpers.notifySubscribers()\n return state.api!\n }\n","// Pure serialization helpers for HTMLFormElement.\n// No DOM mutation, no controller state — safe to tree-shake into any bundle.\n\nimport type { SerializedFormResult, SerializedFormValue } from './types'\n\nconst isEmptyFile = (value: FormDataEntryValue): value is File =>\n value instanceof File && value.size === 0 && value.name === ''\n\nconst appendValue = (\n data: Record<string, SerializedFormValue>,\n key: string,\n value: FormDataEntryValue\n): void => {\n if (!Object.prototype.hasOwnProperty.call(data, key)) {\n Object.defineProperty(data, key, {\n value,\n writable: true,\n enumerable: true,\n configurable: true\n })\n return\n }\n const current = data[key] as SerializedFormValue\n if (Array.isArray(current)) {\n current.push(value)\n return\n }\n data[key] = [current, value]\n}\n\nexport const parseFormData = (\n formElement: HTMLFormElement,\n submitter?: HTMLElement | null\n): SerializedFormResult => {\n const raw = submitter\n ? new FormData(formElement, submitter)\n : new FormData(formElement)\n const formData = new FormData()\n const data: Record<string, SerializedFormValue> = {}\n\n raw.forEach((value, key) => {\n if (isEmptyFile(value)) return\n formData.append(key, value)\n appendValue(data, key, value)\n })\n\n return { data, formData }\n}\n","// api/get-data.ts\n// Returns the form serialized as both a plain object and a fresh\n// FormData instance. Empty file inputs are filtered out.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { SerializedFormResult } from '../core/types'\nimport { parseFormData } from '../core/serialize'\n\nexport const createGetData =\n (_state: FormControllerState, _helpers: FormControllerHelpers) =>\n (): SerializedFormResult => {\n if (!_state.element) return { data: {}, formData: new FormData() }\n return parseFormData(_state.element)\n }\n","// api/get-field.ts\n// Returns the underlying DOM field(s) for a given name:\n// - null when no field matches\n// - a single element when there's exactly one\n// - an array when there are multiple (radios, checkbox groups)\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldElement } from '../core/types'\n\nexport const createGetField =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string): FormFieldElement | FormFieldElement[] | null => {\n const fields = helpers.getFieldsByName(name)\n if (fields.length === 0) return null\n return fields.length === 1 ? fields[0]! : fields\n }\n","// Shared mutable state for the controller plus the small pure helpers used\n// by both core utilities and the api method factories.\n\nimport type {\n FieldFormatConfig,\n FormController,\n FormControllerOptions,\n FormCleanup,\n FormErrors,\n FormFieldElement,\n FormFieldWatcher,\n FormFieldsWatcher,\n FormStateListener,\n FormStateSnapshot,\n FormValues,\n ValidationResult,\n ValidationSchema,\n VisualAttributes\n} from './types'\n\nexport interface FormControllerState {\n element: HTMLFormElement | null\n options: FormControllerOptions\n attributes: Required<VisualAttributes>\n validators: ValidationSchema\n watchedFields: Map<string, Set<FormFieldWatcher>>\n // Watchers registered with a list of fields. `fields` is deduplicated\n // and keeps the order the caller passed.\n groupWatchers: Set<{ fields: string[]; callback: FormFieldsWatcher }>\n subscribers: Set<FormStateListener>\n submitHandlers: Set<{\n callback: import('./types').FormSubmitHandler\n preventDefault: boolean\n }>\n fieldCache: Map<string, FormFieldElement[]>\n manualErrors: FormErrors\n validationErrors: FormErrors\n validationGroupErrors: FormErrors\n validationElementErrors: Map<string, Map<FormFieldElement, string[]>>\n isValidated: boolean\n autoSubmitEnabled: boolean\n autoSubmitDebounce: number\n submitCount: number\n pendingSubmitCount: number\n autoSubmitTimer: ReturnType<typeof setTimeout> | null\n /** True while an automatic `requestSubmit()` is dispatching `submit`. */\n isAutoSubmitting: boolean\n /** Batches several programmatic writes (`prefill`) into one auto-submit. */\n autoSubmitSuspended: boolean\n /** True while `reset()` runs the native reset it already handles. */\n isResetting: boolean\n isDestroyed: boolean\n listeners: Array<{\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n /**\n * `true` when the listener was registered with `capture: true`.\n * Required for matching `removeEventListener` on teardown —\n * the spec treats capture and bubble as distinct registrations.\n */\n capture?: boolean\n }>\n mutationObserver: MutationObserver | null\n cleanups: Set<FormCleanup>\n // Tracks every field that `format()` is currently formatting, so\n // re-bindings are idempotent and `destroy()` can clean up the\n // associated listeners + hidden raw mirror. Keyed by the canonical\n // field name (the one the developer wrote in the HTML and the one\n // the backend reads). `displayName` is the visible input's name\n // (defaults to `${canonical}_displayed`).\n formattedFields: Map<\n string,\n {\n config: FieldFormatConfig\n displayName: string\n mirrorIsOwned: boolean\n }\n >\n // Back-reference to the assembled public controller. Populated by the\n // controller orchestrator after the api method factories are wired.\n api: FormController | null\n}\n\n// Internal helpers bound by the controller orchestrator and consumed by\n// the api method factories. Kept here so api/*.ts only depends on the\n// shape, not on the orchestrator implementation.\nexport interface FormControllerHelpers {\n notifySubscribers: () => void\n clearFieldCache: () => void\n getFieldsByName: (name: string) => FormFieldElement[]\n getTrackedFieldNames: () => string[]\n getValues: () => FormValues\n getMergedErrors: () => FormErrors\n syncVisualState: (names?: string[]) => void\n validateNames: (names?: string[]) => ValidationResult\n emitFieldWatchers: (name: string) => void\n scheduleAutoSubmit: () => void\n applyReset: () => void\n commitOwnMutations: (selects: HTMLSelectElement[]) => void\n}\n\nexport const createEmptyFormState = (): FormStateSnapshot => ({\n values: {},\n errors: {},\n filledFields: [],\n isValid: true,\n isValidated: false,\n autoSubmit: false,\n isSubmitting: false,\n submitCount: 0\n})\n\nexport const cloneErrors = (errors: FormErrors): FormErrors =>\n Object.fromEntries(\n Object.entries(errors).map(([field, messages]) => [field, [...messages]])\n )\n\nexport const mergeErrors = (left: FormErrors, right: FormErrors): FormErrors => {\n const merged: FormErrors = { ...left }\n for (const [field, messages] of Object.entries(right)) {\n merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages]\n }\n return merged\n}\n","// api/get-state.ts\n// Builds a snapshot of values, errors, filled fields and submission\n// metadata. Pure read — does not mutate controller state.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormStateSnapshot } from '../core/types'\nimport { cloneErrors, createEmptyFormState } from '../core/state'\n\nexport const createGetState =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (): FormStateSnapshot => {\n const values = helpers.getValues()\n const errors = cloneErrors(helpers.getMergedErrors())\n const filledFields = Object.keys(values).filter(name => {\n const value = values[name]\n if (Array.isArray(value)) return value.length > 0\n if (typeof value === 'string') return value.trim().length > 0\n return value !== undefined\n })\n\n return {\n ...createEmptyFormState(),\n values,\n errors,\n filledFields,\n isValid: Object.keys(errors).length === 0,\n isValidated: state.isValidated,\n autoSubmit: state.autoSubmitEnabled,\n isSubmitting: state.pendingSubmitCount > 0,\n submitCount: state.submitCount\n }\n }\n","// Low-level DOM helpers used by the controller orchestrator and by api\n// methods that need direct DOM access. Pure: no controller state.\n\nimport type { FormFieldElement, FormFieldValue, FormTarget } from './types'\n\nconst isFormFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\n// Convention: a name ending with \"[]\" signals multi-value inputs (the\n// de facto HTML form pattern used by PHP, Rails, Express, Spring, etc.\n// to collect repeated inputs as an array on the server). The `[]`\n// suffix is the only signal the controller uses; bare names keep the\n// original first-value semantics.\nconst isArraySyntax = (field: FormFieldElement): boolean =>\n typeof field.name === 'string' && field.name.endsWith('[]')\n\nexport const resolveFormElement = (target: FormTarget): HTMLFormElement | null => {\n if (!target) return null\n if (target instanceof HTMLFormElement) return target\n if (typeof target === 'string') {\n const node = document.getElementById(target)\n return node instanceof HTMLFormElement ? node : null\n }\n if ('current' in target) {\n return target.current instanceof HTMLFormElement ? target.current : null\n }\n return null\n}\n\nexport const getNamedFields = (form: HTMLFormElement): FormFieldElement[] =>\n Array.from(form.elements).filter(\n (element): element is FormFieldElement =>\n isFormFieldElement(element) && Boolean(element.name)\n )\n\nexport const queryNamedFields = (\n form: HTMLFormElement,\n name: string\n): FormFieldElement[] => getNamedFields(form).filter(field => field.name === name)\n\nexport const isFieldElement = (value: Element): value is FormFieldElement =>\n isFormFieldElement(value)\n\nexport const isFieldFilled = (field: FormFieldElement): boolean => {\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox' || field.type === 'radio') return field.checked\n if (field.type === 'file') return Boolean(field.files && field.files.length > 0)\n return field.value.trim() !== ''\n }\n return field.value !== ''\n}\n\nexport const applyBooleanAttribute = (\n field: FormFieldElement,\n attribute: string,\n enabled: boolean\n): void => {\n if (enabled) {\n field.setAttribute(attribute, '')\n } else {\n field.removeAttribute(attribute)\n }\n}\n\nexport const readFieldValue = (fields: FormFieldElement[]): FormFieldValue => {\n if (fields.length === 0) return undefined\n const first = fields[0]\n if (!first) return undefined\n\n // Multi-value inputs: name=\"foo[]\". Only treat the group as an array\n // when there is more than one matching input — a single input with a\n // `[]` suffix still returns a plain string, matching the non-array\n // semantics and avoiding a one-element array that callers would\n // have to flatten.\n if (isArraySyntax(first) && fields.length > 1) {\n if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {\n return fields.map(f => f.value)\n }\n\n if (first instanceof HTMLInputElement) {\n if (first.type === 'radio') {\n // Radio groups stay single-valued even with the `[]` suffix —\n // they semantically mean \"one of these\". Find the checked one.\n const checked = fields.find(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n return checked?.value ?? ''\n }\n\n if (first.type === 'checkbox') {\n // Always return an array of checked values (no single-value\n // collapse) so `Array.isArray(value)` validators stay correct.\n return fields\n .filter(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n .map(f => f.value)\n }\n\n if (first.type === 'file') {\n // Concatenate every selected file across all matching inputs.\n return fields.flatMap(f =>\n f instanceof HTMLInputElement && f.files ? Array.from(f.files) : []\n )\n }\n }\n\n // text / email / password / number / hidden — one string per input.\n return fields.map(f => f.value)\n }\n\n if (first instanceof HTMLSelectElement && first.multiple) {\n return Array.from(first.selectedOptions, option => option.value)\n }\n\n if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {\n return first.value\n }\n\n if (first instanceof HTMLInputElement) {\n if (first.type === 'radio') {\n const checked = fields.find(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n return checked?.value ?? ''\n }\n\n if (first.type === 'checkbox') {\n const values = fields\n .filter(\n (f): f is HTMLInputElement =>\n f instanceof HTMLInputElement && f.checked\n )\n .map(f => f.value)\n return values.length > 1 ? values : (values[0] ?? '')\n }\n\n if (first.type === 'file') {\n return first.files ? Array.from(first.files) : []\n }\n }\n\n return first.value\n}\n\nexport const writeFieldValue = (fields: FormFieldElement[], value: unknown): void => {\n const normalizedArray = Array.isArray(value)\n ? value.map(item => String(item))\n : null\n const normalizedValue = value === undefined || value === null ? '' : String(value)\n\n // For `name=\"foo[]\"` fields receiving an array, distribute one element\n // per input. Surplus inputs (more inputs than array elements) are\n // cleared to ''; surplus array elements (more elements than inputs)\n // are dropped — there's no input to write to. The distribution only\n // applies to text-like inputs; checkbox / radio / file keep their\n // own special semantics.\n const distributeArray =\n fields.length > 0 &&\n fields[0] !== undefined &&\n isArraySyntax(fields[0]) &&\n normalizedArray !== null\n\n for (let index = 0; index < fields.length; index++) {\n const field = fields[index]\n if (!field) continue\n\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox') {\n field.checked = normalizedArray\n ? normalizedArray.includes(field.value)\n : normalizedValue === field.value\n continue\n }\n if (field.type === 'radio') {\n field.checked = field.value === normalizedValue\n continue\n }\n if (field.type === 'file') {\n if (Array.isArray(value) && value.length === 0) field.value = ''\n continue\n }\n if (distributeArray && normalizedArray) {\n field.value = normalizedArray[index] ?? ''\n continue\n }\n field.value = normalizedValue\n continue\n }\n\n if (field instanceof HTMLSelectElement && field.multiple) {\n const selectedValues = normalizedArray ?? [normalizedValue]\n for (const option of field.options) {\n option.selected = selectedValues.includes(option.value)\n }\n continue\n }\n\n if (distributeArray && normalizedArray) {\n field.value = normalizedArray[index] ?? ''\n continue\n }\n\n field.value = normalizedValue\n }\n}\n\nexport const clearAttributes = (form: HTMLFormElement, attributes: string[]): void => {\n for (const attribute of attributes) {\n getNamedFields(form).forEach(field => field.removeAttribute(attribute))\n }\n}\n\nexport const submitForm = (form: HTMLFormElement): void => {\n if (typeof form.requestSubmit === 'function') {\n form.requestSubmit()\n return\n }\n const submitButton = form.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) as HTMLButtonElement | HTMLInputElement | null\n if (submitButton) {\n submitButton.click()\n return\n }\n form.submit()\n}\n","// api/get-value.ts\n// Returns the current value of a field, with normalization for checkboxes,\n// radios, files, and multi-value inputs.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldValue } from '../core/types'\nimport { readFieldValue } from '../core/dom'\n\nexport const createGetValue =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string): FormFieldValue => readFieldValue(helpers.getFieldsByName(name))\n","// api/observe.ts\n// Registers a callback that runs on mount and whenever the field changes.\n// Accepts one field name or a list of names. Returns an unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormFieldsWatcher, FormFieldWatcher } from '../core/types'\n\nconst observeField = (state: FormControllerState, field: string, callback: FormFieldWatcher) => {\n const callbacks = state.watchedFields.get(field) ?? new Set<FormFieldWatcher>()\n callbacks.add(callback)\n state.watchedFields.set(field, callbacks)\n\n if (state.element) {\n callback(state.api!.getValue(field), state.api!.getField(field), state.element, state.api!.getState())\n }\n\n return () => {\n const current = state.watchedFields.get(field)\n current?.delete(callback)\n if (current && current.size === 0) {\n state.watchedFields.delete(field)\n }\n }\n}\n\nconst observeFields = (\n state: FormControllerState,\n fields: string[],\n callback: FormFieldsWatcher\n) => {\n const names = Array.from(new Set(fields))\n if (names.length === 0) return () => undefined\n const entry = { fields: names, callback }\n state.groupWatchers.add(entry)\n\n if (state.element) {\n const values = Object.fromEntries(names.map(name => [name, state.api!.getValue(name)]))\n callback(values, null, state.element, state.api!.getState())\n }\n\n return () => {\n state.groupWatchers.delete(entry)\n }\n}\n\nexport const createObserve = (state: FormControllerState, _helpers: FormControllerHelpers) => {\n function observe(field: string, callback: FormFieldWatcher): () => void\n function observe(fields: string[], callback: FormFieldsWatcher): () => void\n function observe(field: string | string[], callback: FormFieldWatcher | FormFieldsWatcher) {\n if (state.isDestroyed) return () => undefined\n return Array.isArray(field)\n ? observeFields(state, field, callback as FormFieldsWatcher)\n : observeField(state, field, callback as FormFieldWatcher)\n }\n return observe\n}\n","// api/on-submit.ts\n// Registers a submit handler. preventDefault=true intercepts valid submits,\n// which is the right choice for AJAX/fetch flows. Invalid submits are\n// always prevented regardless of the flag.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormSubmitHandler } from '../core/types'\n\nexport const createOnSubmit =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (callback: FormSubmitHandler, preventDefault = true) => {\n if (state.isDestroyed) return state.api!\n state.submitHandlers.add({ callback, preventDefault })\n return state.api!\n }\n","// api/prefill.ts\n// Reads window.location.search and writes matching values into the form.\n// Pass a field name to scope prefill to a single field. Repeated keys\n// (`?tags[]=a&tags[]=b`) are written together as one array.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createPrefill =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fieldName?: string) => {\n if (!state.element || state.isDestroyed) return state.api!\n\n const params = new URLSearchParams(window.location.search)\n const keys = Array.from(new Set(params.keys())).filter(\n key => !fieldName || fieldName === key\n )\n if (keys.length === 0) return state.api!\n\n // Every written field still runs the delegated pipeline (watchers,\n // validation, visual state); auto-submit waits for the whole batch.\n state.autoSubmitSuspended = true\n try {\n for (const key of keys) {\n const values = params.getAll(key)\n state.api!.setValue(key, values.length > 1 ? values : values[0])\n }\n } finally {\n state.autoSubmitSuspended = false\n }\n helpers.scheduleAutoSubmit()\n return state.api!\n }\n","// api/reset.ts\n// Resets the native form, clears manual and validation errors, strips\n// css-filled/css-error attributes, re-emits field watchers and notifies\n// subscribers. Native reset buttons run the same state pass.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\n\nexport const createReset =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n () => {\n if (!state.element || state.isDestroyed) return state.api!\n\n state.isResetting = true\n try {\n state.element.reset()\n } finally {\n state.isResetting = false\n }\n helpers.applyReset()\n return state.api!\n }\n","// api/validate.ts\n// Runs validation. Marks the form as validated, syncs visual state, and\n// returns the validation result for callers that want it.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { ValidationResult } from '../core/types'\n\nexport const createValidate =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields?: string[]): ValidationResult => {\n // A destroyed controller owns no errors; never repaint the form again.\n if (state.isDestroyed) return { isValid: true, errors: {} }\n state.isValidated = true\n // validateNames synchronizes visual state for the same field set.\n return helpers.validateNames(fields)\n }\n","// api/revalidate.ts\n// Alias of validate(); kept separate for readability at call sites that\n// want to express \"re-run validation now\".\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport { createValidate } from './validate'\n\nexport const createRevalidate = createValidate\n","// api/set-errors.ts\n// Sets manual errors. Accepts an array of field names (each gets a\n// generic message) or a FormErrors map with per-field messages.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormErrors } from '../core/types'\nimport { cloneErrors } from '../core/state'\n\nexport const createSetErrors =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (fields: string[] | FormErrors) => {\n if (state.isDestroyed) return state.api!\n if (Array.isArray(fields)) {\n state.manualErrors = {\n ...state.manualErrors,\n ...Object.fromEntries(fields.map(field => [field, ['Invalid value.']]))\n }\n } else {\n state.manualErrors = {\n ...state.manualErrors,\n ...cloneErrors(fields)\n }\n }\n\n helpers.syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields))\n helpers.notifySubscribers()\n return state.api!\n }\n","// api/set-options.ts\n// Replaces the <option>/<optgroup> children of every <select> with the\n// given name. Labels are written as text, never as HTML. The previous\n// selection survives when its value is still listed (unless the caller\n// marks options as `selected` or passes `keepValue: false`). The change\n// pipeline (validation, watchers, subscribers, auto-submit) runs through\n// one `input` event, and only when a selected value actually changed.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { SelectOption, SelectOptionInput, SetOptionsConfig } from '../core/types'\n\nconst isGroup = (\n entry: SelectOptionInput\n): entry is Extract<SelectOptionInput, { options: unknown }> =>\n typeof entry === 'object' &&\n entry !== null &&\n Array.isArray((entry as { options?: unknown }).options)\n\nconst createOption = (entry: string | number | SelectOption): HTMLOptionElement => {\n const option = document.createElement('option')\n if (typeof entry === 'object') {\n option.value = String(entry.value)\n option.textContent = entry.label ?? String(entry.value)\n option.disabled = Boolean(entry.disabled)\n if (entry.selected) option.defaultSelected = true\n } else {\n option.value = String(entry)\n option.textContent = String(entry)\n }\n return option\n}\n\nconst buildNodes = (options: SelectOptionInput[]) => {\n const nodes: Array<HTMLOptionElement | HTMLOptGroupElement> = []\n let hasExplicitSelection = false\n const track = (option: HTMLOptionElement) => {\n if (option.defaultSelected) hasExplicitSelection = true\n return option\n }\n\n for (const entry of options) {\n if (entry === null || entry === undefined) continue\n if (isGroup(entry)) {\n const group = document.createElement('optgroup')\n group.label = entry.label\n group.disabled = Boolean(entry.disabled)\n for (const child of entry.options) {\n if (child === null || child === undefined) continue\n group.appendChild(track(createOption(child)))\n }\n nodes.push(group)\n continue\n }\n nodes.push(track(createOption(entry)))\n }\n\n return { nodes, hasExplicitSelection }\n}\n\nconst selectedValues = (select: HTMLSelectElement): string[] =>\n Array.from(select.selectedOptions, option => option.value)\n\nconst restoreSelection = (select: HTMLSelectElement, previous: string[]) => {\n if (previous.length === 0) return\n const options = Array.from(select.options)\n if (select.multiple) {\n for (const option of options) option.selected = previous.includes(option.value)\n return\n }\n const match = options.find(option => option.value === previous[0])\n if (match) match.selected = true\n}\n\nconst sameValues = (left: string[], right: string[]) =>\n left.length === right.length && left.every((value, index) => value === right[index])\n\nexport const createSetOptions =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string, options: SelectOptionInput[], config: SetOptionsConfig = {}) => {\n if (!state.element || state.isDestroyed) return state.api!\n const selects = helpers\n .getFieldsByName(name)\n .filter((field): field is HTMLSelectElement => field instanceof HTMLSelectElement)\n if (selects.length === 0) return state.api!\n\n const keepValue = config.keepValue ?? true\n const changed: HTMLSelectElement[] = []\n\n for (const select of selects) {\n const previous = selectedValues(select)\n const { nodes, hasExplicitSelection } = buildNodes(options)\n select.replaceChildren(...nodes)\n if (keepValue && !hasExplicitSelection) restoreSelection(select, previous)\n if (!sameValues(previous, selectedValues(select))) changed.push(select)\n }\n\n // The option swap is handled here; the mutation observer must not\n // process it a second time.\n helpers.commitOwnMutations(selects)\n\n changed[0]?.dispatchEvent(new Event('input', { bubbles: true }))\n return state.api!\n }\n","// api/set-value.ts\n// Writes a value into a field and dispatches the correct DOM event so\n// listeners, validators, and visual state run as if a user typed.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport { writeFieldValue } from '../core/dom'\n\nexport const createSetValue =\n (state: FormControllerState, helpers: FormControllerHelpers) =>\n (name: string, value: unknown) => {\n if (state.isDestroyed) return state.api!\n const fields = helpers.getFieldsByName(name)\n if (fields.length === 0) return state.api!\n\n writeFieldValue(fields, value)\n const firstField = fields[0]\n if (!firstField) return state.api!\n\n firstField.dispatchEvent(new Event('input', { bubbles: true }))\n return state.api!\n }\n","// api/subscribe.ts\n// Subscribes to global form state. Listener fires once immediately with\n// the current snapshot, then on every state mutation. Returns an\n// unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormStateListener } from '../core/types'\n\nexport const createSubscribe =\n (state: FormControllerState, _helpers: FormControllerHelpers) =>\n (listener: FormStateListener) => {\n if (state.isDestroyed) return () => undefined\n state.subscribers.add(listener)\n listener(state.api!.getState())\n return () => {\n state.subscribers.delete(listener)\n }\n }\n","// api/unwatch.ts\n// Removes watched callbacks. With no args, clears every watcher. With only\n// a field, removes all callbacks for that field. With field + callback,\n// removes just that callback. A list of fields targets watchers registered\n// with that same list (order and duplicates do not matter).\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormController, FormFieldsWatcher, FormFieldWatcher } from '../core/types'\n\nconst sameFields = (left: string[], right: Set<string>) =>\n left.length === right.size && left.every(name => right.has(name))\n\nexport const createUnwatch = (state: FormControllerState, _helpers: FormControllerHelpers) => {\n function unwatch(field?: string, callback?: FormFieldWatcher): FormController\n function unwatch(fields: string[], callback?: FormFieldsWatcher): FormController\n function unwatch(\n field?: string | string[],\n callback?: FormFieldWatcher | FormFieldsWatcher\n ): FormController {\n if (field === undefined || field === '') {\n state.watchedFields.clear()\n state.groupWatchers.clear()\n return state.api!\n }\n\n if (Array.isArray(field)) {\n const names = new Set(field)\n for (const entry of Array.from(state.groupWatchers)) {\n if (!sameFields(entry.fields, names)) continue\n if (callback && entry.callback !== callback) continue\n state.groupWatchers.delete(entry)\n }\n return state.api!\n }\n\n if (!callback) {\n state.watchedFields.delete(field)\n return state.api!\n }\n\n const callbacks = state.watchedFields.get(field)\n callbacks?.delete(callback as FormFieldWatcher)\n if (callbacks && callbacks.size === 0) {\n state.watchedFields.delete(field)\n }\n return state.api!\n }\n return unwatch\n}\n","// api/watch.ts\n// Chainable alias over `observe`. Use this when you want a fluent setup\n// without holding the returned unsubscribe function.\n\nimport type { FormControllerHelpers, FormControllerState } from '../core/state'\nimport type { FormController, FormFieldsWatcher, FormFieldWatcher } from '../core/types'\nimport { createObserve } from './observe'\n\nexport const createWatch = (state: FormControllerState, helpers: FormControllerHelpers) => {\n const observe = createObserve(state, helpers)\n function watch(field: string, callback: FormFieldWatcher): FormController\n function watch(fields: string[], callback: FormFieldsWatcher): FormController\n function watch(field: string | string[], callback: FormFieldWatcher | FormFieldsWatcher) {\n if (Array.isArray(field)) observe(field, callback as FormFieldsWatcher)\n else observe(field, callback as FormFieldWatcher)\n return state.api!\n }\n return watch\n}\n","// Pure validation routines. No DOM, no controller state.\n\nimport type {\n FieldValidationContext,\n FieldValidationRules,\n FormErrors,\n FormFieldValue,\n FormValues,\n RuleConfig,\n ValueValidationRules,\n ValidationResult,\n ValidationSchema\n} from './types'\n\nconst resolveRule = <T>(rule: RuleConfig<T> | undefined) => {\n if (rule === undefined) {\n return { value: undefined as T | undefined, message: undefined as string | undefined }\n }\n if (typeof rule === 'object' && rule !== null && 'value' in rule) {\n return { value: rule.value, message: rule.message }\n }\n return { value: rule, message: undefined as string | undefined }\n}\n\nconst hasValue = (value: FormFieldValue): boolean => {\n if (Array.isArray(value)) return value.length > 0\n if (typeof value === 'string') return value.trim().length > 0\n return value !== undefined\n}\n\nconst getValueLength = (value: FormFieldValue): number => {\n if (Array.isArray(value)) return value.length\n if (typeof value === 'string') return value.length\n return 0\n}\n\nconst toPatternTarget = (value: FormFieldValue): string => {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n return value\n .map(entry => (typeof entry === 'string' ? entry : entry.name))\n .join(',')\n }\n return ''\n}\n\nconst valuesAreEqual = (left: FormFieldValue, right: FormFieldValue): boolean => {\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((entry, index) => entry === right[index])\n }\n return left === right\n}\n\nconst DECIMAL_PATTERN = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)$/\n\nconst parseStrictNumber = (value: FormFieldValue): number | undefined => {\n if (typeof value !== 'string') return undefined\n const candidate = value.trim()\n if (!DECIMAL_PATTERN.test(candidate)) return undefined\n const number = Number(candidate)\n return Number.isFinite(number) ? number : undefined\n}\n\nexport interface FieldValidationItem {\n value: FormFieldValue\n element?: import('./types').FormFieldElement\n}\n\nexport interface DetailedValidationResult {\n groupErrors: string[]\n itemErrors: Array<{\n index: number\n element?: import('./types').FormFieldElement\n messages: string[]\n }>\n}\n\nconst validateValue = (\n field: string,\n value: FormFieldValue,\n rules: ValueValidationRules,\n values: FormValues,\n contextOverrides: Partial<Pick<FieldValidationContext, 'element' | 'index'>> = {}\n): string[] => {\n const errors: string[] = []\n const context: FieldValidationContext = {\n field,\n value,\n values,\n ...contextOverrides\n }\n const required = resolveRule(rules.required)\n const minLength = resolveRule(rules.minLength)\n const maxLength = resolveRule(rules.maxLength)\n const pattern = resolveRule(rules.pattern)\n const numeric = resolveRule(rules.numeric)\n const min = resolveRule(rules.min)\n const max = resolveRule(rules.max)\n\n if (required.value && !hasValue(value)) {\n errors.push(required.message ?? 'This field is required.')\n }\n if (minLength.value !== undefined && getValueLength(value) < minLength.value) {\n errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`)\n }\n if (maxLength.value !== undefined && getValueLength(value) > maxLength.value) {\n errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`)\n }\n if (pattern.value && hasValue(value)) {\n pattern.value.lastIndex = 0\n const matches = pattern.value.test(toPatternTarget(value))\n pattern.value.lastIndex = 0\n if (!matches) {\n errors.push(pattern.message ?? 'Value does not match the required pattern.')\n }\n }\n\n if (hasValue(value) && (numeric.value || min.value !== undefined || max.value !== undefined)) {\n const number = parseStrictNumber(value)\n if (number === undefined) {\n errors.push(numeric.message ?? 'Value must be a number.')\n } else {\n if (min.value !== undefined && number < min.value) {\n errors.push(min.message ?? `Minimum value is ${min.value}.`)\n }\n if (max.value !== undefined && number > max.value) {\n errors.push(max.message ?? `Maximum value is ${max.value}.`)\n }\n }\n }\n\n const custom = rules.validate\n ? Array.isArray(rules.validate)\n ? rules.validate\n : [rules.validate]\n : []\n\n for (const validator of custom) {\n const result = validator(context)\n if (typeof result === 'string' && result.length > 0) errors.push(result)\n if (result === false) errors.push('Validation failed.')\n }\n\n return errors\n}\n\nexport const validateFieldValueDetailed = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues,\n items?: FieldValidationItem[]\n): DetailedValidationResult => {\n const groupErrors = validateValue(field, value, rules, values)\n const sameAs = resolveRule(rules.sameAs)\n\n if (sameAs.value !== undefined) {\n const otherValue = values[sameAs.value]\n if (hasValue(value) && hasValue(otherValue) && !valuesAreEqual(value, otherValue)) {\n groupErrors.push(sameAs.message ?? `Value must match ${sameAs.value}.`)\n }\n }\n\n const itemErrors: DetailedValidationResult['itemErrors'] = []\n if (rules.each) {\n const sourceItems: FieldValidationItem[] =\n items ??\n (Array.isArray(value)\n ? value.map(entry => ({\n value: typeof entry === 'string' ? entry : ([entry] as File[])\n }))\n : [{ value }])\n\n sourceItems.forEach((item, index) => {\n const overrides: Partial<Pick<FieldValidationContext, 'element' | 'index'>> = {\n index\n }\n if (item.element) overrides.element = item.element\n const messages = validateValue(field, item.value, rules.each!, values, overrides)\n if (messages.length === 0) return\n const error: DetailedValidationResult['itemErrors'][number] = {\n index,\n messages\n }\n if (item.element) error.element = item.element\n itemErrors.push(error)\n })\n }\n\n return { groupErrors, itemErrors }\n}\n\nexport const validateFieldValue = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues\n): string[] => {\n const result = validateFieldValueDetailed(field, value, rules, values)\n return [...result.groupErrors, ...result.itemErrors.flatMap(item => item.messages)]\n}\n\nexport const validateValues = (\n values: FormValues,\n schema: ValidationSchema\n): ValidationResult => {\n const errors: FormErrors = {}\n for (const [field, rules] of Object.entries(schema)) {\n const messages = validateFieldValue(field, values[field], rules, values)\n if (messages.length > 0) errors[field] = messages\n }\n return {\n isValid: Object.keys(errors).length === 0,\n errors\n }\n}\n","// Core orchestrator. Wires shared state, internal helpers and the public\n// api method factories into a single FormController instance.\n//\n// Internal event handlers and DOM wiring live here. Every public method\n// lives in `../api/<method>.ts` as an isolated factory.\n\nimport { createAppend } from '../api/append'\nimport { createAddCleanup } from '../api/add-cleanup'\nimport { createAutoSubmit } from '../api/auto-submit'\nimport { createClearErrors } from '../api/clear-errors'\nimport { createDestroy } from '../api/destroy'\nimport { createDisableAutoSubmit } from '../api/disable-auto-submit'\nimport {\n createFormat,\n createFormatAll,\n resolveCanonicalForName,\n resolveDisplayNameForName,\n resetFormattedFields\n} from '../api/format'\nimport { createGetData } from '../api/get-data'\nimport { createGetField } from '../api/get-field'\nimport { createGetState } from '../api/get-state'\nimport { createGetValue } from '../api/get-value'\nimport { createObserve } from '../api/observe'\nimport { createOnSubmit } from '../api/on-submit'\nimport { createPrefill } from '../api/prefill'\nimport { createReset } from '../api/reset'\nimport { createRevalidate } from '../api/revalidate'\nimport { createSetErrors } from '../api/set-errors'\nimport { createSetOptions } from '../api/set-options'\nimport { createSetValue } from '../api/set-value'\nimport { createSubscribe } from '../api/subscribe'\nimport { createUnwatch } from '../api/unwatch'\nimport { createValidate } from '../api/validate'\nimport { createWatch } from '../api/watch'\nimport { validateFieldValueDetailed } from '../core/validation'\nimport { parseFormData } from './serialize'\nimport {\n applyBooleanAttribute,\n clearAttributes,\n getNamedFields,\n isFieldElement,\n isFieldFilled,\n queryNamedFields,\n readFieldValue,\n resolveFormElement,\n submitForm,\n writeFieldValue\n} from './dom'\nimport { cloneErrors, mergeErrors } from './state'\nimport type {\n FormController,\n FormControllerOptions,\n FormFieldElement,\n FormFieldValue,\n FormTarget,\n ValidationResult,\n VisualAttributes\n} from './types'\nimport type { FormControllerHelpers, FormControllerState } from './state'\n\nconst DEFAULT_ATTRIBUTES: Required<VisualAttributes> = {\n filled: 'css-filled',\n error: 'css-error'\n}\n\nconst DEFAULT_OPTIONS = {\n autoValidate: true,\n clearErrorsOnSubmit: true,\n clearManualErrorsOnChange: true\n} satisfies Pick<\n FormControllerOptions,\n 'autoValidate' | 'clearErrorsOnSubmit' | 'clearManualErrorsOnChange'\n>\n\nexport const createFormController = (\n target: FormTarget,\n options: FormControllerOptions = {}\n): FormController => {\n const element = resolveFormElement(target)\n const attributes = { ...DEFAULT_ATTRIBUTES, ...options.attributes }\n const normalizedOptions: FormControllerOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n attributes\n }\n\n const state: FormControllerState = {\n element,\n options: normalizedOptions,\n attributes,\n validators: normalizedOptions.validators ?? {},\n watchedFields: new Map(),\n groupWatchers: new Set(),\n subscribers: new Set(),\n submitHandlers: new Set(),\n fieldCache: new Map(),\n manualErrors: {},\n validationErrors: {},\n validationGroupErrors: {},\n validationElementErrors: new Map(),\n isValidated: Boolean(normalizedOptions.autoValidate),\n autoSubmitEnabled: false,\n autoSubmitDebounce: 0,\n submitCount: 0,\n pendingSubmitCount: 0,\n autoSubmitTimer: null,\n isAutoSubmitting: false,\n autoSubmitSuspended: false,\n isResetting: false,\n isDestroyed: false,\n listeners: [],\n mutationObserver: null,\n cleanups: new Set(),\n formattedFields: new Map(),\n api: null\n }\n\n // Reverse cross-field references once so source changes can revalidate\n // dependent fields without installing per-field listeners.\n const validationDependents = new Map<string, Set<string>>()\n for (const [field, rules] of Object.entries(state.validators)) {\n const sources = new Set<string>()\n const sameAs = rules.sameAs\n if (sameAs !== undefined) {\n sources.add(typeof sameAs === 'string' ? sameAs : sameAs.value)\n }\n if (typeof rules.dependsOn === 'string') sources.add(rules.dependsOn)\n else rules.dependsOn?.forEach(source => sources.add(source))\n\n for (const source of sources) {\n const dependents = validationDependents.get(source) ?? new Set<string>()\n dependents.add(field)\n validationDependents.set(source, dependents)\n }\n }\n\n // ------- Internal helpers (no DOM wiring of their own) -----------------\n\n const notifySubscribers = () => {\n if (!state.api) return\n const snapshot = state.api.getState()\n state.subscribers.forEach(listener => listener(snapshot))\n }\n\n const addListener = (\n node: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject,\n capture?: boolean\n ) => {\n if (capture) {\n node.addEventListener(type, handler, { capture: true })\n } else {\n node.addEventListener(type, handler)\n }\n // `exactOptionalPropertyTypes: true` rejects explicit `undefined`\n // values for optional properties; only attach `capture` when it\n // actually has a value.\n const entry: {\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n capture?: boolean\n } = { element: node, type, handler }\n if (capture !== undefined) entry.capture = capture\n state.listeners.push(entry)\n }\n\n const clearFieldCache = () => state.fieldCache.clear()\n\n const getFieldsByName = (name: string): FormFieldElement[] => {\n if (!state.element) return []\n const fields = queryNamedFields(state.element, name)\n state.fieldCache.set(name, fields)\n return fields\n }\n\n // Group every named control in one pass over `form.elements`. Reading\n // all values field-by-field would rescan the collection once per name.\n const indexFieldsByName = (): Map<string, FormFieldElement[]> => {\n const index = new Map<string, FormFieldElement[]>()\n if (!state.element) return index\n for (const field of getNamedFields(state.element)) {\n const bucket = index.get(field.name)\n if (bucket) bucket.push(field)\n else index.set(field.name, [field])\n }\n return index\n }\n\n const getTrackedFieldNames = (index = indexFieldsByName()): string[] => {\n if (!state.element) return Object.keys(state.validators)\n const names = new Set<string>(Object.keys(state.validators))\n for (const name of index.keys()) names.add(name)\n // The formatted registry keeps the canonical name as the bucket\n // key. The display name (e.g. `phone_displayed`) is also a\n // tracked field because the developer can `watch`/`getValue` it\n // and `getData()` exposes it in the serialized payload.\n for (const [canonical, entry] of state.formattedFields) {\n names.add(canonical)\n if (entry.displayName && entry.displayName !== canonical) {\n names.add(entry.displayName)\n }\n }\n return Array.from(names)\n }\n\n const getValues = () => {\n const values: Record<string, FormFieldValue> = {}\n const index = indexFieldsByName()\n for (const name of getTrackedFieldNames(index)) {\n values[name] = readFieldValue(index.get(name) ?? [])\n }\n return values\n }\n\n const getMergedErrors = () => mergeErrors(state.validationErrors, state.manualErrors)\n\n const syncVisualState = (names?: string[]) => {\n if (!state.element) return\n\n // Resolve every input name to its display name so visual\n // attributes (`css-filled`, `css-error`) land on the visible\n // input, never on the hidden raw mirror. After `format()` runs\n // the canonical name (`phone`) is held by the hidden, which\n // lives at the end of the form, outside any label wrapper —\n // so writing the attribute there is invisible to the project\n // CSS that targets `:has([css-error])` on a parent label. The\n // visual attribute contract is documented in\n // `api/format.ts:resolveDisplayNameForName` and in\n // `docs/css-styling.md`.\n //\n // Errors are still keyed by canonical name (the backend's\n // view of the field); reverse-resolve so the lookup works\n // whether the caller passed canonical, display, or both.\n const sourceNames = names ?? getTrackedFieldNames()\n for (const name of sourceNames) {\n const displayName = resolveDisplayNameForName(state, name)\n const canonical = resolveCanonicalForName(state, name) ?? name\n const fields = getFieldsByName(displayName)\n const hasGroupError = Boolean(\n state.validationGroupErrors[canonical]?.length || state.manualErrors[canonical]?.length\n )\n const elementErrors = state.validationElementErrors.get(canonical)\n fields.forEach(field => {\n const hasError = hasGroupError || Boolean(elementErrors?.get(field)?.length)\n applyBooleanAttribute(field, attributes.filled, isFieldFilled(field))\n applyBooleanAttribute(field, attributes.error, hasError)\n if (hasError) field.setAttribute('aria-invalid', 'true')\n else field.removeAttribute('aria-invalid')\n })\n }\n }\n\n // readFieldValue/writeFieldValue are exported from core/dom for direct\n // callers; referenced here so the linter keeps them as part of the\n // controlled API surface.\n void readFieldValue\n void writeFieldValue\n\n const validateNames = (names?: string[]): ValidationResult => {\n const targetNames = names ?? Object.keys(state.validators)\n const values = getValues()\n const nextValidationErrors = names ? cloneErrors(state.validationErrors) : {}\n const nextGroupErrors = names ? cloneErrors(state.validationGroupErrors) : {}\n const nextElementErrors = names\n ? new Map(state.validationElementErrors)\n : new Map<string, Map<FormFieldElement, string[]>>()\n\n for (const name of targetNames) {\n const rules = state.validators[name]\n if (!rules) {\n delete nextValidationErrors[name]\n delete nextGroupErrors[name]\n nextElementErrors.delete(name)\n continue\n }\n const fields = getFieldsByName(name)\n const displayFields = getFieldsByName(resolveDisplayNameForName(state, name))\n const items = fields.map((field, index) => ({\n value: readFieldValue([field]),\n element: displayFields[index] ?? field\n }))\n const result = validateFieldValueDetailed(name, values[name], rules, values, items)\n const messages = [...result.groupErrors, ...result.itemErrors.flatMap(item => item.messages)]\n if (messages.length > 0) nextValidationErrors[name] = messages\n else delete nextValidationErrors[name]\n\n if (result.groupErrors.length > 0) nextGroupErrors[name] = result.groupErrors\n else delete nextGroupErrors[name]\n\n const perElement = new Map<FormFieldElement, string[]>()\n result.itemErrors.forEach(item => {\n if (item.element) perElement.set(item.element, item.messages)\n })\n if (perElement.size > 0) nextElementErrors.set(name, perElement)\n else nextElementErrors.delete(name)\n }\n\n state.validationErrors = nextValidationErrors\n state.validationGroupErrors = nextGroupErrors\n state.validationElementErrors = nextElementErrors\n syncVisualState(names)\n\n return {\n isValid: Object.keys(getMergedErrors()).length === 0,\n errors: cloneErrors(getMergedErrors())\n }\n }\n\n const getAffectedValidationNames = (name: string): string[] => {\n const affected: string[] = []\n const pending = [name]\n const visited = new Set<string>()\n\n for (let index = 0; index < pending.length; index += 1) {\n const current = pending[index]!\n if (visited.has(current)) continue\n visited.add(current)\n affected.push(current)\n\n for (const dependent of validationDependents.get(current) ?? []) {\n if (!visited.has(dependent)) pending.push(dependent)\n }\n }\n\n return affected\n }\n\n const emitSingleWatchers = (name: string) => {\n if (!state.element || !state.api) return\n const callbacks = state.watchedFields.get(name)\n if (!callbacks || callbacks.size === 0) return\n const value = state.api.getValue(name)\n const fieldElement = state.api.getField(name)\n const snapshot = state.api.getState()\n callbacks.forEach(callback => callback(value, fieldElement, state.element!, snapshot))\n }\n\n // Calls every multi-field watcher that lists one of `names`, once, with\n // the first matching name as `changed`. `null` calls every one of them\n // with `changed: null` (reset).\n const emitGroupWatchers = (names: string[] | null) => {\n if (!state.element || !state.api || state.groupWatchers.size === 0) return\n let snapshot: ReturnType<FormController['getState']> | undefined\n for (const entry of Array.from(state.groupWatchers)) {\n const changed = names ? names.find(name => entry.fields.includes(name)) : null\n if (changed === undefined) continue\n snapshot ??= state.api.getState()\n const values = Object.fromEntries(\n entry.fields.map(field => [field, state.api!.getValue(field)])\n )\n entry.callback(values, changed, state.element, snapshot)\n }\n }\n\n const emitFieldWatchers = (name: string) => {\n emitSingleWatchers(name)\n emitGroupWatchers([name])\n }\n\n // `requestSubmit()` dispatches `submit` synchronously, so the flag tells\n // the submit handler that no user asked to submit. An invalid automatic\n // submission must not move focus away from the field being edited.\n const runAutoSubmit = () => {\n state.autoSubmitTimer = null\n if (!state.element || state.isDestroyed || !state.autoSubmitEnabled) return\n state.isAutoSubmitting = true\n try {\n submitForm(state.element)\n } finally {\n state.isAutoSubmitting = false\n }\n }\n\n const scheduleAutoSubmit = () => {\n if (!state.element || !state.autoSubmitEnabled || state.autoSubmitSuspended) return\n if (state.autoSubmitTimer) clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n if (state.autoSubmitDebounce > 0) {\n state.autoSubmitTimer = setTimeout(runAutoSubmit, state.autoSubmitDebounce)\n return\n }\n runAutoSubmit()\n }\n\n // Last selection seen for every <select>, so option-list mutations made\n // outside the controller fire watchers only when the selection changed.\n const selectSnapshots = new WeakMap<HTMLSelectElement, string>()\n\n const readSelectSnapshot = (select: HTMLSelectElement) =>\n Array.from(select.selectedOptions, option => option.value).join('\\u0000')\n\n const snapshotSelect = (select: HTMLSelectElement) => {\n selectSnapshots.set(select, readSelectSnapshot(select))\n }\n\n const snapshotAllSelects = () => {\n if (!state.element) return\n for (const field of getNamedFields(state.element)) {\n if (field instanceof HTMLSelectElement) snapshotSelect(field)\n }\n }\n\n const emitAllFieldWatchers = () => {\n for (const name of Array.from(state.watchedFields.keys())) emitSingleWatchers(name)\n emitGroupWatchers(null)\n }\n\n // Shared by `reset()` and native reset buttons: values are already back\n // to their defaults, so clear every error and resynchronize the DOM.\n const applyReset = () => {\n if (!state.element || state.isDestroyed) return\n clearFieldCache()\n resetFormattedFields(state)\n state.manualErrors = {}\n state.validationErrors = {}\n state.validationGroupErrors = {}\n state.validationElementErrors.clear()\n clearAttributes(state.element, [attributes.error, attributes.filled, 'aria-invalid'])\n syncVisualState()\n snapshotAllSelects()\n emitAllFieldWatchers()\n notifySubscribers()\n }\n\n const helpers: FormControllerHelpers = {\n notifySubscribers,\n clearFieldCache,\n getFieldsByName,\n getTrackedFieldNames: () => getTrackedFieldNames(),\n getValues,\n getMergedErrors,\n syncVisualState,\n validateNames,\n emitFieldWatchers,\n scheduleAutoSubmit,\n applyReset,\n commitOwnMutations: selects => commitOwnMutations(selects)\n }\n\n // ------- DOM event wiring ---------------------------------------------\n\n const handleDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) return\n const name = target.name\n if (!name) return\n\n clearFieldCache()\n if (target instanceof HTMLSelectElement) snapshotSelect(target)\n\n // A formatted field is exposed under two names: the canonical\n // (e.g. `phone`, on the hidden raw mirror) and the display\n // (`phone_displayed`, on the visible). Resolve whichever side\n // fired this event to the canonical so the controller's\n // validation + error-clearing path runs once on the field the\n // backend actually reads. The display name is the visible's\n // name — `syncVisualState` targets it so visual attributes\n // (`css-filled`, `css-error`) land on the element the user\n // sees, not on the hidden. Project CSS commonly uses\n // `:has([css-filled])` on a parent label to animate the\n // label; that selector only matches when the visible (inside\n // the label) carries the attribute, never the hidden.\n const canonical = resolveCanonicalForName(state, name) ?? name\n const displayName = resolveDisplayNameForName(state, name)\n\n if (normalizedOptions.clearManualErrorsOnChange) {\n delete state.manualErrors[canonical]\n }\n\n syncVisualState([displayName])\n\n const affectedValidationNames = getAffectedValidationNames(canonical)\n if (\n state.isValidated &&\n affectedValidationNames.some(field => state.validators[field] !== undefined)\n ) {\n validateNames(affectedValidationNames)\n }\n\n emitSingleWatchers(canonical)\n if (canonical !== name) emitSingleWatchers(name)\n emitGroupWatchers(canonical !== name ? [canonical, name] : [canonical])\n notifySubscribers()\n scheduleAutoSubmit()\n }\n\n const handleExternalDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) return\n if (target.form !== state.element || state.element?.contains(target)) return\n handleDelegatedEvent(event)\n }\n\n const isFocusable = (candidate: FormFieldElement) => {\n if (!candidate.isConnected || candidate.disabled || candidate.hidden) return false\n return !(candidate instanceof HTMLInputElement && candidate.type === 'hidden')\n }\n\n // Focus the invalid control that comes first in the document, not the\n // first rule declared in the schema, so keyboard users land where the\n // form visually starts failing.\n const focusFirstInvalidField = (errors: Record<string, string[]>) => {\n const candidates: FormFieldElement[] = []\n for (const name of Object.keys(errors)) {\n const fields = getFieldsByName(resolveDisplayNameForName(state, name)).filter(isFocusable)\n const elementErrors = state.validationElementErrors.get(name)\n const field = fields.find(candidate => elementErrors?.has(candidate)) ?? fields[0]\n if (field) candidates.push(field)\n }\n candidates.sort((left, right) =>\n left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1\n )\n candidates[0]?.focus()\n }\n\n const handleSubmitEvent = (event: Event) => {\n if (!state.element || state.isDestroyed || !state.api) return\n\n // A submission the user started supersedes a pending debounced\n // auto-submit; letting the timer run would submit the form twice.\n if (!state.isAutoSubmitting && state.autoSubmitTimer) {\n clearTimeout(state.autoSubmitTimer)\n state.autoSubmitTimer = null\n }\n\n if (normalizedOptions.clearErrorsOnSubmit) state.manualErrors = {}\n\n const validation = state.api.validate()\n const handlers = Array.from(state.submitHandlers)\n const shouldPrevent = validation.isValid\n ? handlers.some(handler => handler.preventDefault)\n : true\n\n if (shouldPrevent) event.preventDefault()\n\n state.submitCount += 1\n notifySubscribers()\n\n if (!validation.isValid) {\n if (!state.isAutoSubmitting) focusFirstInvalidField(validation.errors)\n return\n }\n\n const candidate = event as Event & { submitter?: unknown }\n const submitter = candidate.submitter instanceof HTMLElement\n ? candidate.submitter\n : null\n const { data, formData } = parseFormData(state.element, submitter)\n const snapshot = state.api.getState()\n const pending: Promise<void>[] = []\n let synchronousError: unknown\n let hasSynchronousError = false\n try {\n for (const handler of handlers) {\n const result = handler.callback(state.element!, data, formData, snapshot)\n if (result && typeof result.then === 'function') {\n pending.push(\n Promise.resolve(result).catch(error => {\n console.error('[forms] submit handler failed', error)\n })\n )\n }\n }\n } catch (error) {\n synchronousError = error\n hasSynchronousError = true\n }\n\n if (pending.length > 0) {\n state.pendingSubmitCount += 1\n notifySubscribers()\n void Promise.allSettled(pending).then(() => {\n state.pendingSubmitCount = Math.max(0, state.pendingSubmitCount - 1)\n if (!state.isDestroyed) notifySubscribers()\n })\n }\n\n if (hasSynchronousError) throw synchronousError\n }\n\n // The `reset` event fires before the browser restores default values,\n // and a user-initiated reset runs microtasks between the two steps, so\n // the state pass waits for the next task. `reset()` handles itself.\n const handleResetEvent = (event: Event) => {\n if (state.isResetting) return\n const timer = setTimeout(() => {\n state.cleanups.delete(cancel)\n if (!event.defaultPrevented) applyReset()\n }, 0)\n const cancel = () => clearTimeout(timer)\n state.cleanups.add(cancel)\n }\n\n const touchesFields = (node: Node) =>\n node instanceof Element &&\n (isFieldElement(node) || node.querySelector('input, select, textarea') !== null)\n\n // Error messages or other markup rendered into the form by a subscriber\n // must not re-enter validation; that would notify the same subscriber\n // again and loop. Only control additions/removals and renames count.\n const isStructural = (record: MutationRecord) =>\n record.type === 'attributes' ||\n Array.from(record.addedNodes).some(touchesFields) ||\n Array.from(record.removedNodes).some(touchesFields)\n\n const isOptionNode = (node: Node) =>\n node instanceof HTMLOptionElement || node instanceof HTMLOptGroupElement\n\n // The <select> whose option list a childList record changed, if any.\n const optionListOwner = (record: MutationRecord): HTMLSelectElement | null => {\n if (record.type !== 'childList') return null\n const touchesOptions =\n Array.from(record.addedNodes).some(isOptionNode) ||\n Array.from(record.removedNodes).some(isOptionNode)\n if (!touchesOptions) return null\n const target = record.target\n if (target instanceof HTMLSelectElement) return target\n if (\n target instanceof HTMLOptGroupElement &&\n target.parentElement instanceof HTMLSelectElement\n ) {\n return target.parentElement\n }\n return null\n }\n\n const handleMutations = (records: MutationRecord[]) => {\n if (state.isDestroyed) return\n const structural = records.some(isStructural)\n const changedNames = new Set<string>()\n\n for (const record of records) {\n const select = optionListOwner(record)\n if (!select || !select.name) continue\n const next = readSelectSnapshot(select)\n if (selectSnapshots.get(select) !== next) changedNames.add(select.name)\n selectSnapshots.set(select, next)\n }\n\n if (!structural && changedNames.size === 0) return\n clearFieldCache()\n\n if (structural) {\n snapshotAllSelects()\n if (state.isValidated) validateNames()\n else syncVisualState()\n } else {\n const affected = new Set<string>()\n for (const name of changedNames) {\n for (const field of getAffectedValidationNames(name)) affected.add(field)\n }\n const names = Array.from(affected)\n syncVisualState(Array.from(changedNames))\n if (state.isValidated && names.some(field => state.validators[field] !== undefined)) {\n validateNames(names)\n }\n }\n\n for (const name of changedNames) emitFieldWatchers(name)\n notifySubscribers()\n }\n\n // Called by api methods that rewrite option lists themselves: drop the\n // records those writes produced, keep processing everything else.\n const commitOwnMutations = (selects: HTMLSelectElement[]) => {\n selects.forEach(snapshotSelect)\n const pending = state.mutationObserver?.takeRecords() ?? []\n const foreign = pending.filter(\n record => !selects.some(select => select.contains(record.target))\n )\n if (foreign.length > 0) handleMutations(foreign)\n }\n\n const startMutationObserver = () => {\n if (!state.element || typeof MutationObserver === 'undefined') return\n\n state.mutationObserver = new MutationObserver(handleMutations)\n\n state.mutationObserver.observe(state.element, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['name', 'type']\n })\n }\n\n // ------- Public api composition --------------------------------------\n\n const api: FormController = {\n get element() {\n return state.element\n },\n get f() {\n return state.element\n },\n get options() {\n return state.options\n },\n onSubmit: createOnSubmit(state, helpers),\n addCleanup: createAddCleanup(state, helpers),\n watch: createWatch(state, helpers),\n observe: createObserve(state, helpers),\n unwatch: createUnwatch(state, helpers),\n subscribe: createSubscribe(state, helpers),\n prefill: createPrefill(state, helpers),\n append: createAppend(state, helpers),\n setErrors: createSetErrors(state, helpers),\n clearErrors: createClearErrors(state, helpers),\n setValue: createSetValue(state, helpers),\n setOptions: createSetOptions(state, helpers),\n getValue: createGetValue(state, helpers),\n getField: createGetField(state, helpers),\n validate: createValidate(state, helpers),\n revalidate: createRevalidate(state, helpers),\n reset: createReset(state, helpers),\n autoSubmit: createAutoSubmit(state, helpers),\n disableAutoSubmit: createDisableAutoSubmit(state, helpers),\n getData: createGetData(state, helpers),\n getState: createGetState(state, helpers),\n format: createFormat(state, helpers),\n formatAll: createFormatAll(state, helpers),\n destroy: createDestroy(state, helpers)\n }\n\n state.api = api\n\n // ------- Lifecycle hooks ---------------------------------------------\n\n if (state.element) {\n addListener(state.element, 'input', handleDelegatedEvent)\n addListener(document, 'input', handleExternalDelegatedEvent)\n addListener(state.element, 'submit', handleSubmitEvent)\n addListener(state.element, 'reset', handleResetEvent)\n snapshotAllSelects()\n startMutationObserver()\n }\n\n if (normalizedOptions.autoSubmit) {\n api.autoSubmit(normalizedOptions.autoSubmit)\n }\n\n if (normalizedOptions.formats) {\n for (const config of Object.values(normalizedOptions.formats)) {\n api.format(config)\n }\n }\n\n if (state.isValidated) validateNames()\n else syncVisualState()\n\n return api\n}\n","// api/form.ts\n// Public entry point: the `form(target, options)` factory.\n// Thin wrapper around the core orchestrator for ergonomic imports.\n\nimport { createFormController } from '../core/controller'\nimport type { FormControllerOptions, FormTarget } from '../core/types'\n\nexport const form = (\n target: FormTarget,\n options: FormControllerOptions = {}\n) => createFormController(target, options)\n","// Vanilla mirror of the browser IIFE registry helpers.\n// Module-level singleton: the same shape as `window.Forms`, but\n// importable from any bundler. Consumers can spread it into their own\n// globals (`{ ...browser, regex }`) or use it directly.\n//\n// The IIFE bundle (`./global.ts`) consumes this same object — single\n// source of truth for the registry helpers.\n\nimport { form } from '../api/form'\nimport type {\n FormController,\n FormControllerOptions,\n FormTarget\n} from '../core/types'\n\nexport interface NewFormInput {\n id: string\n options?: FormControllerOptions\n}\n\nexport interface FormsAvailable {\n [id: string]: FormController\n}\n\nexport interface FormsApi {\n form: (\n target: FormTarget,\n options?: FormControllerOptions\n ) => FormController\n newForm: (input: NewFormInput) => FormController | undefined\n destroyForm: (id: string) => void\n available: FormsAvailable\n}\n\nconst available: FormsAvailable = {}\n\nconst newForm = (input: NewFormInput): FormController | undefined => {\n const { id, options } = input\n if (!id) {\n console.error('Form ID is required')\n return\n }\n available[id]?.destroy()\n const controller = form(id, { ...options })\n available[id] = controller\n return controller\n}\n\nconst destroyForm = (id: string): void => {\n if (!id) {\n console.error('Form ID is required')\n return\n }\n const controller = available[id]\n if (controller) {\n controller.destroy()\n delete available[id]\n } else {\n console.warn(`Form with ID ${id} not found`)\n }\n}\n\nexport const browser: FormsApi = {\n form,\n newForm,\n destroyForm,\n available\n}\n","// Browser entrypoint. Exposes a minimal surface as a single global\n// accessible via `window.Forms` (or `globalThis.Forms`).\n//\n// Public shape:\n// - Forms.form(target, options)\n// - Forms.newForm({ id, options })\n// - Forms.destroyForm(id)\n// - Forms.available (registry keyed by form id)\n//\n// The IIFE bundle consumes the same `browser` singleton as the vanilla\n// entrypoint — single source of truth for the registry helpers.\n\nimport { browser } from './registry'\nimport type { FormsApi } from './registry'\n\nconst Forms: FormsApi = browser\n\nexport const form = Forms.form\nexport const newForm = Forms.newForm\nexport const destroyForm = Forms.destroyForm\nexport const available = Forms.available\n\ndeclare global {\n interface Window {\n Forms: FormsApi\n }\n}\n\nif (typeof globalThis !== 'undefined') {\n ;(globalThis as typeof globalThis & { Forms: FormsApi }).Forms = Forms\n}\n\nexport default Forms\n"],"mappings":"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","names":["available","destroyForm","form","newForm","state","state","state","state","form","newCaret","state","registry","state","state","state","state","form","selectedValues","state","state","state","state","state","state","state","state","state","state","state","state","state","addListener","target","form","newForm","destroyForm","available"]}