@vaadin/overlay 25.2.14 → 25.2.15
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
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"type": {
|
|
34
34
|
"text": "boolean"
|
|
35
35
|
},
|
|
36
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
36
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
37
37
|
"attribute": "focus-trap"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"type": {
|
|
64
64
|
"text": "boolean"
|
|
65
65
|
},
|
|
66
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
66
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
67
67
|
"fieldName": "focusTrap"
|
|
68
68
|
},
|
|
69
69
|
{
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"type": {
|
|
139
139
|
"text": "boolean"
|
|
140
140
|
},
|
|
141
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
141
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
142
142
|
"attribute": "focus-trap",
|
|
143
143
|
"inheritedFrom": {
|
|
144
144
|
"name": "OverlayFocusMixin",
|
|
@@ -289,7 +289,7 @@
|
|
|
289
289
|
"type": {
|
|
290
290
|
"text": "boolean"
|
|
291
291
|
},
|
|
292
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
292
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
293
293
|
"fieldName": "focusTrap",
|
|
294
294
|
"inheritedFrom": {
|
|
295
295
|
"name": "OverlayFocusMixin",
|
|
@@ -682,7 +682,7 @@
|
|
|
682
682
|
"type": {
|
|
683
683
|
"text": "boolean"
|
|
684
684
|
},
|
|
685
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
685
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
686
686
|
"attribute": "focus-trap",
|
|
687
687
|
"inheritedFrom": {
|
|
688
688
|
"name": "OverlayFocusMixin",
|
|
@@ -942,7 +942,7 @@
|
|
|
942
942
|
"type": {
|
|
943
943
|
"text": "boolean"
|
|
944
944
|
},
|
|
945
|
-
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.",
|
|
945
|
+
"description": "When true, opening the overlay moves focus to the first focusable child,\nor to the overlay part with tabindex if there are no focusable children.\n\nAn element inside the overlay that has `autofocus` set, such as\n`<vaadin-text-field autofocus>`, receives focus on open instead.",
|
|
946
946
|
"fieldName": "focusTrap",
|
|
947
947
|
"inheritedFrom": {
|
|
948
948
|
"name": "OverlayFocusMixin",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/overlay",
|
|
3
|
-
"version": "25.2.
|
|
3
|
+
"version": "25.2.15",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
|
-
"@vaadin/a11y-base": "~25.2.
|
|
38
|
-
"@vaadin/component-base": "~25.2.
|
|
39
|
-
"@vaadin/vaadin-themable-mixin": "~25.2.
|
|
37
|
+
"@vaadin/a11y-base": "~25.2.15",
|
|
38
|
+
"@vaadin/component-base": "~25.2.15",
|
|
39
|
+
"@vaadin/vaadin-themable-mixin": "~25.2.15",
|
|
40
40
|
"lit": "^3.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@vaadin/aura": "~25.2.
|
|
44
|
-
"@vaadin/chai-plugins": "~25.2.
|
|
45
|
-
"@vaadin/test-runner-commands": "~25.2.
|
|
43
|
+
"@vaadin/aura": "~25.2.15",
|
|
44
|
+
"@vaadin/chai-plugins": "~25.2.15",
|
|
45
|
+
"@vaadin/test-runner-commands": "~25.2.15",
|
|
46
46
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
47
|
-
"@vaadin/vaadin-lumo-styles": "~25.2.
|
|
47
|
+
"@vaadin/vaadin-lumo-styles": "~25.2.15",
|
|
48
48
|
"sinon": "^22.0.0"
|
|
49
49
|
},
|
|
50
50
|
"customElements": "custom-elements.json",
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "e0f3c1f28d7393af441fe3c9a790dba3e6ce3912"
|
|
52
52
|
}
|
|
@@ -13,6 +13,9 @@ export declare class OverlayFocusMixinClass {
|
|
|
13
13
|
/**
|
|
14
14
|
* When true, opening the overlay moves focus to the first focusable child,
|
|
15
15
|
* or to the overlay part with tabindex if there are no focusable children.
|
|
16
|
+
*
|
|
17
|
+
* An element inside the overlay that has `autofocus` set, such as
|
|
18
|
+
* `<vaadin-text-field autofocus>`, receives focus on open instead.
|
|
16
19
|
* @attr {boolean} focus-trap
|
|
17
20
|
*/
|
|
18
21
|
focusTrap: boolean;
|
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { FocusRestorationController } from '@vaadin/a11y-base/src/focus-restoration-controller.js';
|
|
7
7
|
import { FocusTrapController } from '@vaadin/a11y-base/src/focus-trap-controller.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getDeepActiveElement,
|
|
10
|
+
getFocusableElements,
|
|
11
|
+
isElementFocused,
|
|
12
|
+
isElementHidden,
|
|
13
|
+
isKeyboardActive,
|
|
14
|
+
} from '@vaadin/a11y-base/src/focus-utils.js';
|
|
9
15
|
|
|
10
16
|
export const OverlayFocusMixin = (superClass) =>
|
|
11
17
|
class OverlayFocusMixin extends superClass {
|
|
@@ -14,6 +20,9 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
14
20
|
/**
|
|
15
21
|
* When true, opening the overlay moves focus to the first focusable child,
|
|
16
22
|
* or to the overlay part with tabindex if there are no focusable children.
|
|
23
|
+
*
|
|
24
|
+
* An element inside the overlay that has `autofocus` set, such as
|
|
25
|
+
* `<vaadin-text-field autofocus>`, receives focus on open instead.
|
|
17
26
|
* @attr {boolean} focus-trap
|
|
18
27
|
*/
|
|
19
28
|
focusTrap: {
|
|
@@ -41,11 +50,25 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Whether the overlay moves, traps and restores focus. Override to return
|
|
55
|
+
* false in overlays that never do: focus properties are then ignored and
|
|
56
|
+
* the focus controllers are not created.
|
|
57
|
+
* @protected
|
|
58
|
+
*/
|
|
59
|
+
static get manageFocus() {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
44
63
|
constructor() {
|
|
45
64
|
super();
|
|
46
65
|
|
|
47
|
-
this.
|
|
48
|
-
|
|
66
|
+
this.__manageFocus = this.constructor.manageFocus;
|
|
67
|
+
|
|
68
|
+
if (this.__manageFocus) {
|
|
69
|
+
this.__focusTrapController = new FocusTrapController(this);
|
|
70
|
+
this.__focusRestorationController = new FocusRestorationController();
|
|
71
|
+
}
|
|
49
72
|
}
|
|
50
73
|
|
|
51
74
|
/**
|
|
@@ -61,8 +84,10 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
61
84
|
ready() {
|
|
62
85
|
super.ready();
|
|
63
86
|
|
|
64
|
-
|
|
65
|
-
|
|
87
|
+
if (this.__manageFocus) {
|
|
88
|
+
this.addController(this.__focusTrapController);
|
|
89
|
+
this.addController(this.__focusRestorationController);
|
|
90
|
+
}
|
|
66
91
|
}
|
|
67
92
|
|
|
68
93
|
/**
|
|
@@ -80,6 +105,10 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
80
105
|
* @protected
|
|
81
106
|
*/
|
|
82
107
|
_resetFocus() {
|
|
108
|
+
if (!this.__manageFocus) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
83
112
|
if (this.focusTrap) {
|
|
84
113
|
this.__focusTrapController.releaseFocus();
|
|
85
114
|
}
|
|
@@ -97,18 +126,34 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
97
126
|
* @protected
|
|
98
127
|
*/
|
|
99
128
|
_saveFocus() {
|
|
129
|
+
if (!this.__manageFocus) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
100
133
|
if (this.restoreFocusOnClose) {
|
|
101
134
|
this.__focusRestorationController.saveFocus(this.restoreFocusNode);
|
|
102
135
|
}
|
|
103
136
|
}
|
|
104
137
|
|
|
105
138
|
/**
|
|
106
|
-
* Trap focus within the overlay after opening has completed.
|
|
139
|
+
* Trap focus within the overlay after opening has completed. Focus moves
|
|
140
|
+
* to the first element with `autofocus` inside the overlay, otherwise to
|
|
141
|
+
* the first focusable element.
|
|
107
142
|
*
|
|
108
143
|
* @protected
|
|
109
144
|
*/
|
|
110
145
|
_trapFocus() {
|
|
146
|
+
if (!this.__manageFocus) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
111
150
|
if (this.focusTrap && !isElementHidden(this._focusTrapRoot)) {
|
|
151
|
+
const focusables = getFocusableElements(this._focusTrapRoot);
|
|
152
|
+
if (!focusables.some(isElementFocused)) {
|
|
153
|
+
const target = focusables.find((el) => this.#hasAutofocus(el));
|
|
154
|
+
target?.focus({ focusVisible: isKeyboardActive() });
|
|
155
|
+
}
|
|
156
|
+
|
|
112
157
|
this.__focusTrapController.trapFocus(this._focusTrapRoot);
|
|
113
158
|
}
|
|
114
159
|
}
|
|
@@ -149,4 +194,27 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
149
194
|
}
|
|
150
195
|
return n === this._contentRoot;
|
|
151
196
|
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Returns true if the element has `autofocus`, or belongs to a custom
|
|
200
|
+
* element that has it (e.g. the input of `<vaadin-text-field autofocus>`).
|
|
201
|
+
* As with native `autofocus`, a plain `<div autofocus>` does not apply to
|
|
202
|
+
* its children. Stops at the focus trap root, whose `autofocus` refers to the overlay.
|
|
203
|
+
* Walks the flat tree, the same way focusable elements are collected from the
|
|
204
|
+
* focus trap root, so it never leaves the overlay when content is slotted from the owner.
|
|
205
|
+
*
|
|
206
|
+
* @param {HTMLElement} element
|
|
207
|
+
* @return {boolean}
|
|
208
|
+
*/
|
|
209
|
+
#hasAutofocus(element) {
|
|
210
|
+
const focusTrapRoot = this._focusTrapRoot;
|
|
211
|
+
let node = element;
|
|
212
|
+
while (node && node !== focusTrapRoot && node !== this) {
|
|
213
|
+
if (node.autofocus && (node === element || customElements.get(node.localName))) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
node = node.assignedSlot || node.parentNode || node.host;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
152
220
|
};
|