@vaadin/field-base 23.1.2 → 23.2.0-alpha3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/field-base",
3
- "version": "23.1.2",
3
+ "version": "23.2.0-alpha3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "@open-wc/dedupe-mixin": "^1.3.0",
34
34
  "@polymer/polymer": "^3.0.0",
35
- "@vaadin/component-base": "^23.1.2",
35
+ "@vaadin/component-base": "23.2.0-alpha3",
36
36
  "lit": "^2.0.0"
37
37
  },
38
38
  "devDependencies": {
@@ -40,5 +40,5 @@
40
40
  "@vaadin/testing-helpers": "^0.3.2",
41
41
  "sinon": "^13.0.2"
42
42
  },
43
- "gitHead": "6fb205c6e9a761feadfb779dd5d7af96d3102e56"
43
+ "gitHead": "06e5875be93ca50da2846dafc65a8531010c0576"
44
44
  }
@@ -3,10 +3,10 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import type { InputMixinClass } from './input-mixin.js';
10
10
 
11
11
  /**
12
12
  * A mixin to manage the checked state.
@@ -3,10 +3,10 @@
3
3
  * Copyright (c) 2021 - 2022 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';
7
- import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
- import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
9
- import { TabindexMixinClass } from '@vaadin/component-base/src/tabindex-mixin.js';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
9
+ import type { TabindexMixinClass } from '@vaadin/component-base/src/tabindex-mixin.js';
10
10
 
11
11
  /**
12
12
  * A mixin to forward focus to an element in the light DOM.
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 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
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
7
 
8
8
  /**
9
9
  * A mixin to delegate properties and attributes to a target element.
@@ -3,10 +3,10 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import type { LabelMixinClass } from './label-mixin.js';
9
+ import type { ValidateMixinClass } from './validate-mixin.js';
10
10
 
11
11
  /**
12
12
  * A mixin to provide common field logic: label, error message and helper text.
@@ -89,10 +89,6 @@ export const FieldMixin = (superclass) =>
89
89
  this._helperController = new HelperController(this);
90
90
  this._errorController = new ErrorController(this);
91
91
 
92
- this.addController(this._fieldAriaController);
93
- this.addController(this._helperController);
94
- this.addController(this._errorController);
95
-
96
92
  this._labelController.addEventListener('label-changed', (event) => {
97
93
  const { hasLabel, node } = event.detail;
98
94
  this.__labelChanged(hasLabel, node);
@@ -104,6 +100,15 @@ export const FieldMixin = (superclass) =>
104
100
  });
105
101
  }
106
102
 
103
+ /** @protected */
104
+ ready() {
105
+ super.ready();
106
+
107
+ this.addController(this._fieldAriaController);
108
+ this.addController(this._helperController);
109
+ this.addController(this._errorController);
110
+ }
111
+
107
112
  /** @private */
