@vaadin/field-base 22.0.0-alpha9 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/package.json +5 -4
- package/src/checked-mixin.d.ts +18 -10
- package/src/delegate-focus-mixin.d.ts +20 -11
- package/src/delegate-state-mixin.d.ts +5 -8
- package/src/field-aria-controller.d.ts +56 -0
- package/src/field-aria-controller.js +175 -0
- package/src/field-mixin.d.ts +30 -12
- package/src/field-mixin.js +101 -39
- package/src/input-constraints-mixin.d.ts +13 -12
- package/src/input-control-mixin.d.ts +29 -12
- package/src/input-control-mixin.js +1 -1
- package/src/input-field-mixin.d.ts +30 -9
- package/src/input-mixin.d.ts +22 -9
- package/src/label-mixin.d.ts +12 -9
- package/src/label-mixin.js +1 -1
- package/src/{aria-label-controller.d.ts → labelled-input-controller.d.ts} +2 -2
- package/src/{aria-label-controller.js → labelled-input-controller.js} +2 -16
- package/src/pattern-mixin.d.ts +16 -9
- package/src/pattern-mixin.js +1 -1
- package/src/shadow-focus-mixin.d.ts +14 -12
- package/src/slot-label-mixin.d.ts +6 -11
- package/src/slot-styles-mixin.d.ts +6 -9
- package/src/slot-target-mixin.d.ts +7 -14
- package/src/text-area-controller.js +1 -1
- package/src/validate-mixin.d.ts +3 -8
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# @vaadin/field-base
|
|
2
2
|
|
|
3
|
-
A set of mixins
|
|
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
|
|
3
|
+
"version": "22.0.0",
|
|
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
|
|
34
|
+
"@vaadin/component-base": "^22.0.0",
|
|
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.
|
|
39
|
+
"@vaadin/testing-helpers": "^0.3.2",
|
|
39
40
|
"sinon": "^9.2.1"
|
|
40
41
|
},
|
|
41
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "b668e9b1a975227fbe34beb70d1cd5b03dce2348"
|
|
42
43
|
}
|
package/src/checked-mixin.d.ts
CHANGED
|
@@ -3,19 +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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
export declare class CheckedMixinClass {
|
|
23
|
+
/**
|
|
24
|
+
* True if the element is checked.
|
|
25
|
+
*/
|
|
26
|
+
checked: boolean;
|
|
20
27
|
|
|
21
|
-
|
|
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 {
|
|
7
|
-
import {
|
|
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
|
|
13
|
+
export declare function DelegateFocusMixin<T extends Constructor<HTMLElement>>(
|
|
14
|
+
base: T
|
|
15
|
+
): T & Constructor<DelegateFocusMixinClass> & Constructor<DisabledMixinClass> & Constructor<FocusMixinClass>;
|
|
13
16
|
|
|
14
|
-
|
|
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:
|
|
32
|
-
|
|
30
|
+
readonly focusElement: HTMLElement | null | undefined;
|
|
31
|
+
|
|
32
|
+
protected _addFocusListeners(element: HTMLElement): void;
|
|
33
|
+
|
|
34
|
+
protected _removeFocusListeners(element: HTMLElement): void;
|
|
33
35
|
|
|
34
|
-
|
|
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
|
|
11
|
+
export declare function DelegateStateMixin<T extends Constructor<HTMLElement>>(
|
|
12
|
+
base: T
|
|
13
|
+
): T & Constructor<DelegateStateMixinClass>;
|
|
11
14
|
|
|
12
|
-
|
|
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
|
+
}
|
package/src/field-mixin.d.ts
CHANGED
|
@@ -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 {
|
|
7
|
-
import {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/src/field-mixin.js
CHANGED
|
@@ -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
|
/**
|
|
@@ -59,7 +62,6 @@ export const FieldMixin = (superclass) =>
|
|
|
59
62
|
'error-message': () => {
|
|
60
63
|
const error = document.createElement('div');
|
|
61
64
|
error.textContent = this.errorMessage;
|
|
62
|
-
error.setAttribute('aria-live', 'assertive');
|
|
63
65
|
return error;
|
|
64
66
|
}
|
|
65
67
|
};
|
|
@@ -67,27 +69,30 @@ export const FieldMixin = (superclass) =>
|
|
|
67
69
|
|
|
68
70
|
static get observers() {
|
|
69
71
|
return [
|
|
70
|
-
'__ariaChanged(invalid, _helperId)',
|
|
71
72
|
'__observeOffsetHeight(errorMessage, invalid, label, helperText)',
|
|
72
|
-
'_updateErrorMessage(invalid, errorMessage)'
|
|
73
|
+
'_updateErrorMessage(invalid, errorMessage)',
|
|
74
|
+
'_invalidChanged(invalid)',
|
|
75
|
+
'_requiredChanged(required)',
|
|
76
|
+
'_helperIdChanged(_helperId)'
|
|
73
77
|
];
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* @protected
|
|
82
|
+
* @return {HTMLElement}
|
|
83
|
+
*/
|
|
77
84
|
get _errorNode() {
|
|
78
85
|
return this._getDirectSlotChild('error-message');
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* @protected
|
|
90
|
+
* @return {HTMLElement}
|
|
91
|
+
*/
|
|
82
92
|
get _helperNode() {
|
|
83
93
|
return this._getDirectSlotChild('helper');
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
/** @protected */
|
|
87
|
-
get _ariaAttr() {
|
|
88
|
-
return 'aria-describedby';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
96
|
constructor() {
|
|
92
97
|
super();
|
|
93
98
|
|
|
@@ -98,6 +103,8 @@ export const FieldMixin = (superclass) =>
|
|
|
98
103
|
|
|
99
104
|
// Save generated ID to restore later
|
|
100
105
|
this.__savedHelperId = this._helperId;
|
|
106
|
+
|
|
107
|
+
this._fieldAriaController = new FieldAriaController(this);
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
/** @protected */
|
|
@@ -158,6 +165,8 @@ export const FieldMixin = (superclass) =>
|
|
|
158
165
|
this.__applyDefaultHelper(this.helperText);
|
|
159
166
|
}
|
|
160
167
|
});
|
|
168
|
+
|
|
169
|
+
this.addController(this._fieldAriaController);
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
/** @private */
|
|
@@ -169,14 +178,20 @@ export const FieldMixin = (superclass) =>
|
|
|
169
178
|
}
|
|
170
179
|
}
|
|
171
180
|
|
|
172
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* @param {HTMLElement} helper
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
173
185
|
__applyCustomHelper(helper) {
|
|
174
186
|
this.__updateHelperId(helper);
|
|
175
187
|
this._currentHelper = helper;
|
|
176
188
|
this.__toggleHasHelper(helper.children.length > 0 || this.__isNotEmpty(helper.textContent));
|
|
177
189
|
}
|
|
178
190
|
|
|
179
|
-
/**
|
|
191
|
+
/**
|
|
192
|
+
* @param {string} helperText
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
180
195
|
__isNotEmpty(helperText) {
|
|
181
196
|
return helperText && helperText.trim() !== '';
|
|
182
197
|
}
|
|
@@ -192,13 +207,17 @@ export const FieldMixin = (superclass) =>
|
|
|
192
207
|
}
|
|
193
208
|
|
|
194
209
|
helper.id = this.__savedHelperId;
|
|
210
|
+
this._helperId = helper.id;
|
|
195
211
|
this.appendChild(helper);
|
|
196
212
|
this._currentHelper = helper;
|
|
197
213
|
|
|
198
214
|
return helper;
|
|
199
215
|
}
|
|
200
216
|
|
|
201
|
-
/**
|
|
217
|
+
/**
|
|
218
|
+
* @param {string} helperText
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
202
221
|
__applyDefaultHelper(helperText) {
|
|
203
222
|
let helper = this._helperNode;
|
|
204
223
|
|
|
@@ -216,7 +235,10 @@ export const FieldMixin = (superclass) =>
|
|
|
216
235
|
this.__toggleHasHelper(hasHelperText);
|
|
217
236
|
}
|
|
218
237
|
|
|
219
|
-
/**
|
|
238
|
+
/**
|
|
239
|
+
* @param {boolean} hasHelper
|
|
240
|
+
* @private
|
|
241
|
+
*/
|
|
220
242
|
__toggleHasHelper(hasHelper) {
|
|
221
243
|
this.toggleAttribute('has-helper', hasHelper);
|
|
222
244
|
}
|
|
@@ -246,8 +268,25 @@ export const FieldMixin = (superclass) =>
|
|
|
246
268
|
);
|
|
247
269
|
}
|
|
248
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
|
+
|
|
249
287
|
/**
|
|
250
288
|
* @param {boolean} invalid
|
|
289
|
+
* @param {string | null | undefined} errorMessage
|
|
251
290
|
* @protected
|
|
252
291
|
*/
|
|
253
292
|
_updateErrorMessage(invalid, errorMessage) {
|
|
@@ -263,9 +302,20 @@ export const FieldMixin = (superclass) =>
|
|
|
263
302
|
const hasError = Boolean(invalid && errorMessage);
|
|
264
303
|
error.textContent = hasError ? errorMessage : '';
|
|
265
304
|
this.toggleAttribute('has-error-message', hasError);
|
|
305
|
+
|
|
306
|
+
// Role alert will make the error message announce immediately
|
|
307
|
+
// as the field becomes invalid
|
|
308
|
+
if (hasError) {
|
|
309
|
+
error.setAttribute('role', 'alert');
|
|
310
|
+
} else {
|
|
311
|
+
error.removeAttribute('role');
|
|
312
|
+
}
|
|
266
313
|
}
|
|
267
314
|
|
|
268
|
-
/**
|
|
315
|
+
/**
|
|
316
|
+
* @param {HTMLElement} customHelper
|
|
317
|
+
* @private
|
|
318
|
+
*/
|
|
269
319
|
__updateHelperId(customHelper) {
|
|
270
320
|
let newId;
|
|
271
321
|
|
|
@@ -279,39 +329,51 @@ export const FieldMixin = (superclass) =>
|
|
|
279
329
|
this._helperId = newId;
|
|
280
330
|
}
|
|
281
331
|
|
|
282
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* @param {string} helperText
|
|
334
|
+
* @protected
|
|
335
|
+
*/
|
|
283
336
|
_helperTextChanged(helperText) {
|
|
284
337
|
this.__applyDefaultHelper(helperText);
|
|
285
338
|
}
|
|
286
339
|
|
|
287
|
-
/**
|
|
340
|
+
/**
|
|
341
|
+
* @param {HTMLElement | null | undefined} target
|
|
342
|
+
* @protected
|
|
343
|
+
*/
|
|
288
344
|
_ariaTargetChanged(target) {
|
|
289
345
|
if (target) {
|
|
290
|
-
this.
|
|
346
|
+
this._fieldAriaController.setTarget(target);
|
|
291
347
|
}
|
|
292
348
|
}
|
|
293
349
|
|
|
294
|
-
/**
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const ariaIds = attr === 'aria-describedby' ? [helperId] : [this._labelId, helperId];
|
|
302
|
-
|
|
303
|
-
// Error message ID needs to be dynamically added / removed based on the validity
|
|
304
|
-
// Otherwise assistive technologies would announce the error, even if we hide it.
|
|
305
|
-
if (invalid) {
|
|
306
|
-
ariaIds.push(this._errorId);
|
|
307
|
-
}
|
|
350
|
+
/**
|
|
351
|
+
* @param {boolean} required
|
|
352
|
+
* @protected
|
|
353
|
+
*/
|
|
354
|
+
_requiredChanged(required) {
|
|
355
|
+
this._fieldAriaController.setRequired(required);
|
|
356
|
+
}
|
|
308
357
|
|
|
309
|
-
|
|
310
|
-
|
|
358
|
+
/**
|
|
359
|
+
* @param {string} helperId
|
|
360
|
+
* @protected
|
|
361
|
+
*/
|
|
362
|
+
_helperIdChanged(helperId) {
|
|
363
|
+
this._fieldAriaController.setHelperId(helperId);
|
|
311
364
|
}
|
|
312
365
|
|
|
313
|
-
/**
|
|
314
|
-
|
|
315
|
-
|
|
366
|
+
/**
|
|
367
|
+
* @param {boolean} required
|
|
368
|
+
* @protected
|
|
369
|
+
*/
|
|
370
|
+
_invalidChanged(invalid) {
|
|
371
|
+
// Error message ID needs to be dynamically added / removed based on the validity
|
|
372
|
+
// Otherwise assistive technologies would announce the error, even if we hide it.
|
|
373
|
+
if (invalid) {
|
|
374
|
+
this._fieldAriaController.setErrorId(this._errorId);
|
|
375
|
+
} else {
|
|
376
|
+
this._fieldAriaController.setErrorId(null);
|
|
377
|
+
}
|
|
316
378
|
}
|
|
317
379
|
};
|
|
@@ -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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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
|
|
15
|
+
export declare function InputConstraintsMixin<T extends Constructor<HTMLElement>>(
|
|
14
16
|
base: T
|
|
15
|
-
): T &
|
|
17
|
+
): T &
|
|
18
|
+
Constructor<DelegateStateMixinClass> &
|
|
19
|
+
Constructor<DisabledMixinClass> &
|
|
20
|
+
Constructor<InputConstraintsMixinClass> &
|
|
21
|
+
Constructor<InputMixinClass> &
|
|
22
|
+
Constructor<ValidateMixinClass>;
|
|
16
23
|
|
|
17
|
-
|
|
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,22 +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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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
|
|
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
|
-
|
|
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
|
*/
|
|
23
42
|
autoselect: boolean;
|
|
24
43
|
|
|
@@ -48,5 +67,3 @@ interface InputControlMixin extends KeyboardMixin, InputConstraintsMixin, FieldM
|
|
|
48
67
|
*/
|
|
49
68
|
title: string;
|
|
50
69
|
}
|
|
51
|
-
|
|
52
|
-
export { InputControlMixin, InputControlMixinConstructor };
|
|
@@ -24,7 +24,7 @@ export const InputControlMixin = (superclass) =>
|
|
|
24
24
|
static get properties() {
|
|
25
25
|
return {
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* If true, the input text gets fully selected when the field is focused using click or touch / tap.
|
|
28
28
|
*/
|
|
29
29
|
autoselect: {
|
|
30
30
|
type: Boolean,
|
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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 };
|
package/src/input-mixin.d.ts
CHANGED
|
@@ -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
|
|
12
|
+
export declare function InputMixin<T extends Constructor<HTMLElement>>(base: T): T & Constructor<InputMixinClass>;
|
|
12
13
|
|
|
13
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
+
}
|
package/src/label-mixin.d.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
12
|
+
export declare function LabelMixin<T extends Constructor<HTMLElement>>(
|
|
13
|
+
base: T
|
|
14
|
+
): T & Constructor<LabelMixinClass> & Constructor<SlotMixinClass>;
|
|
12
15
|
|
|
13
|
-
|
|
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
|
-
|
|
22
|
+
protected readonly _labelNode: HTMLLabelElement;
|
|
23
|
+
|
|
24
|
+
protected _labelChanged(label: string | null | undefined): void;
|
|
25
|
+
|
|
26
|
+
protected _toggleHasLabelAttribute(): void;
|
|
27
|
+
}
|
package/src/label-mixin.js
CHANGED
|
@@ -69,7 +69,7 @@ export const LabelMixin = dedupingMixin(
|
|
|
69
69
|
this._labelNode.id = this._labelId;
|
|
70
70
|
this._toggleHasLabelAttribute();
|
|
71
71
|
|
|
72
|
-
this.__labelNodeObserver.observe(this._labelNode, { childList: true });
|
|
72
|
+
this.__labelNodeObserver.observe(this._labelNode, { childList: true, subtree: true, characterData: true });
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
import { ReactiveController } from 'lit';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* A controller
|
|
9
|
+
* A controller for linking a `<label>` element with an `<input>` element.
|
|
10
10
|
*/
|
|
11
|
-
export class
|
|
11
|
+
export class LabelledInputController implements ReactiveController {}
|
|
@@ -5,36 +5,22 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* A controller
|
|
8
|
+
* A controller for linking a `<label>` element with an `<input>` element.
|
|
9
9
|
*/
|
|
10
|
-
export class
|
|
10
|
+
export class LabelledInputController {
|
|
11
11
|
constructor(input, label) {
|
|
12
12
|
this.input = input;
|
|
13
|
-
this.label = label;
|
|
14
13
|
this.__preventDuplicateLabelClick = this.__preventDuplicateLabelClick.bind(this);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
hostConnected() {
|
|
18
|
-
const label = this.label;
|
|
19
|
-
const input = this.input;
|
|
20
14
|
|
|
21
15
|
if (label) {
|
|
22
16
|
label.addEventListener('click', this.__preventDuplicateLabelClick);
|
|
23
17
|
|
|
24
18
|
if (input) {
|
|
25
|
-
input.setAttribute('aria-labelledby', label.id);
|
|
26
19
|
label.setAttribute('for', input.id);
|
|
27
20
|
}
|
|
28
21
|
}
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
hostDisconnected() {
|
|
32
|
-
const label = this.label;
|
|
33
|
-
if (label) {
|
|
34
|
-
label.removeEventListener('click', this.__preventDuplicateLabelClick);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
24
|
/**
|
|
39
25
|
* The native platform fires an event for both the click on the label, and also
|
|
40
26
|
* the subsequent click on the native input element caused by label click.
|
package/src/pattern-mixin.d.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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 };
|
package/src/pattern-mixin.js
CHANGED
|
@@ -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 {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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 {
|
|
7
|
-
import {
|
|
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
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
12
|
+
export declare function SlotStylesMixin<T extends Constructor<HTMLElement>>(
|
|
13
|
+
base: T
|
|
14
|
+
): T & Constructor<SlotStylesMixinClass>;
|
|
12
15
|
|
|
13
|
-
|
|
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
|
|
11
|
+
export declare function SlotTargetMixin<T extends Constructor<HTMLElement>>(
|
|
12
|
+
base: T
|
|
13
|
+
): T & Constructor<SlotTargetMixinClass>;
|
|
11
14
|
|
|
12
|
-
|
|
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 };
|
|
@@ -25,7 +25,7 @@ export class TextAreaController extends SlotController {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Ensure every instance has unique ID
|
|
28
|
-
const uniqueId = (TextAreaController._uniqueTextAreaId = 1 + TextAreaController.
|
|
28
|
+
const uniqueId = (TextAreaController._uniqueTextAreaId = 1 + TextAreaController._uniqueTextAreaId || 0);
|
|
29
29
|
host._textareaId = `${host.localName}-${uniqueId}`;
|
|
30
30
|
node.id = host._textareaId;
|
|
31
31
|
|
package/src/validate-mixin.d.ts
CHANGED
|
@@ -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
|
|
11
|
+
export declare function ValidateMixin<T extends Constructor<HTMLElement>>(base: T): T & Constructor<ValidateMixinClass>;
|
|
11
12
|
|
|
12
|
-
|
|
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 };
|