@italia/globals 0.1.0-alpha.1 → 1.0.0-alpha.4

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 (58) hide show
  1. package/custom-elements.json +1655 -168
  2. package/dist/src/base-component/base-component.d.ts +28 -13
  3. package/dist/src/base-component/base-component.d.ts.map +1 -1
  4. package/dist/src/base-component/base-component.js +27 -17
  5. package/dist/src/base-component/base-component.js.map +1 -1
  6. package/dist/src/controllers/aria-keyboard-accordion-controller.d.ts +15 -0
  7. package/dist/src/controllers/aria-keyboard-accordion-controller.d.ts.map +1 -0
  8. package/dist/src/controllers/aria-keyboard-accordion-controller.js +52 -0
  9. package/dist/src/controllers/aria-keyboard-accordion-controller.js.map +1 -0
  10. package/dist/src/controllers/aria-keyboard-list-controller.d.ts +18 -0
  11. package/dist/src/controllers/aria-keyboard-list-controller.d.ts.map +1 -0
  12. package/dist/src/controllers/aria-keyboard-list-controller.js +58 -0
  13. package/dist/src/controllers/aria-keyboard-list-controller.js.map +1 -0
  14. package/dist/src/controllers/collapse-controller.d.ts +12 -0
  15. package/dist/src/controllers/collapse-controller.d.ts.map +1 -0
  16. package/dist/src/controllers/collapse-controller.js +95 -0
  17. package/dist/src/controllers/collapse-controller.js.map +1 -0
  18. package/dist/src/controllers/roving-tabindex-controller.d.ts +85 -0
  19. package/dist/src/controllers/roving-tabindex-controller.d.ts.map +1 -0
  20. package/dist/src/controllers/roving-tabindex-controller.js +200 -0
  21. package/dist/src/controllers/roving-tabindex-controller.js.map +1 -0
  22. package/dist/src/form/form-control.d.ts +61 -0
  23. package/dist/src/form/form-control.d.ts.map +1 -0
  24. package/dist/src/form/form-control.js +259 -0
  25. package/dist/src/form/form-control.js.map +1 -0
  26. package/dist/src/form/form-controller.d.ts +68 -0
  27. package/dist/src/form/form-controller.d.ts.map +1 -0
  28. package/dist/src/form/form-controller.js +398 -0
  29. package/dist/src/form/form-controller.js.map +1 -0
  30. package/dist/src/form/locales/it.d.ts +4 -0
  31. package/dist/src/form/locales/it.d.ts.map +1 -0
  32. package/dist/src/form/locales/it.js +12 -0
  33. package/dist/src/form/locales/it.js.map +1 -0
  34. package/dist/src/index.d.ts +20 -4
  35. package/dist/src/index.d.ts.map +1 -1
  36. package/dist/src/index.js +18 -4
  37. package/dist/src/index.js.map +1 -1
  38. package/dist/src/mixins/validity.d.ts +19 -19
  39. package/dist/src/mixins/validity.d.ts.map +1 -1
  40. package/dist/src/mixins/validity.js +6 -68
  41. package/dist/src/mixins/validity.js.map +1 -1
  42. package/dist/src/stories/formControlReusableStories.d.ts +19 -0
  43. package/dist/src/stories/formControlReusableStories.d.ts.map +1 -0
  44. package/dist/src/stories/formControlReusableStories.js +64 -0
  45. package/dist/src/stories/formControlReusableStories.js.map +1 -0
  46. package/dist/src/stories/reusableUsageGuidelinesStories.d.ts +13 -0
  47. package/dist/src/stories/reusableUsageGuidelinesStories.d.ts.map +1 -0
  48. package/dist/src/stories/reusableUsageGuidelinesStories.js +39 -0
  49. package/dist/src/stories/reusableUsageGuidelinesStories.js.map +1 -0
  50. package/dist/src/window-manager.d.ts +20 -0
  51. package/dist/src/window-manager.d.ts.map +1 -0
  52. package/dist/src/window-manager.js +47 -0
  53. package/dist/src/window-manager.js.map +1 -0
  54. package/package.json +10 -8
  55. package/dist/src/mixins/form.d.ts +0 -363
  56. package/dist/src/mixins/form.d.ts.map +0 -1
  57. package/dist/src/mixins/form.js +0 -36
  58. package/dist/src/mixins/form.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roving-tabindex-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/roving-tabindex-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC;AAEjE,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,WAAW;IACzD;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,GAAG,YAAY,GAAG,UAAU,KAAK,IAAI,CAAC;IAE/E;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;IAE/C;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAwB,CAAC,CAAC,SAAS,WAAW,CAAE,YAAW,kBAAkB;IACxF,OAAO,CAAC,IAAI,CAAyB;IAErC,OAAO,CAAC,MAAM,CAKZ;gBAEU,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAazE,aAAa,IAAI,IAAI;IAKrB,gBAAgB,IAAI,IAAI;IAIxB;;;OAGG;IACH,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IA8B5C;;;;;OAKG;IACH,aAAa,CAAC,WAAW,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO;IAyE5D;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAUxB;;OAEG;IACH,UAAU,IAAI,IAAI;IASlB;;OAEG;IACH,SAAS,IAAI,IAAI;CAQlB"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Roving Tabindex Controller