108
113
  __helperChanged(hasHelper, helperNode) {
109
114
  if (hasHelper) {
@@ -3,11 +3,11 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import type { InputMixinClass } from './input-mixin.js';
10
+ import type { ValidateMixinClass } from './validate-mixin.js';
11
11
 
12
12
  /**
13
13
  * A mixin to combine multiple input validation constraints.
@@ -88,7 +88,7 @@ export const InputConstraintsMixin = dedupingMixin(
88
88
  if (this._hasValidConstraints(constraints)) {
89
89
  this.validate();
90
90
  } else {
91
- this.invalid = false;
91
+ this._setInvalid(false);
92
92
  }
93
93
  }
94
94
 
@@ -3,18 +3,18 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
9
+ import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
10
+ import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
11
+ import type { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
12
+ import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
13
+ import type { FieldMixinClass } from './field-mixin.js';
14
+ import type { InputConstraintsMixinClass } from './input-constraints-mixin.js';
15
+ import type { InputMixinClass } from './input-mixin.js';
16
+ import type { LabelMixinClass } from './label-mixin.js';
17
+ import type { ValidateMixinClass } from './validate-mixin.js';
18
18
 
19
19
  /**
20
20
  * A mixin to provide shared logic for the editable form input controls.
@@ -36,6 +36,19 @@ export declare function InputControlMixin<T extends Constructor<HTMLElement>>(
36
36
  Constructor<ValidateMixinClass>;
37
37
 
38
38
  export declare class InputControlMixinClass {
39
+ /**
40
+ * A pattern matched against individual characters the user inputs.
41
+ *
42
+ * When set, the field will prevent:
43
+ * - `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`
44
+ * - `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`
45
+ * - `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`
46
+ *
47
+ * For example, to allow entering only numbers and minus signs, use:
48
+ * `allowedCharPattern = "[\\d-]"`
49
+ */
50
+ allowedCharPattern: string;
51
+
39
52
  /**
40
53
  * If true, the input text gets fully selected when the field is focused using click or touch / tap.
41
54
  */
@@ -3,6 +3,8 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { timeOut } from '@vaadin/component-base/src/async.js';
7
+ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
6
8
  import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
7
9
  import { DelegateFocusMixin } from './delegate-focus-mixin.js';
8
10
  import { FieldMixin } from './field-mixin.js';
@@ -23,6 +25,22 @@ export const InputControlMixin = (superclass) =>
23
25
  ) {
24
26
  static get properties() {
25
27
  return {
28
+ /**
29
+ * A pattern matched against individual characters the user inputs.
30
+ *
31
+ * When set, the field will prevent:
32
+ * - `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`
33
+ * - `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`
34
+ * - `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`
35
+ *
36
+ * For example, to allow entering only numbers and minus signs, use:
37
+ * `allowedCharPattern = "[\\d-]"`
38
+ */
39
+ allowedCharPattern: {
40
+ type: String,
41
+ observer: '_allowedCharPatternChanged',
42
+ },
43
+
26
44
  /**
27
45
  * If true, the input text gets fully selected when the field is focused using click or touch / tap.
28
46
  */
@@ -80,6 +98,14 @@ export const InputControlMixin = (superclass) =>
80
98
  return [...super.delegateAttrs, 'name', 'type', 'placeholder', 'readonly', 'invalid', 'title'];
81
99
  }
82
100
 
101
+ constructor() {
102
+ super();
103
+
104
+ this._boundOnPaste = this._onPaste.bind(this);
105
+ this._boundOnDrop = this._onDrop.bind(this);
106
+ this._boundOnBeforeInput = this._onBeforeInput.bind(this);
107
+ }
108
+
83
109
  /**
84
110
  * Any element extending this mixin is required to implement this getter.
85
111
  * It returns the reference to the clear button element.
@@ -172,6 +198,115 @@ export const InputControlMixin = (superclass) =>
172
198
  this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
173
199
  }
174
200
 
201
+ /**
202
+ * Override a method from `InputMixin`.
203
+ * @param {!HTMLElement} input
204
+ * @protected
205
+ * @override
206
+ */
207
+ _addInputListeners(input) {
208
+ super._addInputListeners(input);
209
+
210
+ input.addEventListener('paste', this._boundOnPaste);
211
+ input.addEventListener('drop', this._boundOnDrop);
212
+ input.addEventListener('beforeinput', this._boundOnBeforeInput);
213
+ }
214
+
215
+ /**
216
+ * Override a method from `InputMixin`.
217
+ * @param {!HTMLElement} input
218
+ * @protected
219
+ * @override
220
+ */
221
+ _removeInputListeners(input) {
222
+ super._removeInputListeners(input);
223
+
224
+ input.removeEventListener('paste', this._boundOnPaste);
225
+ input.removeEventListener('drop', this._boundOnDrop);
226
+ input.removeEventListener('beforeinput', this._boundOnBeforeInput);
227
+ }
228
+
229
+ /**
230
+ * Override an event listener from `KeyboardMixin`.
231
+ * @param {!KeyboardEvent} event
232
+ * @protected
233
+ * @override
234
+ */
235
+ _onKeyDown(event) {
236
+ super._onKeyDown(event);
237
+
238
+ if (this.allowedCharPattern && !this.__shouldAcceptKey(event)) {
239
+ event.preventDefault();
240
+ this._markInputPrevented();
241
+ }
242
+ }
243
+
244
+ /** @protected */
245
+ _markInputPrevented() {
246
+ // Add input-prevented attribute for 200ms
247
+ this.setAttribute('input-prevented', '');
248
+ this._preventInputDebouncer = Debouncer.debounce(this._preventInputDebouncer, timeOut.after(200), () => {
249
+ this.removeAttribute('input-prevented');
250
+ });
251
+ }
252
+
253
+ /** @private */
254
+ __shouldAcceptKey(event) {
255
+ return (
256
+ event.metaKey ||
257
+ event.ctrlKey ||
258
+ !event.key || // Allow typing anything if event.key is not supported
259
+ event.key.length !== 1 || // Allow "Backspace", "ArrowLeft" etc.
260
+ this.__allowedCharRegExp.test(event.key)
261
+ );
262
+ }
263
+
264
+ /** @private */
265
+ _onPaste(e) {
266
+ if (this.allowedCharPattern) {
267
+ const pastedText = e.clipboardData.getData('text');
268
+ if (!this.__allowedTextRegExp.test(pastedText)) {
269
+ e.preventDefault();
270
+ this._markInputPrevented();
271
+ }
272
+ }
273
+ }
274
+
275
+ /** @private */
276
+ _onDrop(e) {
277
+ if (this.allowedCharPattern) {
278
+ const draggedText = e.dataTransfer.getData('text');
279
+ if (!this.__allowedTextRegExp.test(draggedText)) {
280
+ e.preventDefault();
281
+ this._markInputPrevented();
282
+ }
283
+ }
284
+ }
285
+
286
+ /** @private */
287
+ _onBeforeInput(e) {
288
+ // The `beforeinput` event covers all the cases for `allowedCharPattern`: keyboard, pasting and dropping,
289
+ // but it is still experimental technology so we can't rely on it. It's used here just as an additional check,
290
+ // because it seems to be the only way to detect and prevent specific keys on mobile devices.
291
+ // See https://github.com/vaadin/vaadin-text-field/issues/429
292
+ if (this.allowedCharPattern && e.data && !this.__allowedTextRegExp.test(e.data)) {
293
+ e.preventDefault();
294
+ this._markInputPrevented();
295
+ }
296
+ }
297
+
298
+ /** @private */
299
+ _allowedCharPatternChanged(charPattern) {
300
+ if (charPattern) {
301
+ try {
302
+ this.__allowedCharRegExp = new RegExp(`^${charPattern}$`);
303
+ this.__allowedTextRegExp = new RegExp(`^${charPattern}*$`);
304
+ } catch (e) {
305
+ console.error(e);
306
+ }
307
+ }
308
+ }
309
+
175
310
  /**
176
311
  * Fired when the user commits a value change.
177
312
  *
@@ -23,9 +23,7 @@ export class InputController extends SlotController {
23
23
  }
24
24
 
25
25
  // Ensure every instance has unique ID
26
- const uniqueId = (InputController._uniqueInputId = 1 + InputController._uniqueInputId || 0);
27
- host._inputId = `${host.localName}-${uniqueId}`;
28
- node.id = host._inputId;
26
+ node.id = this.defaultId;
29
27
 
30
28
  if (typeof callback === 'function') {
31
29
  callback(node);
@@ -3,19 +3,19 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
9
+ import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
10
+ import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
11
+ import type { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
12
+ import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
13
+ import type { FieldMixinClass } from './field-mixin.js';
14
+ import type { InputConstraintsMixinClass } from './input-constraints-mixin.js';
15
+ import type { InputControlMixinClass } from './input-control-mixin.js';
16
+ import type { InputMixinClass } from './input-mixin.js';
17
+ import type { LabelMixinClass } from './label-mixin.js';
18
+ import type { ValidateMixinClass } from './validate-mixin.js';
19
19
 
20
20
  /**
21
21
  * A mixin to provide logic for vaadin-text-field and related components.
@@ -47,22 +47,6 @@ export const InputFieldMixin = (superclass) =>
47
47
  autocapitalize: {
48
48
  type: String,
49
49
  },
50
-
51
- /**
52
- * A pattern matched against individual characters the user inputs.
53
- * When set, the field will prevent:
54
- * - `keyDown` events if the entered key doesn't match `/^_enabledCharPattern$/`
55
- * - `paste` events if the pasted text doesn't match `/^_enabledCharPattern*$/`
56
- * - `drop` events if the dropped text doesn't match `/^_enabledCharPattern*$/`
57
- *
58
- * For example, to enable entering only numbers and minus signs,
59
- * `_enabledCharPattern = "[\\d-]"`
60
- * @protected
61
- */
62
- _enabledCharPattern: {
63
- type: String,
64
- observer: '_enabledCharPatternChanged',
65
- },
66
50
  };
67
51
  }
68
52
 
@@ -70,14 +54,6 @@ export const InputFieldMixin = (superclass) =>
70
54
  return [...super.delegateAttrs, 'autocapitalize', 'autocomplete', 'autocorrect'];
71
55
  }
