@vaadin/field-base 22.0.0-beta1 → 22.0.1

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.
package/README.md CHANGED
@@ -1,7 +1,14 @@
1
1
  # @vaadin/field-base
2
2
 
3
- A set of mixins for using by Vaadin field components.
3
+ A set of mixins and controllers used by Vaadin field components.
4
+
5
+ ## Contributing
6
+
7
+ Read the [contributing guide](https://vaadin.com/docs/latest/guide/contributing/overview) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components.
4
8
 
5
9
  ## License
6
10
 
7
11
  Apache License 2.0
12
+
13
+ Vaadin collects usage statistics at development time to improve this product.
14
+ For details and to opt-out, see https://github.com/vaadin/vaadin-usage-statistics.
package/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- export { AriaLabelController } from './src/aria-label-controller.js';
2
1
  export { CheckedMixin } from './src/checked-mixin.js';
3
2
  export { DelegateFocusMixin } from './src/delegate-focus-mixin.js';
4
3
  export { DelegateStateMixin } from './src/delegate-state-mixin.js';
4
+ export { FieldAriaController } from './src/field-aria-controller.js';
5
5
  export { FieldMixin } from './src/field-mixin.js';
6
6
  export { InputController } from './src/input-controller.js';
7
7
  export { InputControlMixin } from './src/input-control-mixin.js';
8
8
  export { InputFieldMixin } from './src/input-field-mixin.js';
9
9
  export { InputMixin } from './src/input-mixin.js';
10
+ export { LabelledInputController } from './src/labelled-input-controller.js';
10
11
  export { LabelMixin } from './src/label-mixin.js';
11
12
  export { PatternMixin } from './src/pattern-mixin.js';
12
13
  export { ShadowFocusMixin } from './src/shadow-focus-mixin.js';
package/index.js CHANGED
@@ -1,12 +1,13 @@
1
- export { AriaLabelController } from './src/aria-label-controller.js';
2
1
  export { CheckedMixin } from './src/checked-mixin.js';
3
2
  export { DelegateFocusMixin } from './src/delegate-focus-mixin.js';
4
3
  export { DelegateStateMixin } from './src/delegate-state-mixin.js';
4
+ export { FieldAriaController } from './src/field-aria-controller.js';
5
5
  export { FieldMixin } from './src/field-mixin.js';
6
6
  export { InputController } from './src/input-controller.js';
7
7
  export { InputControlMixin } from './src/input-control-mixin.js';
8
8
  export { InputFieldMixin } from './src/input-field-mixin.js';
9
9
  export { InputMixin } from './src/input-mixin.js';
10
+ export { LabelledInputController } from './src/labelled-input-controller.js';
10
11
  export { LabelMixin } from './src/label-mixin.js';
11
12
  export { PatternMixin } from './src/pattern-mixin.js';
12
13
  export { ShadowFocusMixin } from './src/shadow-focus-mixin.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/field-base",
3
- "version": "22.0.0-beta1",
3
+ "version": "22.0.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -29,14 +29,15 @@
29
29
  "web-component"
30
30
  ],
31
31
  "dependencies": {
32
+ "@open-wc/dedupe-mixin": "^1.3.0",
32
33
  "@polymer/polymer": "^3.0.0",
33
- "@vaadin/component-base": "22.0.0-beta1",
34
+ "@vaadin/component-base": "^22.0.1",
34
35
  "lit": "^2.0.0"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@esm-bundle/chai": "^4.3.4",
38
- "@vaadin/testing-helpers": "^0.3.0",
39
+ "@vaadin/testing-helpers": "^0.3.2",
39
40
  "sinon": "^9.2.1"
40
41
  },
41
- "gitHead": "4cf8a9d0504994200c610e44b3676114fef49c1e"
42
+ "gitHead": "2b0a2bff0369d6020f7cc33ad35506aa2d1f6f68"
42
43
  }
@@ -3,24 +3,27 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
7
- import { DelegateStateMixin } from './delegate-state-mixin.js';
8
- import { InputMixin } from './input-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import { InputMixinClass } from './input-mixin.js';
9
10
 
10
11
  /**
11
12
  * A mixin to manage the checked state.
12
13
  */
13
- declare function CheckedMixin<T extends new (...args: any[]) => {}>(base: T): T & CheckedMixinConstructor;
14
+ export declare function CheckedMixin<T extends Constructor<object>>(
15
+ base: T
16
+ ): T &
17
+ Constructor<CheckedMixinClass> &
18
+ Constructor<DelegateStateMixinClass> &
19
+ Constructor<DisabledMixinClass> &
20
+ Constructor<InputMixinClass>;
14
21
 
15
- interface CheckedMixinConstructor {
16
- new (...args: any[]): CheckedMixin;
17
- }
18
-
19
- interface CheckedMixin extends DelegateStateMixin, DisabledMixin, InputMixin {
22
+ export declare class CheckedMixinClass {
20
23
  /**
21
24
  * True if the element is checked.
22
25
  */
23
26
  checked: boolean;
24
- }
25
27
 
26
- export { CheckedMixinConstructor, CheckedMixin };
28
+ protected _toggleChecked(checked: boolean): void;
29
+ }
@@ -3,19 +3,18 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
7
- import { FocusMixin } from '@vaadin/component-base/src/focus-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
8
9
 
9
10
  /**
10
11
  * A mixin to forward focus to an element in the light DOM.
11
12
  */
12
- declare function DelegateFocusMixin<T extends new (...args: any[]) => {}>(base: T): T & DelegateFocusMixinConstructor;
13
+ export declare function DelegateFocusMixin<T extends Constructor<HTMLElement>>(
14
+ base: T
15
+ ): T & Constructor<DelegateFocusMixinClass> & Constructor<DisabledMixinClass> & Constructor<FocusMixinClass>;
13
16
 
