@samline/forms 0.1.0 → 1.0.2

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.
Files changed (38) hide show
  1. package/README.md +212 -30
  2. package/dist/browser/global.global.js +2 -1
  3. package/dist/browser/global.global.js.map +1 -1
  4. package/dist/{chunk-D3J67V3G.js → chunk-KIJEFIHP.js} +2 -1
  5. package/dist/chunk-KIJEFIHP.js.map +1 -0
  6. package/dist/{chunk-HP2CJPHY.js → chunk-KKQD25KI.js} +2 -2
  7. package/dist/core/index.d.cts +2 -2
  8. package/dist/core/index.d.ts +2 -2
  9. package/dist/index.cjs +1 -0
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/react/index.cjs +1 -0
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.d.cts +1 -1
  17. package/dist/react/index.d.ts +1 -1
  18. package/dist/react/index.js +1 -1
  19. package/dist/svelte/index.cjs +1 -0
  20. package/dist/svelte/index.cjs.map +1 -1
  21. package/dist/svelte/index.d.cts +1 -1
  22. package/dist/svelte/index.d.ts +1 -1
  23. package/dist/svelte/index.js +1 -1
  24. package/dist/{types-gvovPPPU.d.cts → types-C0_1rYlm.d.cts} +1 -0
  25. package/dist/{types-gvovPPPU.d.ts → types-C0_1rYlm.d.ts} +1 -0
  26. package/dist/vanilla/index.cjs +1 -0
  27. package/dist/vanilla/index.cjs.map +1 -1
  28. package/dist/vanilla/index.d.cts +1 -1
  29. package/dist/vanilla/index.d.ts +1 -1
  30. package/dist/vanilla/index.js +2 -2
  31. package/dist/vue/index.cjs +1 -0
  32. package/dist/vue/index.cjs.map +1 -1
  33. package/dist/vue/index.d.cts +1 -1
  34. package/dist/vue/index.d.ts +1 -1
  35. package/dist/vue/index.js +1 -1
  36. package/package.json +2 -2
  37. package/dist/chunk-D3J67V3G.js.map +0 -1
  38. /package/dist/{chunk-HP2CJPHY.js.map → chunk-KKQD25KI.js.map} +0 -0
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
  # @samline/forms
2
2
 
3
- Controlador de formularios para HTML nativo, React, Vue, Svelte y uso directo en browser.
3
+ Form controller for native HTML forms, React, Vue, Svelte, and direct browser usage.
4
4
 
5
- ## Contents
5
+ ## Table of Contents
6
6
 