72
56
 
73
- constructor() {
74
- super();
75
-
76
- this._boundOnPaste = this._onPaste.bind(this);
77
- this._boundOnDrop = this._onDrop.bind(this);
78
- this._boundOnBeforeInput = this._onBeforeInput.bind(this);
79
- }
80
-
81
57
  /**
82
58
  * @param {HTMLElement} input
83
59
  * @protected
@@ -149,97 +125,4 @@ export const InputFieldMixin = (superclass) =>
149
125
  this.validate();
150
126
  }
151
127
  }
152
-
153
- /**
154
- * Override a method from `InputMixin`.
155
- * @param {!HTMLElement} input
156
- * @protected
157
- * @override
158
- */
159
- _addInputListeners(input) {
160
- super._addInputListeners(input);
161
-
162
- input.addEventListener('paste', this._boundOnPaste);
163
- input.addEventListener('drop', this._boundOnDrop);
164
- input.addEventListener('beforeinput', this._boundOnBeforeInput);
165
- }
166
-
167
- /**
168
- * Override a method from `InputMixin`.
169
- * @param {!HTMLElement} input
170
- * @protected
171
- * @override
172
- */
173
- _removeInputListeners(input) {
174
- super._removeInputListeners(input);
175
-
176
- input.removeEventListener('paste', this._boundOnPaste);
177
- input.removeEventListener('drop', this._boundOnDrop);
178
- input.removeEventListener('beforeinput', this._boundOnBeforeInput);
179
- }
180
-
181
- /**
182
- * Override an event listener from `InputControlMixin`
183
- * to avoid adding a separate listener.
184
- * @param {!KeyboardEvent} event
185
- * @protected
186
- * @override
187
- */
188
- _onKeyDown(event) {
189
- if (this._enabledCharPattern && !this.__shouldAcceptKey(event)) {
190
- event.preventDefault();
191
- }
192
-
193
- super._onKeyDown(event);
194
- }
195
-
196
- /** @private */
197
- __shouldAcceptKey(event) {
198
- return (
199
- event.metaKey ||
200
- event.ctrlKey ||
201
- !event.key || // Allow typing anything if event.key is not supported
202
- event.key.length !== 1 || // Allow "Backspace", "ArrowLeft" etc.
203
- this.__enabledCharRegExp.test(event.key)
204
- );
205
- }
206
-
207
- /** @private */
208
- _onPaste(e) {
209
- if (this._enabledCharPattern) {
210
- const pastedText = (e.clipboardData || window.clipboardData).getData('text');
211
- if (!this.__enabledTextRegExp.test(pastedText)) {
212
- e.preventDefault();
213
- }
214
- }
215
- }
216
-
217
- /** @private */
218
- _onDrop(e) {
219
- if (this._enabledCharPattern) {
220
- const draggedText = e.dataTransfer.getData('text');
221
- if (!this.__enabledTextRegExp.test(draggedText)) {
222
- e.preventDefault();
223
- }
224
- }
225
- }
226
-
227
- /** @private */
228
- _onBeforeInput(e) {
229
- // The `beforeinput` event covers all the cases for `_enabledCharPattern`: keyboard, pasting and dropping,
230
- // but it is still experimental technology so we can't rely on it. It's used here just as an additional check,
231
- // because it seems to be the only way to detect and prevent specific keys on mobile devices.
232
- // See https://github.com/vaadin/vaadin-text-field/issues/429
233
- if (this._enabledCharPattern && e.data && !this.__enabledTextRegExp.test(e.data)) {
234
- e.preventDefault();
235
- }
236
- }
237
-
238
- /** @private */
239
- _enabledCharPatternChanged(charPattern) {
240
- if (charPattern) {
241
- this.__enabledCharRegExp = new RegExp(`^${charPattern}$`);
242
- this.__enabledTextRegExp = new RegExp(`^${charPattern}*$`);
243
- }
244
- }
245
128
  };
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 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
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
7
 
