@vaadin/a11y-base 25.2.0-alpha9 → 25.2.0-beta2
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-elements.json +192 -11
- package/package.json +6 -6
- package/src/active-mixin.d.ts +1 -1
- package/src/active-mixin.js +0 -4
- package/src/announce.js +1 -1
- package/src/aria-hidden.js +1 -1
- package/src/aria-modal-controller.d.ts +2 -3
- package/src/delegate-focus-mixin.js +222 -223
- package/src/disabled-mixin.js +47 -48
- package/src/focus-mixin.js +83 -84
- package/src/keyboard-direction-mixin.js +1 -4
- package/src/keyboard-mixin.js +65 -66
- package/src/list-mixin.js +5 -38
- package/src/tabindex-mixin.js +0 -3
package/src/focus-mixin.js
CHANGED
|
@@ -8,101 +8,100 @@ import { isKeyboardActive } from './focus-utils.js';
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A mixin to handle `focused` and `focus-ring` attributes based on focus.
|
|
11
|
-
*
|
|
12
|
-
* @polymerMixin
|
|
13
11
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
12
|
+
const FocusMixinImplementation = (superclass) => {
|
|
13
|
+
return class FocusMixinClass extends superclass {
|
|
14
|
+
/**
|
|
15
|
+
* @protected
|
|
16
|
+
* @return {boolean}
|
|
17
|
+
*/
|
|
18
|
+
get _keyboardActive() {
|
|
19
|
+
return isKeyboardActive();
|
|
20
|
+
}
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
/** @protected */
|
|
23
|
+
ready() {
|
|
24
|
+
this.addEventListener('focusin', (e) => {
|
|
25
|
+
if (this._shouldSetFocus(e)) {
|
|
26
|
+
this._setFocused(true);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
this.addEventListener('focusout', (e) => {
|
|
31
|
+
if (this._shouldRemoveFocus(e)) {
|
|
32
|
+
this._setFocused(false);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
// In super.ready() other 'focusin' and 'focusout' listeners might be
|
|
37
|
+
// added, so we call it after our own ones to ensure they execute first.
|
|
38
|
+
// Issue to watch out: when incorrect, <vaadin-combo-box> refocuses the
|
|
39
|
+
// input field on iOS after "Done" is pressed.
|
|
40
|
+
super.ready();
|
|
41
|
+
}
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
/** @protected */
|
|
44
|
+
disconnectedCallback() {
|
|
45
|
+
super.disconnectedCallback();
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
47
|
+
// In non-Chrome browsers, blur does not fire on the element when it is disconnected.
|
|
48
|
+
// reproducible in `<vaadin-date-picker>` when closing on `Cancel` or `Today` click.
|
|
49
|
+
if (this.hasAttribute('focused')) {
|
|
50
|
+
this._setFocused(false);
|
|
55
51
|
}
|
|
52
|
+
}
|
|
56
53
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
/**
|
|
55
|
+
* @param {FocusOptions=} options
|
|
56
|
+
* @protected
|
|
57
|
+
* @override
|
|
58
|
+
*/
|
|
59
|
+
focus(options) {
|
|
60
|
+
super.focus(options);
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
62
|
+
// Set focus-ring attribute on programmatic focus by default
|
|
63
|
+
// unless explicitly disabled by `{ focusVisible: false }`.
|
|
64
|
+
if (options?.focusVisible !== false) {
|
|
65
|
+
this.setAttribute('focus-ring', '');
|
|
70
66
|
}
|
|
67
|
+
}
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Override to change how focused and focus-ring attributes are set.
|
|
71
|
+
*
|
|
72
|
+
* @param {boolean} focused
|
|
73
|
+
* @protected
|
|
74
|
+
*/
|
|
75
|
+
_setFocused(focused) {
|
|
76
|
+
this.toggleAttribute('focused', focused);
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
// Focus-ring is true when the element was focused from the keyboard.
|
|
79
|
+
// Focus Ring [A11ycasts]: https://youtu.be/ilj2P5-5CjI
|
|
80
|
+
this.toggleAttribute('focus-ring', focused && this._keyboardActive);
|
|
81
|
+
}
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Override to define if the field receives focus based on the event.
|
|
85
|
+
*
|
|
86
|
+
* @param {FocusEvent} _event
|
|
87
|
+
* @return {boolean}
|
|
88
|
+
* @protected
|
|
89
|
+
*/
|
|
90
|
+
_shouldSetFocus(_event) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Override to define if the field loses focus based on the event.
|
|
96
|
+
*
|
|
97
|
+
* @param {FocusEvent} _event
|
|
98
|
+
* @return {boolean}
|
|
99
|
+
* @protected
|
|
100
|
+
*/
|
|
101
|
+
_shouldRemoveFocus(_event) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const FocusMixin = dedupeMixin(FocusMixinImplementation);
|
|
@@ -8,9 +8,6 @@ import { KeyboardMixin } from './keyboard-mixin.js';
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A mixin for navigating items with keyboard.
|
|
11
|
-
*
|
|
12
|
-
* @polymerMixin
|
|
13
|
-
* @mixes KeyboardMixin
|
|
14
11
|
*/
|
|
15
12
|
export const KeyboardDirectionMixin = (superclass) =>
|
|
16
13
|
class KeyboardDirectionMixinClass extends KeyboardMixin(superclass) {
|
|
@@ -127,7 +124,7 @@ export const KeyboardDirectionMixin = (superclass) =>
|
|
|
127
124
|
|
|
128
125
|
if (idx >= 0) {
|
|
129
126
|
event.preventDefault();
|
|
130
|
-
this._focus(idx, { focusVisible: true }, true);
|
|
127
|
+
this._focus(idx, { focusVisible: true, preventScroll: true }, true);
|
|
131
128
|
}
|
|
132
129
|
}
|
|
133
130
|
|
package/src/keyboard-mixin.js
CHANGED
|
@@ -9,77 +9,76 @@ import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
|
9
9
|
* A mixin that manages keyboard handling.
|
|
10
10
|
* The mixin subscribes to the keyboard events while an actual implementation
|
|
11
11
|
* for the event handlers is left to the client (a component or another mixin).
|
|
12
|
-
*
|
|
13
|
-
* @polymerMixin
|
|
14
12
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ready()
|
|
20
|
-
super.ready();
|
|
13
|
+
const KeyboardMixinImplementation = (superclass) => {
|
|
14
|
+
return class KeyboardMixinClass extends superclass {
|
|
15
|
+
/** @protected */
|
|
16
|
+
ready() {
|
|
17
|
+
super.ready();
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
this.addEventListener('keydown', (event) => {
|
|
20
|
+
this._onKeyDown(event);
|
|
21
|
+
});
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
this.addEventListener('keyup', (event) => {
|
|
24
|
+
this._onKeyUp(event);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
28
|
+
/**
|
|
29
|
+
* A handler for the `keydown` event. By default, it calls
|
|
30
|
+
* separate methods for handling "Enter" and "Escape" keys.
|
|
31
|
+
* Override the method to implement your own behavior.
|
|
32
|
+
*
|
|
33
|
+
* @param {KeyboardEvent} event
|
|
34
|
+
* @protected
|
|
35
|
+
*/
|
|
36
|
+
_onKeyDown(event) {
|
|
37
|
+
switch (event.key) {
|
|
38
|
+
case 'Enter':
|
|
39
|
+
this._onEnter(event);
|
|
40
|
+
break;
|
|
41
|
+
case 'Escape':
|
|
42
|
+
this._onEscape(event);
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
break;
|
|
50
46
|
}
|
|
47
|
+
}
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
/**
|
|
50
|
+
* A handler for the `keyup` event. By default, it does nothing.
|
|
51
|
+
* Override the method to implement your own behavior.
|
|
52
|
+
*
|
|
53
|
+
* @param {KeyboardEvent} _event
|
|
54
|
+
* @protected
|
|
55
|
+
*/
|
|
56
|
+
_onKeyUp(_event) {
|
|
57
|
+
// To be implemented.
|
|
58
|
+
}
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
/**
|
|
61
|
+
* A handler for the "Enter" key. By default, it does nothing.
|
|
62
|
+
* Override the method to implement your own behavior.
|
|
63
|
+
*
|
|
64
|
+
* @param {KeyboardEvent} _event
|
|
65
|
+
* @protected
|
|
66
|
+
*/
|
|
67
|
+
_onEnter(_event) {
|
|
68
|
+
// To be implemented.
|
|
69
|
+
}
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
71
|
+
/**
|
|
72
|
+
* A handler for the "Escape" key. By default, it does nothing.
|
|
73
|
+
* Override the method to implement your own behavior.
|
|
74
|
+
*
|
|
75
|
+
* @param {KeyboardEvent} _event
|
|
76
|
+
* @protected
|
|
77
|
+
*/
|
|
78
|
+
_onEscape(_event) {
|
|
79
|
+
// To be implemented.
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const KeyboardMixin = dedupeMixin(KeyboardMixinImplementation);
|
package/src/list-mixin.js
CHANGED
|
@@ -12,9 +12,6 @@ import { KeyboardDirectionMixin } from './keyboard-direction-mixin.js';
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* A mixin for list elements, facilitating navigation and selection of items.
|
|
15
|
-
*
|
|
16
|
-
* @polymerMixin
|
|
17
|
-
* @mixes KeyboardDirectionMixin
|
|
18
15
|
*/
|
|
19
16
|
export const ListMixin = (superClass) =>
|
|
20
17
|
class ListMixinClass extends KeyboardDirectionMixin(superClass) {
|
|
@@ -285,40 +282,19 @@ export const ListMixin = (superClass) =>
|
|
|
285
282
|
});
|
|
286
283
|
this._setFocusable(idx);
|
|
287
284
|
this._scrollToItem(idx);
|
|
288
|
-
super._focus(idx, options);
|
|
285
|
+
super._focus(idx, options ?? { preventScroll: true });
|
|
289
286
|
}
|
|
290
287
|
|
|
291
288
|
/**
|
|
292
|
-
* Scroll the container to have the
|
|
289
|
+
* Scroll the container to have the item visible.
|
|
293
290
|
* @param {number} idx
|
|
294
291
|
* @protected
|
|
295
292
|
*/
|
|
296
293
|
_scrollToItem(idx) {
|
|
297
|
-
const item = this.
|
|
298
|
-
if (
|
|
299
|
-
|
|
294
|
+
const item = this._getItems()[idx];
|
|
295
|
+
if (item) {
|
|
296
|
+
item.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
300
297
|
}
|
|
301
|
-
|
|
302
|
-
const props = this._vertical ? ['top', 'bottom'] : this._isRTL ? ['right', 'left'] : ['left', 'right'];
|
|
303
|
-
|
|
304
|
-
const scrollerRect = this._scrollerElement.getBoundingClientRect();
|
|
305
|
-
const nextItemRect = (this.items[idx + 1] || item).getBoundingClientRect();
|
|
306
|
-
const prevItemRect = (this.items[idx - 1] || item).getBoundingClientRect();
|
|
307
|
-
|
|
308
|
-
let scrollDistance = 0;
|
|
309
|
-
if (
|
|
310
|
-
(!this._isRTL && nextItemRect[props[1]] >= scrollerRect[props[1]]) ||
|
|
311
|
-
(this._isRTL && nextItemRect[props[1]] <= scrollerRect[props[1]])
|
|
312
|
-
) {
|
|
313
|
-
scrollDistance = nextItemRect[props[1]] - scrollerRect[props[1]];
|
|
314
|
-
} else if (
|
|
315
|
-
(!this._isRTL && prevItemRect[props[0]] <= scrollerRect[props[0]]) ||
|
|
316
|
-
(this._isRTL && prevItemRect[props[0]] >= scrollerRect[props[0]])
|
|
317
|
-
) {
|
|
318
|
-
scrollDistance = prevItemRect[props[0]] - scrollerRect[props[0]];
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
this._scroll(scrollDistance);
|
|
322
298
|
}
|
|
323
299
|
|
|
324
300
|
/**
|
|
@@ -350,13 +326,4 @@ export const ListMixin = (superClass) =>
|
|
|
350
326
|
|
|
351
327
|
return super._isItemFocusable(item);
|
|
352
328
|
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Fired when the selection is changed.
|
|
356
|
-
* Not fired when used in `multiple` selection mode.
|
|
357
|
-
*
|
|
358
|
-
* @event selected-changed
|
|
359
|
-
* @param {Object} detail
|
|
360
|
-
* @param {Object} detail.value the index of the item selected in the items array.
|
|
361
|
-
*/
|
|
362
329
|
};
|
package/src/tabindex-mixin.js
CHANGED
|
@@ -10,9 +10,6 @@ import { DisabledMixin } from './disabled-mixin.js';
|
|
|
10
10
|
*
|
|
11
11
|
* The attribute is set to -1 whenever the user disables the element
|
|
12
12
|
* and restored with the last known value once the element is enabled.
|
|
13
|
-
*
|
|
14
|
-
* @polymerMixin
|
|
15
|
-
* @mixes DisabledMixin
|
|
16
13
|
*/
|
|
17
14
|
export const TabindexMixin = (superclass) =>
|
|
18
15
|
class TabindexMixinClass extends DisabledMixin(superclass) {
|