@vaadin/field-base 23.2.16 → 23.2.18
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/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +4 -4
- package/src/checked-mixin.d.ts +2 -2
- package/src/checked-mixin.js +2 -2
- package/src/delegate-focus-mixin.d.ts +48 -0
- package/src/delegate-focus-mixin.js +228 -0
- package/src/delegate-state-mixin.d.ts +20 -0
- package/src/delegate-state-mixin.js +125 -0
- package/src/error-controller.d.ts +8 -3
- package/src/error-controller.js +65 -53
- package/src/field-aria-controller.d.ts +1 -1
- package/src/field-aria-controller.js +11 -11
- package/src/field-mixin.d.ts +1 -1
- package/src/field-mixin.js +28 -24
- package/src/helper-controller.d.ts +5 -3
- package/src/helper-controller.js +147 -47
- package/src/input-constraints-mixin.d.ts +4 -2
- package/src/input-constraints-mixin.js +2 -2
- package/src/input-control-mixin.d.ts +3 -3
- package/src/input-control-mixin.js +4 -4
- package/src/input-controller.d.ts +1 -1
- package/src/input-controller.js +8 -5
- package/src/input-field-mixin.d.ts +3 -3
- package/src/input-field-mixin.js +10 -10
- package/src/input-mixin.d.ts +3 -5
- package/src/input-mixin.js +10 -26
- package/src/label-controller.d.ts +8 -3
- package/src/label-controller.js +149 -45
- package/src/label-mixin.d.ts +1 -1
- package/src/label-mixin.js +8 -13
- package/src/labelled-input-controller.d.ts +1 -1
- package/src/labelled-input-controller.js +2 -2
- package/src/pattern-mixin.d.ts +13 -3
- package/src/pattern-mixin.js +50 -2
- package/src/shadow-focus-mixin.d.ts +23 -0
- package/src/shadow-focus-mixin.js +97 -0
- package/src/slot-styles-mixin.d.ts +1 -1
- package/src/slot-styles-mixin.js +1 -1
- package/src/slot-target-controller.d.ts +31 -0
- package/src/slot-target-controller.js +123 -0
- package/src/styles/clear-button-styles.d.ts +1 -1
- package/src/styles/clear-button-styles.js +2 -2
- package/src/styles/field-shared-styles.d.ts +1 -1
- package/src/styles/field-shared-styles.js +1 -1
- package/src/styles/input-field-container-styles.d.ts +1 -1
- package/src/styles/input-field-container-styles.js +1 -1
- package/src/styles/input-field-shared-styles.d.ts +1 -1
- package/src/styles/input-field-shared-styles.js +1 -1
- package/src/text-area-controller.d.ts +1 -1
- package/src/text-area-controller.js +8 -5
- package/src/validate-mixin.d.ts +1 -1
- package/src/validate-mixin.js +1 -1
- package/src/virtual-keyboard-controller.d.ts +1 -1
- package/src/virtual-keyboard-controller.js +1 -1
package/src/error-controller.js
CHANGED
|
@@ -1,16 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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 {
|
|
6
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A controller that manages the error message node content.
|
|
10
10
|
*/
|
|
11
|
-
export class ErrorController extends
|
|
11
|
+
export class ErrorController extends SlotController {
|
|
12
12
|
constructor(host) {
|
|
13
|
-
super(
|
|
13
|
+
super(
|
|
14
|
+
host,
|
|
15
|
+
'error-message',
|
|
16
|
+
() => document.createElement('div'),
|
|
17
|
+
(_host, node) => {
|
|
18
|
+
this.__updateErrorId(node);
|
|
19
|
+
|
|
20
|
+
this.__updateHasError();
|
|
21
|
+
},
|
|
22
|
+
true,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* ID attribute value set on the error message element.
|
|
28
|
+
*
|
|
29
|
+
* @return {string}
|
|
30
|
+
*/
|
|
31
|
+
get errorId() {
|
|
32
|
+
return this.node && this.node.id;
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
/**
|
|
@@ -21,7 +40,7 @@ export class ErrorController extends SlotChildObserveController {
|
|
|
21
40
|
setErrorMessage(errorMessage) {
|
|
22
41
|
this.errorMessage = errorMessage;
|
|
23
42
|
|
|
24
|
-
this.
|
|
43
|
+
this.__updateHasError();
|
|
25
44
|
}
|
|
26
45
|
|
|
27
46
|
/**
|
|
@@ -32,33 +51,7 @@ export class ErrorController extends SlotChildObserveController {
|
|
|
32
51
|
setInvalid(invalid) {
|
|
33
52
|
this.invalid = invalid;
|
|
34
53
|
|
|
35
|
-
this.
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Override method inherited from `SlotController` to not run
|
|
40
|
-
* initializer on the custom slotted node unnecessarily.
|
|
41
|
-
*
|
|
42
|
-
* @param {Node} node
|
|
43
|
-
* @protected
|
|
44
|
-
* @override
|
|
45
|
-
*/
|
|
46
|
-
initAddedNode(node) {
|
|
47
|
-
if (node !== this.defaultNode) {
|
|
48
|
-
// There is no need to run `initNode`.
|
|
49
|
-
this.initCustomNode(node);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Override to initialize the newly added default error message.
|
|
55
|
-
*
|
|
56
|
-
* @param {Node} errorNode
|
|
57
|
-
* @protected
|
|
58
|
-
* @override
|
|
59
|
-
*/
|
|
60
|
-
initNode(errorNode) {
|
|
61
|
-
this.updateDefaultNode(errorNode);
|
|
54
|
+
this.__updateHasError();
|
|
62
55
|
}
|
|
63
56
|
|
|
64
57
|
/**
|
|
@@ -69,43 +62,53 @@ export class ErrorController extends SlotChildObserveController {
|
|
|
69
62
|
* @override
|
|
70
63
|
*/
|
|
71
64
|
initCustomNode(errorNode) {
|
|
65
|
+
this.__updateErrorId(errorNode);
|
|
66
|
+
|
|
72
67
|
// Save the custom error message content on the host.
|
|
73
68
|
if (errorNode.textContent && !this.errorMessage) {
|
|
74
69
|
this.errorMessage = errorNode.textContent.trim();
|
|
75
70
|
}
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
super.initCustomNode(errorNode);
|
|
72
|
+
this.__updateHasError();
|
|
79
73
|
}
|
|
80
74
|
|
|
81
75
|
/**
|
|
82
|
-
* Override
|
|
83
|
-
* to restore the default error message element.
|
|
76
|
+
* Override to cleanup error message node when it's removed.
|
|
84
77
|
*
|
|
78
|
+
* @param {Node} node
|
|
85
79
|
* @protected
|
|
86
80
|
* @override
|
|
87
81
|
*/
|
|
88
|
-
|
|
89
|
-
this.
|
|
82
|
+
teardownNode(node) {
|
|
83
|
+
let errorNode = this.getSlotChild();
|
|
84
|
+
|
|
85
|
+
// If custom error was removed, restore the default one.
|
|
86
|
+
if (!errorNode && node !== this.defaultNode) {
|
|
87
|
+
errorNode = this.attachDefaultNode();
|
|
88
|
+
|
|
89
|
+
// Run initializer to update default error message ID.
|
|
90
|
+
this.initNode(errorNode);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.__updateHasError();
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* Note: unlike with other controllers, this method is
|
|
97
|
-
* called for both default and custom error message.
|
|
98
|
-
*
|
|
99
|
-
* @param {Node | undefined} node
|
|
100
|
-
* @protected
|
|
101
|
-
* @override
|
|
97
|
+
* @param {string} error
|
|
98
|
+
* @private
|
|
102
99
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
100
|
+
__isNotEmpty(error) {
|
|
101
|
+
return Boolean(error && error.trim() !== '');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @private */
|
|
105
|
+
__updateHasError() {
|
|
106
|
+
const errorNode = this.node;
|
|
107
|
+
const hasError = Boolean(this.invalid && this.__isNotEmpty(this.errorMessage));
|
|
106
108
|
|
|
109
|
+
// Update both default and custom error message node.
|
|
107
110
|
if (errorNode) {
|
|
108
|
-
errorNode.textContent = hasError ? errorMessage : '';
|
|
111
|
+
errorNode.textContent = hasError ? this.errorMessage : '';
|
|
109
112
|
errorNode.hidden = !hasError;
|
|
110
113
|
|
|
111
114
|
// Role alert will make the error message announce immediately
|
|
@@ -117,7 +120,16 @@ export class ErrorController extends SlotChildObserveController {
|
|
|
117
120
|
}
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
this.host.toggleAttribute('has-error-message', hasError);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {HTMLElement} errorNode
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
__updateErrorId(errorNode) {
|
|
131
|
+
if (!errorNode.id) {
|
|
132
|
+
errorNode.id = this.defaultId;
|
|
133
|
+
}
|
|
122
134
|
}
|
|
123
135
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/component-base/src/dom-utils.js';
|
|
@@ -15,16 +15,6 @@ export class FieldAriaController {
|
|
|
15
15
|
this.__required = false;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* `true` if the target element is the host component itself, `false` otherwise.
|
|
20
|
-
*
|
|
21
|
-
* @return {boolean}
|
|
22
|
-
* @private
|
|
23
|
-
*/
|
|
24
|
-
get __isGroupField() {
|
|
25
|
-
return this.__target === this.host;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
18
|
/**
|
|
29
19
|
* Sets a target element to which ARIA attributes are added.
|
|
30
20
|
*
|
|
@@ -91,6 +81,16 @@ export class FieldAriaController {
|
|
|
91
81
|
this.__helperId = helperId;
|
|
92
82
|
}
|
|
93
83
|
|
|
84
|
+
/**
|
|
85
|
+
* `true` if the target element is the host component itself, `false` otherwise.
|
|
86
|
+
*
|
|
87
|
+
* @return {boolean}
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
get __isGroupField() {
|
|
91
|
+
return this.__target === this.host;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
94
|
/**
|
|
95
95
|
* @param {string | null | undefined} labelId
|
|
96
96
|
* @param {string | null | undefined} oldLabelId
|
package/src/field-mixin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
package/src/field-mixin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
@@ -56,27 +56,9 @@ export const FieldMixin = (superclass) =>
|
|
|
56
56
|
return ['_invalidChanged(invalid)', '_requiredChanged(required)'];
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this._fieldAriaController = new FieldAriaController(this);
|
|
63
|
-
this._helperController = new HelperController(this);
|
|
64
|
-
this._errorController = new ErrorController(this);
|
|
65
|
-
|
|
66
|
-
this._errorController.addEventListener('slot-content-changed', (event) => {
|
|
67
|
-
this.toggleAttribute('has-error-message', event.detail.hasContent);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
this._labelController.addEventListener('slot-content-changed', (event) => {
|
|
71
|
-
const { hasContent, node } = event.detail;
|
|
72
|
-
this.__labelChanged(hasContent, node);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
this._helperController.addEventListener('slot-content-changed', (event) => {
|
|
76
|
-
const { hasContent, node } = event.detail;
|
|
77
|
-
this.toggleAttribute('has-helper', hasContent);
|
|
78
|
-
this.__helperChanged(hasContent, node);
|
|
79
|
-
});
|
|
59
|
+
/** @protected */
|
|
60
|
+
get _errorId() {
|
|
61
|
+
return this._errorController.errorId;
|
|
80
62
|
}
|
|
81
63
|
|
|
82
64
|
/**
|
|
@@ -87,6 +69,11 @@ export const FieldMixin = (superclass) =>
|
|
|
87
69
|
return this._errorController.node;
|
|
88
70
|
}
|
|
89
71
|
|
|
72
|
+
/** @protected */
|
|
73
|
+
get _helperId() {
|
|
74
|
+
return this._helperController.helperId;
|
|
75
|
+
}
|
|
76
|
+
|
|
90
77
|
/**
|
|
91
78
|
* @protected
|
|
92
79
|
* @return {HTMLElement}
|
|
@@ -95,6 +82,24 @@ export const FieldMixin = (superclass) =>
|
|
|
95
82
|
return this._helperController.node;
|
|
96
83
|
}
|
|
97
84
|
|
|
85
|
+
constructor() {
|
|
86
|
+
super();
|
|
87
|
+
|
|
88
|
+
this._fieldAriaController = new FieldAriaController(this);
|
|
89
|
+
this._helperController = new HelperController(this);
|
|
90
|
+
this._errorController = new ErrorController(this);
|
|
91
|
+
|
|
92
|
+
this._labelController.addEventListener('label-changed', (event) => {
|
|
93
|
+
const { hasLabel, node } = event.detail;
|
|
94
|
+
this.__labelChanged(hasLabel, node);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
this._helperController.addEventListener('helper-changed', (event) => {
|
|
98
|
+
const { hasHelper, node } = event.detail;
|
|
99
|
+
this.__helperChanged(hasHelper, node);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
98
103
|
/** @protected */
|
|
99
104
|
ready() {
|
|
100
105
|
super.ready();
|
|
@@ -173,8 +178,7 @@ export const FieldMixin = (superclass) =>
|
|
|
173
178
|
// Error message ID needs to be dynamically added / removed based on the validity
|
|
174
179
|
// Otherwise assistive technologies would announce the error, even if we hide it.
|
|
175
180
|
if (invalid) {
|
|
176
|
-
|
|
177
|
-
this._fieldAriaController.setErrorId(node && node.id);
|
|
181
|
+
this._fieldAriaController.setErrorId(this._errorController.errorId);
|
|
178
182
|
} else {
|
|
179
183
|
this._fieldAriaController.setErrorId(null);
|
|
180
184
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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 {
|
|
6
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A controller that manages the helper node content.
|
|
10
10
|
*/
|
|
11
|
-
export class HelperController extends
|
|
11
|
+
export class HelperController extends SlotController {
|
|
12
12
|
/**
|
|
13
13
|
* String used for the helper text.
|
|
14
14
|
*/
|
|
15
15
|
helperText: string | null | undefined;
|
|
16
16
|
|
|
17
|
+
helperId: string;
|
|
18
|
+
|
|
17
19
|
/**
|
|
18
20
|
* Set helper text based on corresponding host property.
|
|
19
21
|
*/
|
package/src/helper-controller.js
CHANGED
|
@@ -1,89 +1,189 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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 {
|
|
6
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A controller that manages the helper node content.
|
|
10
10
|
*/
|
|
11
|
-
export class HelperController extends
|
|
11
|
+
export class HelperController extends SlotController {
|
|
12
12
|
constructor(host) {
|
|
13
|
-
// Do not provide
|
|
14
|
-
super(host, 'helper', null);
|
|
13
|
+
// Do not provide slot factory, as only create helper lazily.
|
|
14
|
+
super(host, 'helper', null, null, true);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get helperId() {
|
|
18
|
+
return this.node && this.node.id;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
|
-
*
|
|
22
|
+
* Override to initialize the newly added custom helper.
|
|
23
|
+
*
|
|
24
|
+
* @param {Node} helperNode
|
|
25
|
+
* @protected
|
|
26
|
+
* @override
|
|
27
|
+
*/
|
|
28
|
+
initCustomNode(helperNode) {
|
|
29
|
+
this.__updateHelperId(helperNode);
|
|
30
|
+
|
|
31
|
+
this.__observeHelper(helperNode);
|
|
32
|
+
|
|
33
|
+
const hasHelper = this.__hasHelper(helperNode);
|
|
34
|
+
this.__toggleHasHelper(hasHelper);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Override to cleanup helper node when it's removed.
|
|
19
39
|
*
|
|
40
|
+
* @param {Node} _node
|
|
41
|
+
* @protected
|
|
42
|
+
* @override
|
|
43
|
+
*/
|
|
44
|
+
teardownNode(_node) {
|
|
45
|
+
// The observer does not exist when the default helper is removed.
|
|
46
|
+
if (this.__helperIdObserver) {
|
|
47
|
+
this.__helperIdObserver.disconnect();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const helperNode = this.getSlotChild();
|
|
51
|
+
|
|
52
|
+
// Custom node is added to helper slot
|
|
53
|
+
if (helperNode && helperNode !== this.defaultNode) {
|
|
54
|
+
const hasHelper = this.__hasHelper(helperNode);
|
|
55
|
+
this.__toggleHasHelper(hasHelper);
|
|
56
|
+
} else {
|
|
57
|
+
// Restore default helper if needed
|
|
58
|
+
this.__applyDefaultHelper(this.helperText, helperNode);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Set helper text based on corresponding host property.
|
|
20
64
|
* @param {string} helperText
|
|
21
65
|
*/
|
|
22
66
|
setHelperText(helperText) {
|
|
23
67
|
this.helperText = helperText;
|
|
24
68
|
|
|
25
|
-
// Restore the default helper, if needed.
|
|
26
69
|
const helperNode = this.getSlotChild();
|
|
27
|
-
if (!helperNode) {
|
|
28
|
-
this.
|
|
70
|
+
if (!helperNode || helperNode === this.defaultNode) {
|
|
71
|
+
this.__applyDefaultHelper(helperText, helperNode);
|
|
29
72
|
}
|
|
73
|
+
}
|
|
30
74
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
75
|
+
/**
|
|
76
|
+
* @param {HTMLElement} helperNode
|
|
77
|
+
* @return {boolean}
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
__hasHelper(helperNode) {
|
|
81
|
+
if (!helperNode) {
|
|
82
|
+
return false;
|
|
34
83
|
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
helperNode.children.length > 0 ||
|
|
87
|
+
(helperNode.nodeType === Node.ELEMENT_NODE && customElements.get(helperNode.localName)) ||
|
|
88
|
+
this.__isNotEmpty(helperNode.textContent)
|
|
89
|
+
);
|
|
35
90
|
}
|
|
36
91
|
|
|
37
92
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
93
|
+
* @param {string} helperText
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
__isNotEmpty(helperText) {
|
|
97
|
+
return helperText && helperText.trim() !== '';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} helperText
|
|
102
|
+
* @param {Node} helperNode
|
|
103
|
+
* @private
|
|
44
104
|
*/
|
|
45
|
-
|
|
46
|
-
const
|
|
105
|
+
__applyDefaultHelper(helperText, helperNode) {
|
|
106
|
+
const hasHelperText = this.__isNotEmpty(helperText);
|
|
47
107
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.
|
|
108
|
+
if (hasHelperText && !helperNode) {
|
|
109
|
+
// Set slot factory lazily to only create helper node when needed.
|
|
110
|
+
this.slotFactory = () => document.createElement('div');
|
|
51
111
|
|
|
52
|
-
|
|
112
|
+
helperNode = this.attachDefaultNode();
|
|
53
113
|
|
|
54
|
-
|
|
55
|
-
this.
|
|
114
|
+
this.__updateHelperId(helperNode);
|
|
115
|
+
this.__observeHelper(helperNode);
|
|
56
116
|
}
|
|
117
|
+
|
|
118
|
+
if (helperNode) {
|
|
119
|
+
helperNode.textContent = helperText;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.__toggleHasHelper(hasHelperText);
|
|
57
123
|
}
|
|
58
124
|
|
|
59
125
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* @param {Node | undefined} node
|
|
64
|
-
* @protected
|
|
65
|
-
* @override
|
|
126
|
+
* @param {HTMLElement} helperNode
|
|
127
|
+
* @private
|
|
66
128
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
129
|
+
__observeHelper(helperNode) {
|
|
130
|
+
this.__helperObserver = new MutationObserver((mutations) => {
|
|
131
|
+
mutations.forEach((mutation) => {
|
|
132
|
+
const target = mutation.target;
|
|
71
133
|
|
|
72
|
-
|
|
73
|
-
|
|
134
|
+
// Ensure the mutation target is the currently connected helper
|
|
135
|
+
// to ignore async mutations dispatched for removed element.
|
|
136
|
+
const isHelperMutation = target === this.node;
|
|
137
|
+
|
|
138
|
+
if (mutation.type === 'attributes') {
|
|
139
|
+
// We use attributeFilter to only observe ID mutation,
|
|
140
|
+
// no need to check for attribute name separately.
|
|
141
|
+
if (isHelperMutation && target.id !== this.defaultId) {
|
|
142
|
+
this.__updateHelperId(target);
|
|
143
|
+
}
|
|
144
|
+
} else if (isHelperMutation || target.parentElement === this.node) {
|
|
145
|
+
// Update has-helper when textContent changes
|
|
146
|
+
const hasHelper = this.__hasHelper(this.node);
|
|
147
|
+
this.__toggleHasHelper(hasHelper);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Observe changes to helper ID attribute, text content and children.
|
|
153
|
+
this.__helperObserver.observe(helperNode, {
|
|
154
|
+
attributes: true,
|
|
155
|
+
attributeFilter: ['id'],
|
|
156
|
+
childList: true,
|
|
157
|
+
subtree: true,
|
|
158
|
+
characterData: true,
|
|
159
|
+
});
|
|
74
160
|
}
|
|
75
161
|
|
|
76
162
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* @param {Node} node
|
|
80
|
-
* @protected
|
|
81
|
-
* @override
|
|
163
|
+
* @param {boolean} hasHelper
|
|
164
|
+
* @private
|
|
82
165
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
166
|
+
__toggleHasHelper(hasHelper) {
|
|
167
|
+
this.host.toggleAttribute('has-helper', hasHelper);
|
|
168
|
+
|
|
169
|
+
// Make it possible for other mixins to observe change
|
|
170
|
+
this.dispatchEvent(
|
|
171
|
+
new CustomEvent('helper-changed', {
|
|
172
|
+
detail: {
|
|
173
|
+
hasHelper,
|
|
174
|
+
node: this.node,
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
);
|
|
178
|
+
}
|
|
86
179
|
|
|
87
|
-
|
|
180
|
+
/**
|
|
181
|
+
* @param {HTMLElement} helperNode
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
__updateHelperId(helperNode) {
|
|
185
|
+
if (!helperNode.id) {
|
|
186
|
+
helperNode.id = this.defaultId;
|
|
187
|
+
}
|
|
88
188
|
}
|
|
89
189
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
-
import type {
|
|
7
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
8
|
+
import type { DelegateStateMixinClass } from './delegate-state-mixin.js';
|
|
8
9
|
import type { InputMixinClass } from './input-mixin.js';
|
|
9
10
|
import type { ValidateMixinClass } from './validate-mixin.js';
|
|
10
11
|
|
|
@@ -14,6 +15,7 @@ import type { ValidateMixinClass } from './validate-mixin.js';
|
|
|
14
15
|
export declare function InputConstraintsMixin<T extends Constructor<HTMLElement>>(
|
|
15
16
|
base: T,
|
|
16
17
|
): Constructor<DelegateStateMixinClass> &
|
|
18
|
+
Constructor<DisabledMixinClass> &
|
|
17
19
|
Constructor<InputConstraintsMixinClass> &
|
|
18
20
|
Constructor<InputMixinClass> &
|
|
19
21
|
Constructor<ValidateMixinClass> &
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
-
import { DelegateStateMixin } from '
|
|
7
|
+
import { DelegateStateMixin } from './delegate-state-mixin.js';
|
|
8
8
|
import { InputMixin } from './input-mixin.js';
|
|
9
9
|
import { ValidateMixin } from './validate-mixin.js';
|
|
10
10
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
7
|
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
8
|
-
import type { DelegateFocusMixinClass } from '@vaadin/component-base/src/delegate-focus-mixin.js';
|
|
9
|
-
import type { DelegateStateMixinClass } from '@vaadin/component-base/src/delegate-state-mixin.js';
|
|
10
8
|
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
11
9
|
import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
12
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
13
|
import type { FieldMixinClass } from './field-mixin.js';
|
|
14
14
|
import type { InputConstraintsMixinClass } from './input-constraints-mixin.js';
|
|
15
15
|
import type { InputMixinClass } from './input-mixin.js';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
7
7
|
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
8
|
-
import { DelegateFocusMixin } from '@vaadin/component-base/src/delegate-focus-mixin.js';
|
|
9
8
|
import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
9
|
+
import { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
10
10
|
import { FieldMixin } from './field-mixin.js';
|
|
11
11
|
import { InputConstraintsMixin } from './input-constraints-mixin.js';
|
|
12
12
|
import { SlotStylesMixin } from './slot-styles-mixin.js';
|
|
@@ -315,8 +315,8 @@ export const InputControlMixin = (superclass) =>
|
|
|
315
315
|
_allowedCharPatternChanged(charPattern) {
|
|
316
316
|
if (charPattern) {
|
|
317
317
|
try {
|
|
318
|
-
this.__allowedCharRegExp = new RegExp(`^${charPattern}
|
|
319
|
-
this.__allowedTextRegExp = new RegExp(`^${charPattern}
|
|
318
|
+
this.__allowedCharRegExp = new RegExp(`^${charPattern}$`);
|
|
319
|
+
this.__allowedTextRegExp = new RegExp(`^${charPattern}*$`);
|
|
320
320
|
} catch (e) {
|
|
321
321
|
console.error(e);
|
|
322
322
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2021 -
|
|
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
6
|
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|