8
8
  /**
9
9
  * A mixin to store the reference to an input element
@@ -3,8 +3,8 @@
3
3
  * Copyright (c) 2021 - 2022 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';
7
- import { LabelController } from './label-controller.js';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { LabelController } from './label-controller.js';
8
8
 
9
9
  /**
10
10
  * A mixin to provide label via corresponding property or named slot.
@@ -43,6 +43,12 @@ export const LabelMixin = dedupingMixin(
43
43
  super();
44
44
 
45
45
  this._labelController = new LabelController(this);
46
+ }
47
+
48
+ /** @protected */
49
+ ready() {
50
+ super.ready();
51
+
46
52
  this.addController(this._labelController);
47
53
  }
48
54
 
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { ReactiveController } from 'lit';
6
+ import type { ReactiveController } from 'lit';
7
7
 
8
8
  /**
9
9
  * A controller for linking a `<label>` element with an `<input>` element.
@@ -3,12 +3,12 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
9
+ import type { InputConstraintsMixinClass } from './input-constraints-mixin.js';
10
+ import type { InputMixinClass } from './input-mixin.js';
11
+ import type { ValidateMixinClass } from './validate-mixin.js';
12
12
 
13
13
  /**
14
14
  * A mixin to provide `pattern` and `preventInvalidInput` properties.
@@ -34,6 +34,7 @@ export declare class PatternMixinClass {
34
34
  * When set to true, user is prevented from typing a value that
35
35
  * conflicts with the given `pattern`.
36
36
  * @attr {boolean} prevent-invalid-input
37
+ * @deprecated Please use `allowedCharPattern` instead.
37
38
  */