14
- interface DelegateFocusMixinConstructor {
15
- new (...args: any[]): DelegateFocusMixin;
16
- }
17
-
18
- interface DelegateFocusMixin extends DisabledMixin, FocusMixin {
17
+ export declare class DelegateFocusMixinClass {
19
18
  /**
20
19
  * Specify that this control should have input focus when the page loads.
21
20
  */
@@ -28,7 +27,17 @@ interface DelegateFocusMixin extends DisabledMixin, FocusMixin {
28
27
  * Any component implementing this mixin is expected to provide it
29
28
  * by using `this._setFocusElement(input)` Polymer API.
30
29
  */
31
- readonly focusElement: Element | null | undefined;
32
- }
30
+ readonly focusElement: HTMLElement | null | undefined;
31
+
32
+ protected _addFocusListeners(element: HTMLElement): void;
33
+
34
+ protected _removeFocusListeners(element: HTMLElement): void;
33
35
 
34
- export { DelegateFocusMixinConstructor, DelegateFocusMixin };
36
+ protected _focusElementChanged(element: HTMLElement, oldElement: HTMLElement): void;
37
+
38
+ protected _onBlur(event: FocusEvent): void;
39
+
40
+ protected _onFocus(event: FocusEvent): void;
41
+
42
+ protected _setFocusElement(element: HTMLElement): void;
43
+ }
@@ -3,21 +3,18 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
6
7
 
7
8
  /**
8
9
  * A mixin to delegate properties and attributes to a target element.
9
10
  */
10
- declare function DelegateStateMixin<T extends new (...args: any[]) => {}>(base: T): T & DelegateStateMixinConstructor;
11
+ export declare function DelegateStateMixin<T extends Constructor<HTMLElement>>(
12
+ base: T
13
+ ): T & Constructor<DelegateStateMixinClass>;
11
14
 
12
- interface DelegateStateMixinConstructor {
13
- new (...args: any[]): DelegateStateMixin;
14
- }
15
-
16
- interface DelegateStateMixin {
15
+ export declare class DelegateStateMixinClass {
17
16
  /**
18
17
  * A target element to which attributes and properties are delegated.
19
18
  */
20
19
  stateTarget: HTMLElement | null;
21
20
  }
22
-
23
- export { DelegateStateMixinConstructor, DelegateStateMixin };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * A controller for managing ARIA attributes for a field element:
9
+ * either the component itself or slotted `<input>` element.
10
+ */
11
+ export class FieldAriaController {
12
+ constructor(host: HTMLElement);
13
+
14
+ /**
15
+ * The controller host element.
16
+ */
17
+ host: HTMLElement;
18
+
19
+ /**
20
+ * Sets a target element to which ARIA attributes are added.
21
+ */
22
+ setTarget(target: HTMLElement): void;
23
+
24
+ /**
25
+ * Toggles the `aria-required` attribute on the target element
26
+ * if the target is the host component (e.g. a field group).
27
+ * Otherwise, it does nothing.
28
+ */
29
+ setRequired(required: boolean): void;
30
+
31
+ /**
32
+ * Links the target element with a slotted label element
33
+ * via the target's attribute `aria-labelledby`.
34
+ *
35
+ * To unlink the previous slotted label element, pass `null` as `labelId`.
36
+ */
37
+ setLabelId(labelId: string | null): void;
38
+
39
+ /**
40
+ * Links the target element with a slotted error element via the target's attribute:
41
+ * - `aria-labelledby` if the target is the host component (e.g a field group).
42
+ * - `aria-describedby` otherwise.
43
+ *
44
+ * To unlink the previous slotted error element, pass `null` as `errorId`.
45
+ */
46
+ setErrorId(errorId: string | null): void;
47
+
48
+ /**
49
+ * Links the target element with a slotted helper element via the target's attribute:
50
+ * - `aria-labelledby` if the target is the host component (e.g a field group).
51
+ * - `aria-describedby` otherwise.
52
+ *
53
+ * To unlink the previous slotted helper element, pass `null` as `helperId`.
54
+ */
55
+ setHelperId(helperId: string | null): void;
56
+ }
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * A controller for managing ARIA attributes for a field element:
9
+ * either the component itself or slotted `<input>` element.
10
+ */
11
+ export class FieldAriaController {
12
+ constructor(host) {
13
+ this.host = host;
14
+ this.__required = false;
15
+ }
16
+
17
+ /**
18
+ * Sets a target element to which ARIA attributes are added.
19
+ *
20
+ * @param {HTMLElement} target
21
+ */
22
+ setTarget(target) {
23
+ this.__target = target;
24
+ this.__setAriaRequiredAttribute(this.__required);
25
+ this.__setLabelIdToAriaAttribute(this.__labelId);
26
+ this.__setErrorIdToAriaAttribute(this.__errorId);
27
+ this.__setHelperIdToAriaAttribute(this.__helperId);
28
+ }
29
+
30
+ /**
31
+ * Toggles the `aria-required` attribute on the target element
32
+ * if the target is the host component (e.g. a field group).
33
+ * Otherwise, it does nothing.
34
+ *
35
+ * @param {boolean} required
36
+ */
37
+ setRequired(required) {
38
+ this.__setAriaRequiredAttribute(required);
39
+ this.__required = required;
40
+ }
41
+
42
+ /**
43
+ * Links the target element with a slotted label element
44
+ * via the target's attribute `aria-labelledby`.
45
+ *
46
+ * To unlink the previous slotted label element, pass `null` as `labelId`.
47
+ *
48
+ * @param {string | null} labelId
49
+ */
50
+ setLabelId(labelId) {
51
+ this.__setLabelIdToAriaAttribute(labelId, this.__labelId);
52
+ this.__labelId = labelId;
53
+ }
54
+
55
+ /**
56
+ * Links the target element with a slotted error element via the target's attribute:
57
+ * - `aria-labelledby` if the target is the host component (e.g a field group).
58
+ * - `aria-describedby` otherwise.
59
+ *
60
+ * To unlink the previous slotted error element, pass `null` as `errorId`.
61
+ *
62
+ * @param {string | null} errorId
63
+ */
64
+ setErrorId(errorId) {
65
+ this.__setErrorIdToAriaAttribute(errorId, this.__errorId);
66
+ this.__errorId = errorId;
67
+ }
68
+
69
+ /**
70
+ * Links the target element with a slotted helper element via the target's attribute:
71
+ * - `aria-labelledby` if the target is the host component (e.g a field group).
72
+ * - `aria-describedby` otherwise.
73
+ *
74
+ * To unlink the previous slotted helper element, pass `null` as `helperId`.
75
+ *
76
+ * @param {string | null} helperId
77
+ */
78
+ setHelperId(helperId) {
79
+ this.__setHelperIdToAriaAttribute(helperId, this.__helperId);
80
+ this.__helperId = helperId;
81
+ }
82
+
83
+ /**
84
+ * `true` if the target element is the host component itself, `false` otherwise.
85
+ *
86
+ * @return {boolean}
87
+ * @private
88
+ */
89
+ get __isGroupField() {
90
+ return this.__target === this.host;
91
+ }
92
+
93
+ /**
94
+ * @param {string | null | undefined} labelId
95
+ * @param {string | null | undefined} oldLabelId
96
+ * @private
97
+ */
98
+ __setLabelIdToAriaAttribute(labelId, oldLabelId) {
99
+ this.__setAriaAttributeId('aria-labelledby', labelId, oldLabelId);
100
+ }
101
+
102
+ /**
103
+ * @param {string | null | undefined} errorId
104
+ * @param {string | null | undefined} oldErrorId
105
+ * @private
106
+ */
107
+ __setErrorIdToAriaAttribute(errorId, oldErrorId) {
108
+ // For groups, add all IDs to aria-labelledby rather than aria-describedby -
109
+ // that should guarantee that it's announced when the group is entered.
110
+ if (this.__isGroupField) {
111
+ this.__setAriaAttributeId('aria-labelledby', errorId, oldErrorId);
112
+ } else {
113
+ this.__setAriaAttributeId('aria-describedby', errorId, oldErrorId);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * @param {string | null | undefined} helperId
119
+ * @param {string | null | undefined} oldHelperId
120
+ * @private
121
+ */
122
+ __setHelperIdToAriaAttribute(helperId, oldHelperId) {
123
+ // For groups, add all IDs to aria-labelledby rather than aria-describedby -
124
+ // that should guarantee that it's announced when the group is entered.
125
+ if (this.__isGroupField) {
126
+ this.__setAriaAttributeId('aria-labelledby', helperId, oldHelperId);
127
+ } else {
128
+ this.__setAriaAttributeId('aria-describedby', helperId, oldHelperId);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * @param {boolean} required
134
+ * @private
135
+ */
136
+ __setAriaRequiredAttribute(required) {
137
+ if (!this.__target) {
138
+ return;
139
+ }
140
+
141
+ if (!this.__isGroupField) {
142
+ // native <input> or <textarea>, required is enough
143
+ return;
144
+ }
145
+
146
+ if (required) {
147
+ this.__target.setAttribute('aria-required', 'true');
148
+ } else {
149
+ this.__target.removeAttribute('aria-required');
150
+ }
151
+ }
152
+
153
+ /**
154
+ * @param {string | null | undefined} newId
155
+ * @param {string | null | undefined} oldId
156
+ * @private
157
+ */
158
+ __setAriaAttributeId(attr, newId, oldId) {
159
+ if (!this.__target) {
160
+ return;
161
+ }
162
+
163
+ const value = this.__target.getAttribute(attr);
164
+ const ids = value ? new Set(value.split(' ')) : new Set();
165
+
166
+ if (oldId) {
167
+ ids.delete(oldId);
168
+ }
169
+ if (newId) {
170
+ ids.add(newId);
171
+ }
172
+
173
+ this.__target.setAttribute(attr, [...ids].join(' '));
174
+ }
175
+ }
@@ -3,19 +3,23 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { LabelMixin } from './label-mixin.js';
7
- import { ValidateMixin } from './validate-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import { LabelMixinClass } from './label-mixin.js';
9
+ import { ValidateMixinClass } from './validate-mixin.js';
8
10
 
9
11
  /**
10
12
  * A mixin to provide common field logic: label, error message and helper text.
11
13
  */
12
- declare function FieldMixin<T extends new (...args: any[]) => {}>(base: T): T & FieldMixinConstructor;
14
+ export declare function FieldMixin<T extends Constructor<HTMLElement>>(
15
+ superclass: T
16
+ ): T &
17
+ Constructor<ControllerMixinClass> &
18
+ Constructor<FieldMixinClass> &
19
+ Constructor<LabelMixinClass> &
20
+ Constructor<ValidateMixinClass>;
13
21
 
14
- interface FieldMixinConstructor {
15
- new (...args: any[]): FieldMixin;
16
- }
17
-
18
- interface FieldMixin extends LabelMixin, ValidateMixin {
22
+ export declare class FieldMixinClass {
19
23
  /**
20
24
  * A target element to which ARIA attributes are set.
21
25
  */
@@ -29,11 +33,25 @@ interface FieldMixin extends LabelMixin, ValidateMixin {
29
33
  helperText: string | null | undefined;
30
34
 
31
35
  /**
32
- * Error to show when the field is invalid.
36
+ * Error message to show when the field is invalid.
33
37
  *
34
38
  * @attr {string} error-message
35
39
  */
36
- errorMessage: string;
37
- }
40
+ errorMessage: string | null | undefined;
41
+
42
+ protected readonly _errorNode: HTMLElement;
43
+
44
+ protected readonly _helperNode?: HTMLElement;
45
+
46
+ protected _helperTextChanged(helperText: string | null | undefined): void;
38
47
 
39
- export { FieldMixin, FieldMixinConstructor };
48
+ protected _ariaTargetChanged(target: HTMLElement): void;
49
+
50
+ protected _updateErrorMessage(invalid: boolean, errorMessage: string | null | undefined): void;
51
+
52
+ protected _requiredChanged(required: boolean): void;
53
+
54
+ protected _helperIdChanged(helperId: string): void;
55
+
56
+ protected _invalidChanged(invalid: boolean): void;
57
+ }
@@ -4,8 +4,10 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
7
- import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
7
  import { animationFrame } from '@vaadin/component-base/src/async.js';
8
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
9
+ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
10
+ import { FieldAriaController } from './field-aria-controller.js';
9
11
  import { LabelMixin } from './label-mixin.js';
10
12
  import { ValidateMixin } from './validate-mixin.js';
11
13
 
@@ -13,11 +15,12 @@ import { ValidateMixin } from './validate-mixin.js';
13
15
  * A mixin to provide common field logic: label, error message and helper text.
14
16
  *
15
17
  * @polymerMixin
18
+ * @mixes ControllerMixin
16
19
  * @mixes LabelMixin
17
20
  * @mixes ValidateMixin
18
21
  */
19
22
  export const FieldMixin = (superclass) =>
20
- class FieldMixinClass extends ValidateMixin(LabelMixin(superclass)) {
23
+ class FieldMixinClass extends ValidateMixin(LabelMixin(ControllerMixin(superclass))) {
21
24
  static get properties() {
22
25
  return {
23
26
  /**
@@ -66,9 +69,11 @@ export const FieldMixin = (superclass) =>
66
69
 
67
70
  static get observers() {
68
71
  return [
69
- '__ariaChanged(invalid, _helperId, required)',
70
72
  '__observeOffsetHeight(errorMessage, invalid, label, helperText)',
71
- '_updateErrorMessage(invalid, errorMessage)'
73
+ '_updateErrorMessage(invalid, errorMessage)',
74
+ '_invalidChanged(invalid)',
75
+ '_requiredChanged(required)',
76
+ '_helperIdChanged(_helperId)'
72
77
  ];
73
78
  }
74
79
 
@@ -88,14 +93,6 @@ export const FieldMixin = (superclass) =>
88
93
  return this._getDirectSlotChild('helper');
89
94
  }
90
95
 
91
- /**
92
- * @protected
93
- * @return {string}
94
- */
95
- get _ariaAttr() {
96
- return 'aria-describedby';
97
- }
98
-
99
96
  constructor() {
100
97
  super();
101
98
 
@@ -106,6 +103,8 @@ export const FieldMixin = (superclass) =>
106
103
 
107
104
  // Save generated ID to restore later
108
105
  this.__savedHelperId = this._helperId;
106
+
107
+ this._fieldAriaController = new FieldAriaController(this);
109
108
  }
110
109
 
111
110
  /** @protected */
@@ -166,6 +165,8 @@ export const FieldMixin = (superclass) =>
166
165
  this.__applyDefaultHelper(this.helperText);
167
166
  }
168
167
  });
168
+
169
+ this.addController(this._fieldAriaController);
169
170
  }
170
171
 
171
172
  /** @private */
@@ -206,6 +207,7 @@ export const FieldMixin = (superclass) =>
206
207
  }
207
208
 
208
209
  helper.id = this.__savedHelperId;
210
+ this._helperId = helper.id;
209
211
  this.appendChild(helper);
210
212
  this._currentHelper = helper;
211
213
 
@@ -266,9 +268,25 @@ export const FieldMixin = (superclass) =>
266
268
  );
267
269
  }
268
270
 
271
+ /**
272
+ * @protected
273
+ * @override
274
+ */
275
+ _toggleHasLabelAttribute() {
276
+ super._toggleHasLabelAttribute();
277
+
278
+ // Label ID should be only added when the label content is present.
279
+ // Otherwise, it may conflict with an `aria-label` attribute possibly added by the user.
280
+ if (this.hasAttribute('has-label')) {
281
+ this._fieldAriaController.setLabelId(this._labelId);
282
+ } else {
283
+ this._fieldAriaController.setLabelId(null);
284
+ }
285
+ }
286
+
269
287
  /**
270
288
  * @param {boolean} invalid
271
- * @param {string} errorMessage
289
+ * @param {string | null | undefined} errorMessage
272
290
  * @protected
273
291
  */
274
292
  _updateErrorMessage(invalid, errorMessage) {
@@ -283,6 +301,7 @@ export const FieldMixin = (superclass) =>
283
301
  }
284
302
  const hasError = Boolean(invalid && errorMessage);
285
303
  error.textContent = hasError ? errorMessage : '';
304
+ error.hidden = !hasError;
286
305
  this.toggleAttribute('has-error-message', hasError);
287
306
 
288
307
  // Role alert will make the error message announce immediately
@@ -320,66 +339,42 @@ export const FieldMixin = (superclass) =>
320
339
  }
321
340
 
322
341
  /**
323
- * @param {HTMLElement} target
342
+ * @param {HTMLElement | null | undefined} target
324
343
  * @protected
325
344
  */
326
345
  _ariaTargetChanged(target) {
327
346
  if (target) {
328
- this._updateAriaAttribute(target, this.invalid, this._helperId);
329
- this._updateAriaRequiredAttribute(target, this.required);
347
+ this._fieldAriaController.setTarget(target);
330
348
  }
331
349
  }
332
350
 
333
351
  /**
334
- * @param {HTMLElement} target
335
- * @param {boolean} invalid
336
- * @param {string} helperId
352
+ * @param {boolean} required
337
353
  * @protected
338
354
  */
339
- _updateAriaAttribute(target, invalid, helperId) {
340
- const attr = this._ariaAttr;
341
-
342
- if (target && attr) {
343
- // For groups, add all IDs to aria-labelledby rather than aria-describedby -
344
- // that should guarantee that it's announced when the group is entered.
345
- const ariaIds = attr === 'aria-describedby' ? [helperId] : [this._labelId, helperId];
346
-
347
- // Error message ID needs to be dynamically added / removed based on the validity
348
- // Otherwise assistive technologies would announce the error, even if we hide it.
349
- if (invalid) {
350
- ariaIds.push(this._errorId);
351
- }
352
-
353
- target.setAttribute(attr, ariaIds.join(' '));
354
- }
355
+ _requiredChanged(required) {
356
+ this._fieldAriaController.setRequired(required);
355
357
  }
356
358
 
357
359
  /**
358
- * @param {HTMLElement} target
359
- * @param {boolean} required
360
+ * @param {string} helperId
360
361
  * @protected
361
362
  */
362
- _updateAriaRequiredAttribute(target, required) {
363
- if (target !== this) {
364
- // native <input> or <textarea>, required is enough
365
- return;
366
- }
367
-
368
- if (required) {
369
- target.setAttribute('aria-required', true);
370
- } else {
371
- target.removeAttribute('aria-required');
372
- }
363
+ _helperIdChanged(helperId) {
364
+ this._fieldAriaController.setHelperId(helperId);
373
365
  }
374
366
 
375
367
  /**
376
- * @param {boolean} invalid
377
- * @param {string} helperId
378
368
  * @param {boolean} required
379
- * @private
369
+ * @protected
380
370
  */
381
- __ariaChanged(invalid, helperId, required) {
382
- this._updateAriaAttribute(this.ariaTarget, invalid, helperId);
383
- this._updateAriaRequiredAttribute(this.ariaTarget, required);
371
+ _invalidChanged(invalid) {
372
+ // Error message ID needs to be dynamically added / removed based on the validity
373
+ // Otherwise assistive technologies would announce the error, even if we hide it.
374
+ if (invalid) {
375
+ this._fieldAriaController.setErrorId(this._errorId);
376
+ } else {
377
+ this._fieldAriaController.setErrorId(null);
378
+ }
384
379
  }
385
380
  };
@@ -3,26 +3,27 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { DelegateStateMixin } from './delegate-state-mixin.js';
7
- import { InputMixin } from './input-mixin.js';
8
- import { ValidateMixin } from './validate-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import { InputMixinClass } from './input-mixin.js';
10
+ import { ValidateMixinClass } from './validate-mixin.js';
9
11
 
10
12
  /**
11
13
  * A mixin to combine multiple input validation constraints.
12
14
  */
13
- declare function InputConstraintsMixin<T extends new (...args: any[]) => {}>(
15
+ export declare function InputConstraintsMixin<T extends Constructor<HTMLElement>>(
14
16
  base: T
15
- ): T & InputConstraintsMixinConstructor;
17
+ ): T &
18
+ Constructor<DelegateStateMixinClass> &
19
+ Constructor<DisabledMixinClass> &
20
+ Constructor<InputConstraintsMixinClass> &
21
+ Constructor<InputMixinClass> &
22
+ Constructor<ValidateMixinClass>;
16
23
 
17
- interface InputConstraintsMixinConstructor {
18
- new (...args: any[]): InputConstraintsMixin;
19
- }
20
-
21
- interface InputConstraintsMixin extends DelegateStateMixin, InputMixin, ValidateMixin {
24
+ export declare class InputConstraintsMixinClass {
22
25
  /**
23
26
  * Returns true if the current input value satisfies all constraints (if any).
24
27
  */
25
28
  checkValidity(): boolean;
26
29
  }
27
-
28
- export { InputConstraintsMixin, InputConstraintsMixinConstructor };
@@ -3,20 +3,39 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
7
- import { FieldMixin } from './field-mixin.js';
8
- import { InputConstraintsMixin } from './input-constraints-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
9
+ import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
10
+ import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
11
+ import { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
12
+ import { DelegateStateMixinClass } from './delegate-state-mixin.js';
13
+ import { FieldMixinClass } from './field-mixin.js';
14
+ import { InputConstraintsMixinClass } from './input-constraints-mixin.js';
15
+ import { InputMixinClass } from './input-mixin.js';
16
+ import { LabelMixinClass } from './label-mixin.js';
17
+ import { ValidateMixinClass } from './validate-mixin.js';
9
18
 
10
19
  /**
11
20
  * A mixin to provide shared logic for the editable form input controls.
12
21
  */
13
- declare function InputControlMixin<T extends new (...args: any[]) => {}>(base: T): T & InputControlMixinConstructor;
22
+ export declare function InputControlMixin<T extends Constructor<HTMLElement>>(
23
+ base: T
24
+ ): T &
25
+ Constructor<ControllerMixinClass> &
26
+ Constructor<DelegateFocusMixinClass> &
27
+ Constructor<DelegateStateMixinClass> &
28
+ Constructor<DisabledMixinClass> &
29
+ Constructor<FieldMixinClass> &
30
+ Constructor<FocusMixinClass> &
31
+ Constructor<InputConstraintsMixinClass> &
32
+ Constructor<InputControlMixinClass> &
33
+ Constructor<InputMixinClass> &
34
+ Constructor<KeyboardMixinClass> &
35
+ Constructor<LabelMixinClass> &
36
+ Constructor<ValidateMixinClass>;
14
37
 
15
- interface InputControlMixinConstructor {
16
- new (...args: any[]): InputControlMixin;
17
- }
18
-
19
- interface InputControlMixin extends KeyboardMixin, InputConstraintsMixin, FieldMixin {
38
+ export declare class InputControlMixinClass {
20
39
  /**
21
40
  * If true, the input text gets fully selected when the field is focused using click or touch / tap.
22
41
  */
@@ -48,5 +67,3 @@ interface InputControlMixin extends KeyboardMixin, InputConstraintsMixin, FieldM
48
67
  */
49
68
  title: string;
50
69
  }
51
-
52
- export { InputControlMixin, InputControlMixinConstructor };
@@ -3,18 +3,41 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { InputControlMixin } from './input-control-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
9
+ import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
10
+ import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
11
+ import { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
12
+ import { DelegateStateMixinClass } from './delegate-state-mixin.js';
13
+ import { FieldMixinClass } from './field-mixin.js';
14
+ import { InputConstraintsMixinClass } from './input-constraints-mixin.js';
15
+ import { InputControlMixinClass } from './input-control-mixin.js';
16
+ import { InputMixinClass } from './input-mixin.js';
17
+ import { LabelMixinClass } from './label-mixin.js';
18
+ import { ValidateMixinClass } from './validate-mixin.js';
7
19
 
8
20
  /**
9
21
  * A mixin to provide logic for vaadin-text-field and related components.
10
22
  */
11
- declare function InputFieldMixin<T extends new (...args: any[]) => {}>(base: T): T & InputFieldMixinConstructor;
23
+ export declare function InputFieldMixin<T extends Constructor<HTMLElement>>(
24
+ base: T
25
+ ): T &
26
+ Constructor<ControllerMixinClass> &
27
+ Constructor<DelegateFocusMixinClass> &
28
+ Constructor<DelegateStateMixinClass> &
29
+ Constructor<DisabledMixinClass> &
30
+ Constructor<FieldMixinClass> &
31
+ Constructor<FocusMixinClass> &
32
+ Constructor<InputConstraintsMixinClass> &
33
+ Constructor<InputControlMixinClass> &
34
+ Constructor<InputFieldMixinClass> &
35
+ Constructor<InputMixinClass> &
36
+ Constructor<KeyboardMixinClass> &
37
+ Constructor<LabelMixinClass> &
38
+ Constructor<ValidateMixinClass>;
12
39
 
13
- interface InputFieldMixinConstructor {
14
- new (...args: any[]): InputFieldMixin;
15
- }
16
-
17
- interface InputFieldMixin extends InputControlMixin {
40
+ export declare class InputFieldMixinClass {
18
41
  /**
19
42
  * Whether the value of the control can be automatically completed by the browser.
20
43
  * List of available options at:
@@ -42,5 +65,3 @@ interface InputFieldMixin extends InputControlMixin {
42
65
  */
43
66
  autocapitalize: 'on' | 'off' | 'none' | 'characters' | 'words' | 'sentences' | undefined;
44
67
  }
45
-
46
- export { InputFieldMixin, InputFieldMixinConstructor };
@@ -3,18 +3,15 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
6
7
 
7
8
  /**
8
9
  * A mixin to store the reference to an input element
9
10
  * and add input and change event listeners to it.
10
11
  */
11
- declare function InputMixin<T extends new (...args: any[]) => {}>(base: T): T & InputMixinConstructor;
12
+ export declare function InputMixin<T extends Constructor<HTMLElement>>(base: T): T & Constructor<InputMixinClass>;
12
13
 
13
- interface InputMixinConstructor {
14
- new (...args: any[]): InputMixin;
15
- }
16
-
17
- interface InputMixin {
14
+ export declare class InputMixinClass {
18
15
  /**
19
16
  * A reference to the input element controlled by the mixin.
20
17
  * Any component implementing this mixin is expected to provide it
@@ -24,7 +21,7 @@ interface InputMixin {
24
21
  * However, the input element does not have to always be native <input>:
25
22
  * as an example, <vaadin-combo-box-light> accepts other components.
26
23
  */
27
- readonly inputElement: HTMLInputElement;
24
+ readonly inputElement: HTMLElement;
28
25
 
29
26
  /**
30
27
  * The value of the field.
@@ -35,6 +32,22 @@ interface InputMixin {
35
32
  * Clear the value of the field.
36
33
  */
37
34
  clear(): void;
38
- }
39
35
 
40
- export { InputMixin, InputMixinConstructor };
36
+ protected _addInputListeners(input: HTMLElement): void;
37
+
38
+ protected _removeInputListeners(input: HTMLElement): void;
39
+
40
+ protected _forwardInputValue(input: HTMLElement): void;
41
+
42
+ protected _inputElementChanged(input: HTMLElement, oldInput: HTMLElement): void;
43
+
44
+ protected _onChange(event: void): void;
45
+
46
+ protected _onInput(event: void): void;
47
+
48
+ protected _setInputElement(input: HTMLElement): void;
49
+
50
+ protected _toggleHasValue(value: boolean): void;
51
+
52
+ protected _valueChanged(value?: string, oldValue?: string): void;
53
+ }
@@ -3,22 +3,25 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { SlotMixin } from '@vaadin/component-base/src/slot-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { SlotMixinClass } from '@vaadin/component-base/src/slot-mixin.js';
7
8
 
8
9
  /**
9
10
  * A mixin to provide label via corresponding property or named slot.
10
11
  */
11
- declare function LabelMixin<T extends new (...args: any[]) => {}>(base: T): T & LabelMixinConstructor;
12
+ export declare function LabelMixin<T extends Constructor<HTMLElement>>(
13
+ base: T
14
+ ): T & Constructor<LabelMixinClass> & Constructor<SlotMixinClass>;
12
15
 
13
- interface LabelMixinConstructor {
14
- new (...args: any[]): LabelMixin;
15
- }
16
-
17
- interface LabelMixin extends SlotMixin {
16
+ export declare class LabelMixinClass {
18
17
  /**
19
18
  * String used for a label element.
20
19
  */
21
20
  label: string | null | undefined;
22
- }
23
21
 
24
- export { LabelMixinConstructor, LabelMixin };
22
+ protected readonly _labelNode: HTMLLabelElement;
23
+
24
+ protected _labelChanged(label: string | null | undefined): void;
25
+
26
+ protected _toggleHasLabelAttribute(): void;
27
+ }
@@ -87,7 +87,6 @@ export const LabelMixin = dedupingMixin(
87
87
  const hasLabel = this._labelNode.children.length > 0 || this._labelNode.textContent.trim() !== '';
88
88
 
89
89
  this.toggleAttribute('has-label', hasLabel);
90
- this.dispatchEvent(new CustomEvent('has-label-changed', { detail: { value: hasLabel } }));
91
90
  }
92
91
  }
93
92
  }
@@ -6,6 +6,6 @@
6
6
  import { ReactiveController } from 'lit';
7
7
 
8
8
  /**
9
- * A controller to link an input element with a slotted `<label>` element.
9
+ * A controller for linking a `<label>` element with an `<input>` element.
10
10
  */
11
- export class AriaLabelController implements ReactiveController {}
11
+ export class LabelledInputController implements ReactiveController {}
@@ -5,10 +5,10 @@
5
5
  */
6
6
 
7
7
  /**
8
- * A controller to link an input element with a slotted `<label>` element.
8
+ * A controller for linking a `<label>` element with an `<input>` element.
9
9
  */
10
- export class AriaLabelController {
11
- constructor(host, input, label) {
10
+ export class LabelledInputController {
11
+ constructor(input, label) {
12
12
  this.input = input;
13
13
  this.__preventDuplicateLabelClick = this.__preventDuplicateLabelClick.bind(this);
14
14
 
@@ -17,11 +17,6 @@ export class AriaLabelController {
17
17
 
18
18
  if (input) {
19
19
  label.setAttribute('for', input.id);
20
-
21
- this.__setAriaLabelledBy(input, host.hasAttribute('has-label') ? label.id : null);
22
- host.addEventListener('has-label-changed', (event) =>
23
- this.__setAriaLabelledBy(input, event.detail.value ? label.id : null)
24
- );
25
20
  }
26
21
  }
27
22
  }
@@ -41,18 +36,4 @@ export class AriaLabelController {
41
36
  };
42
37
  this.input.addEventListener('click', inputClickHandler);
43
38
  }
44
-
45
- /**
46
- * Sets or removes the `aria-labelledby` attribute on the input element.
47
- * @param {HTMLElement} input
48
- * @param {string | null | undefined} value
49
- * @private
50
- */
51
- __setAriaLabelledBy(input, value) {
52
- if (value) {
53
- input.setAttribute('aria-labelledby', value);
54
- } else {
55
- input.removeAttribute('aria-labelledby');
56
- }
57
- }
58
39
  }
@@ -3,18 +3,27 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { InputConstraintsMixin } from './input-constraints-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import { InputConstraintsMixinClass } from './input-constraints-mixin.js';
10
+ import { InputMixinClass } from './input-mixin.js';
11
+ import { ValidateMixinClass } from './validate-mixin.js';
7
12
 
8
13
  /**
9
14
  * A mixin to provide `pattern` and `preventInvalidInput` properties.
10
15
  */
11
- declare function PatternMixin<T extends new (...args: any[]) => {}>(base: T): T & PatternMixinConstructor;
16
+ export declare function PatternMixin<T extends Constructor<HTMLElement>>(
17
+ base: T
18
+ ): T &
19
+ Constructor<DelegateStateMixinClass> &
20
+ Constructor<DisabledMixinClass> &
21
+ Constructor<InputConstraintsMixinClass> &
22
+ Constructor<InputMixinClass> &
23
+ Constructor<PatternMixinClass> &
24
+ Constructor<ValidateMixinClass>;
12
25
 
13
- interface PatternMixinConstructor {
14
- new (...args: any[]): PatternMixin;
15
- }
16
-
17
- interface PatternMixin extends InputConstraintsMixin {
26
+ export declare class PatternMixinClass {
18
27
  /**
19
28
  * A regular expression that the value is checked against.
20
29
  * The pattern must match the entire value, not just some subset.
@@ -28,5 +37,3 @@ interface PatternMixin extends InputConstraintsMixin {
28
37
  */
29
38
  preventInvalidInput: boolean | null | undefined;
30
39
  }
31
-
32
- export { PatternMixin, PatternMixinConstructor };
@@ -3,8 +3,8 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { Debouncer } from '@vaadin/component-base/src/debounce.js';
7
6
  import { timeOut } from '@vaadin/component-base/src/async.js';
7
+ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
8
  import { InputConstraintsMixin } from './input-constraints-mixin.js';
9
9
 
10
10
  /**
@@ -3,19 +3,21 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
7
- import { TabindexMixin } from '@vaadin/component-base/src/tabindex-mixin.js';
8
- import { DelegateFocusMixin } from './delegate-focus-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
9
+ import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
10
+ import { TabindexMixinClass } from '@vaadin/component-base/src/tabindex-mixin.js';
11
+ import { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
9
12
 
10
13
  /**
11
14
  * A mixin to forward focus to an element in the shadow DOM.
12
15
  */
13
- declare function ShadowFocusMixin<T extends new (...args: any[]) => {}>(base: T): T & ShadowFocusMixinConstructor;
14
-
15
- interface ShadowFocusMixinConstructor {
16
- new (...args: any[]): ShadowFocusMixin;
17
- }
18
-
19
- interface ShadowFocusMixin extends KeyboardMixin, TabindexMixin, DelegateFocusMixin {}
20
-
21
- export { ShadowFocusMixinConstructor, ShadowFocusMixin };
16
+ export declare function ShadowFocusMixin<T extends Constructor<HTMLElement>>(
17
+ base: T
18
+ ): T &
19
+ Constructor<DelegateFocusMixinClass> &
20
+ Constructor<DisabledMixinClass> &
21
+ Constructor<FocusMixinClass> &
22
+ Constructor<KeyboardMixinClass> &
23
+ Constructor<TabindexMixinClass>;
@@ -3,18 +3,13 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { LabelMixin } from './label-mixin.js';
7
- import { SlotTargetMixin } from './slot-target-mixin.js';
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
7
+ import { LabelMixinClass } from './label-mixin.js';
8
+ import { SlotTargetMixinClass } from './slot-target-mixin.js';
8
9
 
9
10
  /**
10
11
  * A mixin to forward any content from the default slot to the label node.
11
12
  */
12
- declare function SlotLabelMixin<T extends new (...args: any[]) => {}>(base: T): T & SlotLabelMixinConstructor;
13
-
14
- interface SlotLabelMixinConstructor {
15
- new (...args: any[]): SlotLabelMixin;
16
- }
17
-
18
- interface SlotLabelMixin extends SlotTargetMixin, LabelMixin {}
19
-
20
- export { SlotLabelMixinConstructor, SlotLabelMixin };
13
+ export declare function SlotLabelMixin<T extends Constructor<HTMLElement>>(
14
+ base: T
15
+ ): T & Constructor<LabelMixinClass> & Constructor<SlotTargetMixinClass>;
@@ -3,22 +3,19 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
6
7
 
7
8
  /**
8
9
  * Mixin to insert styles into the outer scope to handle slotted components.
9
10
  * This is useful e.g. to hide native `<input type="number">` controls.
10
11
  */
11
- declare function SlotStylesMixin<T extends new (...args: any[]) => {}>(base: T): T & SlotStylesMixinConstructor;
12
+ export declare function SlotStylesMixin<T extends Constructor<HTMLElement>>(
13
+ base: T
14
+ ): T & Constructor<SlotStylesMixinClass>;
12
15
 
13
- interface SlotStylesMixinConstructor {
14
- new (...args: any[]): SlotStylesMixin;
15
- }
16
-
17
- interface SlotStylesMixin {
16
+ export declare class SlotStylesMixinClass {
18
17
  /**
19
18
  * List of styles to insert into root.
20
19
  */
21
- readonly slotStyles: string[];
20
+ protected readonly slotStyles: string[];
22
21
  }
23
-
24
- export { SlotStylesMixinConstructor, SlotStylesMixin };
@@ -3,30 +3,23 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
6
7
 
7
8
  /**
8
9
  * A mixin to copy the content from a source slot to a target element.
9
10
  */
10
- declare function SlotTargetMixin<T extends new (...args: any[]) => {}>(base: T): T & SlotTargetMixinConstructor;
11
+ export declare function SlotTargetMixin<T extends Constructor<HTMLElement>>(
12
+ base: T
13
+ ): T & Constructor<SlotTargetMixinClass>;
11
14
 
12
- interface SlotTargetMixinConstructor {
13
- new (...args: any[]): SlotTargetMixin;
14
- }
15
-
16
- interface SlotTargetMixin {
15
+ export declare class SlotTargetMixinClass {
17
16
  /**
18
17
  * A reference to the source slot from which the content is copied to the target element.
19
- *
20
- * @protected
21
18
  */
22
- _sourceSlot: HTMLSlotElement;
19
+ protected readonly _sourceSlot: HTMLSlotElement;
23
20
 
24
21
  /**
25
22
  * A reference to the target element to which the content is copied from the source slot.
26
- *
27
- * @protected
28
23
  */
29
- _slotTarget: HTMLElement;
24
+ protected readonly _slotTarget: HTMLElement;
30
25
  }
31
-
32
- export { SlotTargetMixinConstructor, SlotTargetMixin };
@@ -3,17 +3,14 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { Constructor } from '@open-wc/dedupe-mixin';
6
7
 
7
8
  /**
8
9
  * A mixin to provide required state and validation logic.
9
10
  */
10
- declare function ValidateMixin<T extends new (...args: any[]) => {}>(base: T): T & ValidateMixinConstructor;
11
+ export declare function ValidateMixin<T extends Constructor<HTMLElement>>(base: T): T & Constructor<ValidateMixinClass>;
11
12
 
12
- interface ValidateMixinConstructor {
13
- new (...args: any[]): ValidateMixin;
14
- }
15
-
16
- interface ValidateMixin {
13
+ export declare class ValidateMixinClass {
17
14
  /**
18
15
  * Set to true when the field is invalid.
19
16
  */
@@ -34,5 +31,3 @@ interface ValidateMixin {
34
31
  */
35
32
  checkValidity(): boolean;
36
33
  }
37
-
38
- export { ValidateMixinConstructor, ValidateMixin };