7
7
  - [Installation](#installation)
8
- - [CDN / Browser](#browser)
8
+ - [CDN / Browser](#cdn--browser)
9
9
  - [Entrypoints](#entrypoints)
10
10
  - [Quick Start](#quick-start)
11
- - [API](#api)
11
+ - [What You Can Do](#what-you-can-do)
12
+ - [API Reference](#api-reference)
13
+ - [Examples](#examples)
12
14
  - [Documentation](#documentation)
13
15
  - [License](#license)
14
16
 
@@ -30,17 +32,41 @@ yarn add @samline/forms
30
32
  bun add @samline/forms
31
33
  ```
32
34
 
35
+ ## CDN / Browser
36
+
37
+ Use the browser build when you do not have a bundler and need to run the package directly in HTML.
38
+
39
+ ```html
40
+ <script src="https://unpkg.com/@samline/forms@1.0.2/dist/browser/global.global.js"></script>
41
+ ```
42
+
43
+ Pin the version in production.
44
+
45
+ The browser build exposes `window.forms`.
46
+
47
+ ```html
48
+ <form id="contact-form">
49
+ <input name="email" type="email" />
50
+ </form>
51
+
52
+ <script src="https://unpkg.com/@samline/forms@1.0.2/dist/browser/global.global.js"></script>
53
+ <script>
54
+ const contactForm = window.forms.form('contact-form')
55
+ contactForm.validate()
56
+ </script>
57
+ ```
58
+
33
59
  ## Entrypoints
34
60
 
35
- | Entrypoint | Uso |
61
+ | Entrypoint | Use |
36
62
  | --- | --- |
37
- | `@samline/forms` | API vanilla principal |
38
- | `@samline/forms/core` | Tipos, serialización y validación |
39
- | `@samline/forms/vanilla` | Alias explícito de la API DOM |
40
- | `@samline/forms/react` | Hook para React |
41
- | `@samline/forms/vue` | Composable para Vue |
42
- | `@samline/forms/svelte` | Store y action para Svelte |
43
- | `@samline/forms/browser` | Bundle global para script tag |
63
+ | `@samline/forms` | Main vanilla API |
64
+ | `@samline/forms/core` | Types, serialization, and validation |
65
+ | `@samline/forms/vanilla` | Explicit DOM API entrypoint |
66
+ | `@samline/forms/react` | React hook |
67
+ | `@samline/forms/vue` | Vue composable |
68
+ | `@samline/forms/svelte` | Svelte store and action |
69
+ | `@samline/forms/browser` | Browser global bundle |
44
70
 
45
71
  ## Quick Start
46
72
 
@@ -61,13 +87,180 @@ contactForm.onSubmit((element, data, formData, state) => {
61
87
  })
62
88
  ```
63
89
 
64
- ## API
90
+ ## What You Can Do
91
+
92
+ - bind to a form by id, element, or ref-like target
93
+ - read and write field values
94
+ - serialize form values to both a plain object and `FormData`
95
+ - watch individual fields and subscribe to global form state
96
+ - prefill values from the current URL query string
97
+ - mark filled and error states through DOM attributes for styling
98
+ - run built-in validation rules and custom validators
99
+ - trigger submit handlers with optional auto-submit behavior
100
+ - reset, inspect, and destroy the controller cleanly
101
+
102
+ ## API Reference
103
+
104
+ ### form(target, options)
105
+
106
+ Creates a controller from:
107
+
108
+ - a form id string
109
+ - a real `HTMLFormElement`
110
+ - a ref-like object with `current`
111
+
112
+ ### Properties
113
+
114
+ - `element`: the bound `HTMLFormElement | null`
115
+ - `f`: alias of `element`
116
+ - `options`: normalized controller options
117
+
118
+ ### Submission
119
+
120
+ - `onSubmit(callback, preventDefault?)`
121
+ - `autoSubmit(options?)`
122
+ - `disableAutoSubmit()`
123
+
124
+ `onSubmit` accepts an optional second argument named `preventDefault`.
125
+
126
+ - `onSubmit(callback)` is equivalent to `onSubmit(callback, true)`
127
+ - with `true`, valid submissions are intercepted, which is the right choice for `fetch` or AJAX flows
128
+ - with `false`, valid submissions continue with the browser's native form submit behavior
129
+ - invalid submissions are still prevented, even when you pass `false`
130
+
131
+ ### Field observation
132
+
133
+ - `watch(field, callback)`
134
+ - `observe(field, callback)`
135
+ - `subscribe(listener)`
136
+ - `unwatch(field?, callback?)`
137
+
138
+ ### Field values
139
+
140
+ - `setValue(name, value)`
141
+ - `getValue(name)`
142
+ - `getField(name)`
143
+ - `prefill(fieldName?)`
144
+
145
+ ### Validation and errors
146
+
147
+ - `validate(fields?)`
148
+ - `revalidate(fields?)`
149
+ - `setErrors(fields)`
150
+ - `clearErrors(fields?)`
151
+
152
+ ### Form lifecycle and state
153
+
154
+ - `getData()`
155
+ - `getState()`
156
+ - `append(options)`
157
+ - `reset()`
158
+ - `destroy()`
159
+
160
+ ### Validation options
161
+
162
+ Built-in rules supported through `validators`:
163
+
164
+ - `required`
165
+ - `minLength`
166
+ - `maxLength`
167
+ - `pattern`
168
+ - `validate` for custom callbacks
169
+
170
+ ## Examples
171
+
172
+ ### Bind by id
173
+
174
+ ```ts
175
+ import { form } from '@samline/forms'
176
+
177
+ const profileForm = form('profile-form')
178
+ ```
179
+
180
+ ### Bind by element
181
+
182
+ ```ts
183
+ const element = document.querySelector('#profile-form') as HTMLFormElement
184
+ const profileForm = form(element)
185
+ ```
186
+
187
+ ### Watch a field
188
+
189
+ ```ts
190
+ const profileForm = form('profile-form')
191
+
192
+ profileForm.watch('email', value => {
193
+ console.log('email changed:', value)
194
+ })
195
+ ```
196
+
197
+ ### Validate with built-in rules
198
+
199
+ ```ts
200
+ const profileForm = form('profile-form', {
201
+ validators: {
202
+ email: {
203
+ required: true,
204
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
205
+ },
206
+ password: {
207
+ minLength: 8
208
+ }
209
+ }
210
+ })
211
+
212
+ const result = profileForm.validate()
213
+ console.log(result.isValid, result.errors)
214
+ ```
215
+
216
+ ### Submit with fetch
217
+
218
+ ```ts
219
+ const profileForm = form('profile-form')
220
+
221
+ profileForm.onSubmit(async (_element, _data, formData) => {
222
+ await fetch('/api/profile', {
223
+ method: 'POST',
224
+ body: formData
225
+ })
226
+ })
227
+ ```
228
+
229
+ This uses the default `preventDefault = true`, so the package intercepts the valid submit and lets you handle the request yourself.
65
230
 
66
- - `form(target, options)` crea un controlador para un `form` real o un id.
67
- - `watch` y `observe` reaccionan a cambios por campo.
68
- - `validate` y `revalidate` ejecutan reglas básicas compartidas.
69
- - `setErrors` y `clearErrors` mantienen el estado visual y lógico.
70
- - `getData` devuelve objeto serializado y `FormData` listo para `fetch`.
231
+ ### Submit with native form behavior
232
+
233
+ ```ts
234
+ const profileForm = form('profile-form')
235
+
236
+ profileForm.onSubmit(() => {
237
+ console.log('validation passed')
238
+ }, false)
239
+ ```
240
+
241
+ Use `false` when the form should continue with its normal HTML submission after validation succeeds, for example in server-rendered applications such as Laravel with Blade.
242
+
243
+ If validation fails, the package still prevents the submit.
244
+
245
+ ### Prefill from the URL
246
+
247
+ ```ts
248
+ const profileForm = form('profile-form')
249
+ profileForm.prefill()
250
+ ```
251
+
252
+ ### Work with form state
253
+
254
+ ```ts
255
+ const profileForm = form('profile-form')
256
+
257
+ const unsubscribe = profileForm.subscribe(state => {
258
+ console.log(state.values)
259
+ console.log(state.errors)
260
+ })
261
+
262
+ unsubscribe()
263
+ ```
71
264
 
72
265
  ## Documentation
73
266
 
@@ -79,15 +272,4 @@ contactForm.onSubmit((element, data, formData, state) => {
79
272
 
80
273
  ## License
81
274
 
82
- MIT
83
-
84
- ## Browser
85
-
86
- El build browser expone `window.SamlineForms` para proyectos sin bundler.
87
-
88
- ```html
89
- <script src="/dist/browser/global.global.js"></script>
90
- <script>
91
- const contactForm = window.SamlineForms.form('contact-form')
92
- </script>
93
- ```
275
+ MIT
@@ -462,6 +462,7 @@ var SamlineForms = (() => {
462
462
  const isFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
463
463
  const api = {
464
464
  element,
465
+ f: element,
465
466
  options: normalizedOptions,
466
467
  onSubmit(callback, preventDefault = true) {
467
468
  submitHandlers.add({ callback, preventDefault });
@@ -714,7 +715,7 @@ var SamlineForms = (() => {
714
715
  };
715
716
  if (typeof globalThis !== "undefined") {
716
717
  ;
717
- globalThis.SamlineForms = browserApi;
718
+ globalThis.forms = browserApi;
718
719
  }
719
720
  var global_default = browserApi;
720
721
  return __toCommonJS(global_exports);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/browser/global.ts","../../src/core/serialize.ts","../../src/core/state.ts","../../src/core/validation.ts","../../src/internal/dom.ts","../../src/internal/controller.ts","../../src/vanilla/index.ts"],"sourcesContent":["import { parseFormData, validateValues } from '../core'\nimport { createFormController, form } from '../vanilla'\n\nconst browserApi = {\n createFormController,\n form,\n parseFormData,\n validateValues\n}\n\ndeclare global {\n interface Window {\n SamlineForms: typeof browserApi\n }\n}\n\nif (typeof globalThis !== 'undefined') {\n ;(globalThis as typeof globalThis & { SamlineForms: typeof browserApi }).SamlineForms =\n browserApi\n}\n\nexport default browserApi","import 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) => {\n const current = data[key]\n\n if (current === undefined) {\n data[key] = value\n return\n }\n\n if (Array.isArray(current)) {\n current.push(value)\n return\n }\n\n data[key] = [current, value]\n}\n\nexport const parseFormData = (\n formElement: HTMLFormElement\n): SerializedFormResult => {\n const rawFormData = new FormData(formElement)\n const formData = new FormData()\n const data: Record<string, SerializedFormValue> = {}\n\n rawFormData.forEach((value, key) => {\n if (isEmptyFile(value)) {\n return\n }\n\n formData.append(key, value)\n appendValue(data, key, value)\n })\n\n return { data, formData }\n}","import type { FormStateSnapshot } from './types'\n\nexport const createEmptyFormState = (): FormStateSnapshot => ({\n values: {},\n errors: {},\n filledFields: [],\n isValid: true,\n isValidated: false,\n autoSubmit: false,\n submitCount: 0\n})","import type {\n FieldValidationContext,\n FieldValidationRules,\n FormErrors,\n FormFieldValue,\n FormValues,\n RuleConfig,\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\n if (typeof rule === 'object' && rule !== null && 'value' in rule) {\n return { value: rule.value, message: rule.message }\n }\n\n return { value: rule, message: undefined as string | undefined }\n}\n\nconst hasValue = (value: FormFieldValue) => {\n if (Array.isArray(value)) {\n return value.length > 0\n }\n\n return typeof value === 'string' ? value.trim().length > 0 : value !== undefined\n}\n\nconst getValueLength = (value: FormFieldValue) => {\n if (Array.isArray(value)) {\n return value.length\n }\n\n if (typeof value === 'string') {\n return value.length\n }\n\n return 0\n}\n\nconst toPatternTarget = (value: FormFieldValue) => {\n if (typeof value === 'string') {\n return value\n }\n\n if (Array.isArray(value)) {\n return value\n .map(entry => (typeof entry === 'string' ? entry : entry.name))\n .join(',')\n }\n\n return ''\n}\n\nexport const validateFieldValue = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues\n) => {\n const errors: string[] = []\n const context: FieldValidationContext = { field, value, values }\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\n if (required.value && !hasValue(value)) {\n errors.push(required.message ?? 'This field is required.')\n }\n\n if (minLength.value !== undefined && getValueLength(value) < minLength.value) {\n errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`)\n }\n\n if (maxLength.value !== undefined && getValueLength(value) > maxLength.value) {\n errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`)\n }\n\n if (pattern.value && hasValue(value) && !pattern.value.test(toPatternTarget(value))) {\n errors.push(pattern.message ?? 'Value does not match the required pattern.')\n }\n\n const customValidators = rules.validate\n ? Array.isArray(rules.validate)\n ? rules.validate\n : [rules.validate]\n : []\n\n for (const validator of customValidators) {\n const result = validator(context)\n\n if (typeof result === 'string' && result.length > 0) {\n errors.push(result)\n }\n\n if (result === false) {\n errors.push('Validation failed.')\n }\n }\n\n return errors\n}\n\nexport const validateValues = (\n values: FormValues,\n schema: ValidationSchema\n): ValidationResult => {\n const errors: FormErrors = {}\n\n for (const [field, rules] of Object.entries(schema)) {\n const messages = validateFieldValue(field, values[field], rules, values)\n if (messages.length > 0) {\n errors[field] = messages\n }\n }\n\n return {\n isValid: Object.keys(errors).length === 0,\n errors\n }\n}","import type { FormFieldElement, FormFieldValue, FormTarget } from '../core/types'\n\nconst isFormFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\nexport const resolveFormElement = (target: FormTarget): HTMLFormElement | null => {\n if (!target) {\n return null\n }\n\n if (target instanceof HTMLFormElement) {\n return target\n }\n\n if (typeof target === 'string') {\n const element = document.getElementById(target)\n return element instanceof HTMLFormElement ? element : null\n }\n\n if ('current' in target) {\n return target.current instanceof HTMLFormElement ? target.current : null\n }\n\n return null\n}\n\nexport const getNamedFields = (form: HTMLFormElement): FormFieldElement[] =>\n Array.from(form.querySelectorAll('input[name], select[name], textarea[name]')).filter(\n isFormFieldElement\n )\n\nexport const queryNamedFields = (\n form: HTMLFormElement,\n name: string\n): FormFieldElement[] => getNamedFields(form).filter(field => field.name === name)\n\nexport const isFieldFilled = (field: FormFieldElement) => {\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox' || field.type === 'radio') {\n return field.checked\n }\n\n if (field.type === 'file') {\n return Boolean(field.files && field.files.length > 0)\n }\n\n return field.value.trim() !== ''\n }\n\n return field.value !== ''\n}\n\nexport const applyBooleanAttribute = (\n field: FormFieldElement,\n attribute: string,\n enabled: boolean\n) => {\n if (enabled) {\n field.setAttribute(attribute, '')\n return\n }\n\n field.removeAttribute(attribute)\n}\n\nexport const readFieldValue = (\n fields: FormFieldElement[]\n): FormFieldValue => {\n if (fields.length === 0) {\n return undefined\n }\n\n const firstField = fields[0]\n if (!firstField) {\n return undefined\n }\n\n if (firstField instanceof HTMLSelectElement || firstField instanceof HTMLTextAreaElement) {\n return firstField.value\n }\n\n if (firstField.type === 'radio') {\n const checked = fields.find(\n field => field instanceof HTMLInputElement && field.checked\n ) as HTMLInputElement | undefined\n\n return checked?.value ?? ''\n }\n\n if (firstField.type === 'checkbox') {\n const values = fields\n .filter(field => field instanceof HTMLInputElement && field.checked)\n .map(field => (field as HTMLInputElement).value)\n\n return values.length > 1 ? values : (values[0] ?? '')\n }\n\n if (firstField.type === 'file') {\n return firstField.files ? Array.from(firstField.files) : []\n }\n\n return firstField.value\n}\n\nexport const writeFieldValue = (\n fields: FormFieldElement[],\n value: unknown\n) => {\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 (const field of fields) {\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\n if (field.type === 'radio') {\n field.checked = field.value === normalizedValue\n continue\n }\n\n if (field.type === 'file') {\n if (Array.isArray(value) && value.length === 0) {\n field.value = ''\n }\n continue\n }\n\n field.value = normalizedValue\n continue\n }\n\n field.value = normalizedValue\n }\n}\n\nexport const clearAttributes = (\n form: HTMLFormElement,\n attributes: string[]\n) => {\n for (const attribute of attributes) {\n form.querySelectorAll(`[${attribute}]`).forEach(element => {\n element.removeAttribute(attribute)\n })\n }\n}\n\nexport const submitForm = (form: HTMLFormElement) => {\n if (typeof form.requestSubmit === 'function') {\n form.requestSubmit()\n return\n }\n\n const submitButton = form.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) as HTMLButtonElement | HTMLInputElement | null\n\n if (submitButton) {\n submitButton.click()\n return\n }\n\n form.submit()\n}","import { createEmptyFormState, parseFormData, validateFieldValue } from '../core'\nimport type {\n AppendContentOptions,\n AutoSubmitOptions,\n FormController,\n FormControllerOptions,\n FormErrors,\n FormFieldElement,\n FormFieldWatcher,\n FormSubmitHandler,\n FormStateListener,\n FormStateSnapshot,\n FormTarget,\n ValidationResult,\n VisualAttributes\n} from '../core/types'\nimport {\n applyBooleanAttribute,\n clearAttributes,\n getNamedFields,\n isFieldFilled,\n queryNamedFields,\n readFieldValue,\n resolveFormElement,\n submitForm,\n writeFieldValue\n} from './dom'\n\nconst DEFAULT_ATTRIBUTES: VisualAttributes = {\n filled: 'css-filled',\n error: 'css-error'\n}\n\nconst DEFAULT_OPTIONS: Required<\n Pick<FormControllerOptions, 'autoValidate' | 'clearErrorsOnSubmit'>\n> = {\n autoValidate: true,\n clearErrorsOnSubmit: true\n}\n\nconst mergeErrors = (left: FormErrors, right: FormErrors) => {\n const merged: FormErrors = { ...left }\n\n for (const [field, messages] of Object.entries(right)) {\n merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages]\n }\n\n return merged\n}\n\nconst cloneErrors = (errors: FormErrors) =>\n Object.fromEntries(\n Object.entries(errors).map(([field, messages]) => [field, [...messages]])\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 validators = normalizedOptions.validators ?? {}\n const watchedFields = new Map<string, Set<FormFieldWatcher>>()\n const listeners: Array<{\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n }> = []\n const subscribers = new Set<FormStateListener>()\n const submitHandlers = new Set<{\n callback: FormSubmitHandler\n preventDefault: boolean\n }>()\n const fieldCache = new Map<string, FormFieldElement[]>()\n\n let manualErrors: FormErrors = {}\n let validationErrors: FormErrors = {}\n let isValidated = Boolean(normalizedOptions.autoValidate)\n let autoSubmitEnabled = false\n let autoSubmitDebounce = 0\n let submitCount = 0\n let autoSubmitTimer: ReturnType<typeof setTimeout> | null = null\n let mutationObserver: MutationObserver | null = null\n let isDestroyed = false\n\n const notifySubscribers = () => {\n const state = api.getState()\n subscribers.forEach(listener => listener(state))\n }\n\n const addListener = (\n listenerTarget: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject\n ) => {\n listenerTarget.addEventListener(type, handler)\n listeners.push({ element: listenerTarget, type, handler })\n }\n\n const clearFieldCache = () => {\n fieldCache.clear()\n }\n\n const getFieldsByName = (name: string) => {\n if (!element) {\n return []\n }\n\n if (!fieldCache.has(name)) {\n fieldCache.set(name, queryNamedFields(element, name))\n }\n\n return fieldCache.get(name) ?? []\n }\n\n const getTrackedFieldNames = () => {\n if (!element) {\n return Object.keys(validators)\n }\n\n const names = new Set<string>(Object.keys(validators))\n for (const field of getNamedFields(element)) {\n names.add(field.name)\n }\n\n return Array.from(names)\n }\n\n const getValues = () => {\n const values: FormStateSnapshot['values'] = {}\n for (const name of getTrackedFieldNames()) {\n values[name] = api.getValue(name)\n }\n return values\n }\n\n const getMergedErrors = () => mergeErrors(validationErrors, manualErrors)\n\n const syncVisualState = (names?: string[]) => {\n if (!element) {\n return\n }\n\n const targetNames = names ?? getTrackedFieldNames()\n const errors = getMergedErrors()\n\n for (const name of targetNames) {\n const fields = getFieldsByName(name)\n const hasError = Boolean(errors[name]?.length)\n for (const field of fields) {\n applyBooleanAttribute(field, attributes.filled, isFieldFilled(field))\n applyBooleanAttribute(field, attributes.error, hasError)\n }\n }\n }\n\n const validateNames = (names?: string[]) => {\n const targetNames = names ?? Object.keys(validators)\n const values = getValues()\n const nextValidationErrors = names ? cloneErrors(validationErrors) : {}\n\n for (const name of targetNames) {\n const rules = validators[name]\n\n if (!rules) {\n delete nextValidationErrors[name]\n continue\n }\n\n const errors = validateFieldValue(name, values[name], rules, values)\n if (errors.length > 0) {\n nextValidationErrors[name] = errors\n } else {\n delete nextValidationErrors[name]\n }\n }\n\n validationErrors = nextValidationErrors\n syncVisualState(names)\n\n return {\n isValid: Object.keys(getMergedErrors()).length === 0,\n errors: cloneErrors(getMergedErrors())\n } satisfies ValidationResult\n }\n\n const emitFieldWatchers = (name: string) => {\n if (!element) {\n return\n }\n\n const callbacks = watchedFields.get(name)\n if (!callbacks || callbacks.size === 0) {\n return\n }\n\n const value = api.getValue(name)\n const state = api.getState()\n callbacks.forEach(callback => callback(value, element, state))\n }\n\n const scheduleAutoSubmit = () => {\n if (!element || !autoSubmitEnabled) {\n return\n }\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n }\n\n if (autoSubmitDebounce > 0) {\n autoSubmitTimer = setTimeout(() => submitForm(element), autoSubmitDebounce)\n return\n }\n\n submitForm(element)\n }\n\n const handleDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) {\n return\n }\n\n const name = target.name\n if (!name) {\n return\n }\n\n clearFieldCache()\n syncVisualState([name])\n\n if (isValidated && validators[name]) {\n validateNames([name])\n }\n\n emitFieldWatchers(name)\n notifySubscribers()\n scheduleAutoSubmit()\n }\n\n const handleSubmitEvent = (event: Event) => {\n if (!element || isDestroyed) {\n return\n }\n\n if (normalizedOptions.clearErrorsOnSubmit) {\n manualErrors = {}\n }\n\n const validation = api.validate()\n const handlers = Array.from(submitHandlers)\n const shouldPrevent = validation.isValid\n ? handlers.some(handler => handler.preventDefault)\n : true\n\n if (shouldPrevent) {\n event.preventDefault()\n }\n\n submitCount += 1\n notifySubscribers()\n\n if (!validation.isValid) {\n return\n }\n\n const { data, formData } = api.getData()\n const state = api.getState()\n handlers.forEach(handler => handler.callback(element, data, formData, state))\n }\n\n const startMutationObserver = () => {\n if (!element || typeof MutationObserver === 'undefined') {\n return\n }\n\n mutationObserver = new MutationObserver(() => {\n clearFieldCache()\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n notifySubscribers()\n })\n\n mutationObserver.observe(element, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['name', 'type']\n })\n }\n\n const isFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\n const api: FormController = {\n element,\n options: normalizedOptions,\n onSubmit(callback, preventDefault = true) {\n submitHandlers.add({ callback, preventDefault })\n return api\n },\n watch(field, callback) {\n api.observe(field, callback)\n return api\n },\n observe(field, callback) {\n const callbacks = watchedFields.get(field) ?? new Set<FormFieldWatcher>()\n callbacks.add(callback)\n watchedFields.set(field, callbacks)\n\n if (element) {\n callback(api.getValue(field), element, api.getState())\n }\n\n return () => {\n const currentCallbacks = watchedFields.get(field)\n currentCallbacks?.delete(callback)\n if (currentCallbacks && currentCallbacks.size === 0) {\n watchedFields.delete(field)\n }\n }\n },\n unwatch(field, callback) {\n if (!field) {\n watchedFields.clear()\n return api\n }\n\n if (!callback) {\n watchedFields.delete(field)\n return api\n }\n\n const callbacks = watchedFields.get(field)\n callbacks?.delete(callback)\n if (callbacks && callbacks.size === 0) {\n watchedFields.delete(field)\n }\n return api\n },\n subscribe(listener) {\n subscribers.add(listener)\n listener(api.getState())\n return () => {\n subscribers.delete(listener)\n }\n },\n prefill(fieldName) {\n if (!element) {\n return api\n }\n\n const queryParams = new URLSearchParams(window.location.search)\n queryParams.forEach((value, key) => {\n if (fieldName && fieldName !== key) {\n return\n }\n\n api.setValue(key, value)\n })\n return api\n },\n append({ tag, content, class: className, atStart = false }: AppendContentOptions) {\n if (!element) {\n return null\n }\n\n clearFieldCache()\n if (className) {\n const classSelector = className.trim().split(/\\s+/)[0]\n element.querySelector(`.${classSelector}`)?.remove()\n }\n\n const node = document.createElement(tag)\n if (className) {\n node.className = className\n }\n node.innerHTML = content\n\n if (atStart && element.firstChild) {\n element.insertBefore(node, element.firstChild)\n } else {\n element.appendChild(node)\n }\n\n return node\n },\n setErrors(fields) {\n if (Array.isArray(fields)) {\n manualErrors = {\n ...manualErrors,\n ...Object.fromEntries(fields.map(field => [field, ['Invalid value.']]))\n }\n } else {\n manualErrors = {\n ...manualErrors,\n ...cloneErrors(fields)\n }\n }\n\n syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields))\n notifySubscribers()\n return api\n },\n clearErrors(fields) {\n if (!fields) {\n manualErrors = {}\n syncVisualState()\n notifySubscribers()\n return api\n }\n\n for (const field of fields) {\n delete manualErrors[field]\n }\n\n syncVisualState(fields)\n notifySubscribers()\n return api\n },\n setValue(name, value) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return api\n }\n\n writeFieldValue(fields, value)\n const firstField = fields[0]\n if (!firstField) {\n return api\n }\n\n const eventType =\n firstField instanceof HTMLSelectElement ||\n (firstField instanceof HTMLInputElement &&\n (firstField.type === 'checkbox' || firstField.type === 'radio'))\n ? 'change'\n : 'input'\n\n firstField.dispatchEvent(new Event(eventType, { bubbles: true }))\n return api\n },\n validate(fields) {\n isValidated = true\n syncVisualState(fields)\n return validateNames(fields)\n },\n revalidate(fields) {\n return api.validate(fields)\n },\n reset() {\n if (!element) {\n return api\n }\n\n element.reset()\n manualErrors = {}\n validationErrors = {}\n clearAttributes(element, [attributes.error, attributes.filled])\n if (isValidated) {\n syncVisualState()\n }\n notifySubscribers()\n return api\n },\n autoSubmit(nextOptions = true) {\n autoSubmitEnabled = nextOptions !== false\n autoSubmitDebounce =\n typeof nextOptions === 'object' && nextOptions\n ? nextOptions.debounce ?? 0\n : 0\n notifySubscribers()\n return api\n },\n disableAutoSubmit() {\n autoSubmitEnabled = false\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n notifySubscribers()\n return api\n },\n getValue(name) {\n return readFieldValue(getFieldsByName(name))\n },\n getField(name) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return null\n }\n const [firstField] = fields\n if (!firstField) {\n return null\n }\n return fields.length === 1 ? firstField : fields\n },\n getData() {\n if (!element) {\n return { data: {}, formData: new FormData() }\n }\n return parseFormData(element)\n },\n getState() {\n const values = getValues()\n const errors = cloneErrors(getMergedErrors())\n const filledFields = getTrackedFieldNames().filter(name => {\n const value = values[name]\n return Array.isArray(value)\n ? value.length > 0\n : typeof value === 'string'\n ? value.trim().length > 0\n : value !== undefined\n })\n\n return {\n ...createEmptyFormState(),\n values,\n errors,\n filledFields,\n isValid: Object.keys(errors).length === 0,\n isValidated,\n autoSubmit: autoSubmitEnabled,\n submitCount\n }\n },\n destroy() {\n if (isDestroyed) {\n return\n }\n\n isDestroyed = true\n for (const listener of listeners) {\n listener.element.removeEventListener(listener.type, listener.handler)\n }\n listeners.length = 0\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n\n mutationObserver?.disconnect()\n mutationObserver = null\n watchedFields.clear()\n subscribers.clear()\n submitHandlers.clear()\n clearFieldCache()\n manualErrors = {}\n validationErrors = {}\n }\n }\n\n if (element) {\n addListener(element, 'input', handleDelegatedEvent)\n addListener(element, 'change', handleDelegatedEvent)\n addListener(element, 'submit', handleSubmitEvent)\n startMutationObserver()\n }\n\n if (normalizedOptions.autoSubmit) {\n const autoSubmitOption = normalizedOptions.autoSubmit as boolean | AutoSubmitOptions\n api.autoSubmit(autoSubmitOption)\n }\n\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n\n return api\n}","import type { FormControllerOptions, FormTarget } from '../core'\nimport { createFormController } from '../internal/controller'\n\nexport const form = (\n target: FormTarget,\n options?: FormControllerOptions\n) => createFormController(target, options)\n\nexport { createFormController }"],"mappings":"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","names":["form","target"]}
1
+ {"version":3,"sources":["../../src/browser/global.ts","../../src/core/serialize.ts","../../src/core/state.ts","../../src/core/validation.ts","../../src/internal/dom.ts","../../src/internal/controller.ts","../../src/vanilla/index.ts"],"sourcesContent":["import { parseFormData, validateValues } from '../core'\nimport { createFormController, form } from '../vanilla'\n\nconst browserApi = {\n createFormController,\n form,\n parseFormData,\n validateValues\n}\n\ndeclare global {\n interface Window {\n forms: typeof browserApi\n }\n}\n\nif (typeof globalThis !== 'undefined') {\n ;(globalThis as typeof globalThis & { forms: typeof browserApi }).forms =\n browserApi\n}\n\nexport default browserApi","import 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) => {\n const current = data[key]\n\n if (current === undefined) {\n data[key] = value\n return\n }\n\n if (Array.isArray(current)) {\n current.push(value)\n return\n }\n\n data[key] = [current, value]\n}\n\nexport const parseFormData = (\n formElement: HTMLFormElement\n): SerializedFormResult => {\n const rawFormData = new FormData(formElement)\n const formData = new FormData()\n const data: Record<string, SerializedFormValue> = {}\n\n rawFormData.forEach((value, key) => {\n if (isEmptyFile(value)) {\n return\n }\n\n formData.append(key, value)\n appendValue(data, key, value)\n })\n\n return { data, formData }\n}","import type { FormStateSnapshot } from './types'\n\nexport const createEmptyFormState = (): FormStateSnapshot => ({\n values: {},\n errors: {},\n filledFields: [],\n isValid: true,\n isValidated: false,\n autoSubmit: false,\n submitCount: 0\n})","import type {\n FieldValidationContext,\n FieldValidationRules,\n FormErrors,\n FormFieldValue,\n FormValues,\n RuleConfig,\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\n if (typeof rule === 'object' && rule !== null && 'value' in rule) {\n return { value: rule.value, message: rule.message }\n }\n\n return { value: rule, message: undefined as string | undefined }\n}\n\nconst hasValue = (value: FormFieldValue) => {\n if (Array.isArray(value)) {\n return value.length > 0\n }\n\n return typeof value === 'string' ? value.trim().length > 0 : value !== undefined\n}\n\nconst getValueLength = (value: FormFieldValue) => {\n if (Array.isArray(value)) {\n return value.length\n }\n\n if (typeof value === 'string') {\n return value.length\n }\n\n return 0\n}\n\nconst toPatternTarget = (value: FormFieldValue) => {\n if (typeof value === 'string') {\n return value\n }\n\n if (Array.isArray(value)) {\n return value\n .map(entry => (typeof entry === 'string' ? entry : entry.name))\n .join(',')\n }\n\n return ''\n}\n\nexport const validateFieldValue = (\n field: string,\n value: FormFieldValue,\n rules: FieldValidationRules,\n values: FormValues\n) => {\n const errors: string[] = []\n const context: FieldValidationContext = { field, value, values }\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\n if (required.value && !hasValue(value)) {\n errors.push(required.message ?? 'This field is required.')\n }\n\n if (minLength.value !== undefined && getValueLength(value) < minLength.value) {\n errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`)\n }\n\n if (maxLength.value !== undefined && getValueLength(value) > maxLength.value) {\n errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`)\n }\n\n if (pattern.value && hasValue(value) && !pattern.value.test(toPatternTarget(value))) {\n errors.push(pattern.message ?? 'Value does not match the required pattern.')\n }\n\n const customValidators = rules.validate\n ? Array.isArray(rules.validate)\n ? rules.validate\n : [rules.validate]\n : []\n\n for (const validator of customValidators) {\n const result = validator(context)\n\n if (typeof result === 'string' && result.length > 0) {\n errors.push(result)\n }\n\n if (result === false) {\n errors.push('Validation failed.')\n }\n }\n\n return errors\n}\n\nexport const validateValues = (\n values: FormValues,\n schema: ValidationSchema\n): ValidationResult => {\n const errors: FormErrors = {}\n\n for (const [field, rules] of Object.entries(schema)) {\n const messages = validateFieldValue(field, values[field], rules, values)\n if (messages.length > 0) {\n errors[field] = messages\n }\n }\n\n return {\n isValid: Object.keys(errors).length === 0,\n errors\n }\n}","import type { FormFieldElement, FormFieldValue, FormTarget } from '../core/types'\n\nconst isFormFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\nexport const resolveFormElement = (target: FormTarget): HTMLFormElement | null => {\n if (!target) {\n return null\n }\n\n if (target instanceof HTMLFormElement) {\n return target\n }\n\n if (typeof target === 'string') {\n const element = document.getElementById(target)\n return element instanceof HTMLFormElement ? element : null\n }\n\n if ('current' in target) {\n return target.current instanceof HTMLFormElement ? target.current : null\n }\n\n return null\n}\n\nexport const getNamedFields = (form: HTMLFormElement): FormFieldElement[] =>\n Array.from(form.querySelectorAll('input[name], select[name], textarea[name]')).filter(\n isFormFieldElement\n )\n\nexport const queryNamedFields = (\n form: HTMLFormElement,\n name: string\n): FormFieldElement[] => getNamedFields(form).filter(field => field.name === name)\n\nexport const isFieldFilled = (field: FormFieldElement) => {\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox' || field.type === 'radio') {\n return field.checked\n }\n\n if (field.type === 'file') {\n return Boolean(field.files && field.files.length > 0)\n }\n\n return field.value.trim() !== ''\n }\n\n return field.value !== ''\n}\n\nexport const applyBooleanAttribute = (\n field: FormFieldElement,\n attribute: string,\n enabled: boolean\n) => {\n if (enabled) {\n field.setAttribute(attribute, '')\n return\n }\n\n field.removeAttribute(attribute)\n}\n\nexport const readFieldValue = (\n fields: FormFieldElement[]\n): FormFieldValue => {\n if (fields.length === 0) {\n return undefined\n }\n\n const firstField = fields[0]\n if (!firstField) {\n return undefined\n }\n\n if (firstField instanceof HTMLSelectElement || firstField instanceof HTMLTextAreaElement) {\n return firstField.value\n }\n\n if (firstField.type === 'radio') {\n const checked = fields.find(\n field => field instanceof HTMLInputElement && field.checked\n ) as HTMLInputElement | undefined\n\n return checked?.value ?? ''\n }\n\n if (firstField.type === 'checkbox') {\n const values = fields\n .filter(field => field instanceof HTMLInputElement && field.checked)\n .map(field => (field as HTMLInputElement).value)\n\n return values.length > 1 ? values : (values[0] ?? '')\n }\n\n if (firstField.type === 'file') {\n return firstField.files ? Array.from(firstField.files) : []\n }\n\n return firstField.value\n}\n\nexport const writeFieldValue = (\n fields: FormFieldElement[],\n value: unknown\n) => {\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 (const field of fields) {\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\n if (field.type === 'radio') {\n field.checked = field.value === normalizedValue\n continue\n }\n\n if (field.type === 'file') {\n if (Array.isArray(value) && value.length === 0) {\n field.value = ''\n }\n continue\n }\n\n field.value = normalizedValue\n continue\n }\n\n field.value = normalizedValue\n }\n}\n\nexport const clearAttributes = (\n form: HTMLFormElement,\n attributes: string[]\n) => {\n for (const attribute of attributes) {\n form.querySelectorAll(`[${attribute}]`).forEach(element => {\n element.removeAttribute(attribute)\n })\n }\n}\n\nexport const submitForm = (form: HTMLFormElement) => {\n if (typeof form.requestSubmit === 'function') {\n form.requestSubmit()\n return\n }\n\n const submitButton = form.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) as HTMLButtonElement | HTMLInputElement | null\n\n if (submitButton) {\n submitButton.click()\n return\n }\n\n form.submit()\n}","import { createEmptyFormState, parseFormData, validateFieldValue } from '../core'\nimport type {\n AppendContentOptions,\n AutoSubmitOptions,\n FormController,\n FormControllerOptions,\n FormErrors,\n FormFieldElement,\n FormFieldWatcher,\n FormSubmitHandler,\n FormStateListener,\n FormStateSnapshot,\n FormTarget,\n ValidationResult,\n VisualAttributes\n} from '../core/types'\nimport {\n applyBooleanAttribute,\n clearAttributes,\n getNamedFields,\n isFieldFilled,\n queryNamedFields,\n readFieldValue,\n resolveFormElement,\n submitForm,\n writeFieldValue\n} from './dom'\n\nconst DEFAULT_ATTRIBUTES: VisualAttributes = {\n filled: 'css-filled',\n error: 'css-error'\n}\n\nconst DEFAULT_OPTIONS: Required<\n Pick<FormControllerOptions, 'autoValidate' | 'clearErrorsOnSubmit'>\n> = {\n autoValidate: true,\n clearErrorsOnSubmit: true\n}\n\nconst mergeErrors = (left: FormErrors, right: FormErrors) => {\n const merged: FormErrors = { ...left }\n\n for (const [field, messages] of Object.entries(right)) {\n merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages]\n }\n\n return merged\n}\n\nconst cloneErrors = (errors: FormErrors) =>\n Object.fromEntries(\n Object.entries(errors).map(([field, messages]) => [field, [...messages]])\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 validators = normalizedOptions.validators ?? {}\n const watchedFields = new Map<string, Set<FormFieldWatcher>>()\n const listeners: Array<{\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n }> = []\n const subscribers = new Set<FormStateListener>()\n const submitHandlers = new Set<{\n callback: FormSubmitHandler\n preventDefault: boolean\n }>()\n const fieldCache = new Map<string, FormFieldElement[]>()\n\n let manualErrors: FormErrors = {}\n let validationErrors: FormErrors = {}\n let isValidated = Boolean(normalizedOptions.autoValidate)\n let autoSubmitEnabled = false\n let autoSubmitDebounce = 0\n let submitCount = 0\n let autoSubmitTimer: ReturnType<typeof setTimeout> | null = null\n let mutationObserver: MutationObserver | null = null\n let isDestroyed = false\n\n const notifySubscribers = () => {\n const state = api.getState()\n subscribers.forEach(listener => listener(state))\n }\n\n const addListener = (\n listenerTarget: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject\n ) => {\n listenerTarget.addEventListener(type, handler)\n listeners.push({ element: listenerTarget, type, handler })\n }\n\n const clearFieldCache = () => {\n fieldCache.clear()\n }\n\n const getFieldsByName = (name: string) => {\n if (!element) {\n return []\n }\n\n if (!fieldCache.has(name)) {\n fieldCache.set(name, queryNamedFields(element, name))\n }\n\n return fieldCache.get(name) ?? []\n }\n\n const getTrackedFieldNames = () => {\n if (!element) {\n return Object.keys(validators)\n }\n\n const names = new Set<string>(Object.keys(validators))\n for (const field of getNamedFields(element)) {\n names.add(field.name)\n }\n\n return Array.from(names)\n }\n\n const getValues = () => {\n const values: FormStateSnapshot['values'] = {}\n for (const name of getTrackedFieldNames()) {\n values[name] = api.getValue(name)\n }\n return values\n }\n\n const getMergedErrors = () => mergeErrors(validationErrors, manualErrors)\n\n const syncVisualState = (names?: string[]) => {\n if (!element) {\n return\n }\n\n const targetNames = names ?? getTrackedFieldNames()\n const errors = getMergedErrors()\n\n for (const name of targetNames) {\n const fields = getFieldsByName(name)\n const hasError = Boolean(errors[name]?.length)\n for (const field of fields) {\n applyBooleanAttribute(field, attributes.filled, isFieldFilled(field))\n applyBooleanAttribute(field, attributes.error, hasError)\n }\n }\n }\n\n const validateNames = (names?: string[]) => {\n const targetNames = names ?? Object.keys(validators)\n const values = getValues()\n const nextValidationErrors = names ? cloneErrors(validationErrors) : {}\n\n for (const name of targetNames) {\n const rules = validators[name]\n\n if (!rules) {\n delete nextValidationErrors[name]\n continue\n }\n\n const errors = validateFieldValue(name, values[name], rules, values)\n if (errors.length > 0) {\n nextValidationErrors[name] = errors\n } else {\n delete nextValidationErrors[name]\n }\n }\n\n validationErrors = nextValidationErrors\n syncVisualState(names)\n\n return {\n isValid: Object.keys(getMergedErrors()).length === 0,\n errors: cloneErrors(getMergedErrors())\n } satisfies ValidationResult\n }\n\n const emitFieldWatchers = (name: string) => {\n if (!element) {\n return\n }\n\n const callbacks = watchedFields.get(name)\n if (!callbacks || callbacks.size === 0) {\n return\n }\n\n const value = api.getValue(name)\n const state = api.getState()\n callbacks.forEach(callback => callback(value, element, state))\n }\n\n const scheduleAutoSubmit = () => {\n if (!element || !autoSubmitEnabled) {\n return\n }\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n }\n\n if (autoSubmitDebounce > 0) {\n autoSubmitTimer = setTimeout(() => submitForm(element), autoSubmitDebounce)\n return\n }\n\n submitForm(element)\n }\n\n const handleDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) {\n return\n }\n\n const name = target.name\n if (!name) {\n return\n }\n\n clearFieldCache()\n syncVisualState([name])\n\n if (isValidated && validators[name]) {\n validateNames([name])\n }\n\n emitFieldWatchers(name)\n notifySubscribers()\n scheduleAutoSubmit()\n }\n\n const handleSubmitEvent = (event: Event) => {\n if (!element || isDestroyed) {\n return\n }\n\n if (normalizedOptions.clearErrorsOnSubmit) {\n manualErrors = {}\n }\n\n const validation = api.validate()\n const handlers = Array.from(submitHandlers)\n const shouldPrevent = validation.isValid\n ? handlers.some(handler => handler.preventDefault)\n : true\n\n if (shouldPrevent) {\n event.preventDefault()\n }\n\n submitCount += 1\n notifySubscribers()\n\n if (!validation.isValid) {\n return\n }\n\n const { data, formData } = api.getData()\n const state = api.getState()\n handlers.forEach(handler => handler.callback(element, data, formData, state))\n }\n\n const startMutationObserver = () => {\n if (!element || typeof MutationObserver === 'undefined') {\n return\n }\n\n mutationObserver = new MutationObserver(() => {\n clearFieldCache()\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n notifySubscribers()\n })\n\n mutationObserver.observe(element, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['name', 'type']\n })\n }\n\n const isFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\n const api: FormController = {\n element,\n f: element,\n options: normalizedOptions,\n onSubmit(callback, preventDefault = true) {\n submitHandlers.add({ callback, preventDefault })\n return api\n },\n watch(field, callback) {\n api.observe(field, callback)\n return api\n },\n observe(field, callback) {\n const callbacks = watchedFields.get(field) ?? new Set<FormFieldWatcher>()\n callbacks.add(callback)\n watchedFields.set(field, callbacks)\n\n if (element) {\n callback(api.getValue(field), element, api.getState())\n }\n\n return () => {\n const currentCallbacks = watchedFields.get(field)\n currentCallbacks?.delete(callback)\n if (currentCallbacks && currentCallbacks.size === 0) {\n watchedFields.delete(field)\n }\n }\n },\n unwatch(field, callback) {\n if (!field) {\n watchedFields.clear()\n return api\n }\n\n if (!callback) {\n watchedFields.delete(field)\n return api\n }\n\n const callbacks = watchedFields.get(field)\n callbacks?.delete(callback)\n if (callbacks && callbacks.size === 0) {\n watchedFields.delete(field)\n }\n return api\n },\n subscribe(listener) {\n subscribers.add(listener)\n listener(api.getState())\n return () => {\n subscribers.delete(listener)\n }\n },\n prefill(fieldName) {\n if (!element) {\n return api\n }\n\n const queryParams = new URLSearchParams(window.location.search)\n queryParams.forEach((value, key) => {\n if (fieldName && fieldName !== key) {\n return\n }\n\n api.setValue(key, value)\n })\n return api\n },\n append({ tag, content, class: className, atStart = false }: AppendContentOptions) {\n if (!element) {\n return null\n }\n\n clearFieldCache()\n if (className) {\n const classSelector = className.trim().split(/\\s+/)[0]\n element.querySelector(`.${classSelector}`)?.remove()\n }\n\n const node = document.createElement(tag)\n if (className) {\n node.className = className\n }\n node.innerHTML = content\n\n if (atStart && element.firstChild) {\n element.insertBefore(node, element.firstChild)\n } else {\n element.appendChild(node)\n }\n\n return node\n },\n setErrors(fields) {\n if (Array.isArray(fields)) {\n manualErrors = {\n ...manualErrors,\n ...Object.fromEntries(fields.map(field => [field, ['Invalid value.']]))\n }\n } else {\n manualErrors = {\n ...manualErrors,\n ...cloneErrors(fields)\n }\n }\n\n syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields))\n notifySubscribers()\n return api\n },\n clearErrors(fields) {\n if (!fields) {\n manualErrors = {}\n syncVisualState()\n notifySubscribers()\n return api\n }\n\n for (const field of fields) {\n delete manualErrors[field]\n }\n\n syncVisualState(fields)\n notifySubscribers()\n return api\n },\n setValue(name, value) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return api\n }\n\n writeFieldValue(fields, value)\n const firstField = fields[0]\n if (!firstField) {\n return api\n }\n\n const eventType =\n firstField instanceof HTMLSelectElement ||\n (firstField instanceof HTMLInputElement &&\n (firstField.type === 'checkbox' || firstField.type === 'radio'))\n ? 'change'\n : 'input'\n\n firstField.dispatchEvent(new Event(eventType, { bubbles: true }))\n return api\n },\n validate(fields) {\n isValidated = true\n syncVisualState(fields)\n return validateNames(fields)\n },\n revalidate(fields) {\n return api.validate(fields)\n },\n reset() {\n if (!element) {\n return api\n }\n\n element.reset()\n manualErrors = {}\n validationErrors = {}\n clearAttributes(element, [attributes.error, attributes.filled])\n if (isValidated) {\n syncVisualState()\n }\n notifySubscribers()\n return api\n },\n autoSubmit(nextOptions = true) {\n autoSubmitEnabled = nextOptions !== false\n autoSubmitDebounce =\n typeof nextOptions === 'object' && nextOptions\n ? nextOptions.debounce ?? 0\n : 0\n notifySubscribers()\n return api\n },\n disableAutoSubmit() {\n autoSubmitEnabled = false\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n notifySubscribers()\n return api\n },\n getValue(name) {\n return readFieldValue(getFieldsByName(name))\n },\n getField(name) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return null\n }\n const [firstField] = fields\n if (!firstField) {\n return null\n }\n return fields.length === 1 ? firstField : fields\n },\n getData() {\n if (!element) {\n return { data: {}, formData: new FormData() }\n }\n return parseFormData(element)\n },\n getState() {\n const values = getValues()\n const errors = cloneErrors(getMergedErrors())\n const filledFields = getTrackedFieldNames().filter(name => {\n const value = values[name]\n return Array.isArray(value)\n ? value.length > 0\n : typeof value === 'string'\n ? value.trim().length > 0\n : value !== undefined\n })\n\n return {\n ...createEmptyFormState(),\n values,\n errors,\n filledFields,\n isValid: Object.keys(errors).length === 0,\n isValidated,\n autoSubmit: autoSubmitEnabled,\n submitCount\n }\n },\n destroy() {\n if (isDestroyed) {\n return\n }\n\n isDestroyed = true\n for (const listener of listeners) {\n listener.element.removeEventListener(listener.type, listener.handler)\n }\n listeners.length = 0\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n\n mutationObserver?.disconnect()\n mutationObserver = null\n watchedFields.clear()\n subscribers.clear()\n submitHandlers.clear()\n clearFieldCache()\n manualErrors = {}\n validationErrors = {}\n }\n }\n\n if (element) {\n addListener(element, 'input', handleDelegatedEvent)\n addListener(element, 'change', handleDelegatedEvent)\n addListener(element, 'submit', handleSubmitEvent)\n startMutationObserver()\n }\n\n if (normalizedOptions.autoSubmit) {\n const autoSubmitOption = normalizedOptions.autoSubmit as boolean | AutoSubmitOptions\n api.autoSubmit(autoSubmitOption)\n }\n\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n\n return api\n}","import type { FormControllerOptions, FormTarget } from '../core'\nimport { createFormController } from '../internal/controller'\n\nexport const form = (\n target: FormTarget,\n options?: FormControllerOptions\n) => createFormController(target, options)\n\nexport { createFormController }"],"mappings":"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","names":["form","target"]}
@@ -324,6 +324,7 @@ var createFormController = (target, options = {}) => {
324
324
  const isFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
325
325
  const api = {
326
326
  element,
327
+ f: element,
327
328
  options: normalizedOptions,
328
329
  onSubmit(callback, preventDefault = true) {
329
330
  submitHandlers.add({ callback, preventDefault });
@@ -568,4 +569,4 @@ export {
568
569
  resolveFormElement,
569
570
  createFormController
570
571
  };
571
- //# sourceMappingURL=chunk-D3J67V3G.js.map
572
+ //# sourceMappingURL=chunk-KIJEFIHP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/dom.ts","../src/internal/controller.ts"],"sourcesContent":["import type { FormFieldElement, FormFieldValue, FormTarget } from '../core/types'\n\nconst isFormFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\nexport const resolveFormElement = (target: FormTarget): HTMLFormElement | null => {\n if (!target) {\n return null\n }\n\n if (target instanceof HTMLFormElement) {\n return target\n }\n\n if (typeof target === 'string') {\n const element = document.getElementById(target)\n return element instanceof HTMLFormElement ? element : null\n }\n\n if ('current' in target) {\n return target.current instanceof HTMLFormElement ? target.current : null\n }\n\n return null\n}\n\nexport const getNamedFields = (form: HTMLFormElement): FormFieldElement[] =>\n Array.from(form.querySelectorAll('input[name], select[name], textarea[name]')).filter(\n isFormFieldElement\n )\n\nexport const queryNamedFields = (\n form: HTMLFormElement,\n name: string\n): FormFieldElement[] => getNamedFields(form).filter(field => field.name === name)\n\nexport const isFieldFilled = (field: FormFieldElement) => {\n if (field instanceof HTMLInputElement) {\n if (field.type === 'checkbox' || field.type === 'radio') {\n return field.checked\n }\n\n if (field.type === 'file') {\n return Boolean(field.files && field.files.length > 0)\n }\n\n return field.value.trim() !== ''\n }\n\n return field.value !== ''\n}\n\nexport const applyBooleanAttribute = (\n field: FormFieldElement,\n attribute: string,\n enabled: boolean\n) => {\n if (enabled) {\n field.setAttribute(attribute, '')\n return\n }\n\n field.removeAttribute(attribute)\n}\n\nexport const readFieldValue = (\n fields: FormFieldElement[]\n): FormFieldValue => {\n if (fields.length === 0) {\n return undefined\n }\n\n const firstField = fields[0]\n if (!firstField) {\n return undefined\n }\n\n if (firstField instanceof HTMLSelectElement || firstField instanceof HTMLTextAreaElement) {\n return firstField.value\n }\n\n if (firstField.type === 'radio') {\n const checked = fields.find(\n field => field instanceof HTMLInputElement && field.checked\n ) as HTMLInputElement | undefined\n\n return checked?.value ?? ''\n }\n\n if (firstField.type === 'checkbox') {\n const values = fields\n .filter(field => field instanceof HTMLInputElement && field.checked)\n .map(field => (field as HTMLInputElement).value)\n\n return values.length > 1 ? values : (values[0] ?? '')\n }\n\n if (firstField.type === 'file') {\n return firstField.files ? Array.from(firstField.files) : []\n }\n\n return firstField.value\n}\n\nexport const writeFieldValue = (\n fields: FormFieldElement[],\n value: unknown\n) => {\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 (const field of fields) {\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\n if (field.type === 'radio') {\n field.checked = field.value === normalizedValue\n continue\n }\n\n if (field.type === 'file') {\n if (Array.isArray(value) && value.length === 0) {\n field.value = ''\n }\n continue\n }\n\n field.value = normalizedValue\n continue\n }\n\n field.value = normalizedValue\n }\n}\n\nexport const clearAttributes = (\n form: HTMLFormElement,\n attributes: string[]\n) => {\n for (const attribute of attributes) {\n form.querySelectorAll(`[${attribute}]`).forEach(element => {\n element.removeAttribute(attribute)\n })\n }\n}\n\nexport const submitForm = (form: HTMLFormElement) => {\n if (typeof form.requestSubmit === 'function') {\n form.requestSubmit()\n return\n }\n\n const submitButton = form.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) as HTMLButtonElement | HTMLInputElement | null\n\n if (submitButton) {\n submitButton.click()\n return\n }\n\n form.submit()\n}","import { createEmptyFormState, parseFormData, validateFieldValue } from '../core'\nimport type {\n AppendContentOptions,\n AutoSubmitOptions,\n FormController,\n FormControllerOptions,\n FormErrors,\n FormFieldElement,\n FormFieldWatcher,\n FormSubmitHandler,\n FormStateListener,\n FormStateSnapshot,\n FormTarget,\n ValidationResult,\n VisualAttributes\n} from '../core/types'\nimport {\n applyBooleanAttribute,\n clearAttributes,\n getNamedFields,\n isFieldFilled,\n queryNamedFields,\n readFieldValue,\n resolveFormElement,\n submitForm,\n writeFieldValue\n} from './dom'\n\nconst DEFAULT_ATTRIBUTES: VisualAttributes = {\n filled: 'css-filled',\n error: 'css-error'\n}\n\nconst DEFAULT_OPTIONS: Required<\n Pick<FormControllerOptions, 'autoValidate' | 'clearErrorsOnSubmit'>\n> = {\n autoValidate: true,\n clearErrorsOnSubmit: true\n}\n\nconst mergeErrors = (left: FormErrors, right: FormErrors) => {\n const merged: FormErrors = { ...left }\n\n for (const [field, messages] of Object.entries(right)) {\n merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages]\n }\n\n return merged\n}\n\nconst cloneErrors = (errors: FormErrors) =>\n Object.fromEntries(\n Object.entries(errors).map(([field, messages]) => [field, [...messages]])\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 validators = normalizedOptions.validators ?? {}\n const watchedFields = new Map<string, Set<FormFieldWatcher>>()\n const listeners: Array<{\n element: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n }> = []\n const subscribers = new Set<FormStateListener>()\n const submitHandlers = new Set<{\n callback: FormSubmitHandler\n preventDefault: boolean\n }>()\n const fieldCache = new Map<string, FormFieldElement[]>()\n\n let manualErrors: FormErrors = {}\n let validationErrors: FormErrors = {}\n let isValidated = Boolean(normalizedOptions.autoValidate)\n let autoSubmitEnabled = false\n let autoSubmitDebounce = 0\n let submitCount = 0\n let autoSubmitTimer: ReturnType<typeof setTimeout> | null = null\n let mutationObserver: MutationObserver | null = null\n let isDestroyed = false\n\n const notifySubscribers = () => {\n const state = api.getState()\n subscribers.forEach(listener => listener(state))\n }\n\n const addListener = (\n listenerTarget: EventTarget,\n type: string,\n handler: EventListenerOrEventListenerObject\n ) => {\n listenerTarget.addEventListener(type, handler)\n listeners.push({ element: listenerTarget, type, handler })\n }\n\n const clearFieldCache = () => {\n fieldCache.clear()\n }\n\n const getFieldsByName = (name: string) => {\n if (!element) {\n return []\n }\n\n if (!fieldCache.has(name)) {\n fieldCache.set(name, queryNamedFields(element, name))\n }\n\n return fieldCache.get(name) ?? []\n }\n\n const getTrackedFieldNames = () => {\n if (!element) {\n return Object.keys(validators)\n }\n\n const names = new Set<string>(Object.keys(validators))\n for (const field of getNamedFields(element)) {\n names.add(field.name)\n }\n\n return Array.from(names)\n }\n\n const getValues = () => {\n const values: FormStateSnapshot['values'] = {}\n for (const name of getTrackedFieldNames()) {\n values[name] = api.getValue(name)\n }\n return values\n }\n\n const getMergedErrors = () => mergeErrors(validationErrors, manualErrors)\n\n const syncVisualState = (names?: string[]) => {\n if (!element) {\n return\n }\n\n const targetNames = names ?? getTrackedFieldNames()\n const errors = getMergedErrors()\n\n for (const name of targetNames) {\n const fields = getFieldsByName(name)\n const hasError = Boolean(errors[name]?.length)\n for (const field of fields) {\n applyBooleanAttribute(field, attributes.filled, isFieldFilled(field))\n applyBooleanAttribute(field, attributes.error, hasError)\n }\n }\n }\n\n const validateNames = (names?: string[]) => {\n const targetNames = names ?? Object.keys(validators)\n const values = getValues()\n const nextValidationErrors = names ? cloneErrors(validationErrors) : {}\n\n for (const name of targetNames) {\n const rules = validators[name]\n\n if (!rules) {\n delete nextValidationErrors[name]\n continue\n }\n\n const errors = validateFieldValue(name, values[name], rules, values)\n if (errors.length > 0) {\n nextValidationErrors[name] = errors\n } else {\n delete nextValidationErrors[name]\n }\n }\n\n validationErrors = nextValidationErrors\n syncVisualState(names)\n\n return {\n isValid: Object.keys(getMergedErrors()).length === 0,\n errors: cloneErrors(getMergedErrors())\n } satisfies ValidationResult\n }\n\n const emitFieldWatchers = (name: string) => {\n if (!element) {\n return\n }\n\n const callbacks = watchedFields.get(name)\n if (!callbacks || callbacks.size === 0) {\n return\n }\n\n const value = api.getValue(name)\n const state = api.getState()\n callbacks.forEach(callback => callback(value, element, state))\n }\n\n const scheduleAutoSubmit = () => {\n if (!element || !autoSubmitEnabled) {\n return\n }\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n }\n\n if (autoSubmitDebounce > 0) {\n autoSubmitTimer = setTimeout(() => submitForm(element), autoSubmitDebounce)\n return\n }\n\n submitForm(element)\n }\n\n const handleDelegatedEvent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element) || !isFieldElement(target)) {\n return\n }\n\n const name = target.name\n if (!name) {\n return\n }\n\n clearFieldCache()\n syncVisualState([name])\n\n if (isValidated && validators[name]) {\n validateNames([name])\n }\n\n emitFieldWatchers(name)\n notifySubscribers()\n scheduleAutoSubmit()\n }\n\n const handleSubmitEvent = (event: Event) => {\n if (!element || isDestroyed) {\n return\n }\n\n if (normalizedOptions.clearErrorsOnSubmit) {\n manualErrors = {}\n }\n\n const validation = api.validate()\n const handlers = Array.from(submitHandlers)\n const shouldPrevent = validation.isValid\n ? handlers.some(handler => handler.preventDefault)\n : true\n\n if (shouldPrevent) {\n event.preventDefault()\n }\n\n submitCount += 1\n notifySubscribers()\n\n if (!validation.isValid) {\n return\n }\n\n const { data, formData } = api.getData()\n const state = api.getState()\n handlers.forEach(handler => handler.callback(element, data, formData, state))\n }\n\n const startMutationObserver = () => {\n if (!element || typeof MutationObserver === 'undefined') {\n return\n }\n\n mutationObserver = new MutationObserver(() => {\n clearFieldCache()\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n notifySubscribers()\n })\n\n mutationObserver.observe(element, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['name', 'type']\n })\n }\n\n const isFieldElement = (value: Element): value is FormFieldElement =>\n value instanceof HTMLInputElement ||\n value instanceof HTMLSelectElement ||\n value instanceof HTMLTextAreaElement\n\n const api: FormController = {\n element,\n f: element,\n options: normalizedOptions,\n onSubmit(callback, preventDefault = true) {\n submitHandlers.add({ callback, preventDefault })\n return api\n },\n watch(field, callback) {\n api.observe(field, callback)\n return api\n },\n observe(field, callback) {\n const callbacks = watchedFields.get(field) ?? new Set<FormFieldWatcher>()\n callbacks.add(callback)\n watchedFields.set(field, callbacks)\n\n if (element) {\n callback(api.getValue(field), element, api.getState())\n }\n\n return () => {\n const currentCallbacks = watchedFields.get(field)\n currentCallbacks?.delete(callback)\n if (currentCallbacks && currentCallbacks.size === 0) {\n watchedFields.delete(field)\n }\n }\n },\n unwatch(field, callback) {\n if (!field) {\n watchedFields.clear()\n return api\n }\n\n if (!callback) {\n watchedFields.delete(field)\n return api\n }\n\n const callbacks = watchedFields.get(field)\n callbacks?.delete(callback)\n if (callbacks && callbacks.size === 0) {\n watchedFields.delete(field)\n }\n return api\n },\n subscribe(listener) {\n subscribers.add(listener)\n listener(api.getState())\n return () => {\n subscribers.delete(listener)\n }\n },\n prefill(fieldName) {\n if (!element) {\n return api\n }\n\n const queryParams = new URLSearchParams(window.location.search)\n queryParams.forEach((value, key) => {\n if (fieldName && fieldName !== key) {\n return\n }\n\n api.setValue(key, value)\n })\n return api\n },\n append({ tag, content, class: className, atStart = false }: AppendContentOptions) {\n if (!element) {\n return null\n }\n\n clearFieldCache()\n if (className) {\n const classSelector = className.trim().split(/\\s+/)[0]\n element.querySelector(`.${classSelector}`)?.remove()\n }\n\n const node = document.createElement(tag)\n if (className) {\n node.className = className\n }\n node.innerHTML = content\n\n if (atStart && element.firstChild) {\n element.insertBefore(node, element.firstChild)\n } else {\n element.appendChild(node)\n }\n\n return node\n },\n setErrors(fields) {\n if (Array.isArray(fields)) {\n manualErrors = {\n ...manualErrors,\n ...Object.fromEntries(fields.map(field => [field, ['Invalid value.']]))\n }\n } else {\n manualErrors = {\n ...manualErrors,\n ...cloneErrors(fields)\n }\n }\n\n syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields))\n notifySubscribers()\n return api\n },\n clearErrors(fields) {\n if (!fields) {\n manualErrors = {}\n syncVisualState()\n notifySubscribers()\n return api\n }\n\n for (const field of fields) {\n delete manualErrors[field]\n }\n\n syncVisualState(fields)\n notifySubscribers()\n return api\n },\n setValue(name, value) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return api\n }\n\n writeFieldValue(fields, value)\n const firstField = fields[0]\n if (!firstField) {\n return api\n }\n\n const eventType =\n firstField instanceof HTMLSelectElement ||\n (firstField instanceof HTMLInputElement &&\n (firstField.type === 'checkbox' || firstField.type === 'radio'))\n ? 'change'\n : 'input'\n\n firstField.dispatchEvent(new Event(eventType, { bubbles: true }))\n return api\n },\n validate(fields) {\n isValidated = true\n syncVisualState(fields)\n return validateNames(fields)\n },\n revalidate(fields) {\n return api.validate(fields)\n },\n reset() {\n if (!element) {\n return api\n }\n\n element.reset()\n manualErrors = {}\n validationErrors = {}\n clearAttributes(element, [attributes.error, attributes.filled])\n if (isValidated) {\n syncVisualState()\n }\n notifySubscribers()\n return api\n },\n autoSubmit(nextOptions = true) {\n autoSubmitEnabled = nextOptions !== false\n autoSubmitDebounce =\n typeof nextOptions === 'object' && nextOptions\n ? nextOptions.debounce ?? 0\n : 0\n notifySubscribers()\n return api\n },\n disableAutoSubmit() {\n autoSubmitEnabled = false\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n notifySubscribers()\n return api\n },\n getValue(name) {\n return readFieldValue(getFieldsByName(name))\n },\n getField(name) {\n const fields = getFieldsByName(name)\n if (fields.length === 0) {\n return null\n }\n const [firstField] = fields\n if (!firstField) {\n return null\n }\n return fields.length === 1 ? firstField : fields\n },\n getData() {\n if (!element) {\n return { data: {}, formData: new FormData() }\n }\n return parseFormData(element)\n },\n getState() {\n const values = getValues()\n const errors = cloneErrors(getMergedErrors())\n const filledFields = getTrackedFieldNames().filter(name => {\n const value = values[name]\n return Array.isArray(value)\n ? value.length > 0\n : typeof value === 'string'\n ? value.trim().length > 0\n : value !== undefined\n })\n\n return {\n ...createEmptyFormState(),\n values,\n errors,\n filledFields,\n isValid: Object.keys(errors).length === 0,\n isValidated,\n autoSubmit: autoSubmitEnabled,\n submitCount\n }\n },\n destroy() {\n if (isDestroyed) {\n return\n }\n\n isDestroyed = true\n for (const listener of listeners) {\n listener.element.removeEventListener(listener.type, listener.handler)\n }\n listeners.length = 0\n\n if (autoSubmitTimer) {\n clearTimeout(autoSubmitTimer)\n autoSubmitTimer = null\n }\n\n mutationObserver?.disconnect()\n mutationObserver = null\n watchedFields.clear()\n subscribers.clear()\n submitHandlers.clear()\n clearFieldCache()\n manualErrors = {}\n validationErrors = {}\n }\n }\n\n if (element) {\n addListener(element, 'input', handleDelegatedEvent)\n addListener(element, 'change', handleDelegatedEvent)\n addListener(element, 'submit', handleSubmitEvent)\n startMutationObserver()\n }\n\n if (normalizedOptions.autoSubmit) {\n const autoSubmitOption = normalizedOptions.autoSubmit as boolean | AutoSubmitOptions\n api.autoSubmit(autoSubmitOption)\n }\n\n if (isValidated) {\n syncVisualState()\n validateNames()\n }\n\n return api\n}"],"mappings":"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","names":["target"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createFormController
3
- } from "./chunk-D3J67V3G.js";
3
+ } from "./chunk-KIJEFIHP.js";
4
4
 
5
5
  // src/vanilla/index.ts
6
6
  var form = (target, options) => createFormController(target, options);
@@ -8,4 +8,4 @@ var form = (target, options) => createFormController(target, options);
8
8
  export {
9
9
  form
10
10
  };
11
- //# sourceMappingURL=chunk-HP2CJPHY.js.map
11
+ //# sourceMappingURL=chunk-KKQD25KI.js.map
@@ -1,5 +1,5 @@
1
- import { S as SerializedFormResult, l as FormStateSnapshot, i as FormFieldValue, b as FieldValidationRules, o as FormValues, q as ValidationSchema, V as ValidationResult } from '../types-gvovPPPU.cjs';
2
- export { A as AppendContentOptions, a as AutoSubmitOptions, F as FieldValidationContext, c as FieldValidator, d as FormController, e as FormControllerOptions, f as FormDataPrimitive, g as FormErrors, h as FormFieldElement, j as FormFieldWatcher, k as FormStateListener, m as FormSubmitHandler, n as FormTarget, R as RuleConfig, p as SerializedFormValue, r as VisualAttributes } from '../types-gvovPPPU.cjs';
1
+ import { S as SerializedFormResult, l as FormStateSnapshot, i as FormFieldValue, b as FieldValidationRules, o as FormValues, q as ValidationSchema, V as ValidationResult } from '../types-C0_1rYlm.cjs';
2
+ export { A as AppendContentOptions, a as AutoSubmitOptions, F as FieldValidationContext, c as FieldValidator, d as FormController, e as FormControllerOptions, f as FormDataPrimitive, g as FormErrors, h as FormFieldElement, j as FormFieldWatcher, k as FormStateListener, m as FormSubmitHandler, n as FormTarget, R as RuleConfig, p as SerializedFormValue, r as VisualAttributes } from '../types-C0_1rYlm.cjs';
3
3
 
4
4
  declare const parseFormData: (formElement: HTMLFormElement) => SerializedFormResult;
5
5
 
@@ -1,5 +1,5 @@
1
- import { S as SerializedFormResult, l as FormStateSnapshot, i as FormFieldValue, b as FieldValidationRules, o as FormValues, q as ValidationSchema, V as ValidationResult } from '../types-gvovPPPU.js';
2
- export { A as AppendContentOptions, a as AutoSubmitOptions, F as FieldValidationContext, c as FieldValidator, d as FormController, e as FormControllerOptions, f as FormDataPrimitive, g as FormErrors, h as FormFieldElement, j as FormFieldWatcher, k as FormStateListener, m as FormSubmitHandler, n as FormTarget, R as RuleConfig, p as SerializedFormValue, r as VisualAttributes } from '../types-gvovPPPU.js';
1
+ import { S as SerializedFormResult, l as FormStateSnapshot, i as FormFieldValue, b as FieldValidationRules, o as FormValues, q as ValidationSchema, V as ValidationResult } from '../types-C0_1rYlm.js';
2
+ export { A as AppendContentOptions, a as AutoSubmitOptions, F as FieldValidationContext, c as FieldValidator, d as FormController, e as FormControllerOptions, f as FormDataPrimitive, g as FormErrors, h as FormFieldElement, j as FormFieldWatcher, k as FormStateListener, m as FormSubmitHandler, n as FormTarget, R as RuleConfig, p as SerializedFormValue, r as VisualAttributes } from '../types-C0_1rYlm.js';
3
3
 
4
4
  declare const parseFormData: (formElement: HTMLFormElement) => SerializedFormResult;
5
5
 
package/dist/index.cjs CHANGED
@@ -467,6 +467,7 @@ var createFormController = (target, options = {}) => {
467
467
  const isFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
468
468
  const api = {
469
469
  element,
470
+ f: element,
470
471
  options: normalizedOptions,
471
472
  onSubmit(callback, preventDefault = true) {
472
473
  submitHandlers.add({ callback, preventDefault });