@vaadin/component-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/custom_typings/vaadin-usage-statistics.d.ts +2 -2
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +3 -3
- package/src/a11y-announcer.d.ts +1 -1
- package/src/a11y-announcer.js +1 -1
- package/src/active-mixin.d.ts +1 -1
- package/src/active-mixin.js +1 -1
- package/src/async.d.ts +0 -3
- package/src/async.js +1 -2
- package/src/browser-utils.js +7 -7
- package/src/controller-mixin.d.ts +1 -1
- package/src/controller-mixin.js +1 -1
- package/src/debounce.js +2 -2
- package/src/dir-helper.d.ts +42 -0
- package/src/dir-helper.js +93 -0
- package/src/dir-mixin.d.ts +4 -2
- package/src/dir-mixin.js +39 -17
- package/src/disabled-mixin.d.ts +1 -1
- package/src/disabled-mixin.js +1 -1
- package/src/dom-utils.d.ts +1 -6
- package/src/dom-utils.js +1 -11
- package/src/element-mixin.d.ts +1 -1
- package/src/element-mixin.js +5 -11
- package/src/focus-mixin.d.ts +1 -1
- package/src/focus-mixin.js +2 -2
- package/src/focus-trap-controller.d.ts +1 -1
- package/src/focus-trap-controller.js +22 -22
- package/src/focus-utils.d.ts +1 -1
- package/src/focus-utils.js +57 -57
- package/src/gestures.d.ts +12 -6
- package/src/gestures.js +4 -6
- package/src/iron-list-core.js +11 -21
- package/src/keyboard-mixin.d.ts +1 -1
- package/src/keyboard-mixin.js +1 -1
- package/src/media-query-controller.d.ts +1 -1
- package/src/media-query-controller.js +1 -1
- package/src/overflow-controller.d.ts +1 -1
- package/src/overflow-controller.js +3 -3
- package/src/polylit-mixin.d.ts +3 -3
- package/src/polylit-mixin.js +4 -9
- package/src/resize-mixin.d.ts +1 -1
- package/src/resize-mixin.js +21 -11
- package/src/slot-controller.d.ts +5 -33
- package/src/slot-controller.js +40 -103
- package/src/slot-mixin.d.ts +18 -0
- package/src/slot-mixin.js +60 -0
- package/src/tabindex-mixin.d.ts +1 -1
- package/src/tabindex-mixin.js +1 -1
- package/src/templates.js +1 -1
- package/src/unique-id-utils.d.ts +1 -1
- package/src/unique-id-utils.js +1 -1
- package/src/virtualizer-iron-list-adapter.js +2 -6
- package/src/virtualizer.js +18 -18
- package/src/delegate-focus-mixin.d.ts +0 -48
- package/src/delegate-focus-mixin.js +0 -228
- package/src/delegate-state-mixin.d.ts +0 -20
- package/src/delegate-state-mixin.js +0 -125
- package/src/dir-utils.d.ts +0 -19
- package/src/dir-utils.js +0 -36
- package/src/keyboard-direction-mixin.d.ts +0 -41
- package/src/keyboard-direction-mixin.js +0 -192
- package/src/list-mixin.d.ts +0 -57
- package/src/list-mixin.js +0 -354
- package/src/overlay-class-mixin.d.ts +0 -33
- package/src/overlay-class-mixin.js +0 -79
- package/src/slot-child-observe-controller.d.ts +0 -28
- package/src/slot-child-observe-controller.js +0 -176
- package/src/tooltip-controller.d.ts +0 -86
- package/src/tooltip-controller.js +0 -130
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
-
import { FocusMixin } from './focus-mixin.js';
|
|
8
|
-
import { TabindexMixin } from './tabindex-mixin.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A mixin to forward focus to an element in the light DOM.
|
|
12
|
-
*
|
|
13
|
-
* @polymerMixin
|
|
14
|
-
* @mixes FocusMixin
|
|
15
|
-
* @mixes TabindexMixin
|
|
16
|
-
*/
|
|
17
|
-
export const DelegateFocusMixin = dedupingMixin(
|
|
18
|
-
(superclass) =>
|
|
19
|
-
class DelegateFocusMixinClass extends FocusMixin(TabindexMixin(superclass)) {
|
|
20
|
-
static get properties() {
|
|
21
|
-
return {
|
|
22
|
-
/**
|
|
23
|
-
* Specify that this control should have input focus when the page loads.
|
|
24
|
-
*/
|
|
25
|
-
autofocus: {
|
|
26
|
-
type: Boolean,
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* A reference to the focusable element controlled by the mixin.
|
|
31
|
-
* It can be an input, textarea, button or any element with tabindex > -1.
|
|
32
|
-
*
|
|
33
|
-
* Any component implementing this mixin is expected to provide it
|
|
34
|
-
* by using `this._setFocusElement(input)` Polymer API.
|
|
35
|
-
*
|
|
36
|
-
* Toggling `tabindex` attribute on the host element propagates its value to `focusElement`.
|
|
37
|
-
*
|
|
38
|
-
* @protected
|
|
39
|
-
* @type {!HTMLElement}
|
|
40
|
-
*/
|
|
41
|
-
focusElement: {
|
|
42
|
-
type: Object,
|
|
43
|
-
readOnly: true,
|
|
44
|
-
observer: '_focusElementChanged',
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Override the property from `TabIndexMixin`
|
|
49
|
-
* to ensure the `tabindex` attribute of the focus element
|
|
50
|
-
* will be restored to `0` after re-enabling the element.
|
|
51
|
-
*
|
|
52
|
-
* @protected
|
|
53
|
-
* @override
|
|
54
|
-
*/
|
|
55
|
-
_lastTabIndex: {
|
|
56
|
-
value: 0,
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
constructor() {
|
|
62
|
-
super();
|
|
63
|
-
|
|
64
|
-
this._boundOnBlur = this._onBlur.bind(this);
|
|
65
|
-
this._boundOnFocus = this._onFocus.bind(this);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** @protected */
|
|
69
|
-
ready() {
|
|
70
|
-
super.ready();
|
|
71
|
-
|
|
72
|
-
if (this.autofocus && !this.disabled) {
|
|
73
|
-
requestAnimationFrame(() => {
|
|
74
|
-
this.focus();
|
|
75
|
-
this.setAttribute('focus-ring', '');
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @protected
|
|
82
|
-
* @override
|
|
83
|
-
*/
|
|
84
|
-
focus() {
|
|
85
|
-
if (!this.focusElement || this.disabled) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.focusElement.focus();
|
|
90
|
-
this._setFocused(true);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @protected
|
|
95
|
-
* @override
|
|
96
|
-
*/
|
|
97
|
-
blur() {
|
|
98
|
-
if (!this.focusElement) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
this.focusElement.blur();
|
|
102
|
-
this._setFocused(false);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @protected
|
|
107
|
-
* @override
|
|
108
|
-
*/
|
|
109
|
-
click() {
|
|
110
|
-
if (this.focusElement && !this.disabled) {
|
|
111
|
-
this.focusElement.click();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** @protected */
|
|
116
|
-
_focusElementChanged(element, oldElement) {
|
|
117
|
-
if (element) {
|
|
118
|
-
element.disabled = this.disabled;
|
|
119
|
-
this._addFocusListeners(element);
|
|
120
|
-
this.__forwardTabIndex(this.tabindex);
|
|
121
|
-
} else if (oldElement) {
|
|
122
|
-
this._removeFocusListeners(oldElement);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @param {HTMLElement} element
|
|
128
|
-
* @protected
|
|
129
|
-
*/
|
|
130
|
-
_addFocusListeners(element) {
|
|
131
|
-
element.addEventListener('blur', this._boundOnBlur);
|
|
132
|
-
element.addEventListener('focus', this._boundOnFocus);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* @param {HTMLElement} element
|
|
137
|
-
* @protected
|
|
138
|
-
*/
|
|
139
|
-
_removeFocusListeners(element) {
|
|
140
|
-
element.removeEventListener('blur', this._boundOnBlur);
|
|
141
|
-
element.removeEventListener('focus', this._boundOnFocus);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Focus event does not bubble, so we dispatch it manually
|
|
146
|
-
* on the host element to support adding focus listeners
|
|
147
|
-
* when the focusable element is placed in light DOM.
|
|
148
|
-
* @param {FocusEvent} event
|
|
149
|
-
* @protected
|
|
150
|
-
*/
|
|
151
|
-
_onFocus(event) {
|
|
152
|
-
event.stopPropagation();
|
|
153
|
-
this.dispatchEvent(new Event('focus'));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Blur event does not bubble, so we dispatch it manually
|
|
158
|
-
* on the host element to support adding blur listeners
|
|
159
|
-
* when the focusable element is placed in light DOM.
|
|
160
|
-
* @param {FocusEvent} event
|
|
161
|
-
* @protected
|
|
162
|
-
*/
|
|
163
|
-
_onBlur(event) {
|
|
164
|
-
event.stopPropagation();
|
|
165
|
-
this.dispatchEvent(new Event('blur'));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @param {Event} event
|
|
170
|
-
* @return {boolean}
|
|
171
|
-
* @protected
|
|
172
|
-
* @override
|
|
173
|
-
*/
|
|
174
|
-
_shouldSetFocus(event) {
|
|
175
|
-
return event.target === this.focusElement;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* @param {boolean} disabled
|
|
180
|
-
* @param {boolean} oldDisabled
|
|
181
|
-
* @protected
|
|
182
|
-
* @override
|
|
183
|
-
*/
|
|
184
|
-
_disabledChanged(disabled, oldDisabled) {
|
|
185
|
-
super._disabledChanged(disabled, oldDisabled);
|
|
186
|
-
|
|
187
|
-
if (this.focusElement) {
|
|
188
|
-
this.focusElement.disabled = disabled;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (disabled) {
|
|
192
|
-
this.blur();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Override an observer from `TabindexMixin`.
|
|
198
|
-
* Do not call super to remove tabindex attribute
|
|
199
|
-
* from the host after it has been forwarded.
|
|
200
|
-
* @param {string} tabindex
|
|
201
|
-
* @protected
|
|
202
|
-
* @override
|
|
203
|
-
*/
|
|
204
|
-
_tabindexChanged(tabindex) {
|
|
205
|
-
this.__forwardTabIndex(tabindex);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** @private */
|
|
209
|
-
__forwardTabIndex(tabindex) {
|
|
210
|
-
if (tabindex !== undefined && this.focusElement) {
|
|
211
|
-
this.focusElement.tabIndex = tabindex;
|
|
212
|
-
|
|
213
|
-
// Preserve tabindex="-1" on the host element
|
|
214
|
-
if (tabindex !== -1) {
|
|
215
|
-
this.tabindex = undefined;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (this.disabled && tabindex) {
|
|
220
|
-
// If tabindex attribute was changed while component was disabled
|
|
221
|
-
if (tabindex !== -1) {
|
|
222
|
-
this._lastTabIndex = tabindex;
|
|
223
|
-
}
|
|
224
|
-
this.tabindex = undefined;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
);
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A mixin to delegate properties and attributes to a target element.
|
|
10
|
-
*/
|
|
11
|
-
export declare function DelegateStateMixin<T extends Constructor<HTMLElement>>(
|
|
12
|
-
base: T,
|
|
13
|
-
): Constructor<DelegateStateMixinClass> & T;
|
|
14
|
-
|
|
15
|
-
export declare class DelegateStateMixinClass {
|
|
16
|
-
/**
|
|
17
|
-
* A target element to which attributes and properties are delegated.
|
|
18
|
-
*/
|
|
19
|
-
stateTarget: HTMLElement | null;
|
|
20
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A mixin to delegate properties and attributes to a target element.
|
|
10
|
-
*
|
|
11
|
-
* @polymerMixin
|
|
12
|
-
*/
|
|
13
|
-
export const DelegateStateMixin = dedupingMixin(
|
|
14
|
-
(superclass) =>
|
|
15
|
-
class DelegateStateMixinClass extends superclass {
|
|
16
|
-
static get properties() {
|
|
17
|
-
return {
|
|
18
|
-
/**
|
|
19
|
-
* A target element to which attributes and properties are delegated.
|
|
20
|
-
* @protected
|
|
21
|
-
*/
|
|
22
|
-
stateTarget: {
|
|
23
|
-
type: Object,
|
|
24
|
-
observer: '_stateTargetChanged',
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* An array of the host attributes to delegate to the target element.
|
|
31
|
-
*/
|
|
32
|
-
static get delegateAttrs() {
|
|
33
|
-
return [];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* An array of the host properties to delegate to the target element.
|
|
38
|
-
*/
|
|
39
|
-
static get delegateProps() {
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** @protected */
|
|
44
|
-
ready() {
|
|
45
|
-
super.ready();
|
|
46
|
-
|
|
47
|
-
this._createDelegateAttrsObserver();
|
|
48
|
-
this._createDelegatePropsObserver();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** @protected */
|
|
52
|
-
_stateTargetChanged(target) {
|
|
53
|
-
if (target) {
|
|
54
|
-
this._ensureAttrsDelegated();
|
|
55
|
-
this._ensurePropsDelegated();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** @protected */
|
|
60
|
-
_createDelegateAttrsObserver() {
|
|
61
|
-
this._createMethodObserver(`_delegateAttrsChanged(${this.constructor.delegateAttrs.join(', ')})`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** @protected */
|
|
65
|
-
_createDelegatePropsObserver() {
|
|
66
|
-
this._createMethodObserver(`_delegatePropsChanged(${this.constructor.delegateProps.join(', ')})`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** @protected */
|
|
70
|
-
_ensureAttrsDelegated() {
|
|
71
|
-
this.constructor.delegateAttrs.forEach((name) => {
|
|
72
|
-
this._delegateAttribute(name, this[name]);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** @protected */
|
|
77
|
-
_ensurePropsDelegated() {
|
|
78
|
-
this.constructor.delegateProps.forEach((name) => {
|
|
79
|
-
this._delegateProperty(name, this[name]);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** @protected */
|
|
84
|
-
_delegateAttrsChanged(...values) {
|
|
85
|
-
this.constructor.delegateAttrs.forEach((name, index) => {
|
|
86
|
-
this._delegateAttribute(name, values[index]);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** @protected */
|
|
91
|
-
_delegatePropsChanged(...values) {
|
|
92
|
-
this.constructor.delegateProps.forEach((name, index) => {
|
|
93
|
-
this._delegateProperty(name, values[index]);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** @protected */
|
|
98
|
-
_delegateAttribute(name, value) {
|
|
99
|
-
if (!this.stateTarget) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (name === 'invalid') {
|
|
104
|
-
this._delegateAttribute('aria-invalid', value ? 'true' : false);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (typeof value === 'boolean') {
|
|
108
|
-
this.stateTarget.toggleAttribute(name, value);
|
|
109
|
-
} else if (value) {
|
|
110
|
-
this.stateTarget.setAttribute(name, value);
|
|
111
|
-
} else {
|
|
112
|
-
this.stateTarget.removeAttribute(name);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** @protected */
|
|
117
|
-
_delegateProperty(name, value) {
|
|
118
|
-
if (!this.stateTarget) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.stateTarget[name] = value;
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
);
|
package/src/dir-utils.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Get the scrollLeft value of the element relative to the direction
|
|
9
|
-
*/
|
|
10
|
-
export declare function getNormalizedScrollLeft(element: HTMLElement, direction: string | null): number;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Set the scrollLeft value of the element relative to the direction
|
|
14
|
-
*/
|
|
15
|
-
export declare function setNormalizedScrollLeft(
|
|
16
|
-
element: HTMLElement,
|
|
17
|
-
direction: string | null,
|
|
18
|
-
scrollLeft: number,
|
|
19
|
-
): void;
|
package/src/dir-utils.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Get the scrollLeft value of the element relative to the direction
|
|
9
|
-
*
|
|
10
|
-
* @param {HTMLElement} element
|
|
11
|
-
* @param {string} direction current direction of the element
|
|
12
|
-
* @return {number} the scrollLeft value.
|
|
13
|
-
*/
|
|
14
|
-
export function getNormalizedScrollLeft(element, direction) {
|
|
15
|
-
const { scrollLeft } = element;
|
|
16
|
-
if (direction !== 'rtl') {
|
|
17
|
-
return scrollLeft;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return element.scrollWidth - element.clientWidth + scrollLeft;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Set the scrollLeft value of the element relative to the direction
|
|
25
|
-
*
|
|
26
|
-
* @param {HTMLElement} element
|
|
27
|
-
* @param {string} direction current direction of the element
|
|
28
|
-
* @param {number} scrollLeft the scrollLeft value to be set
|
|
29
|
-
*/
|
|
30
|
-
export function setNormalizedScrollLeft(element, direction, scrollLeft) {
|
|
31
|
-
if (direction !== 'rtl') {
|
|
32
|
-
element.scrollLeft = scrollLeft;
|
|
33
|
-
} else {
|
|
34
|
-
element.scrollLeft = element.clientWidth - element.scrollWidth + scrollLeft;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2022 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
-
import type { KeyboardMixinClass } from './keyboard-mixin.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A mixin for navigating items with keyboard.
|
|
11
|
-
*/
|
|
12
|
-
export declare function KeyboardDirectionMixin<T extends Constructor<HTMLElement>>(
|
|
13
|
-
base: T,
|
|
14
|
-
): Constructor<KeyboardDirectionMixinClass> & Constructor<KeyboardMixinClass> & T;
|
|
15
|
-
|
|
16
|
-
export declare class KeyboardDirectionMixinClass {
|
|
17
|
-
protected readonly focused: Element | null;
|
|
18
|
-
|
|
19
|
-
protected readonly _vertical: boolean;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Returns index of the next item that satisfies the given condition,
|
|
23
|
-
* based on the index of the current item and a numeric increment.
|
|
24
|
-
*/
|
|
25
|
-
protected _getAvailableIndex(
|
|
26
|
-
items: Element[],
|
|
27
|
-
index: number,
|
|
28
|
-
increment: number,
|
|
29
|
-
condition: (item: Element) => boolean,
|
|
30
|
-
): number;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Focus the item at given index. Override this method to add custom logic.
|
|
34
|
-
*/
|
|
35
|
-
protected _focus(index: number, navigating: boolean): void;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Focus the given item. Override this method to add custom logic.
|
|
39
|
-
*/
|
|
40
|
-
protected _focusItem(item: Element, navigating: boolean): void;
|
|
41
|
-
}
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2022 - 2023 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { isElementFocused, isElementHidden } from './focus-utils.js';
|
|
7
|
-
import { KeyboardMixin } from './keyboard-mixin.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A mixin for navigating items with keyboard.
|
|
11
|
-
*
|
|
12
|
-
* @polymerMixin
|
|
13
|
-
* @mixes KeyboardMixin
|
|
14
|
-
*/
|
|
15
|
-
export const KeyboardDirectionMixin = (superclass) =>
|
|
16
|
-
class KeyboardDirectionMixinClass extends KeyboardMixin(superclass) {
|
|
17
|
-
/**
|
|
18
|
-
* @return {Element | null}
|
|
19
|
-
* @protected
|
|
20
|
-
*/
|
|
21
|
-
get focused() {
|
|
22
|
-
return (this._getItems() || []).find(isElementFocused);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @return {boolean}
|
|
27
|
-
* @protected
|
|
28
|
-
*/
|
|
29
|
-
get _vertical() {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** @protected */
|
|
34
|
-
focus() {
|
|
35
|
-
const items = this._getItems();
|
|
36
|
-
if (Array.isArray(items)) {
|
|
37
|
-
const idx = this._getAvailableIndex(items, 0, null, (item) => !isElementHidden(item));
|
|
38
|
-
if (idx >= 0) {
|
|
39
|
-
items[idx].focus();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Get the list of items participating in keyboard navigation.
|
|
46
|
-
* By default, it treats all the light DOM children as items.
|
|
47
|
-
* Override this method to provide custom list of elements.
|
|
48
|
-
*
|
|
49
|
-
* @return {Element[]}
|
|
50
|
-
* @protected
|
|
51
|
-
*/
|
|
52
|
-
_getItems() {
|
|
53
|
-
return Array.from(this.children);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Override an event listener from `KeyboardMixin`.
|
|
58
|
-
*
|
|
59
|
-
* @param {!KeyboardEvent} event
|
|
60
|
-
* @protected
|
|
61
|
-
* @override
|
|
62
|
-
*/
|
|
63
|
-
_onKeyDown(event) {
|
|
64
|
-
super._onKeyDown(event);
|
|
65
|
-
|
|
66
|
-
if (event.metaKey || event.ctrlKey) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const { key } = event;
|
|
71
|
-
const items = this._getItems() || [];
|
|
72
|
-
const currentIdx = items.indexOf(this.focused);
|
|
73
|
-
|
|
74
|
-
let idx;
|
|
75
|
-
let increment;
|
|
76
|
-
|
|
77
|
-
const isRTL = !this._vertical && this.getAttribute('dir') === 'rtl';
|
|
78
|
-
const dirIncrement = isRTL ? -1 : 1;
|
|
79
|
-
|
|
80
|
-
if (this.__isPrevKey(key)) {
|
|
81
|
-
increment = -dirIncrement;
|
|
82
|
-
idx = currentIdx - dirIncrement;
|
|
83
|
-
} else if (this.__isNextKey(key)) {
|
|
84
|
-
increment = dirIncrement;
|
|
85
|
-
idx = currentIdx + dirIncrement;
|
|
86
|
-
} else if (key === 'Home') {
|
|
87
|
-
increment = 1;
|
|
88
|
-
idx = 0;
|
|
89
|
-
} else if (key === 'End') {
|
|
90
|
-
increment = -1;
|
|
91
|
-
idx = items.length - 1;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
idx = this._getAvailableIndex(items, idx, increment, (item) => !isElementHidden(item));
|
|
95
|
-
|
|
96
|
-
if (idx >= 0) {
|
|
97
|
-
event.preventDefault();
|
|
98
|
-
this._focus(idx, true);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @param {string} key
|
|
104
|
-
* @return {boolean}
|
|
105
|
-
* @private
|
|
106
|
-
*/
|
|
107
|
-
__isPrevKey(key) {
|
|
108
|
-
return this._vertical ? key === 'ArrowUp' : key === 'ArrowLeft';
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @param {string} key
|
|
113
|
-
* @return {boolean}
|
|
114
|
-
* @private
|
|
115
|
-
*/
|
|
116
|
-
__isNextKey(key) {
|
|
117
|
-
return this._vertical ? key === 'ArrowDown' : key === 'ArrowRight';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Focus the item at given index. Override this method to add custom logic.
|
|
122
|
-
*
|
|
123
|
-
* @param {number} index
|
|
124
|
-
* @param {boolean} navigating
|
|
125
|
-
* @protected
|
|
126
|
-
*/
|
|
127
|
-
_focus(index, navigating = false) {
|
|
128
|
-
const items = this._getItems();
|
|
129
|
-
|
|
130
|
-
this._focusItem(items[index], navigating);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Focus the given item. Override this method to add custom logic.
|
|
135
|
-
*
|
|
136
|
-
* @param {Element} item
|
|
137
|
-
* @param {boolean} navigating
|
|
138
|
-
* @protected
|
|
139
|
-
*/
|
|
140
|
-
_focusItem(item) {
|
|
141
|
-
if (item) {
|
|
142
|
-
item.focus();
|
|
143
|
-
|
|
144
|
-
// Generally, the items are expected to implement `FocusMixin`
|
|
145
|
-
// that would set this attribute based on the `keydown` event.
|
|
146
|
-
// We set it manually to handle programmatic focus() calls.
|
|
147
|
-
item.setAttribute('focus-ring', '');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Returns index of the next item that satisfies the given condition,
|
|
153
|
-
* based on the index of the current item and a numeric increment.
|
|
154
|
-
*
|
|
155
|
-
* @param {Element[]} items - array of items to iterate over
|
|
156
|
-
* @param {number} index - index of the current item
|
|
157
|
-
* @param {number} increment - numeric increment, can be either 1 or -1
|
|
158
|
-
* @param {Function} condition - function used to check the item
|
|
159
|
-
* @return {number}
|
|
160
|
-
* @protected
|
|
161
|
-
*/
|
|
162
|
-
_getAvailableIndex(items, index, increment, condition) {
|
|
163
|
-
const totalItems = items.length;
|
|
164
|
-
let idx = index;
|
|
165
|
-
for (let i = 0; typeof idx === 'number' && i < totalItems; i += 1, idx += increment || 1) {
|
|
166
|
-
if (idx < 0) {
|
|
167
|
-
idx = totalItems - 1;
|
|
168
|
-
} else if (idx >= totalItems) {
|
|
169
|
-
idx = 0;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const item = items[idx];
|
|
173
|
-
|
|
174
|
-
if (!item.hasAttribute('disabled') && this.__isMatchingItem(item, condition)) {
|
|
175
|
-
return idx;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return -1;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Returns true if the item matches condition.
|
|
183
|
-
*
|
|
184
|
-
* @param {Element} item - item to check
|
|
185
|
-
* @param {Function} condition - function used to check the item
|
|
186
|
-
* @return {number}
|
|
187
|
-
* @private
|
|
188
|
-
*/
|
|
189
|
-
__isMatchingItem(item, condition) {
|
|
190
|
-
return typeof condition === 'function' ? condition(item) : true;
|
|
191
|
-
}
|
|
192
|
-
};
|