a11y-form-validator 1.0.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +390 -0
  4. package/dist/A11yFormValidator-D0n6br-b.d.ts +335 -0
  5. package/dist/A11yFormValidator-D0n6br-b.d.ts.map +1 -0
  6. package/dist/addons/character-count.d.ts +38 -0
  7. package/dist/addons/character-count.d.ts.map +1 -0
  8. package/dist/addons/character-count.js +161 -0
  9. package/dist/addons/character-count.js.map +1 -0
  10. package/dist/addons/error-summary.d.ts +29 -0
  11. package/dist/addons/error-summary.d.ts.map +1 -0
  12. package/dist/addons/error-summary.js +4 -0
  13. package/dist/default-BHBWPNeK.d.ts +7 -0
  14. package/dist/default-BHBWPNeK.d.ts.map +1 -0
  15. package/dist/default-DFnPBuVC.js +18 -0
  16. package/dist/default-DFnPBuVC.js.map +1 -0
  17. package/dist/docs.d.ts +66 -0
  18. package/dist/docs.d.ts.map +1 -0
  19. package/dist/docs.js +204 -0
  20. package/dist/docs.js.map +1 -0
  21. package/dist/error-summary-FnZoUC72.js +99 -0
  22. package/dist/error-summary-FnZoUC72.js.map +1 -0
  23. package/dist/helpers-c_THOe-Q.js +150 -0
  24. package/dist/helpers-c_THOe-Q.js.map +1 -0
  25. package/dist/index.d.ts +37 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +1197 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/index.min.js +2 -0
  30. package/dist/index.min.js.map +1 -0
  31. package/dist/locales/ar.json +13 -0
  32. package/dist/locales/en.json +13 -0
  33. package/dist/locales/es.json +13 -0
  34. package/dist/locales/fr.json +13 -0
  35. package/dist/locales/hi.json +13 -0
  36. package/dist/locales/it.json +13 -0
  37. package/dist/locales/ja.json +13 -0
  38. package/dist/locales/ko.json +13 -0
  39. package/dist/locales/nl.json +13 -0
  40. package/dist/locales/pl.json +13 -0
  41. package/dist/locales/pt-BR.json +13 -0
  42. package/dist/locales/ru.json +13 -0
  43. package/dist/locales/tr.json +13 -0
  44. package/dist/locales/uk.json +13 -0
  45. package/dist/locales/zh-CN.json +13 -0
  46. package/dist/minimal-40_EIW9U.d.ts +7 -0
  47. package/dist/minimal-40_EIW9U.d.ts.map +1 -0
  48. package/dist/minimal-Bm3pKoN7.js +15 -0
  49. package/dist/minimal-Bm3pKoN7.js.map +1 -0
  50. package/dist/no-summary-BI1pTld5.d.ts +7 -0
  51. package/dist/no-summary-BI1pTld5.d.ts.map +1 -0
  52. package/dist/no-summary-DQCNtzs6.js +16 -0
  53. package/dist/no-summary-DQCNtzs6.js.map +1 -0
  54. package/dist/presets/default.d.ts +3 -0
  55. package/dist/presets/default.js +5 -0
  56. package/dist/presets/minimal.d.ts +3 -0
  57. package/dist/presets/minimal.js +3 -0
  58. package/dist/presets/no-summary.d.ts +3 -0
  59. package/dist/presets/no-summary.js +3 -0
  60. package/dist/styles.css +91 -0
  61. package/package.json +95 -0