3
+ *
4
+ * Implements the ARIA roving tabindex pattern for keyboard navigation.
5
+ * See: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * private rovingTabindex = new RovingTabindexController(this, {
10
+ * getItems: () => Array.from(this.querySelectorAll('my-item')),
11
+ * onSelect: (item) => this.selectItem(item),
12
+ * });
13
+ * ```
14
+ */
15
+ export class RovingTabindexController {
16
+ constructor(host, config) {
17
+ this.host = host;
18
+ this.config = {
19
+ wrap: true,
20
+ direction: 'both',
21
+ selectOnFocus: false,
22
+ skipItem: (item) => item.hasAttribute('disabled') || item.disabled === true,
23
+ ...config,
24
+ };
25
+ host.addController(this);
26
+ }
27
+ // eslint-disable-next-line class-methods-use-this
28
+ hostConnected() {
29
+ // Controller is ready when host connects
30
+ }
31
+ // eslint-disable-next-line class-methods-use-this
32
+ hostDisconnected() {
33
+ // Cleanup if needed
34
+ }
35
+ /**
36
+ * Update tabindex values for all items
37
+ * @param activeIndex - Index of the item that should be tabbable (default: 0 or first non-disabled)
38
+ */
39
+ updateTabindices(activeIndex) {
40
+ const items = this.config.getItems();
41
+ if (!items || items.length === 0) {
42
+ return;
43
+ }
44
+ // Find the active index
45
+ let targetIndex = activeIndex ?? 0;
46
+ // If no active index specified, use first non-disabled item
47
+ if (activeIndex === undefined) {
48
+ targetIndex = items.findIndex((item) => !this.config.skipItem(item));
49
+ if (targetIndex === -1) {
50
+ targetIndex = 0; // Fallback to first item if all disabled
51
+ }
52
+ }
53
+ // Set tabindex for all items
54
+ items.forEach((item, index) => {
55
+ const itemElement = item;
56
+ if (this.config.skipItem(itemElement)) {
57
+ // eslint-disable-next-line no-param-reassign
58
+ itemElement.tabIndex = -1;
59
+ }
60
+ else {
61
+ // eslint-disable-next-line no-param-reassign
62
+ itemElement.tabIndex = index === targetIndex ? 0 : -1;
63
+ }
64
+ });
65
+ }
66
+ /**
67
+ * Handle keyboard navigation
68
+ * @param currentItem - The currently focused item
69
+ * @param event - The keyboard event
70
+ * @returns true if the event was handled, false otherwise
71
+ */
72
+ handleKeydown(currentItem, event) {
73
+ const { direction } = this.config;
74
+ const { key } = event;
75
+ // Determine if this key should be handled based on direction
76
+ const isVertical = key === 'ArrowUp' || key === 'ArrowDown';
77
+ const isHorizontal = key === 'ArrowLeft' || key === 'ArrowRight';
78
+ const isHome = key === 'Home';
79
+ const isEnd = key === 'End';
80
+ const shouldHandle = isHome ||
81
+ isEnd ||
82
+ (direction === 'both' && (isVertical || isHorizontal)) ||
83
+ (direction === 'vertical' && isVertical) ||
84
+ (direction === 'horizontal' && isHorizontal);
85
+ if (!shouldHandle) {
86
+ return false;
87
+ }
88
+ // Prevent default behavior (page scrolling)
89
+ event.preventDefault();
90
+ const items = this.config.getItems();
91
+ const currentIndex = items.indexOf(currentItem);
92
+ if (currentIndex === -1) {
93
+ return false;
94
+ }
95
+ let nextIndex = currentIndex;
96
+ // Handle Home/End keys
97
+ if (isHome) {
98
+ nextIndex = 0;
99
+ }
100
+ else if (isEnd) {
101
+ nextIndex = items.length - 1;
102
+ }
103
+ else {
104
+ // Handle arrow keys
105
+ const isNext = key === 'ArrowDown' || key === 'ArrowRight';
106
+ const isPrev = key === 'ArrowUp' || key === 'ArrowLeft';
107
+ if (isNext) {
108
+ nextIndex = this.getNextIndex(items, currentIndex, 1);
109
+ }
110
+ else if (isPrev) {
111
+ nextIndex = this.getNextIndex(items, currentIndex, -1);
112
+ }
113
+ }
114
+ // Skip disabled items
115
+ nextIndex = this.findNextValidIndex(items, nextIndex, nextIndex > currentIndex ? 1 : -1);
116
+ if (nextIndex !== -1 && nextIndex !== currentIndex) {
117
+ const nextItem = items[nextIndex];
118
+ // Update tabindices
119
+ this.updateTabindices(nextIndex);
120
+ // Focus the next item
121
+ nextItem.focus();
122
+ // Optionally select/activate the item
123
+ if (this.config.selectOnFocus && this.config.onSelect) {
124
+ this.config.onSelect(nextItem, event);
125
+ }
126
+ return true;
127
+ }
128
+ return false;
129
+ }
130
+ /**
131
+ * Get the next index based on direction
132
+ */
133
+ getNextIndex(items, currentIndex, direction) {
134
+ const { wrap } = this.config;
135
+ let nextIndex = currentIndex + direction;
136
+ if (wrap) {
137
+ // Wrap around
138
+ if (nextIndex < 0) {
139
+ nextIndex = items.length - 1;
140
+ }
141
+ else if (nextIndex >= items.length) {
142
+ nextIndex = 0;
143
+ }
144
+ }
145
+ else {
146
+ // Clamp to bounds
147
+ nextIndex = Math.max(0, Math.min(items.length - 1, nextIndex));
148
+ }
149
+ return nextIndex;
150
+ }
151
+ /**
152
+ * Find the next valid (non-disabled) index
153
+ */
154
+ findNextValidIndex(items, startIndex, direction) {
155
+ const maxAttempts = items.length;
156
+ let attempts = 0;
157
+ let index = startIndex;
158
+ while (attempts < maxAttempts) {
159
+ if (!this.config.skipItem(items[index])) {
160
+ return index;
161
+ }
162
+ index = this.getNextIndex(items, index, direction);
163
+ attempts += 1;
164
+ }
165
+ // All items are disabled
166
+ return -1;
167
+ }
168
+ /**
169
+ * Set focus to a specific item
170
+ */
171
+ focusItem(item) {
172
+ const items = this.config.getItems();
173
+ const index = items.indexOf(item);
174
+ if (index !== -1) {
175
+ this.updateTabindices(index);
176
+ item.focus();
177
+ }
178
+ }
179
+ /**
180
+ * Set focus to the first non-disabled item
181
+ */
182
+ focusFirst() {
183
+ const items = this.config.getItems();
184
+ const firstValidIndex = this.findNextValidIndex(items, 0, 1);
185
+ if (firstValidIndex !== -1) {
186
+ this.focusItem(items[firstValidIndex]);
187
+ }
188
+ }
189
+ /**
190
+ * Set focus to the last non-disabled item
191
+ */
192
+ focusLast() {
193
+ const items = this.config.getItems();
194
+ const lastValidIndex = this.findNextValidIndex(items, items.length - 1, -1);
195
+ if (lastValidIndex !== -1) {
196
+ this.focusItem(items[lastValidIndex]);
197
+ }
198
+ }
199
+ }
200
+ //# sourceMappingURL=roving-tabindex-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["../../../src/controllers/roving-tabindex-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport interface RovingTabindexConfig<T extends HTMLElement> {\n /**\n * Selector or function to get the items to manage\n */\n getItems: () => T[];\n\n /**\n * Callback when an item is selected/activated\n */\n onSelect?: (item: T, event: KeyboardEvent | PointerEvent | MouseEvent) => void;\n\n /**\n * Whether items wrap around (last -> first and vice versa)\n * @default true\n */\n wrap?: boolean;\n\n /**\n * Direction of navigation\n * @default 'both'\n */\n direction?: 'horizontal' | 'vertical' | 'both';\n\n /**\n * Whether to select items on focus (vs just focusing)\n * @default false\n */\n selectOnFocus?: boolean;\n\n /**\n * Custom logic to determine if an item should be skipped\n * @default (item) => item.hasAttribute('disabled')\n */\n skipItem?: (item: T) => boolean;\n}\n\n/**\n * Roving Tabindex Controller\n *\n * Implements the ARIA roving tabindex pattern for keyboard navigation.\n * See: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex\n *\n * Usage:\n * ```ts\n * private rovingTabindex = new RovingTabindexController(this, {\n * getItems: () => Array.from(this.querySelectorAll('my-item')),\n * onSelect: (item) => this.selectItem(item),\n * });\n * ```\n */\nexport class RovingTabindexController<T extends HTMLElement> implements ReactiveController {\n private host: ReactiveControllerHost;\n\n private config: RovingTabindexConfig<T> & {\n wrap: boolean;\n direction: 'horizontal' | 'vertical' | 'both';\n selectOnFocus: boolean;\n skipItem: (item: T) => boolean;\n };\n\n constructor(host: ReactiveControllerHost, config: RovingTabindexConfig<T>) {\n this.host = host;\n this.config = {\n wrap: true,\n direction: 'both',\n selectOnFocus: false,\n skipItem: (item) => item.hasAttribute('disabled') || (item as any).disabled === true,\n ...config,\n };\n host.addController(this);\n }\n\n // eslint-disable-next-line class-methods-use-this\n hostConnected(): void {\n // Controller is ready when host connects\n }\n\n // eslint-disable-next-line class-methods-use-this\n hostDisconnected(): void {\n // Cleanup if needed\n }\n\n /**\n * Update tabindex values for all items\n * @param activeIndex - Index of the item that should be tabbable (default: 0 or first non-disabled)\n */\n updateTabindices(activeIndex?: number): void {\n const items = this.config.getItems();\n if (!items || items.length === 0) {\n return;\n }\n\n // Find the active index\n let targetIndex = activeIndex ?? 0;\n\n // If no active index specified, use first non-disabled item\n if (activeIndex === undefined) {\n targetIndex = items.findIndex((item) => !this.config.skipItem(item));\n if (targetIndex === -1) {\n targetIndex = 0; // Fallback to first item if all disabled\n }\n }\n\n // Set tabindex for all items\n items.forEach((item, index) => {\n const itemElement = item;\n if (this.config.skipItem(itemElement)) {\n // eslint-disable-next-line no-param-reassign\n itemElement.tabIndex = -1;\n } else {\n // eslint-disable-next-line no-param-reassign\n itemElement.tabIndex = index === targetIndex ? 0 : -1;\n }\n });\n }\n\n /**\n * Handle keyboard navigation\n * @param currentItem - The currently focused item\n * @param event - The keyboard event\n * @returns true if the event was handled, false otherwise\n */\n handleKeydown(currentItem: T, event: KeyboardEvent): boolean {\n const { direction } = this.config;\n const { key } = event;\n\n // Determine if this key should be handled based on direction\n const isVertical = key === 'ArrowUp' || key === 'ArrowDown';\n const isHorizontal = key === 'ArrowLeft' || key === 'ArrowRight';\n const isHome = key === 'Home';\n const isEnd = key === 'End';\n\n const shouldHandle =\n isHome ||\n isEnd ||\n (direction === 'both' && (isVertical || isHorizontal)) ||\n (direction === 'vertical' && isVertical) ||\n (direction === 'horizontal' && isHorizontal);\n\n if (!shouldHandle) {\n return false;\n }\n\n // Prevent default behavior (page scrolling)\n event.preventDefault();\n\n const items = this.config.getItems();\n const currentIndex = items.indexOf(currentItem);\n\n if (currentIndex === -1) {\n return false;\n }\n\n let nextIndex = currentIndex;\n\n // Handle Home/End keys\n if (isHome) {\n nextIndex = 0;\n } else if (isEnd) {\n nextIndex = items.length - 1;\n } else {\n // Handle arrow keys\n const isNext = key === 'ArrowDown' || key === 'ArrowRight';\n const isPrev = key === 'ArrowUp' || key === 'ArrowLeft';\n\n if (isNext) {\n nextIndex = this.getNextIndex(items, currentIndex, 1);\n } else if (isPrev) {\n nextIndex = this.getNextIndex(items, currentIndex, -1);\n }\n }\n\n // Skip disabled items\n nextIndex = this.findNextValidIndex(items, nextIndex, nextIndex > currentIndex ? 1 : -1);\n\n if (nextIndex !== -1 && nextIndex !== currentIndex) {\n const nextItem = items[nextIndex];\n\n // Update tabindices\n this.updateTabindices(nextIndex);\n\n // Focus the next item\n nextItem.focus();\n\n // Optionally select/activate the item\n if (this.config.selectOnFocus && this.config.onSelect) {\n this.config.onSelect(nextItem, event);\n }\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Get the next index based on direction\n */\n private getNextIndex(items: T[], currentIndex: number, direction: 1 | -1): number {\n const { wrap } = this.config;\n let nextIndex = currentIndex + direction;\n\n if (wrap) {\n // Wrap around\n if (nextIndex < 0) {\n nextIndex = items.length - 1;\n } else if (nextIndex >= items.length) {\n nextIndex = 0;\n }\n } else {\n // Clamp to bounds\n nextIndex = Math.max(0, Math.min(items.length - 1, nextIndex));\n }\n\n return nextIndex;\n }\n\n /**\n * Find the next valid (non-disabled) index\n */\n private findNextValidIndex(items: T[], startIndex: number, direction: 1 | -1): number {\n const maxAttempts = items.length;\n let attempts = 0;\n let index = startIndex;\n\n while (attempts < maxAttempts) {\n if (!this.config.skipItem(items[index])) {\n return index;\n }\n\n index = this.getNextIndex(items, index, direction);\n attempts += 1;\n }\n\n // All items are disabled\n return -1;\n }\n\n /**\n * Set focus to a specific item\n */\n focusItem(item: T): void {\n const items = this.config.getItems();\n const index = items.indexOf(item);\n\n if (index !== -1) {\n this.updateTabindices(index);\n item.focus();\n }\n }\n\n /**\n * Set focus to the first non-disabled item\n */\n focusFirst(): void {\n const items = this.config.getItems();\n const firstValidIndex = this.findNextValidIndex(items, 0, 1);\n\n if (firstValidIndex !== -1) {\n this.focusItem(items[firstValidIndex]);\n }\n }\n\n /**\n * Set focus to the last non-disabled item\n */\n focusLast(): void {\n const items = this.config.getItems();\n const lastValidIndex = this.findNextValidIndex(items, items.length - 1, -1);\n\n if (lastValidIndex !== -1) {\n this.focusItem(items[lastValidIndex]);\n }\n }\n}\n"]}
@@ -0,0 +1,61 @@
1
+ import { BaseLocalizedComponent } from '../base-component/base-component.js';
2
+ import { FormControlController } from './form-controller.js';
3
+ export declare class FormControl extends BaseLocalizedComponent {
4
+ protected readonly formControlController: FormControlController;
5
+ _touched: boolean;
6
+ inputElement: HTMLInputElement;
7
+ /** The name of the input, submitted as a name/value pair with form data. */
8
+ name: string;
9
+ /** The current value of the input, submitted as a name/value pair with form data. */
10
+ value: string;
11
+ /** If the input is disabled. */
12
+ disabled: boolean;
13
+ /**
14
+ * By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you
15
+ * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in
16
+ * the same document or shadow root for this to work.
17
+ */
18
+ form: string;
19
+ /** If you implement your custom validation and you won't to trigger default validation */
20
+ customValidation: boolean;
21
+ /** If your input is invalid from your custom validition, set this attribute with message validation */
22
+ validationText: string;
23
+ /** Pattern the `value` must match to be valid */
24
+ pattern?: string;
25
+ /** The input's minimum value. Only applies to date and number input types. */
26
+ min: number | string | Date | undefined;
27
+ /** The input's maximum value. Only applies to date and number input types. */
28
+ max: number | string | Date | undefined;
29
+ /**
30
+ * Specifies the granularity that the value must adhere to, or the special value `any` which means no stepping is
31
+ * implied, allowing any numeric value. Only applies to date and number input types.
32
+ */
33
+ step: number | 'any';
34
+ /** The input's minimum length. */
35
+ minlength: number;
36
+ /** The input's maximum length. */
37
+ maxlength: number;
38
+ /** If the input is required. */
39
+ required: boolean;
40
+ protected isInGroup: boolean;
41
+ /** Gets the validity state object */
42
+ get validity(): ValidityState;
43
+ validationMessage: string;
44
+ /** Gets the associated form, if one exists. */
45
+ getForm(): HTMLFormElement | null;
46
+ checkValidity(): boolean;
47
+ /** Checks for validity and shows the browser's validation message if the control is invalid. */
48
+ reportValidity(): boolean;
49
+ /** Sets a custom validation message. Pass an empty string to restore validity. */
50
+ setCustomValidity(message: string): void;
51
+ protected _handleReady(): void;
52
+ protected _handleInput(e: Event): void;
53
+ protected _handleBlur(e: Event): void;
54
+ protected _handleFocus(e: Event): void;
55
+ protected _handleClick(e: Event): void;
56
+ protected handleValidationMessages(): void;
57
+ protected _handleInvalid(event: Event): void;
58
+ protected _handleChange(e: Event): void;
59
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
60
+ }
61
+ //# sourceMappingURL=form-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-control.d.ts","sourceRoot":"","sources":["../../../src/form/form-control.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,qBAAa,WAAY,SAAQ,sBAAsB;IACrD,SAAS,CAAC,QAAQ,CAAC,qBAAqB,wBAErC;IASH,QAAQ,UAAS;IAGjB,YAAY,EAAG,gBAAgB,CAAC;IAEhC,4EAA4E;IAE5E,IAAI,SAAM;IAEV,qFAAqF;IAErF,KAAK,SAAM;IAEX,gCAAgC;IAEhC,QAAQ,UAAS;IAEjB;;;;OAIG;IACwC,IAAI,SAAM;IAErD,0FAA0F;IAE1F,gBAAgB,UAAS;IAEzB,uGAAuG;IAEvG,cAAc,EAAE,MAAM,CAAM;IAE5B,iDAAiD;IAEjD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,8EAA8E;IAE9E,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAExC,8EAA8E;IAE9E,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAExC;;;OAGG;IAEH,IAAI,EAAE,MAAM,GAAG,KAAK,CAAS;IAE7B,kCAAkC;IAElC,SAAS,SAAM;IAEf,kCAAkC;IAElC,SAAS,SAAM;IAEf,gCAAgC;IAEhC,QAAQ,UAAS;IAIjB,SAAS,CAAC,SAAS,UAAS;IAE5B,qCAAqC;IACrC,IAAW,QAAQ,IAAI,aAAa,CAEnC;IAGM,iBAAiB,SAAM;IAE9B,+CAA+C;IACxC,OAAO,IAAI,eAAe,GAAG,IAAI;IAKjC,aAAa,IAAI,OAAO;IAK/B,gGAAgG;IACzF,cAAc;IAOrB,kFAAkF;IAC3E,iBAAiB,CAAC,OAAO,EAAE,MAAM;IAOxC,SAAS,CAAC,YAAY;IAOtB,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK;IAY/B,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK;IAO9B,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK;IAK/B,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK;IAO/B,SAAS,CAAC,wBAAwB;IAmClC,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK;IAKrC,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK;IAoCvB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC;CAS3E"}
@@ -0,0 +1,259 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { property, query, state } from 'lit/decorators.js';
3
+ import { registerTranslation } from '@italia/i18n';
4
+ import { BaseLocalizedComponent } from '../base-component/base-component.js';
5
+ import { FormControlController } from './form-controller.js';
6
+ import it from './locales/it.js';
7
+ registerTranslation(it);
8
+ export class FormControl extends BaseLocalizedComponent {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.formControlController = new FormControlController(this, {
12
+ assumeInteractionOn: ['it-input', 'it-blur', 'it-change'],
13
+ });
14
+ // TODO: verificare se serve davvero con il fatto che usiamo form-controller
15
+ // static formAssociated = true;
16
+ // @property()
17
+ // internals = this.attachInternals();
18
+ this._touched = false;
19
+ /** The name of the input, submitted as a name/value pair with form data. */
20
+ this.name = '';
21
+ /** The current value of the input, submitted as a name/value pair with form data. */
22
+ this.value = '';
23
+ /** If the input is disabled. */
24
+ this.disabled = false;
25
+ /**
26
+ * By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you
27
+ * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in
28
+ * the same document or shadow root for this to work.
29
+ */
30
+ this.form = '';
31
+ /** If you implement your custom validation and you won't to trigger default validation */
32
+ this.customValidation = false;
33
+ /** If your input is invalid from your custom validition, set this attribute with message validation */
34
+ this.validationText = '';
35
+ /**
36
+ * Specifies the granularity that the value must adhere to, or the special value `any` which means no stepping is
37
+ * implied, allowing any numeric value. Only applies to date and number input types.
38
+ */
39
+ this.step = 'any';
40
+ /** The input's minimum length. */
41
+ this.minlength = -1;
42
+ /** The input's maximum length. */
43
+ this.maxlength = -1;
44
+ /** If the input is required. */
45
+ this.required = false;
46
+ /* For grouped input, like checkbox-group */
47
+ this.isInGroup = false;
48
+ this.validationMessage = '';
49
+ }
50
+ /** Gets the validity state object */
51
+ get validity() {
52
+ return this.inputElement?.validity;
53
+ }
54
+ /** Gets the associated form, if one exists. */
55
+ getForm() {
56
+ return this.formControlController.getForm();
57
+ }
58
+ // Form validation methods
59
+ checkValidity() {
60
+ const inputValid = this.inputElement?.checkValidity() ?? true; // this.inputElement.checkValidity() è la validazione del browser
61
+ return inputValid;
62
+ }
63
+ /** Checks for validity and shows the browser's validation message if the control is invalid. */
64
+ reportValidity() {
65
+ // const ret = this.inputElement.checkValidity();
66
+ const ret = this.checkValidity(); // chiama la checkValidity, che se è stata overridata chiama quella
67
+ this.handleValidationMessages();
68
+ return ret; // this.inputElement.reportValidity();
69
+ }
70
+ /** Sets a custom validation message. Pass an empty string to restore validity. */
71
+ setCustomValidity(message) {
72
+ this.inputElement.setCustomValidity(message);
73
+ this.validationMessage = this.inputElement.validationMessage;
74
+ this.formControlController.updateValidity();
75
+ }
76
+ // Handlers
77
+ _handleReady() {
78
+ requestAnimationFrame(() => {
79
+ this.dispatchEvent(new CustomEvent('it-input-ready', { bubbles: true, detail: { el: this.inputElement } }));
80
+ });
81
+ }
82
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
83
+ _handleInput(e) {
84
+ this.handleValidationMessages();
85
+ this.dispatchEvent(new CustomEvent('it-input', {
86
+ detail: { value: this.inputElement.value, el: this.inputElement },
87
+ bubbles: true,
88
+ composed: true,
89
+ }));
90
+ }
91
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
92
+ _handleBlur(e) {
93
+ this._touched = true;
94
+ this.handleValidationMessages();
95
+ this.dispatchEvent(new FocusEvent('it-blur', { bubbles: true, composed: true }));
96
+ }
97
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
98
+ _handleFocus(e) {
99
+ this.dispatchEvent(new FocusEvent('it-focus', { bubbles: true, composed: true }));
100
+ }
101
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
102
+ _handleClick(e) {
103
+ this.dispatchEvent(new MouseEvent('it-click', { bubbles: true, composed: true }));
104
+ }
105
+ /*
106
+ Override default browser validation messages
107
+ */
108
+ handleValidationMessages() {
109
+ if (!this.customValidation) {
110
+ const _v = this.inputElement.validity;
111
+ const isRequiredHandledByGroup = this.isInGroup === true;
112
+ if (_v.valueMissing && !isRequiredHandledByGroup) {
113
+ this.setCustomValidity(this.$t('validityRequired'));
114
+ }
115
+ else if (_v.patternMismatch) {
116
+ this.setCustomValidity(this.$t('validityPattern'));
117
+ }
118
+ else if (_v.tooShort) {
119
+ this.setCustomValidity(this.$t('validityMinlength').replace('{minlength}', this.minlength.toString()));
120
+ }
121
+ else if (_v.tooLong) {
122
+ this.setCustomValidity(this.$t('validityMaxlength').replace('{maxlength}', this.maxlength.toString()));
123
+ }
124
+ else {
125
+ /* nothing. Usa il messaggio di errore della validazione
126
+ di default del browser per altri errori di validità come:
127
+ - typeMismatch
128
+ - rangeUnderflow
129
+ - rangeOverflow
130
+ - stepMismatch
131
+ - badInput */
132
+ const otherConstraintErrors = _v.typeMismatch || _v.rangeUnderflow || _v.rangeOverflow || _v.stepMismatch || _v.badInput;
133
+ if (!otherConstraintErrors) {
134
+ this.setCustomValidity('');
135
+ }
136
+ }
137
+ }
138
+ this.validationMessage = this.inputElement.validationMessage;
139
+ }
140
+ _handleInvalid(event) {
141
+ this.formControlController.setValidity(false);
142
+ this.formControlController.emitInvalidEvent(event);
143
+ }
144
+ _handleChange(e) {
145
+ const target = e.target;
146
+ let value;
147
+ if (target instanceof HTMLInputElement) {
148
+ switch (target.type) {
149
+ case 'checkbox':
150
+ case 'radio':
151
+ value = target.checked;
152
+ break;
153
+ case 'file':
154
+ value = target.files; // FileList
155
+ break;
156
+ default:
157
+ value = target.value;
158
+ }
159
+ }
160
+ else if (target instanceof HTMLSelectElement) {
161
+ if (target.multiple) {
162
+ value = Array.from(target.selectedOptions).map((o) => o.value);
163
+ }
164
+ else {
165
+ value = target.value;
166
+ }
167
+ }
168
+ else {
169
+ // textarea o altri input con value
170
+ value = target.value;
171
+ }
172
+ this.dispatchEvent(new CustomEvent('it-change', {
173
+ detail: { value, el: target },
174
+ bubbles: true,
175
+ composed: true,
176
+ }));
177
+ }
178
+ updated(changedProperties) {
179
+ super.updated?.(changedProperties);
180
+ if (this.customValidation) {
181
+ this.setCustomValidity(this.validationText ?? '');
182
+ }
183
+ else if (this.formControlController.userInteracted()) {
184
+ this.formControlController.updateValidity();
185
+ }
186
+ }
187
+ }
188
+ __decorate([
189
+ state(),
190
+ __metadata("design:type", Object)
191
+ ], FormControl.prototype, "_touched", void 0);
192
+ __decorate([
193
+ query('.it-form__control'),
194
+ __metadata("design:type", HTMLInputElement)
195
+ ], FormControl.prototype, "inputElement", void 0);
196
+ __decorate([
197
+ property({ type: String, reflect: true }) // from FormControl
198
+ ,
199
+ __metadata("design:type", Object)
200
+ ], FormControl.prototype, "name", void 0);
201
+ __decorate([
202
+ property({ reflect: true }),
203
+ __metadata("design:type", Object)
204
+ ], FormControl.prototype, "value", void 0);
205
+ __decorate([
206
+ property({ type: Boolean, reflect: true }) // from FormControl
207
+ ,
208
+ __metadata("design:type", Object)
209
+ ], FormControl.prototype, "disabled", void 0);
210
+ __decorate([
211
+ property({ reflect: true, type: String }),
212
+ __metadata("design:type", Object)
213
+ ], FormControl.prototype, "form", void 0);
214
+ __decorate([
215
+ property({ type: Boolean, reflect: true, attribute: 'custom-validation' }),
216
+ __metadata("design:type", Object)
217
+ ], FormControl.prototype, "customValidation", void 0);
218
+ __decorate([
219
+ property({ attribute: 'validity-message', reflect: true }),
220
+ __metadata("design:type", String)
221
+ ], FormControl.prototype, "validationText", void 0);
222
+ __decorate([
223
+ property(),
224
+ __metadata("design:type", String)
225
+ ], FormControl.prototype, "pattern", void 0);
226
+ __decorate([
227
+ property(),
228
+ __metadata("design:type", Object)
229
+ ], FormControl.prototype, "min", void 0);
230
+ __decorate([
231
+ property(),
232
+ __metadata("design:type", Object)
233
+ ], FormControl.prototype, "max", void 0);
234
+ __decorate([
235
+ property(),
236
+ __metadata("design:type", Object)
237
+ ], FormControl.prototype, "step", void 0);
238
+ __decorate([
239
+ property({ type: Number }),
240
+ __metadata("design:type", Object)
241
+ ], FormControl.prototype, "minlength", void 0);
242
+ __decorate([
243
+ property({ type: Number }),
244
+ __metadata("design:type", Object)
245
+ ], FormControl.prototype, "maxlength", void 0);
246
+ __decorate([
247
+ property({ type: Boolean, reflect: true }) // from FormControl
248
+ ,
249
+ __metadata("design:type", Object)
250
+ ], FormControl.prototype, "required", void 0);
251
+ __decorate([
252
+ property({ type: Boolean }),
253
+ __metadata("design:type", Object)
254
+ ], FormControl.prototype, "isInGroup", void 0);
255
+ __decorate([
256
+ state(),
257
+ __metadata("design:type", Object)
258
+ ], FormControl.prototype, "validationMessage", void 0);
259
+ //# sourceMappingURL=form-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-control.js","sourceRoot":"","sources":["../../../src/form/form-control.ts"],"names":[],"mappings":"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","sourcesContent":["import { property, query, state } from 'lit/decorators.js';\nimport { registerTranslation } from '@italia/i18n';\nimport { BaseLocalizedComponent } from '../base-component/base-component.js';\nimport { FormControlController } from './form-controller.js';\nimport it from './locales/it.js';\n\nregisterTranslation(it);\n\nexport class FormControl extends BaseLocalizedComponent {\n protected readonly formControlController = new FormControlController(this, {\n assumeInteractionOn: ['it-input', 'it-blur', 'it-change'],\n });\n\n // TODO: verificare se serve davvero con il fatto che usiamo form-controller\n // static formAssociated = true;\n\n // @property()\n // internals = this.attachInternals();\n\n @state()\n _touched = false;\n\n @query('.it-form__control')\n inputElement!: HTMLInputElement; // from FormControl\n\n /** The name of the input, submitted as a name/value pair with form data. */\n @property({ type: String, reflect: true }) // from FormControl\n name = '';\n\n /** The current value of the input, submitted as a name/value pair with form data. */\n @property({ reflect: true })\n value = '';\n\n /** If the input is disabled. */\n @property({ type: Boolean, reflect: true }) // from FormControl\n disabled = false;\n\n /**\n * By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you\n * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in\n * the same document or shadow root for this to work.\n */\n @property({ reflect: true, type: String }) form = '';\n\n /** If you implement your custom validation and you won't to trigger default validation */\n @property({ type: Boolean, reflect: true, attribute: 'custom-validation' })\n customValidation = false;\n\n /** If your input is invalid from your custom validition, set this attribute with message validation */\n @property({ attribute: 'validity-message', reflect: true })\n validationText: string = '';\n\n /** Pattern the `value` must match to be valid */\n @property()\n pattern?: string;\n\n /** The input's minimum value. Only applies to date and number input types. */\n @property()\n min: number | string | Date | undefined;\n\n /** The input's maximum value. Only applies to date and number input types. */\n @property()\n max: number | string | Date | undefined;\n\n /**\n * Specifies the granularity that the value must adhere to, or the special value `any` which means no stepping is\n * implied, allowing any numeric value. Only applies to date and number input types.\n */\n @property()\n step: number | 'any' = 'any';\n\n /** The input's minimum length. */\n @property({ type: Number })\n minlength = -1;\n\n /** The input's maximum length. */\n @property({ type: Number })\n maxlength = -1;\n\n /** If the input is required. */\n @property({ type: Boolean, reflect: true }) // from FormControl\n required = false;\n\n /* For grouped input, like checkbox-group */\n @property({ type: Boolean })\n protected isInGroup = false;\n\n /** Gets the validity state object */\n public get validity(): ValidityState {\n return this.inputElement?.validity;\n }\n\n @state()\n public validationMessage = '';\n\n /** Gets the associated form, if one exists. */\n public getForm(): HTMLFormElement | null {\n return this.formControlController.getForm();\n }\n\n // Form validation methods\n public checkValidity(): boolean {\n const inputValid = this.inputElement?.checkValidity() ?? true; // this.inputElement.checkValidity() è la validazione del browser\n return inputValid;\n }\n\n /** Checks for validity and shows the browser's validation message if the control is invalid. */\n public reportValidity() {\n // const ret = this.inputElement.checkValidity();\n const ret = this.checkValidity(); // chiama la checkValidity, che se è stata overridata chiama quella\n this.handleValidationMessages();\n return ret; // this.inputElement.reportValidity();\n }\n\n /** Sets a custom validation message. Pass an empty string to restore validity. */\n public setCustomValidity(message: string) {\n this.inputElement.setCustomValidity(message);\n this.validationMessage = this.inputElement.validationMessage;\n this.formControlController.updateValidity();\n }\n\n // Handlers\n protected _handleReady() {\n requestAnimationFrame(() => {\n this.dispatchEvent(new CustomEvent('it-input-ready', { bubbles: true, detail: { el: this.inputElement } }));\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleInput(e: Event) {\n this.handleValidationMessages();\n this.dispatchEvent(\n new CustomEvent('it-input', {\n detail: { value: this.inputElement.value, el: this.inputElement },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleBlur(e: Event) {\n this._touched = true;\n this.handleValidationMessages();\n this.dispatchEvent(new FocusEvent('it-blur', { bubbles: true, composed: true }));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleFocus(e: Event) {\n this.dispatchEvent(new FocusEvent('it-focus', { bubbles: true, composed: true }));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleClick(e: Event) {\n this.dispatchEvent(new MouseEvent('it-click', { bubbles: true, composed: true }));\n }\n\n /*\n Override default browser validation messages\n */\n protected handleValidationMessages() {\n if (!this.customValidation) {\n const _v = this.inputElement.validity;\n\n const isRequiredHandledByGroup = this.isInGroup === true;\n\n if (_v.valueMissing && !isRequiredHandledByGroup) {\n this.setCustomValidity(this.$t('validityRequired'));\n } else if (_v.patternMismatch) {\n this.setCustomValidity(this.$t('validityPattern'));\n } else if (_v.tooShort) {\n this.setCustomValidity(this.$t('validityMinlength').replace('{minlength}', this.minlength.toString()));\n } else if (_v.tooLong) {\n this.setCustomValidity(this.$t('validityMaxlength').replace('{maxlength}', this.maxlength.toString()));\n } else {\n /* nothing. Usa il messaggio di errore della validazione\n di default del browser per altri errori di validità come:\n - typeMismatch\n - rangeUnderflow\n - rangeOverflow\n - stepMismatch\n - badInput */\n\n const otherConstraintErrors =\n _v.typeMismatch || _v.rangeUnderflow || _v.rangeOverflow || _v.stepMismatch || _v.badInput;\n\n if (!otherConstraintErrors) {\n this.setCustomValidity('');\n }\n }\n }\n\n this.validationMessage = this.inputElement.validationMessage;\n }\n\n protected _handleInvalid(event: Event) {\n this.formControlController.setValidity(false);\n this.formControlController.emitInvalidEvent(event);\n }\n\n protected _handleChange(e: Event) {\n const target = e.target as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n let value: unknown;\n\n if (target instanceof HTMLInputElement) {\n switch (target.type) {\n case 'checkbox':\n case 'radio':\n value = target.checked;\n break;\n case 'file':\n value = target.files; // FileList\n break;\n default:\n value = target.value;\n }\n } else if (target instanceof HTMLSelectElement) {\n if (target.multiple) {\n value = Array.from(target.selectedOptions).map((o) => o.value);\n } else {\n value = target.value;\n }\n } else {\n // textarea o altri input con value\n value = (target as any).value;\n }\n\n this.dispatchEvent(\n new CustomEvent('it-change', {\n detail: { value, el: target },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n override updated(changedProperties: Map<string | number | symbol, unknown>) {\n super.updated?.(changedProperties);\n\n if (this.customValidation) {\n this.setCustomValidity(this.validationText ?? '');\n } else if (this.formControlController.userInteracted()) {\n this.formControlController.updateValidity();\n }\n }\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ import { FormControl } from './form-control.js';
3
+ export declare const formCollections: WeakMap<HTMLFormElement, Set<FormControl>>;
4
+ export interface FormControlControllerOptions {
5
+ /** A function that returns the form containing the form control. */
6
+ form: (input: FormControl) => HTMLFormElement | null;
7
+ /** A function that returns the form control's name, which will be submitted with the form data. */
8
+ name: (input: FormControl) => string;
9
+ /** A function that returns the form control's current value. */
10
+ value: (input: FormControl) => unknown | unknown[];
11
+ /** A function that returns the form control's current disabled state. If disabled, the value won't be submitted. */
12
+ disabled: (input: FormControl) => boolean;
13
+ reportValidity: (input: FormControl) => boolean;
14
+ checkValidity: (input: FormControl) => boolean;
15
+ /** A function that sets the form control's value */
16
+ setValue: (input: FormControl, value: unknown) => void;
17
+ /**
18
+ * An array of event names to listen to. When all events in the list are emitted, the control will receive validity
19
+ * states such as user-valid and user-invalid.user interacted validity states. */
20
+ assumeInteractionOn: string[];
21
+ }
22
+ /** A reactive controller to allow form controls to participate in form submission, validation, etc. */
23
+ export declare class FormControlController implements ReactiveController {
24
+ host: FormControl & ReactiveControllerHost;
25
+ form?: HTMLFormElement | null;
26
+ options: FormControlControllerOptions;
27
+ submittedOnce: boolean;
28
+ constructor(host: ReactiveControllerHost & FormControl, options?: Partial<FormControlControllerOptions>);
29
+ hostConnected(): void;
30
+ hostDisconnected(): void;
31
+ hostUpdated(): void;
32
+ private attachForm;
33
+ private detachForm;
34
+ private handleFormData;
35
+ private handleFormSubmit;
36
+ private handleFormReset;
37
+ private handleInteraction;
38
+ private checkFormValidity;
39
+ private reportFormValidity;
40
+ private setUserInteracted;
41
+ private doAction;
42
+ /** Returns the associated `<form>` element, if one exists. */
43
+ getForm(): HTMLFormElement | null;
44
+ /** Resets the form, restoring all the control to their default value */
45
+ reset(submitter?: HTMLInputElement | any): void;
46
+ /** Submits the form, triggering validation and form data injection. */
47
+ submit(submitter?: HTMLInputElement | any): void;
48
+ /**
49
+ * Synchronously sets the form control's validity. Call this when you know the future validity but need to update
50
+ * the host element immediately, i.e. before Lit updates the component in the next update.
51
+ */
52
+ setValidity(isValid: boolean): void;
53
+ userInteracted(): boolean;
54
+ /**
55
+ * Updates the form control's validity based on the current value of `host.validity.valid`. Call this when anything
56
+ * that affects constraint validation changes so the component receives the correct validity states.
57
+ */
58
+ updateValidity(): void;
59
+ /**
60
+ * Dispatches a non-bubbling, cancelable custom event of type `it-invalid`.
61
+ * If the `it-invalid` event will be cancelled then the original `invalid`
62
+ * event (which may have been passed as argument) will also be cancelled.
63
+ * If no original `invalid` event has been passed then the `it-invalid`
64
+ * event will be cancelled before being dispatched.
65
+ */
66
+ emitInvalidEvent(originalInvalidEvent?: Event): void;
67
+ }
68
+ //# sourceMappingURL=form-controller.d.ts.map