38
39
  preventInvalidInput: boolean | null | undefined;
39
40
  }
@@ -29,9 +29,11 @@ export const PatternMixin = (superclass) =>
29
29
  * When set to true, user is prevented from typing a value that
30
30
  * conflicts with the given `pattern`.
31
31
  * @attr {boolean} prevent-invalid-input
32
+ * @deprecated Please use `allowedCharPattern` instead.
32
33
  */
33
34
  preventInvalidInput: {
34
35
  type: Boolean,
36
+ observer: '_preventInvalidInputChanged',
35
37
  },
36
38
  };
37
39
  }
@@ -68,4 +70,13 @@ export const PatternMixin = (superclass) =>
68
70
 
69
71
  super._onInput(event);
70
72
  }
73
+
74
+ /** @private */
75
+ _preventInvalidInputChanged(preventInvalidInput) {
76
+ if (preventInvalidInput) {
77
+ console.warn(
78
+ `WARNING: Since Vaadin 23.2, "preventInvalidInput" is deprecated. Please use "allowedCharPattern" instead.`,
79
+ );
80
+ }
81
+ }
71
82
  };
@@ -3,12 +3,12 @@
3
3
  * Copyright (c) 2021 - 2022 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';
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';
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
9
+ import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
10
+ import type { TabindexMixinClass } from '@vaadin/component-base/src/tabindex-mixin.js';
11
+ import type { DelegateFocusMixinClass } from './delegate-focus-mixin.js';
12
12
 