@@ -0,0 +1,335 @@
1
+ //#region src/core/EventEmitter.d.ts
2
+ declare class EventEmitter {
3
+ readonly target: EventTarget;
4
+ constructor(target: EventTarget);
5
+ emit(name: string, detail?: Record<string, unknown>): void;
6
+ on(name: string, handler: EventListener): () => void;
7
+ off(name: string, handler: EventListener): void;
8
+ }
9
+ //#endregion
10
+ //#region src/core/helpers.d.ts
11
+ type RuleOptions = Record<string, unknown>;
12
+ type RuleList = Record<string, true | string | number | RuleOptions>;
13
+ //#endregion
14
+ //#region src/core/FieldController.d.ts
15
+ type FormControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
16
+ type FieldType = 'textarea' | 'select' | 'select-multiple' | 'radio' | 'checkbox' | 'file' | string;
17
+ declare class FieldController {
18
+ readonly validator: A11yFormValidator;
19
+ readonly name: string;
20
+ readonly elements: FormControl[];
21
+ readonly primaryElement: FormControl;
22
+ readonly type: FieldType;
23
+ readonly isGroupedChoice: boolean;
24
+ readonly errorId: string;
25
+ readonly primaryId: string;
26
+ readonly initialDescribedBy: Map<FormControl, string>;
27
+ private readonly generatedPrimaryId;
28
+ serverMessage: string;
29
+ lastError: string;
30
+ touched: boolean;
31
+ dirty: boolean;
32
+ constructor(validator: A11yFormValidator, name: string, elements: FormControl[]);
33
+ detectType(): FieldType;
34
+ getActiveElements(): FormControl[];
35
+ isDisabled(): boolean;
36
+ isHidden(): boolean;
37
+ shouldIgnore(): false | 'disabled' | 'hidden' | 'selector';
38
+ getValue(): FieldValue;
39
+ getFieldConfig(): unknown;
40
+ getDataMessage(ruleName: string): string;
41
+ getLabel(): string;
42
+ getTargetLabel(target: Element | null): string;
43
+ getDescribedBy(): string[];
44
+ connectDescription(id: string): void;
45
+ disconnectDescription(id: string): void;
46
+ setAriaInvalid(isInvalid: boolean, errorId?: string): void;
47
+ setVisualState(state: 'valid' | 'invalid' | 'pending'): void;
48
+ clearVisualState(): void;
49
+ focus(): void;
50
+ markTouched(): void;
51
+ markDirty(): void;
52
+ clearServerMessage(): void;
53
+ setServerMessage(message: string): void;
54
+ getRules(): RuleList;
55
+ getNativeRules(): RuleList;
56
+ getDataRules(): RuleList;
57
+ getValidationContext(ruleName: string, ruleOptions: unknown, allValues: Record<string, FieldValue>): ValidationContext;
58
+ getNativeValidationMessage(): string;
59
+ destroy(): void;
60
+ }
61
+ //#endregion
62
+ //#region src/core/MessageResolver.d.ts
63
+ declare class MessageResolver {
64
+ readonly validator: A11yFormValidator;
65
+ readonly defaultMessages: LocaleMessages;
66
+ constructor(validator: A11yFormValidator);
67
+ detectLocale(): string;
68
+ getLocaleCandidates(locale?: string): string[];
69
+ getLocaleMessage(key: string): MessageValue | undefined;
70
+ resolveValue(message: unknown, context: MessageResolverContext): string;
71
+ getSummaryTitle(count: number): string;
72
+ getSummaryItem(field: FieldController, message: string): string;
73
+ resolve(field: FieldController, ruleName: string, result: ValidationResult): string;
74
+ }
75
+ //#endregion
76
+ //#region src/core/RuleRegistry.d.ts
77
+ declare class RuleRegistry {
78
+ private readonly rules;
79
+ constructor();
80
+ register(name: string, rule: ValidatorRule): this;
81
+ unregister(name: string): this;
82
+ has(name: string): boolean;
83
+ run(name: string, context: ValidationContext): Promise<ValidationResult>;
84
+ normalize(name: string, result: Awaited<ReturnType<ValidatorRule>>): ValidationResult;
85
+ }
86
+ //#endregion
87
+ //#region src/core/ValidationState.d.ts
88
+ type FormValidationState = 'idle' | 'validating' | 'valid' | 'invalid';
89
+ interface FieldValidationState {
90
+ pristine: boolean;
91
+ dirty: boolean;
92
+ touched: boolean;
93
+ pending: boolean;
94
+ valid: boolean;
95
+ invalid: boolean;
96
+ disabled: boolean;
97
+ ignored: boolean;
98
+ }
99
+ interface ValidationStateSnapshot {
100
+ form: FormValidationState;
101
+ fields: Record<string, FieldValidationState>;
102
+ }
103
+ declare class ValidationState {
104
+ private formState;
105
+ private readonly fieldStates;
106
+ constructor();
107
+ ensure(name: string): FieldValidationState;
108
+ updateField(name: string, patch: Partial<FieldValidationState>): FieldValidationState;
109
+ setFormState(state: FormValidationState): void;
110
+ snapshot(): ValidationStateSnapshot;
111
+ }
112
+ //#endregion
113
+ //#region src/core/A11yFormValidator.d.ts
114
+ type ValidateTrigger = 'submit' | 'blur' | 'input' | 'change';
115
+ type ErrorMode = 'inline' | 'native' | 'both';
116
+ type FocusOnError = 'summary' | 'first-invalid' | false;
117
+ type FieldValue = string | boolean | string[] | File[];
118
+ interface ValidationResult {
119
+ valid: boolean;
120
+ messageKey?: string;
121
+ message?: string;
122
+ params?: Record<string, unknown>;
123
+ metadata?: Record<string, unknown>;
124
+ nativeMessage?: string;
125
+ }
126
+ type ValidatorRuleResult = boolean | string | Partial<ValidationResult> | null | undefined;
127
+ interface ValidationContext {
128
+ field: FieldController;
129
+ form: HTMLFormElement;
130
+ value: FieldValue;
131
+ options: RuleOptions;
132
+ allValues: Record<string, FieldValue>;
133
+ validator: A11yFormValidator;
134
+ }
135
+ type ValidatorRule = (context: ValidationContext) => ValidatorRuleResult | Promise<ValidatorRuleResult>;
136
+ type MessageResolverContext = {
137
+ field: FieldController | null;
138
+ fieldName: string;
139
+ fieldLabel: string;
140
+ form: HTMLFormElement;
141
+ rule: string;
142
+ value: unknown;
143
+ params: Record<string, unknown>;
144
+ locale: string;
145
+ };
146
+ type MessageValue = string | ((context: MessageResolverContext) => string);
147
+ interface ValidatorMessages {
148
+ fields?: Record<string, Record<string, MessageValue>>;
149
+ [key: string]: MessageValue | Record<string, Record<string, MessageValue>> | undefined;
150
+ }
151
+ type LocaleMessages = Record<string, MessageValue>;
152
+ interface ValidatorRenderer {
153
+ render(field: FieldController, message: string): void;
154
+ clear(field: FieldController): void;
155
+ destroy?(): void;
156
+ }
157
+ interface ValidatorAddon {
158
+ install(validator: A11yFormValidator): void;
159
+ destroy?(): void;
160
+ }
161
+ type AddonInput = ValidatorAddon;
162
+ interface A11yFormValidatorOptions {
163
+ validateOn: ValidateTrigger | ValidateTrigger[];
164
+ focusOnError: FocusOnError;
165
+ errorMode: ErrorMode;
166
+ useNativeRules: boolean;
167
+ disableNativeUI: boolean;
168
+ validateHidden: boolean;
169
+ ignore: {
170
+ disabled: boolean;
171
+ hidden: boolean;
172
+ selector: string;
173
+ };
174
+ debounce: number;
175
+ messages: ValidatorMessages;
176
+ locales: Record<string, LocaleMessages>;
177
+ locale: string;
178
+ selectors: {
179
+ fields: string;
180
+ };
181
+ addons: AddonInput[];
182
+ renderer: ValidatorRenderer | null;
183
+ rules: Record<string, unknown>;
184
+ }
185
+ type A11yFormValidatorOptionsInput = Partial<Omit<A11yFormValidatorOptions, 'validateOn' | 'addons' | 'ignore' | 'selectors'>> & {
186
+ validateOn?: ValidateTrigger | ValidateTrigger[];
187
+ addons?: AddonInput | AddonInput[];
188
+ ignore?: Partial<A11yFormValidatorOptions['ignore']>;
189
+ selectors?: Partial<A11yFormValidatorOptions['selectors']>;
190
+ };
191
+ interface A11yFormValidatorInstance {
192
+ validate(options?: ValidateOptions): Promise<boolean>;
193
+ validateField(input: FieldInput, options?: ValidateOptions): Promise<boolean>;
194
+ refresh(): this;
195
+ reset(): this;
196
+ clearErrors(): this;
197
+ setErrors(errors?: ServerErrors): this;
198
+ getErrors(): ValidatorErrors;
199
+ getState(): ValidationStateSnapshot;
200
+ enable(): this;
201
+ disable(): this;
202
+ focusOnError(): void;
203
+ destroy(): void;
204
+ }
205
+ interface ValidateOptions {
206
+ reason?: string;
207
+ }
208
+ type FieldInput = FieldController | string | HTMLElement | null | undefined;
209
+ interface ValidatorErrors {
210
+ fields: Record<string, string>;
211
+ form: string[];
212
+ }
213
+ type ServerErrors = Record<string, string | string[] | undefined> & {
214
+ fields?: Record<string, string | string[] | undefined>;
215
+ form?: string | string[];
216
+ _form?: string | string[];
217
+ };
218
+ declare const EVENTS: Readonly<{
219
+ init: "a11y-form-validator:init";
220
+ beforeValidate: "a11y-form-validator:before-validate";
221
+ afterValidate: "a11y-form-validator:after-validate";
222
+ fieldValid: "a11y-form-validator:field-valid";
223
+ fieldInvalid: "a11y-form-validator:field-invalid";
224
+ formValid: "a11y-form-validator:form-valid";
225
+ formInvalid: "a11y-form-validator:form-invalid";
226
+ submitBlocked: "a11y-form-validator:submit-blocked";
227
+ destroy: "a11y-form-validator:destroy";
228
+ }>;
229
+ declare const SELECTORS: Readonly<{
230
+ fields: "input, select, textarea";
231
+ initAll: "[data-a11y-form-validator]";
232
+ }>;
233
+ declare const CLASSES: Readonly<{
234
+ root: "a11y-form-validator";
235
+ initialized: "is-initialized";
236
+ }>;
237
+ declare const ATTRIBUTES: Readonly<{
238
+ describedBy: "aria-describedby";
239
+ errorMessage: "aria-errormessage";
240
+ hidden: "hidden";
241
+ invalid: "aria-invalid";
242
+ noValidate: "novalidate";
243
+ validationState: "data-validation-state";
244
+ }>;
245
+ declare const DEFAULT_OPTIONS: Readonly<{
246
+ validateOn: ValidateTrigger[];
247
+ focusOnError: FocusOnError;
248
+ errorMode: ErrorMode;
249
+ useNativeRules: true;
250
+ disableNativeUI: true;
251
+ validateHidden: false;
252
+ ignore: Readonly<{
253
+ disabled: true;
254
+ hidden: true;
255
+ selector: "";
256
+ }>;
257
+ debounce: 150;
258
+ messages: ValidatorMessages;
259
+ locales: Record<string, LocaleMessages>;
260
+ locale: "";
261
+ selectors: Readonly<{
262
+ fields: "input, select, textarea";
263
+ }>;
264
+ addons: AddonInput[];
265
+ renderer: ValidatorRenderer | null;
266
+ rules: Record<string, unknown>;
267
+ }>;
268
+ declare class A11yFormValidator implements A11yFormValidatorInstance {
269
+ private static readonly instances;
270
+ readonly form: HTMLFormElement;
271
+ readonly options: A11yFormValidatorOptions;
272
+ readonly events: EventEmitter;
273
+ readonly state: ValidationState;
274
+ readonly ruleRegistry: RuleRegistry;
275
+ readonly messageResolver: MessageResolver;
276
+ readonly renderer: ValidatorRenderer;
277
+ fields: FieldController[];
278
+ fieldMap: Map<string, FieldController>;
279
+ enabled: boolean;
280
+ hasSubmitted: boolean;
281
+ formErrors: string[];
282
+ summaryAddon: (ValidatorAddon & {
283
+ hasErrors(): boolean;
284
+ focus(): void;
285
+ }) | null;
286
+ private addons;
287
+ private readonly timers;
288
+ private readonly addedRootClass;
289
+ private readonly addedNoValidate;
290
+ private readonly abortController;
291
+ private readonly validationRuns;
292
+ private destroyed;
293
+ private inlineErrorAnnouncementsMuted;
294
+ private readonly onSubmit;
295
+ private readonly onFocusOut;
296
+ private readonly onInput;
297
+ private readonly onChange;
298
+ constructor(form: HTMLFormElement, options?: A11yFormValidatorOptionsInput);
299
+ static getInstance(form: HTMLFormElement): A11yFormValidator | undefined;
300
+ private normalizeOptions;
301
+ private emit;
302
+ shouldAnnounceInlineErrors(): boolean;
303
+ private shouldMuteInlineErrorsForBatch;
304
+ registerDefaultRules(): void;
305
+ registerRule(name: string, rule: ValidatorRule): this;
306
+ unregisterRule(name: string): this;
307
+ installAddons(): void;
308
+ collectFields(): FieldController[];
309
+ refresh(): this;
310
+ private bindEvents;
311
+ private handleSubmit;
312
+ private handleFocusOut;
313
+ private handleInput;
314
+ private handleChange;
315
+ queueValidation(field: FieldController, reason: string): void;
316
+ findFieldByElement(element: EventTarget | null): FieldController | undefined;
317
+ resolveField(input: FieldInput): FieldController | null;
318
+ getAllValues(): Record<string, FieldValue>;
319
+ validate(options?: ValidateOptions): Promise<boolean>;
320
+ validateField(input: FieldInput, options?: ValidateOptions): Promise<boolean>;
321
+ reset(): this;
322
+ clearErrors(): this;
323
+ setErrors(errors?: ServerErrors): this;
324
+ getErrors(): ValidatorErrors;
325
+ getState(): ValidationStateSnapshot;
326
+ enable(): this;
327
+ disable(): this;
328
+ focusOnError(): void;
329
+ destroy(): void;
330
+ }
331
+ declare function createFormValidator(form: HTMLFormElement, options?: A11yFormValidatorOptionsInput): A11yFormValidatorInstance;
332
+ declare function initFormValidators(options?: A11yFormValidatorOptionsInput, root?: ParentNode): A11yFormValidatorInstance[];
333
+ //#endregion
334
+ export { initFormValidators as A, EventEmitter as B, ValidatorAddon as C, ValidatorRule as D, ValidatorRenderer as E, RuleRegistry as F, MessageResolver as I, FieldController as L, FormValidationState as M, ValidationState as N, ValidatorRuleResult as O, ValidationStateSnapshot as P, FieldType as R, ValidationResult as S, ValidatorMessages as T, SELECTORS as _, ATTRIBUTES as a, ValidateTrigger as b, DEFAULT_OPTIONS as c, FieldInput as d, FieldValue as f, MessageValue as g, MessageResolverContext as h, A11yFormValidatorOptionsInput as i, FieldValidationState as j, createFormValidator as k, EVENTS as l, LocaleMessages as m, A11yFormValidatorInstance as n, AddonInput as o, FocusOnError as p, A11yFormValidatorOptions as r, CLASSES as s, A11yFormValidator as t, ErrorMode as u, ServerErrors as v, ValidatorErrors as w, ValidationContext as x, ValidateOptions as y, FormControl as z };
335
+ //# sourceMappingURL=A11yFormValidator-D0n6br-b.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A11yFormValidator-D0n6br-b.d.ts","names":[],"sources":["../src/core/EventEmitter.ts","../src/core/helpers.ts","../src/core/FieldController.ts","../src/core/MessageResolver.ts","../src/core/RuleRegistry.ts","../src/core/ValidationState.ts","../src/core/A11yFormValidator.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { C as ValidatorAddon, L as FieldController, t as A11yFormValidator } from "../A11yFormValidator-D0n6br-b.js";
2
+
3
+ //#region src/addons/character-count.d.ts
4
+ interface CharacterCountMessages {
5
+ remaining: string;
6
+ over: string;
7
+ minimum: string;
8
+ }
9
+ interface CharacterCountAddonOptions {
10
+ selector?: string;
11
+ threshold?: number;
12
+ messages?: Partial<CharacterCountMessages>;
13
+ }
14
+ interface CharacterCountEntry {
15
+ field: FieldController;
16
+ counter: HTMLElement;
17
+ max: number | null;
18
+ min: number | null;
19
+ }
20
+ interface CharacterCountAddon extends ValidatorAddon {
21
+ validator: A11yFormValidator | null;
22
+ options: Required<Omit<CharacterCountAddonOptions, 'messages'>> & {
23
+ messages: CharacterCountMessages;
24
+ };
25
+ counters: Map<string, CharacterCountEntry>;
26
+ onInput: EventListener | null;
27
+ unsubscribeAfterValidate?: () => void;
28
+ unsubscribeDestroy?: () => void;
29
+ installCounters(): void;
30
+ shouldShow(length: number, max: number | null): boolean;
31
+ update(input: FieldController | string | HTMLElement): void;
32
+ updateAll(): void;
33
+ destroy(): void;
34
+ }
35
+ declare function createCharacterCountAddon(options?: CharacterCountAddonOptions): CharacterCountAddon;
36
+ //#endregion
37
+ export { CharacterCountAddon, CharacterCountAddonOptions, CharacterCountMessages, createCharacterCountAddon, createCharacterCountAddon as default };
38
+ //# sourceMappingURL=character-count.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character-count.d.ts","names":[],"sources":["../../src/addons/character-count.ts"],"sourcesContent":[],"mappings":";;;UAIiB,sBAAA;EAAA,SAAA,EAAA,MAAA;EAMA,IAAA,EAAA,MAAA;EAMP,OAAA,EAAA,MAAA;AAOV;AACa,UAdI,0BAAA,CAcJ;EACY,QAAA,CAAA,EAAA,MAAA;EAAL,SAAA,CAAA,EAAA,MAAA;EAAT,QAAA,CAAA,EAZE,OAYF,CAZU,sBAYV,CAAA;;UATD,mBAAA,CAUc;EAAZ,KAAA,EATH,eASG;EACD,OAAA,EATA,WASA;EAKK,GAAA,EAAA,MAAA,GAAA,IAAA;EAA2B,GAAA,EAAA,MAAA,GAAA,IAAA;;AATgB,UAA1C,mBAAA,SAA4B,cAAc,CAAA;EA0C3C,SAAA,EAzCH,iBAyC4B,GAAA,IAAA;WAxC9B,SAAS,KAAK;cAAuD;;YACpE,YAAY;WACb;;;;;gBAKK,2BAA2B;;;;iBAiC3B,yBAAA,WAAmC,6BAAkC"}
@@ -0,0 +1,161 @@
1
+ import { f as toSafeInteger, r as ensureElementId } from "../helpers-c_THOe-Q.js";
2
+
3
+ //#region src/addons/character-count.ts
4
+ const DEFAULT_OPTIONS = Object.freeze({
5
+ selector: "textarea[maxlength], input[maxlength], textarea[data-character-count], input[data-character-count]",
6
+ threshold: 0,
7
+ messages: Object.freeze({
8
+ remaining: "{remaining} {remainingLabel} remaining.",
9
+ over: "{over} {overLabel} over the limit.",
10
+ minimum: "Enter at least {remaining} more {remainingLabel}."
11
+ })
12
+ });
13
+ function formatMessage(template, values) {
14
+ return String(template).replace(/\{([a-z]+)\}/gi, (_, key) => String(values[key] ?? ""));
15
+ }
16
+ function getLength(value) {
17
+ return Array.from(String(value ?? "")).length;
18
+ }
19
+ function characterLabel(count) {
20
+ return count === 1 ? "character" : "characters";
21
+ }
22
+ function getLimit(element, attributeName, datasetName) {
23
+ const limit = toSafeInteger((element.getAttribute(attributeName) || element.dataset[datasetName]) ?? void 0, NaN, { min: 1 });
24
+ return Number.isFinite(limit) ? limit : null;
25
+ }
26
+ function createCharacterCountAddon(options = {}) {
27
+ return {
28
+ validator: null,
29
+ options: {
30
+ ...DEFAULT_OPTIONS,
31
+ ...options,
32
+ messages: {
33
+ ...DEFAULT_OPTIONS.messages,
34
+ ...options.messages || {}
35
+ }
36
+ },
37
+ counters: /* @__PURE__ */ new Map(),
38
+ onInput: null,
39
+ install(validator) {
40
+ this.validator = validator;
41
+ this.options = {
42
+ ...DEFAULT_OPTIONS,
43
+ ...options,
44
+ messages: {
45
+ ...DEFAULT_OPTIONS.messages,
46
+ ...options.messages || {}
47
+ }
48
+ };
49
+ this.counters = /* @__PURE__ */ new Map();
50
+ this.onInput = (event) => {
51
+ if (!validator) return;
52
+ const field = validator.findFieldByElement(event.target);
53
+ if (field) this.update(field);
54
+ };
55
+ validator.form.addEventListener("input", this.onInput);
56
+ this.installCounters();
57
+ this.unsubscribeAfterValidate = validator.events.on("a11y-form-validator:after-validate", () => this.updateAll());
58
+ this.unsubscribeDestroy = validator.events.on("a11y-form-validator:destroy", () => this.destroy());
59
+ },
60
+ installCounters() {
61
+ if (!this.validator) return;
62
+ this.validator.fields.forEach((field) => {
63
+ const element = field.primaryElement;
64
+ if (!element.matches(this.options.selector)) return;
65
+ const max = getLimit(element, "maxlength", "maxLength");
66
+ const min = getLimit(element, "minlength", "minLength");
67
+ if (!max && !min) return;
68
+ const counter = element.ownerDocument.createElement("div");
69
+ counter.id = `${ensureElementId(element)}-character-count`;
70
+ counter.className = "a11y-form-validator__character-count";
71
+ counter.setAttribute("aria-live", "polite");
72
+ counter.setAttribute("aria-atomic", "true");
73
+ counter.setAttribute("data-character-count-for", field.name);
74
+ element.insertAdjacentElement("afterend", counter);
75
+ field.connectDescription(counter.id);
76
+ this.counters.set(field.name, {
77
+ field,
78
+ counter,
79
+ max,
80
+ min
81
+ });
82
+ this.update(field);
83
+ });
84
+ },
85
+ shouldShow(length, max) {
86
+ if (!max || this.options.threshold <= 0) return true;
87
+ return length >= Math.floor(max * this.options.threshold);
88
+ },
89
+ update(input) {
90
+ const field = this.validator?.resolveField(input);
91
+ const entry = field ? this.counters.get(field.name) : null;
92
+ if (!entry) return;
93
+ const length = getLength(entry.field.getValue());
94
+ const max = entry.max;
95
+ const min = entry.min;
96
+ entry.counter.classList.toggle("is-over-limit", Boolean(max && length > max));
97
+ entry.counter.classList.toggle("is-under-minimum", Boolean(min && length > 0 && length < min));
98
+ if (!this.shouldShow(length, max)) {
99
+ entry.counter.textContent = "";
100
+ entry.counter.hidden = true;
101
+ return;
102
+ }
103
+ entry.counter.hidden = false;
104
+ if (max && length > max) {
105
+ const over = length - max;
106
+ entry.counter.textContent = formatMessage(this.options.messages.over, {
107
+ over,
108
+ overLabel: characterLabel(over),
109
+ count: length,
110
+ max,
111
+ min
112
+ });
113
+ return;
114
+ }
115
+ if (min && length > 0 && length < min) {
116
+ const remaining = min - length;
117
+ entry.counter.textContent = formatMessage(this.options.messages.minimum, {
118
+ remaining,
119
+ remainingLabel: characterLabel(remaining),
120
+ count: length,
121
+ max,
122
+ min
123
+ });
124
+ return;
125
+ }
126
+ if (max) {
127
+ const remaining = max - length;
128
+ entry.counter.textContent = formatMessage(this.options.messages.remaining, {
129
+ remaining,
130
+ remainingLabel: characterLabel(remaining),
131
+ count: length,
132
+ max,
133
+ min
134
+ });
135
+ return;
136
+ }
137
+ entry.counter.textContent = "";
138
+ entry.counter.hidden = true;
139
+ },
140
+ updateAll() {
141
+ this.counters.forEach(({ field }) => this.update(field));
142
+ },
143
+ destroy() {
144
+ if (this.validator && this.onInput) this.validator.form.removeEventListener("input", this.onInput);
145
+ this.unsubscribeAfterValidate?.();
146
+ this.unsubscribeDestroy?.();
147
+ this.counters.forEach(({ field, counter }) => {
148
+ field.disconnectDescription(counter.id);
149
+ counter.remove();
150
+ });
151
+ this.counters.clear();
152
+ this.onInput = null;
153
+ this.validator = null;
154
+ }
155
+ };
156
+ }
157
+ var character_count_default = createCharacterCountAddon;
158
+
159
+ //#endregion
160
+ export { createCharacterCountAddon, character_count_default as default };
161
+ //# sourceMappingURL=character-count.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character-count.js","names":[],"sources":["../../src/addons/character-count.ts"],"sourcesContent":["import type { A11yFormValidator, ValidatorAddon } from '../core/A11yFormValidator.js';\nimport type { FieldController } from '../core/FieldController.js';\nimport { ensureElementId, toSafeInteger } from '../core/helpers.js';\n\nexport interface CharacterCountMessages {\n remaining: string;\n over: string;\n minimum: string;\n}\n\nexport interface CharacterCountAddonOptions {\n selector?: string;\n threshold?: number;\n messages?: Partial<CharacterCountMessages>;\n}\n\ninterface CharacterCountEntry {\n field: FieldController;\n counter: HTMLElement;\n max: number | null;\n min: number | null;\n}\n\nexport interface CharacterCountAddon extends ValidatorAddon {\n validator: A11yFormValidator | null;\n options: Required<Omit<CharacterCountAddonOptions, 'messages'>> & { messages: CharacterCountMessages };\n counters: Map<string, CharacterCountEntry>;\n onInput: EventListener | null;\n unsubscribeAfterValidate?: () => void;\n unsubscribeDestroy?: () => void;\n installCounters(): void;\n shouldShow(length: number, max: number | null): boolean;\n update(input: FieldController | string | HTMLElement): void;\n updateAll(): void;\n destroy(): void;\n}\n\nconst DEFAULT_OPTIONS = Object.freeze({\n selector: 'textarea[maxlength], input[maxlength], textarea[data-character-count], input[data-character-count]',\n threshold: 0,\n messages: Object.freeze({\n remaining: '{remaining} {remainingLabel} remaining.',\n over: '{over} {overLabel} over the limit.',\n minimum: 'Enter at least {remaining} more {remainingLabel}.'\n })\n});\n\nfunction formatMessage(template: string, values: Record<string, string | number | null>): string {\n return String(template).replace(/\\{([a-z]+)\\}/gi, (_, key: string) => String(values[key] ?? ''));\n}\n\nfunction getLength(value: unknown): number {\n return Array.from(String(value ?? '')).length;\n}\n\nfunction characterLabel(count: number): string {\n return count === 1 ? 'character' : 'characters';\n}\n\nfunction getLimit(element: HTMLElement, attributeName: string, datasetName: string): number | null {\n const value = element.getAttribute(attributeName) || element.dataset[datasetName];\n const limit = toSafeInteger(value ?? undefined, Number.NaN, { min: 1 });\n return Number.isFinite(limit) ? limit : null;\n}\n\nexport function createCharacterCountAddon(options: CharacterCountAddonOptions = {}): CharacterCountAddon {\n return {\n validator: null,\n options: {\n ...DEFAULT_OPTIONS,\n ...options,\n messages: {\n ...DEFAULT_OPTIONS.messages,\n ...(options.messages || {})\n }\n },\n counters: new Map(),\n onInput: null,\n\n install(validator: A11yFormValidator): void {\n this.validator = validator;\n this.options = {\n ...DEFAULT_OPTIONS,\n ...options,\n messages: {\n ...DEFAULT_OPTIONS.messages,\n ...(options.messages || {})\n }\n };\n this.counters = new Map();\n this.onInput = (event) => {\n if (!validator) {\n return;\n }\n\n const field = validator.findFieldByElement(event.target);\n if (field) {\n this.update(field);\n }\n };\n validator.form.addEventListener('input', this.onInput);\n this.installCounters();\n this.unsubscribeAfterValidate = validator.events.on('a11y-form-validator:after-validate', () => this.updateAll());\n this.unsubscribeDestroy = validator.events.on('a11y-form-validator:destroy', () => this.destroy());\n },\n\n installCounters(): void {\n if (!this.validator) {\n return;\n }\n\n this.validator.fields.forEach((field) => {\n const element = field.primaryElement;\n if (!element.matches(this.options.selector)) {\n return;\n }\n\n const max = getLimit(element, 'maxlength', 'maxLength');\n const min = getLimit(element, 'minlength', 'minLength');\n if (!max && !min) {\n return;\n }\n\n const counter = element.ownerDocument.createElement('div');\n counter.id = `${ensureElementId(element)}-character-count`;\n counter.className = 'a11y-form-validator__character-count';\n counter.setAttribute('aria-live', 'polite');\n counter.setAttribute('aria-atomic', 'true');\n counter.setAttribute('data-character-count-for', field.name);\n element.insertAdjacentElement('afterend', counter);\n field.connectDescription(counter.id);\n this.counters.set(field.name, { field, counter, max, min });\n this.update(field);\n });\n },\n\n shouldShow(length: number, max: number | null): boolean {\n if (!max || this.options.threshold <= 0) {\n return true;\n }\n\n return length >= Math.floor(max * this.options.threshold);\n },\n\n update(input: FieldController | string | HTMLElement): void {\n const field = this.validator?.resolveField(input);\n const entry = field ? this.counters.get(field.name) : null;\n if (!entry) {\n return;\n }\n\n const length = getLength(entry.field.getValue());\n const max = entry.max;\n const min = entry.min;\n entry.counter.classList.toggle('is-over-limit', Boolean(max && length > max));\n entry.counter.classList.toggle('is-under-minimum', Boolean(min && length > 0 && length < min));\n\n if (!this.shouldShow(length, max)) {\n entry.counter.textContent = '';\n entry.counter.hidden = true;\n return;\n }\n\n entry.counter.hidden = false;\n if (max && length > max) {\n const over = length - max;\n entry.counter.textContent = formatMessage(this.options.messages.over, {\n over,\n overLabel: characterLabel(over),\n count: length,\n max,\n min\n });\n return;\n }\n\n if (min && length > 0 && length < min) {\n const remaining = min - length;\n entry.counter.textContent = formatMessage(this.options.messages.minimum, {\n remaining,\n remainingLabel: characterLabel(remaining),\n count: length,\n max,\n min\n });\n return;\n }\n\n if (max) {\n const remaining = max - length;\n entry.counter.textContent = formatMessage(this.options.messages.remaining, {\n remaining,\n remainingLabel: characterLabel(remaining),\n count: length,\n max,\n min\n });\n return;\n }\n\n entry.counter.textContent = '';\n entry.counter.hidden = true;\n },\n\n updateAll(): void {\n this.counters.forEach(({ field }) => this.update(field));\n },\n\n destroy(): void {\n if (this.validator && this.onInput) {\n this.validator.form.removeEventListener('input', this.onInput);\n }\n this.unsubscribeAfterValidate?.();\n this.unsubscribeDestroy?.();\n this.counters.forEach(({ field, counter }) => {\n field.disconnectDescription(counter.id);\n counter.remove();\n });\n this.counters.clear();\n this.onInput = null;\n this.validator = null;\n }\n };\n}\n\nexport default createCharacterCountAddon;\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { C as ValidatorAddon, L as FieldController, t as A11yFormValidator } from "../A11yFormValidator-D0n6br-b.js";
2
+
3
+ //#region src/addons/error-summary.d.ts
4
+ interface ErrorSummaryAddonOptions {
5
+ titleId?: string;
6
+ }
7
+ interface SummaryEntry {
8
+ field: FieldController | null;
9
+ message: string;
10
+ key?: string;
11
+ }
12
+ interface ErrorSummaryAddon extends ValidatorAddon {
13
+ validator: A11yFormValidator | null;
14
+ options: ErrorSummaryAddonOptions;
15
+ container: HTMLElement | null;
16
+ title: HTMLHeadingElement | null;
17
+ list: HTMLUListElement | null;
18
+ unsubscribeAfterValidate?: () => void;
19
+ unsubscribeDestroy?: () => void;
20
+ getErrors(): SummaryEntry[];
21
+ update(): void;
22
+ hasErrors(): boolean;
23
+ focus(): void;
24
+ destroy(): void;
25
+ }
26
+ declare function createErrorSummaryAddon(options?: ErrorSummaryAddonOptions): ErrorSummaryAddon;
27
+ //#endregion
28
+ export { ErrorSummaryAddon, ErrorSummaryAddonOptions, SummaryEntry, createErrorSummaryAddon, createErrorSummaryAddon as default };
29
+ //# sourceMappingURL=error-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-summary.d.ts","names":[],"sources":["../../src/addons/error-summary.ts"],"sourcesContent":[],"mappings":";;;UAIiB,wBAAA;EAAA,OAAA,CAAA,EAAA,MAAA;AAIjB;AAMiB,UANA,YAAA,CAMkB;EACtB,KAAA,EANJ,eAMI,GAAA,IAAA;EACF,OAAA,EAAA,MAAA;EACE,GAAA,CAAA,EAAA,MAAA;;AAEL,UALS,iBAAA,SAA0B,cAKnC,CAAA;EAGO,SAAA,EAPF,iBAOE,GAAA,IAAA;EAR4B,OAAA,EAEhC,wBAFgC;EAAc,SAAA,EAG5C,WAH4C,GAAA,IAAA;EAezC,KAAA,EAXP,kBAWO,GAAuB,IAAA;QAV/B;;;eAGO;;;;;;iBAOC,uBAAA,WAAiC,2BAAgC"}
@@ -0,0 +1,4 @@
1
+ import "../helpers-c_THOe-Q.js";
2
+ import { n as error_summary_default, t as createErrorSummaryAddon } from "../error-summary-FnZoUC72.js";
3
+
4
+ export { createErrorSummaryAddon, error_summary_default as default };
@@ -0,0 +1,7 @@
1
+ import { i as A11yFormValidatorOptionsInput } from "./A11yFormValidator-D0n6br-b.js";
2
+
3
+ //#region src/presets/default.d.ts
4
+ declare function createDefaultPreset(): A11yFormValidatorOptionsInput;
5
+ //#endregion
6
+ export { createDefaultPreset as t };
7
+ //# sourceMappingURL=default-BHBWPNeK.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-BHBWPNeK.d.ts","names":[],"sources":["../src/presets/default.ts"],"sourcesContent":[],"mappings":";;;iBAGgB,mBAAA,CAAA,GAAuB"}
@@ -0,0 +1,18 @@
1
+ import { t as createErrorSummaryAddon } from "./error-summary-FnZoUC72.js";
2
+
3
+ //#region src/presets/default.ts
4
+ function createDefaultPreset() {
5
+ return {
6
+ validateOn: ["submit", "blur"],
7
+ focusOnError: "summary",
8
+ errorMode: "both",
9
+ useNativeRules: true,
10
+ disableNativeUI: true,
11
+ addons: [createErrorSummaryAddon()]
12
+ };
13
+ }
14
+ var default_default = createDefaultPreset;
15
+
16
+ //#endregion
17
+ export { default_default as n, createDefaultPreset as t };
18
+ //# sourceMappingURL=default-DFnPBuVC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-DFnPBuVC.js","names":[],"sources":["../src/presets/default.ts"],"sourcesContent":["import { createErrorSummaryAddon } from '../addons/error-summary.js';\nimport type { A11yFormValidatorOptionsInput } from '../core/A11yFormValidator.js';\n\nexport function createDefaultPreset(): A11yFormValidatorOptionsInput {\n return {\n validateOn: ['submit', 'blur'],\n focusOnError: 'summary',\n errorMode: 'both',\n useNativeRules: true,\n disableNativeUI: true,\n addons: [createErrorSummaryAddon()]\n };\n}\n\nexport default createDefaultPreset;\n"],"mappings":";;;AAGA,SAAgB,sBAAqD;AACnE,QAAO;EACL,YAAY,CAAC,UAAU,OAAO;EAC9B,cAAc;EACd,WAAW;EACX,gBAAgB;EAChB,iBAAiB;EACjB,QAAQ,CAAC,yBAAyB,CAAC;EACpC;;AAGH,sBAAe"}