13
13
  /**
14
14
  * A mixin to forward focus to an element in the shadow DOM.
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 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
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
7
 
8
8
  /**
9
9
  * Mixin to insert styles into the outer scope to handle slotted components.
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { ReactiveController } from 'lit';
6
+ import type { ReactiveController } from 'lit';
7
7
 
8
8
  export class SlotTargetController implements ReactiveController {
9
9
  /**
@@ -41,7 +41,11 @@ export class SlotTargetController {
41
41
 
42
42
  // Ensure the content is up to date when host is connected
43
43
  // to handle e.g. mutating text content while disconnected.
44
- this.__checkAndCopyNodesToSlotTarget();
44
+ // Note, `hostConnected()` is called twice if the controller
45
+ // is initialized in `ready()` when using `ControllerMixin`.
46
+ if (!this.__copying) {
47
+ this.__checkAndCopyNodesToSlotTarget();
48
+ }
45
49
  }
46
50
 
47
51
  /**
@@ -3,6 +3,6 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd..
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { CSSResult } from 'lit';
6
+ import type { CSSResult } from 'lit';
7
7
 
8
8
  export const clearButton: CSSResult;
@@ -3,6 +3,6 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd..
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { CSSResult } from 'lit';
6
+ import type { CSSResult } from 'lit';
7
7
 
8
8
  export const fieldShared: CSSResult;
@@ -3,6 +3,6 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd..
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { CSSResult } from 'lit';
6
+ import type { CSSResult } from 'lit';
7
7
 
8
8
  export const inputFieldContainer: CSSResult;
@@ -3,6 +3,6 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd..
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { CSSResult } from 'lit';
6
+ import type { CSSResult } from 'lit';
7
7
 
8
8
  export const inputFieldShared: CSSResult;
@@ -25,10 +25,7 @@ export class TextAreaController extends SlotController {
25
25
  node.setAttribute('name', name);
26
26
  }
27
27
 
28
- // Ensure every instance has unique ID
29
- const uniqueId = (TextAreaController._uniqueTextAreaId = 1 + TextAreaController._uniqueTextAreaId || 0);
30
- host._textareaId = `${host.localName}-${uniqueId}`;
31
- node.id = host._textareaId;
28
+ node.id = this.defaultId;
32
29
 
33
30
  if (typeof callback === 'function') {
34
31
  callback(node);
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 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
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
7
 
8
8
  /**
9
9
  * A mixin to provide required state and validation logic.
@@ -30,4 +30,12 @@ export declare class ValidateMixinClass {
30
30
  * Returns true if the field value satisfies all constraints (if any).
31
31
  */
32
32
  checkValidity(): boolean;
33
+
34
+ /**
35
+ * Fired whenever the field is validated.
36
+ *
37
+ * @event validated
38
+ * @param {Object} detail
39
+ * @param {boolean} detail.valid the result of the validation.
40
+ */
33
41
  }
@@ -36,12 +36,17 @@ export const ValidateMixin = dedupingMixin(
36
36
  }
37
37
 
38
38
  /**
39
- * Returns true if field is valid, and sets `invalid` based on the field validity.
39
+ * Validates the field and sets the `invalid` property based on the result.
40
+ *
41
+ * The method fires a `validated` event with the result of the validation.
40
42
  *
41
43
  * @return {boolean} True if the value is valid.
42
44
  */
43
45
  validate() {
44
- return !(this.invalid = !this.checkValidity());
46
+ const isValid = this.checkValidity();
47
+ this._setInvalid(!isValid);
48
+ this.dispatchEvent(new CustomEvent('validated', { detail: { valid: isValid } }));
49
+ return isValid;
45
50
  }
46
51
 
47
52
  /**
@@ -52,5 +57,34 @@ export const ValidateMixin = dedupingMixin(
52
57
  checkValidity() {
53
58
  return !this.required || !!this.value;
54
59
  }
60
+
61
+ /**
62
+ * @param {boolean} invalid
63
+ * @protected
64
+ */
65
+ _setInvalid(invalid) {
66
+ if (this._shouldSetInvalid(invalid)) {
67
+ this.invalid = invalid;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Override this method to define whether the given `invalid` state should be set.
73
+ *
74
+ * @param {boolean} _invalid
75
+ * @return {boolean}
76
+ * @protected
77
+ */
78
+ _shouldSetInvalid(_invalid) {
79
+ return true;
80
+ }
81
+
82
+ /**
83
+ * Fired whenever the field is validated.
84
+ *
85
+ * @event validated
86
+ * @param {Object} detail
87
+ * @param {boolean} detail.valid the result of the validation.
88
+ */
55
89
  },
56
90
  );
@@ -3,7 +3,7 @@
3
3
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { ReactiveController } from 'lit';
6
+ import type { ReactiveController } from 'lit';
7
7
 
8
8
  /**
9
9
  * A controller which prevents the virtual keyboard from showing up on mobile devices