@vaadin/popover 25.0.0-alpha1 → 25.0.0-alpha11
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/package.json +11 -12
- package/src/lit/renderer-directives.d.ts +1 -1
- package/src/lit/renderer-directives.js +1 -1
- package/src/styles/vaadin-popover-overlay-base-styles.d.ts +8 -0
- package/src/styles/vaadin-popover-overlay-base-styles.js +210 -0
- package/src/vaadin-popover-overlay-mixin.js +0 -58
- package/src/vaadin-popover-overlay.js +39 -71
- package/src/vaadin-popover.d.ts +15 -20
- package/src/vaadin-popover.js +99 -66
- package/vaadin-popover.js +1 -1
- package/web-types.json +36 -14
- package/web-types.lit.json +15 -8
- package/theme/lumo/vaadin-popover-styles.d.ts +0 -4
- package/theme/lumo/vaadin-popover-styles.js +0 -111
- package/theme/lumo/vaadin-popover.d.ts +0 -2
- package/theme/lumo/vaadin-popover.js +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/popover",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-alpha11",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"lit.d.ts",
|
|
24
24
|
"lit.js",
|
|
25
25
|
"src",
|
|
26
|
-
"theme",
|
|
27
26
|
"vaadin-*.d.ts",
|
|
28
27
|
"vaadin-*.js",
|
|
29
28
|
"web-types.json",
|
|
@@ -37,23 +36,23 @@
|
|
|
37
36
|
],
|
|
38
37
|
"dependencies": {
|
|
39
38
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
40
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
41
|
-
"@vaadin/component-base": "25.0.0-
|
|
42
|
-
"@vaadin/lit-renderer": "25.0.0-
|
|
43
|
-
"@vaadin/overlay": "25.0.0-
|
|
44
|
-
"@vaadin/vaadin-
|
|
45
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha1",
|
|
39
|
+
"@vaadin/a11y-base": "25.0.0-alpha11",
|
|
40
|
+
"@vaadin/component-base": "25.0.0-alpha11",
|
|
41
|
+
"@vaadin/lit-renderer": "25.0.0-alpha11",
|
|
42
|
+
"@vaadin/overlay": "25.0.0-alpha11",
|
|
43
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha11",
|
|
46
44
|
"lit": "^3.0.0"
|
|
47
45
|
},
|
|
48
46
|
"devDependencies": {
|
|
49
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
50
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
51
|
-
"@vaadin/testing-helpers": "^
|
|
47
|
+
"@vaadin/chai-plugins": "25.0.0-alpha11",
|
|
48
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha11",
|
|
49
|
+
"@vaadin/testing-helpers": "^2.0.0",
|
|
50
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-alpha11",
|
|
52
51
|
"sinon": "^18.0.0"
|
|
53
52
|
},
|
|
54
53
|
"web-types": [
|
|
55
54
|
"web-types.json",
|
|
56
55
|
"web-types.lit.json"
|
|
57
56
|
],
|
|
58
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "abfd315ba5a7484a613e0768635a4e8fe945a44b"
|
|
59
58
|
}
|
|
@@ -27,7 +27,7 @@ export class PopoverRendererDirective extends LitRendererDirective<Popover, Popo
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* A Lit directive for populating the content of the `<vaadin-popover
|
|
30
|
+
* A Lit directive for populating the content of the `<vaadin-popover>` element.
|
|
31
31
|
*
|
|
32
32
|
* The directive accepts a renderer callback returning a Lit template and assigns it to the popover
|
|
33
33
|
* via the `renderer` property. The renderer is called once to populate the content when assigned
|
|
@@ -32,7 +32,7 @@ export class PopoverRendererDirective extends LitRendererDirective {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* A Lit directive for populating the content of the `<vaadin-popover
|
|
35
|
+
* A Lit directive for populating the content of the `<vaadin-popover>` element.
|
|
36
36
|
*
|
|
37
37
|
* The directive accepts a renderer callback returning a Lit template and assigns it to the popover
|
|
38
38
|
* via the `renderer` property. The renderer is called once to populate the content when assigned
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2024 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
|
|
8
|
+
|
|
9
|
+
const popoverOverlay = css`
|
|
10
|
+
:host {
|
|
11
|
+
--_arrow-size: var(--vaadin-popover-arrow-size, 8px);
|
|
12
|
+
--_default-offset: 4px;
|
|
13
|
+
--_rtl-multiplier: 1;
|
|
14
|
+
--_border-width: var(--vaadin-popover-border-width, var(--vaadin-overlay-border-width, 1px));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[part='overlay']:focus-visible {
|
|
18
|
+
outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:host([dir='rtl']) {
|
|
22
|
+
--_rtl-multiplier: -1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host([modeless][with-backdrop]) [part='backdrop'] {
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:host([position^='top'][top-aligned]) [part='overlay'],
|
|
30
|
+
:host([position^='bottom'][top-aligned]) [part='overlay'] {
|
|
31
|
+
margin-top: var(--vaadin-popover-offset-top, var(--_default-offset));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
[part='overlay'] {
|
|
35
|
+
position: relative;
|
|
36
|
+
overflow: visible;
|
|
37
|
+
max-height: 100%;
|
|
38
|
+
border: var(--_border-width) solid
|
|
39
|
+
var(--vaadin-popover-border-color, var(--vaadin-overlay-border-color, var(--vaadin-border-color)));
|
|
40
|
+
background: var(--vaadin-popover-background, var(--vaadin-overlay-background, var(--vaadin-background-color)));
|
|
41
|
+
box-shadow: var(--vaadin-popover-box-shadow, var(--vaadin-overlay-box-shadow, 0 8px 24px -4px rgba(0, 0, 0, 0.3)));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
[part='content'] {
|
|
45
|
+
overflow: auto;
|
|
46
|
+
overscroll-behavior: contain;
|
|
47
|
+
box-sizing: border-box;
|
|
48
|
+
max-height: 100%;
|
|
49
|
+
padding: var(--vaadin-popover-padding, var(--vaadin-padding));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host([theme~='no-padding']) [part='content'] {
|
|
53
|
+
padding: 0 !important;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Increase the area of the popover so the pointer can go from the target directly to it. */
|
|
57
|
+
[part='overlay']::before {
|
|
58
|
+
position: absolute;
|
|
59
|
+
content: '';
|
|
60
|
+
inset-block: calc(var(--vaadin-popover-offset-top, var(--_default-offset)) * -1)
|
|
61
|
+
calc(var(--vaadin-popover-offset-bottom, var(--_default-offset)) * -1);
|
|
62
|
+
inset-inline: calc(var(--vaadin-popover-offset-start, var(--_default-offset)) * -1)
|
|
63
|
+
calc(var(--vaadin-popover-offset-end, var(--_default-offset)) * -1);
|
|
64
|
+
z-index: -1;
|
|
65
|
+
pointer-events: auto;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:host([position^='top'][bottom-aligned]) [part='overlay'],
|
|
69
|
+
:host([position^='bottom'][bottom-aligned]) [part='overlay'] {
|
|
70
|
+
margin-bottom: var(--vaadin-popover-offset-bottom, var(--_default-offset));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:host([position^='start'][start-aligned]) [part='overlay'],
|
|
74
|
+
:host([position^='end'][start-aligned]) [part='overlay'] {
|
|
75
|
+
margin-inline-start: var(--vaadin-popover-offset-start, var(--_default-offset));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
:host([position^='start'][end-aligned]) [part='overlay'],
|
|
79
|
+
:host([position^='end'][end-aligned]) [part='overlay'] {
|
|
80
|
+
margin-inline-end: var(--vaadin-popover-offset-end, var(--_default-offset));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
[part='arrow'] {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:host([theme~='arrow']) {
|
|
88
|
+
--_default-offset: calc(4px + var(--_arrow-size) / 2);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:host([theme~='arrow']) [part='arrow'] {
|
|
92
|
+
display: block;
|
|
93
|
+
position: absolute;
|
|
94
|
+
background: inherit;
|
|
95
|
+
border: inherit;
|
|
96
|
+
border-start-start-radius: var(--vaadin-popover-arrow-border-radius, 0);
|
|
97
|
+
outline: inherit;
|
|
98
|
+
box-shadow: inherit;
|
|
99
|
+
width: var(--_arrow-size);
|
|
100
|
+
height: var(--_arrow-size);
|
|
101
|
+
rotate: 45deg;
|
|
102
|
+
--o: 20px; /* clip-path outset, how far outward it extends to reveal the outline and box shadow */
|
|
103
|
+
--b: var(--_border-width);
|
|
104
|
+
/* We need this elaborate clip-path to allow the arrow bg and border to cover
|
|
105
|
+
the overlay border but prevent the outline and box-shadow from covering it */
|
|
106
|
+
clip-path: polygon(
|
|
107
|
+
calc(var(--o) * -1) calc(var(--o) * -1),
|
|
108
|
+
calc(100% + var(--o) - var(--b)) calc(var(--o) * -1),
|
|
109
|
+
calc(100% - var(--b) * 1.4) 0,
|
|
110
|
+
100% 0,
|
|
111
|
+
calc(100% - var(--b)) var(--b),
|
|
112
|
+
calc(100% - var(--b)) calc(var(--b) + var(--ff, 0px)),
|
|
113
|
+
calc(var(--b) + var(--ff, 0px)) calc(100% - var(--b)),
|
|
114
|
+
calc(var(--b)) calc(100% - var(--b)),
|
|
115
|
+
0 100%,
|
|
116
|
+
0 calc(100% - var(--b) * 1.4),
|
|
117
|
+
calc(var(--o) * -1) calc(100% + var(--o) - var(--b))
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Firefox renders a blurry edge for a diagonal clip-path + rotation,
|
|
122
|
+
so we need to extend the clip-path slightly further on the diagonal */
|
|
123
|
+
@supports (-moz-appearance: none) {
|
|
124
|
+
:host([theme~='arrow']) [part='arrow'] {
|
|
125
|
+
--ff: 1px;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* bottom / top */
|
|
130
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[start-aligned]) [part='arrow'] {
|
|
131
|
+
inset-inline-start: calc(var(--_arrow-size) * 2);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned]) [part='arrow'] {
|
|
135
|
+
inset-inline-end: calc(var(--_arrow-size) * 2);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[arrow-centered]) [part='arrow'] {
|
|
139
|
+
inset-inline-start: 50%;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* bottom */
|
|
143
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[top-aligned]) [part='arrow'] {
|
|
144
|
+
top: 0;
|
|
145
|
+
translate: calc(-50% * var(--_rtl-multiplier)) -50%;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned][top-aligned]) [part='arrow'] {
|
|
149
|
+
translate: calc(50% * var(--_rtl-multiplier)) -50%;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* top */
|
|
153
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[bottom-aligned]) [part='arrow'] {
|
|
154
|
+
bottom: 0;
|
|
155
|
+
rotate: 225deg;
|
|
156
|
+
translate: calc(-50% * var(--_rtl-multiplier)) 50%;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
:host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned][bottom-aligned]) [part='arrow'] {
|
|
160
|
+
translate: calc(50% * var(--_rtl-multiplier)) 50%;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* start / end */
|
|
164
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[top-aligned]) [part='arrow'] {
|
|
165
|
+
rotate: -45deg;
|
|
166
|
+
top: calc(var(--_arrow-size) * 2);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[bottom-aligned]) [part='arrow'] {
|
|
170
|
+
rotate: -45deg;
|
|
171
|
+
bottom: calc(var(--_arrow-size) * 2);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
:host([theme~='arrow']:is([position='start'], [position='end'])[top-aligned]) [part='arrow'] {
|
|
175
|
+
top: 50%;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
:host([dir='rtl'][theme~='arrow']:is([position^='start'], [position^='end'])) [part='arrow'] {
|
|
179
|
+
scale: -1;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* end */
|
|
183
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[start-aligned]) [part='arrow'] {
|
|
184
|
+
inset-inline-start: 0;
|
|
185
|
+
translate: calc(-50% * var(--_rtl-multiplier)) -50%;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[start-aligned][bottom-aligned]) [part='arrow'] {
|
|
189
|
+
translate: calc(-50% * var(--_rtl-multiplier)) 50%;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* start */
|
|
193
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[end-aligned]) [part='arrow'] {
|
|
194
|
+
rotate: 135deg;
|
|
195
|
+
inset-inline-end: 0;
|
|
196
|
+
translate: calc(50% * var(--_rtl-multiplier)) -50%;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
:host([theme~='arrow']:is([position^='start'], [position^='end'])[end-aligned][bottom-aligned]) [part='arrow'] {
|
|
200
|
+
translate: calc(50% * var(--_rtl-multiplier)) 50%;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@media (forced-colors: active) {
|
|
204
|
+
:host {
|
|
205
|
+
--_border-width: 3px;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
`;
|
|
209
|
+
|
|
210
|
+
export const popoverOverlayStyles = [overlayStyles, popoverOverlay];
|
|
@@ -5,26 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
7
7
|
import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
|
|
8
|
-
import { setNestedOverlay } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Returns the closest parent overlay for given node, if any.
|
|
12
|
-
* @param {HTMLElement} node
|
|
13
|
-
* @return {HTMLElement}
|
|
14
|
-
*/
|
|
15
|
-
const getClosestOverlay = (node) => {
|
|
16
|
-
let n = node;
|
|
17
|
-
|
|
18
|
-
while (n && n !== node.ownerDocument) {
|
|
19
|
-
n = n.parentNode || n.host;
|
|
20
|
-
|
|
21
|
-
if (n && n._hasOverlayStackMixin) {
|
|
22
|
-
return n;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
};
|
|
28
8
|
|
|
29
9
|
/**
|
|
30
10
|
* A mixin providing common popover overlay functionality.
|
|
@@ -44,34 +24,6 @@ export const PopoverOverlayMixin = (superClass) =>
|
|
|
44
24
|
};
|
|
45
25
|
}
|
|
46
26
|
|
|
47
|
-
static get observers() {
|
|
48
|
-
return ['__openedOrTargetChanged(opened, positionTarget)'];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Tag name prefix used by custom properties.
|
|
53
|
-
* @protected
|
|
54
|
-
* @return {string}
|
|
55
|
-
*/
|
|
56
|
-
get _tagNamePrefix() {
|
|
57
|
-
return 'vaadin-popover';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
requestContentUpdate() {
|
|
61
|
-
super.requestContentUpdate();
|
|
62
|
-
|
|
63
|
-
// Copy custom properties from the owner
|
|
64
|
-
if (this.positionTarget && this.owner) {
|
|
65
|
-
const style = getComputedStyle(this.owner);
|
|
66
|
-
['top', 'bottom', 'start', 'end'].forEach((prop) => {
|
|
67
|
-
this.style.setProperty(
|
|
68
|
-
`--${this._tagNamePrefix}-offset-${prop}`,
|
|
69
|
-
style.getPropertyValue(`--${this._tagNamePrefix}-offset-${prop}`),
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
27
|
/**
|
|
76
28
|
* @protected
|
|
77
29
|
* @override
|
|
@@ -120,14 +72,4 @@ export const PopoverOverlayMixin = (superClass) =>
|
|
|
120
72
|
this.style.top = `${overlayRect.top + offset}px`;
|
|
121
73
|
}
|
|
122
74
|
}
|
|
123
|
-
|
|
124
|
-
/** @private */
|
|
125
|
-
__openedOrTargetChanged(opened, target) {
|
|
126
|
-
if (target) {
|
|
127
|
-
const parent = getClosestOverlay(target);
|
|
128
|
-
if (parent) {
|
|
129
|
-
setNestedOverlay(parent, opened ? this : null);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
75
|
};
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Copyright (c) 2024 - 2025 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 { html, LitElement } from 'lit';
|
|
7
|
+
import { isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
7
8
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
9
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
|
-
import {
|
|
11
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
11
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
+
import { popoverOverlayStyles } from './styles/vaadin-popover-overlay-base-styles.js';
|
|
12
14
|
import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -21,80 +23,15 @@ import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
|
|
|
21
23
|
* @mixes ThemableMixin
|
|
22
24
|
* @private
|
|
23
25
|
*/
|
|
24
|
-
class PopoverOverlay extends PopoverOverlayMixin(
|
|
26
|
+
class PopoverOverlay extends PopoverOverlayMixin(
|
|
27
|
+
DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
|
|
28
|
+
) {
|
|
25
29
|
static get is() {
|
|
26
30
|
return 'vaadin-popover-overlay';
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
static get styles() {
|
|
30
|
-
return
|
|
31
|
-
overlayStyles,
|
|
32
|
-
css`
|
|
33
|
-
:host {
|
|
34
|
-
--_vaadin-popover-content-width: auto;
|
|
35
|
-
--_vaadin-popover-content-height: auto;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
:host([modeless][with-backdrop]) [part='backdrop'] {
|
|
39
|
-
pointer-events: none;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
:host([position^='top'][top-aligned]) [part='overlay'],
|
|
43
|
-
:host([position^='bottom'][top-aligned]) [part='overlay'] {
|
|
44
|
-
margin-top: var(--vaadin-popover-offset-top, 0);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
[part='overlay'] {
|
|
48
|
-
position: relative;
|
|
49
|
-
overflow: visible;
|
|
50
|
-
max-height: 100%;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
[part='content'] {
|
|
54
|
-
overflow: auto;
|
|
55
|
-
box-sizing: border-box;
|
|
56
|
-
max-height: 100%;
|
|
57
|
-
width: var(--_vaadin-popover-content-width);
|
|
58
|
-
height: var(--_vaadin-popover-content-height);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/* Increase the area of the popover so the pointer can go from the target directly to it. */
|
|
62
|
-
[part='overlay']::before {
|
|
63
|
-
position: absolute;
|
|
64
|
-
content: '';
|
|
65
|
-
inset-block: calc(var(--vaadin-popover-offset-top, 0) * -1) calc(var(--vaadin-popover-offset-bottom, 0) * -1);
|
|
66
|
-
inset-inline: calc(var(--vaadin-popover-offset-start, 0) * -1) calc(var(--vaadin-popover-offset-end, 0) * -1);
|
|
67
|
-
z-index: -1;
|
|
68
|
-
pointer-events: auto;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
:host([position^='top'][bottom-aligned]) [part='overlay'],
|
|
72
|
-
:host([position^='bottom'][bottom-aligned]) [part='overlay'] {
|
|
73
|
-
margin-bottom: var(--vaadin-popover-offset-bottom, 0);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
:host([position^='start'][start-aligned]) [part='overlay'],
|
|
77
|
-
:host([position^='end'][start-aligned]) [part='overlay'] {
|
|
78
|
-
margin-inline-start: var(--vaadin-popover-offset-start, 0);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
:host([position^='start'][end-aligned]) [part='overlay'],
|
|
82
|
-
:host([position^='end'][end-aligned]) [part='overlay'] {
|
|
83
|
-
margin-inline-end: var(--vaadin-popover-offset-end, 0);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
[part='arrow'] {
|
|
87
|
-
display: none;
|
|
88
|
-
position: absolute;
|
|
89
|
-
height: 0;
|
|
90
|
-
width: 0;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
:host([theme~='arrow']) [part='arrow'] {
|
|
94
|
-
display: block;
|
|
95
|
-
}
|
|
96
|
-
`,
|
|
97
|
-
];
|
|
34
|
+
return popoverOverlayStyles;
|
|
98
35
|
}
|
|
99
36
|
|
|
100
37
|
/** @protected */
|
|
@@ -107,6 +44,37 @@ class PopoverOverlay extends PopoverOverlayMixin(DirMixin(ThemableMixin(PolylitM
|
|
|
107
44
|
</div>
|
|
108
45
|
`;
|
|
109
46
|
}
|
|
47
|
+
|
|
48
|
+
/** @protected */
|
|
49
|
+
updated(props) {
|
|
50
|
+
super.updated(props);
|
|
51
|
+
|
|
52
|
+
if (props.has('restoreFocusNode') && this.opened) {
|
|
53
|
+
// Save focus to be restored when target is set while opened
|
|
54
|
+
if (this.restoreFocusNode && isElementFocused(this.restoreFocusNode.focusElement || this.restoreFocusNode)) {
|
|
55
|
+
this.__focusRestorationController.saveFocus();
|
|
56
|
+
} else if (!this.restoreFocusNode) {
|
|
57
|
+
// Do not restore focus when target is cleared while opened
|
|
58
|
+
this.__focusRestorationController.focusNode = null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @override
|
|
65
|
+
* @protected
|
|
66
|
+
*/
|
|
67
|
+
get _contentRoot() {
|
|
68
|
+
return this.owner;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @override
|
|
73
|
+
* @protected
|
|
74
|
+
*/
|
|
75
|
+
get _modalRoot() {
|
|
76
|
+
return this.owner;
|
|
77
|
+
}
|
|
110
78
|
}
|
|
111
79
|
|
|
112
80
|
defineCustomElement(PopoverOverlay);
|
package/src/vaadin-popover.d.ts
CHANGED
|
@@ -37,16 +37,13 @@ export type PopoverEventMap = HTMLElementEventMap & PopoverCustomEventMap;
|
|
|
37
37
|
*
|
|
38
38
|
* ### Styling
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
* themable component as the actual visible overlay.
|
|
42
|
-
*
|
|
43
|
-
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
|
|
44
|
-
* for `<vaadin-popover-overlay>` parts.
|
|
45
|
-
*
|
|
46
|
-
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
|
|
40
|
+
* The following shadow DOM parts are available for styling:
|
|
47
41
|
*
|
|
48
42
|
* Part name | Description
|
|
49
43
|
* -----------------|-------------------------------------------
|
|
44
|
+
* `backdrop` | Backdrop of the overlay
|
|
45
|
+
* `overlay` | The overlay container
|
|
46
|
+
* `content` | The overlay content
|
|
50
47
|
* `arrow` | Optional arrow pointing to the target when using `theme="arrow"`
|
|
51
48
|
*
|
|
52
49
|
* The following state attributes are available for styling:
|
|
@@ -55,9 +52,6 @@ export type PopoverEventMap = HTMLElementEventMap & PopoverCustomEventMap;
|
|
|
55
52
|
* -----------------|----------------------------------------
|
|
56
53
|
* `position` | Reflects the `position` property value.
|
|
57
54
|
*
|
|
58
|
-
* Note: the `theme` attribute value set on `<vaadin-popover>` is
|
|
59
|
-
* propagated to the internal `<vaadin-popover-overlay>` component.
|
|
60
|
-
*
|
|
61
55
|
* ### Custom CSS Properties
|
|
62
56
|
*
|
|
63
57
|
* The following custom CSS properties are available on the `<vaadin-popover>` element:
|
|
@@ -96,16 +90,18 @@ declare class Popover extends PopoverPositionMixin(
|
|
|
96
90
|
static setDefaultHoverDelay(hoverDelay: number): void;
|
|
97
91
|
|
|
98
92
|
/**
|
|
99
|
-
* String used to label the
|
|
93
|
+
* String used to label the popover to screen reader users.
|
|
100
94
|
*
|
|
101
95
|
* @attr {string} accessible-name
|
|
96
|
+
* @deprecated Use `aria-label` attribute on the popover instead
|
|
102
97
|
*/
|
|
103
98
|
accessibleName: string | null | undefined;
|
|
104
99
|
|
|
105
100
|
/**
|
|
106
|
-
* Id of the element used as label of the
|
|
101
|
+
* Id of the element used as label of the popover to screen reader users.
|
|
107
102
|
*
|
|
108
103
|
* @attr {string} accessible-name-ref
|
|
104
|
+
* @deprecated Use `aria-labelledby` attribute on the popover instead
|
|
109
105
|
*/
|
|
110
106
|
accessibleNameRef: string | null | undefined;
|
|
111
107
|
|
|
@@ -116,18 +112,16 @@ declare class Popover extends PopoverPositionMixin(
|
|
|
116
112
|
autofocus: boolean;
|
|
117
113
|
|
|
118
114
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @attr {string} content-height
|
|
115
|
+
* Set the height of the overlay.
|
|
116
|
+
* If a unitless number is provided, pixels are assumed.
|
|
122
117
|
*/
|
|
123
|
-
|
|
118
|
+
height: string | null;
|
|
124
119
|
|
|
125
120
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* @attr {string} content-width
|
|
121
|
+
* Set the width of the overlay.
|
|
122
|
+
* If a unitless number is provided, pixels are assumed.
|
|
129
123
|
*/
|
|
130
|
-
|
|
124
|
+
width: string | null;
|
|
131
125
|
|
|
132
126
|
/**
|
|
133
127
|
* The delay in milliseconds before the popover is opened
|
|
@@ -169,6 +163,7 @@ declare class Popover extends PopoverPositionMixin(
|
|
|
169
163
|
* The `role` attribute value to be set on the overlay.
|
|
170
164
|
*
|
|
171
165
|
* @attr {string} overlay-role
|
|
166
|
+
* @deprecated Use standard `role` attribute on the popover instead
|
|
172
167
|
*/
|
|
173
168
|
overlayRole: string;
|
|
174
169
|
|
package/src/vaadin-popover.js
CHANGED
|
@@ -17,7 +17,7 @@ import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
|
17
17
|
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
18
18
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
19
19
|
import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
|
|
20
|
-
import { isLastOverlay } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
|
|
20
|
+
import { isLastOverlay as isLastOverlayBase } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
|
|
21
21
|
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
22
22
|
import { PopoverPositionMixin } from './vaadin-popover-position-mixin.js';
|
|
23
23
|
import { PopoverTargetMixin } from './vaadin-popover-target-mixin.js';
|
|
@@ -148,6 +148,18 @@ class PopoverOpenedStateController {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Returns true if the popover overlay is the last one in the opened overlays stack, ignoring tooltips.
|
|
153
|
+
* @param {HTMLElement} overlay
|
|
154
|
+
* @return {boolean}
|
|
155
|
+
* @protected
|
|
156
|
+
*/
|
|
157
|
+
const isLastOverlay = (overlay) => {
|
|
158
|
+
// Ignore tooltips, popovers should still close when a tooltip is present
|
|
159
|
+
const filter = (o) => o.localName !== 'vaadin-tooltip-overlay';
|
|
160
|
+
return isLastOverlayBase(overlay, filter);
|
|
161
|
+
};
|
|
162
|
+
|
|
151
163
|
/**
|
|
152
164
|
* `<vaadin-popover>` is a Web Component for creating overlays
|
|
153
165
|
* that are positioned next to specified DOM element (target).
|
|
@@ -157,16 +169,13 @@ class PopoverOpenedStateController {
|
|
|
157
169
|
*
|
|
158
170
|
* ### Styling
|
|
159
171
|
*
|
|
160
|
-
*
|
|
161
|
-
* themable component as the actual visible overlay.
|
|
162
|
-
*
|
|
163
|
-
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
|
|
164
|
-
* for `<vaadin-popover-overlay>` parts.
|
|
165
|
-
*
|
|
166
|
-
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
|
|
172
|
+
* The following shadow DOM parts are available for styling:
|
|
167
173
|
*
|
|
168
174
|
* Part name | Description
|
|
169
175
|
* -----------------|-------------------------------------------
|
|
176
|
+
* `backdrop` | Backdrop of the overlay
|
|
177
|
+
* `overlay` | The overlay container
|
|
178
|
+
* `content` | The overlay content
|
|
170
179
|
* `arrow` | Optional arrow pointing to the target when using `theme="arrow"`
|
|
171
180
|
*
|
|
172
181
|
* The following state attributes are available for styling:
|
|
@@ -175,9 +184,6 @@ class PopoverOpenedStateController {
|
|
|
175
184
|
* -----------------|----------------------------------------
|
|
176
185
|
* `position` | Reflects the `position` property value.
|
|
177
186
|
*
|
|
178
|
-
* Note: the `theme` attribute value set on `<vaadin-popover>` is
|
|
179
|
-
* propagated to the internal `<vaadin-popover-overlay>` component.
|
|
180
|
-
*
|
|
181
187
|
* ### Custom CSS Properties
|
|
182
188
|
*
|
|
183
189
|
* The following custom CSS properties are available on the `<vaadin-popover>` element:
|
|
@@ -212,7 +218,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
212
218
|
static get styles() {
|
|
213
219
|
return css`
|
|
214
220
|
:host {
|
|
215
|
-
display:
|
|
221
|
+
display: contents;
|
|
216
222
|
}
|
|
217
223
|
`;
|
|
218
224
|
}
|
|
@@ -220,18 +226,20 @@ class Popover extends PopoverPositionMixin(
|
|
|
220
226
|
static get properties() {
|
|
221
227
|
return {
|
|
222
228
|
/**
|
|
223
|
-
* String used to label the
|
|
229
|
+
* String used to label the popover to screen reader users.
|
|
224
230
|
*
|
|
225
231
|
* @attr {string} accessible-name
|
|
232
|
+
* @deprecated Use `aria-label` attribute on the popover instead
|
|
226
233
|
*/
|
|
227
234
|
accessibleName: {
|
|
228
235
|
type: String,
|
|
229
236
|
},
|
|
230
237
|
|
|
231
238
|
/**
|
|
232
|
-
* Id of the element used as label of the
|
|
239
|
+
* Id of the element used as label of the popover to screen reader users.
|
|
233
240
|
*
|
|
234
241
|
* @attr {string} accessible-name-ref
|
|
242
|
+
* @deprecated Use `aria-labelledby` attribute on the popover instead
|
|
235
243
|
*/
|
|
236
244
|
accessibleNameRef: {
|
|
237
245
|
type: String,
|
|
@@ -246,20 +254,18 @@ class Popover extends PopoverPositionMixin(
|
|
|
246
254
|
},
|
|
247
255
|
|
|
248
256
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
* @attr {string} content-height
|
|
257
|
+
* Set the height of the overlay.
|
|
258
|
+
* If a unitless number is provided, pixels are assumed.
|
|
252
259
|
*/
|
|
253
|
-
|
|
260
|
+
height: {
|
|
254
261
|
type: String,
|
|
255
262
|
},
|
|
256
263
|
|
|
257
264
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* @attr {string} content-width
|
|
265
|
+
* Set the width of the overlay.
|
|
266
|
+
* If a unitless number is provided, pixels are assumed.
|
|
261
267
|
*/
|
|
262
|
-
|
|
268
|
+
width: {
|
|
263
269
|
type: String,
|
|
264
270
|
},
|
|
265
271
|
|
|
@@ -310,14 +316,23 @@ class Popover extends PopoverPositionMixin(
|
|
|
310
316
|
observer: '__openedChanged',
|
|
311
317
|
},
|
|
312
318
|
|
|
319
|
+
/**
|
|
320
|
+
* The `role` attribute value to be set on the popover.
|
|
321
|
+
* When not specified, defaults to 'dialog'.
|
|
322
|
+
*/
|
|
323
|
+
role: {
|
|
324
|
+
type: String,
|
|
325
|
+
reflectToAttribute: true,
|
|
326
|
+
},
|
|
327
|
+
|
|
313
328
|
/**
|
|
314
329
|
* The `role` attribute value to be set on the overlay.
|
|
315
330
|
*
|
|
316
331
|
* @attr {string} overlay-role
|
|
332
|
+
* @deprecated Use standard `role` attribute on the popover instead
|
|
317
333
|
*/
|
|
318
334
|
overlayRole: {
|
|
319
335
|
type: String,
|
|
320
|
-
value: 'dialog',
|
|
321
336
|
},
|
|
322
337
|
|
|
323
338
|
/**
|
|
@@ -405,20 +420,11 @@ class Popover extends PopoverPositionMixin(
|
|
|
405
420
|
value: false,
|
|
406
421
|
sync: true,
|
|
407
422
|
},
|
|
408
|
-
|
|
409
|
-
/** @private */
|
|
410
|
-
__overlayId: {
|
|
411
|
-
type: String,
|
|
412
|
-
},
|
|
413
423
|
};
|
|
414
424
|
}
|
|
415
425
|
|
|
416
426
|
static get observers() {
|
|
417
|
-
return [
|
|
418
|
-
'__updateContentHeight(contentHeight, _overlayElement)',
|
|
419
|
-
'__updateContentWidth(contentWidth, _overlayElement)',
|
|
420
|
-
'__updateAriaAttributes(opened, overlayRole, target)',
|
|
421
|
-
];
|
|
427
|
+
return ['__sizeChanged(width, height, _overlayElement)', '__updateAriaAttributes(opened, role, target)'];
|
|
422
428
|
}
|
|
423
429
|
|
|
424
430
|
/**
|
|
@@ -454,7 +460,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
454
460
|
constructor() {
|
|
455
461
|
super();
|
|
456
462
|
|
|
457
|
-
this.
|
|
463
|
+
this.__generatedId = `vaadin-popover-${generateUniqueId()}`;
|
|
458
464
|
|
|
459
465
|
this.__onGlobalClick = this.__onGlobalClick.bind(this);
|
|
460
466
|
this.__onGlobalKeyDown = this.__onGlobalKeyDown.bind(this);
|
|
@@ -473,10 +479,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
473
479
|
|
|
474
480
|
return html`
|
|
475
481
|
<vaadin-popover-overlay
|
|
476
|
-
id="
|
|
477
|
-
role="${this.overlayRole}"
|
|
478
|
-
aria-label="${ifDefined(this.accessibleName)}"
|
|
479
|
-
aria-labelledby="${ifDefined(this.accessibleNameRef)}"
|
|
482
|
+
id="overlay"
|
|
480
483
|
.renderer="${this.renderer}"
|
|
481
484
|
.owner="${this}"
|
|
482
485
|
theme="${ifDefined(this._theme)}"
|
|
@@ -498,11 +501,14 @@ class Popover extends PopoverPositionMixin(
|
|
|
498
501
|
@opened-changed="${this.__onOpenedChanged}"
|
|
499
502
|
.restoreFocusOnClose="${this.__shouldRestoreFocus}"
|
|
500
503
|
.restoreFocusNode="${this.target}"
|
|
504
|
+
exportparts="backdrop, overlay, content, arrow"
|
|
501
505
|
@vaadin-overlay-escape-press="${this.__onEscapePress}"
|
|
502
506
|
@vaadin-overlay-outside-click="${this.__onOutsideClick}"
|
|
503
507
|
@vaadin-overlay-open="${this.__onOverlayOpened}"
|
|
504
508
|
@vaadin-overlay-closed="${this.__onOverlayClosed}"
|
|
505
|
-
|
|
509
|
+
>
|
|
510
|
+
<slot></slot>
|
|
511
|
+
</vaadin-popover-overlay>
|
|
506
512
|
`;
|
|
507
513
|
}
|
|
508
514
|
|
|
@@ -524,13 +530,52 @@ class Popover extends PopoverPositionMixin(
|
|
|
524
530
|
ready() {
|
|
525
531
|
super.ready();
|
|
526
532
|
|
|
527
|
-
this._overlayElement = this
|
|
533
|
+
this._overlayElement = this.$.overlay;
|
|
534
|
+
|
|
535
|
+
if (!this.hasAttribute('role')) {
|
|
536
|
+
this.role = 'dialog';
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** @protected */
|
|
541
|
+
willUpdate(props) {
|
|
542
|
+
super.willUpdate(props);
|
|
543
|
+
|
|
544
|
+
if (props.has('overlayRole')) {
|
|
545
|
+
this.role = this.overlayRole;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/** @protected */
|
|
550
|
+
updated(props) {
|
|
551
|
+
super.updated(props);
|
|
552
|
+
|
|
553
|
+
if (props.has('accessibleName')) {
|
|
554
|
+
if (this.accessibleName) {
|
|
555
|
+
this.setAttribute('aria-label', this.accessibleName);
|
|
556
|
+
} else {
|
|
557
|
+
this.removeAttribute('aria-label');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (props.has('accessibleNameRef')) {
|
|
562
|
+
if (this.accessibleNameRef) {
|
|
563
|
+
this.setAttribute('aria-labelledby', this.accessibleNameRef);
|
|
564
|
+
} else {
|
|
565
|
+
this.removeAttribute('aria-labelledby');
|
|
566
|
+
}
|
|
567
|
+
}
|
|
528
568
|
}
|
|
529
569
|
|
|
530
570
|
/** @protected */
|
|
531
571
|
connectedCallback() {
|
|
532
572
|
super.connectedCallback();
|
|
533
573
|
|
|
574
|
+
// If no user ID is provided, set generated ID
|
|
575
|
+
if (!this.id) {
|
|
576
|
+
this.id = this.__generatedId;
|
|
577
|
+
}
|
|
578
|
+
|
|
534
579
|
document.documentElement.addEventListener('click', this.__onGlobalClick, true);
|
|
535
580
|
}
|
|
536
581
|
|
|
@@ -585,7 +630,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
585
630
|
}
|
|
586
631
|
|
|
587
632
|
/** @private */
|
|
588
|
-
__updateAriaAttributes(opened,
|
|
633
|
+
__updateAriaAttributes(opened, role, target) {
|
|
589
634
|
if (this.__oldTarget) {
|
|
590
635
|
const oldEffectiveTarget = this.__oldTarget.ariaTarget || this.__oldTarget;
|
|
591
636
|
oldEffectiveTarget.removeAttribute('aria-haspopup');
|
|
@@ -596,13 +641,13 @@ class Popover extends PopoverPositionMixin(
|
|
|
596
641
|
if (target) {
|
|
597
642
|
const effectiveTarget = target.ariaTarget || target;
|
|
598
643
|
|
|
599
|
-
const isDialog =
|
|
644
|
+
const isDialog = role === 'dialog' || role === 'alertdialog';
|
|
600
645
|
effectiveTarget.setAttribute('aria-haspopup', isDialog ? 'dialog' : 'true');
|
|
601
646
|
|
|
602
647
|
effectiveTarget.setAttribute('aria-expanded', opened ? 'true' : 'false');
|
|
603
648
|
|
|
604
649
|
if (opened) {
|
|
605
|
-
effectiveTarget.setAttribute('aria-controls', this.
|
|
650
|
+
effectiveTarget.setAttribute('aria-controls', this.id);
|
|
606
651
|
} else {
|
|
607
652
|
effectiveTarget.removeAttribute('aria-controls');
|
|
608
653
|
}
|
|
@@ -781,7 +826,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
781
826
|
return;
|
|
782
827
|
}
|
|
783
828
|
|
|
784
|
-
if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this.
|
|
829
|
+
if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this.contains(event.relatedTarget)) {
|
|
785
830
|
return;
|
|
786
831
|
}
|
|
787
832
|
|
|
@@ -809,7 +854,7 @@ class Popover extends PopoverPositionMixin(
|
|
|
809
854
|
return;
|
|
810
855
|
}
|
|
811
856
|
|
|
812
|
-
if (this.
|
|
857
|
+
if (this.contains(event.relatedTarget)) {
|
|
813
858
|
return;
|
|
814
859
|
}
|
|
815
860
|
|
|
@@ -840,7 +885,8 @@ class Popover extends PopoverPositionMixin(
|
|
|
840
885
|
if (
|
|
841
886
|
(this.__hasTrigger('focus') && this.__mouseDownInside) ||
|
|
842
887
|
event.relatedTarget === this.target ||
|
|
843
|
-
this._overlayElement
|
|
888
|
+
event.relatedTarget === this._overlayElement ||
|
|
889
|
+
this.contains(event.relatedTarget)
|
|
844
890
|
) {
|
|
845
891
|
return;
|
|
846
892
|
}
|
|
@@ -898,6 +944,11 @@ class Popover extends PopoverPositionMixin(
|
|
|
898
944
|
}
|
|
899
945
|
|
|
900
946
|
if (this.__hasTrigger('focus')) {
|
|
947
|
+
// Do not restore focus if closed on focusout on Tab
|
|
948
|
+
if (isKeyboardActive()) {
|
|
949
|
+
this.__shouldRestoreFocus = false;
|
|
950
|
+
}
|
|
951
|
+
|
|
901
952
|
this._openedStateController.close(true);
|
|
902
953
|
}
|
|
903
954
|
}
|
|
@@ -971,27 +1022,9 @@ class Popover extends PopoverPositionMixin(
|
|
|
971
1022
|
}
|
|
972
1023
|
|
|
973
1024
|
/** @private */
|
|
974
|
-
|
|
975
|
-
const prop = `--_vaadin-popover-content-${dimension}`;
|
|
976
|
-
|
|
977
|
-
if (value) {
|
|
978
|
-
overlay.style.setProperty(prop, value);
|
|
979
|
-
} else {
|
|
980
|
-
overlay.style.removeProperty(prop);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
/** @private */
|
|
985
|
-
__updateContentHeight(height, overlay) {
|
|
986
|
-
if (overlay) {
|
|
987
|
-
this.__updateDimension(overlay, 'height', height);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
/** @private */
|
|
992
|
-
__updateContentWidth(width, overlay) {
|
|
1025
|
+
__sizeChanged(width, height, overlay) {
|
|
993
1026
|
if (overlay) {
|
|
994
|
-
|
|
1027
|
+
requestAnimationFrame(() => overlay.setBounds({ width, height }, false));
|
|
995
1028
|
}
|
|
996
1029
|
}
|
|
997
1030
|
|
package/vaadin-popover.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-popover.js';
|
|
2
2
|
export * from './src/vaadin-popover.js';
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/popover",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha11",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-popover",
|
|
11
|
-
"description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\
|
|
11
|
+
"description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "overlay-class",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "accessible-name",
|
|
48
|
-
"description": "String used to label the
|
|
48
|
+
"description": "String used to label the popover to screen reader users.",
|
|
49
49
|
"value": {
|
|
50
50
|
"type": [
|
|
51
51
|
"string",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"name": "accessible-name-ref",
|
|
59
|
-
"description": "Id of the element used as label of the
|
|
59
|
+
"description": "Id of the element used as label of the popover to screen reader users.",
|
|
60
60
|
"value": {
|
|
61
61
|
"type": [
|
|
62
62
|
"string",
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
|
-
"name": "
|
|
81
|
-
"description": "
|
|
80
|
+
"name": "height",
|
|
81
|
+
"description": "Set the height of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
82
82
|
"value": {
|
|
83
83
|
"type": [
|
|
84
84
|
"string",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
|
-
"name": "
|
|
92
|
-
"description": "
|
|
91
|
+
"name": "width",
|
|
92
|
+
"description": "Set the width of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
93
93
|
"value": {
|
|
94
94
|
"type": [
|
|
95
95
|
"string",
|
|
@@ -142,6 +142,17 @@
|
|
|
142
142
|
]
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
|
+
{
|
|
146
|
+
"name": "role",
|
|
147
|
+
"description": "The `role` attribute value to be set on the popover.\nWhen not specified, defaults to 'dialog'.",
|
|
148
|
+
"value": {
|
|
149
|
+
"type": [
|
|
150
|
+
"string",
|
|
151
|
+
"null",
|
|
152
|
+
"undefined"
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
},
|
|
145
156
|
{
|
|
146
157
|
"name": "overlay-role",
|
|
147
158
|
"description": "The `role` attribute value to be set on the overlay.",
|
|
@@ -257,7 +268,7 @@
|
|
|
257
268
|
},
|
|
258
269
|
{
|
|
259
270
|
"name": "accessibleName",
|
|
260
|
-
"description": "String used to label the
|
|
271
|
+
"description": "String used to label the popover to screen reader users.",
|
|
261
272
|
"value": {
|
|
262
273
|
"type": [
|
|
263
274
|
"string",
|
|
@@ -268,7 +279,7 @@
|
|
|
268
279
|
},
|
|
269
280
|
{
|
|
270
281
|
"name": "accessibleNameRef",
|
|
271
|
-
"description": "Id of the element used as label of the
|
|
282
|
+
"description": "Id of the element used as label of the popover to screen reader users.",
|
|
272
283
|
"value": {
|
|
273
284
|
"type": [
|
|
274
285
|
"string",
|
|
@@ -289,8 +300,8 @@
|
|
|
289
300
|
}
|
|
290
301
|
},
|
|
291
302
|
{
|
|
292
|
-
"name": "
|
|
293
|
-
"description": "
|
|
303
|
+
"name": "height",
|
|
304
|
+
"description": "Set the height of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
294
305
|
"value": {
|
|
295
306
|
"type": [
|
|
296
307
|
"string",
|
|
@@ -300,8 +311,8 @@
|
|
|
300
311
|
}
|
|
301
312
|
},
|
|
302
313
|
{
|
|
303
|
-
"name": "
|
|
304
|
-
"description": "
|
|
314
|
+
"name": "width",
|
|
315
|
+
"description": "Set the width of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
305
316
|
"value": {
|
|
306
317
|
"type": [
|
|
307
318
|
"string",
|
|
@@ -354,6 +365,17 @@
|
|
|
354
365
|
]
|
|
355
366
|
}
|
|
356
367
|
},
|
|
368
|
+
{
|
|
369
|
+
"name": "role",
|
|
370
|
+
"description": "The `role` attribute value to be set on the popover.\nWhen not specified, defaults to 'dialog'.",
|
|
371
|
+
"value": {
|
|
372
|
+
"type": [
|
|
373
|
+
"string",
|
|
374
|
+
"null",
|
|
375
|
+
"undefined"
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
},
|
|
357
379
|
{
|
|
358
380
|
"name": "overlayRole",
|
|
359
381
|
"description": "The `role` attribute value to be set on the overlay.",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/popover",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha11",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"elements": [
|
|
17
17
|
{
|
|
18
18
|
"name": "vaadin-popover",
|
|
19
|
-
"description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\
|
|
19
|
+
"description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -91,28 +91,28 @@
|
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"name": ".accessibleName",
|
|
94
|
-
"description": "String used to label the
|
|
94
|
+
"description": "String used to label the popover to screen reader users.",
|
|
95
95
|
"value": {
|
|
96
96
|
"kind": "expression"
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"name": ".accessibleNameRef",
|
|
101
|
-
"description": "Id of the element used as label of the
|
|
101
|
+
"description": "Id of the element used as label of the popover to screen reader users.",
|
|
102
102
|
"value": {
|
|
103
103
|
"kind": "expression"
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
|
-
"name": ".
|
|
108
|
-
"description": "
|
|
107
|
+
"name": ".height",
|
|
108
|
+
"description": "Set the height of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
109
109
|
"value": {
|
|
110
110
|
"kind": "expression"
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
|
-
"name": ".
|
|
115
|
-
"description": "
|
|
114
|
+
"name": ".width",
|
|
115
|
+
"description": "Set the width of the overlay.\nIf a unitless number is provided, pixels are assumed.",
|
|
116
116
|
"value": {
|
|
117
117
|
"kind": "expression"
|
|
118
118
|
}
|
|
@@ -138,6 +138,13 @@
|
|
|
138
138
|
"kind": "expression"
|
|
139
139
|
}
|
|
140
140
|
},
|
|
141
|
+
{
|
|
142
|
+
"name": ".role",
|
|
143
|
+
"description": "The `role` attribute value to be set on the popover.\nWhen not specified, defaults to 'dialog'.",
|
|
144
|
+
"value": {
|
|
145
|
+
"kind": "expression"
|
|
146
|
+
}
|
|
147
|
+
},
|
|
141
148
|
{
|
|
142
149
|
"name": ".overlayRole",
|
|
143
150
|
"description": "The `role` attribute value to be set on the overlay.",
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/color.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
3
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
4
|
-
import '@vaadin/vaadin-lumo-styles/typography.js';
|
|
5
|
-
import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
|
|
6
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
7
|
-
|
|
8
|
-
const popoverOverlay = css`
|
|
9
|
-
:host {
|
|
10
|
-
--vaadin-popover-offset-top: var(--_vaadin-popover-default-offset);
|
|
11
|
-
--vaadin-popover-offset-bottom: var(--_vaadin-popover-default-offset);
|
|
12
|
-
--vaadin-popover-offset-start: var(--_vaadin-popover-default-offset);
|
|
13
|
-
--vaadin-popover-offset-end: var(--_vaadin-popover-default-offset);
|
|
14
|
-
--vaadin-popover-arrow-size: 0.5rem;
|
|
15
|
-
--_vaadin-popover-default-offset: var(--lumo-space-xs);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
[part='overlay'] {
|
|
19
|
-
outline: none;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
[part='content'] {
|
|
23
|
-
padding: var(--lumo-space-xs) var(--lumo-space-s);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
:host([theme~='no-padding']) [part='content'] {
|
|
27
|
-
padding: 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
:host([theme~='arrow']) {
|
|
31
|
-
--_vaadin-popover-default-offset: calc(var(--lumo-space-s) + var(--vaadin-popover-arrow-size) / 2);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/* top / bottom position */
|
|
35
|
-
:host([theme~='arrow'][position^='top']) [part='arrow'],
|
|
36
|
-
:host([theme~='arrow'][position^='bottom']) [part='arrow'] {
|
|
37
|
-
border-left: var(--vaadin-popover-arrow-size) solid transparent;
|
|
38
|
-
border-right: var(--vaadin-popover-arrow-size) solid transparent;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
:host([theme~='arrow'][position^='bottom'][bottom-aligned]) [part='arrow'],
|
|
42
|
-
:host([theme~='arrow'][position^='top'][bottom-aligned]) [part='arrow'] {
|
|
43
|
-
bottom: calc(var(--vaadin-popover-arrow-size) * -1);
|
|
44
|
-
border-top: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
|
|
45
|
-
filter: drop-shadow(0 2px 1px var(--lumo-shade-10pct));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
:host([theme~='arrow'][position^='bottom'][top-aligned]) [part='arrow'],
|
|
49
|
-
:host([theme~='arrow'][position^='top'][top-aligned]) [part='arrow'] {
|
|
50
|
-
top: calc(var(--vaadin-popover-arrow-size) * -1);
|
|
51
|
-
border-bottom: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
|
|
52
|
-
filter: drop-shadow(0 -2px 1px var(--lumo-shade-10pct));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
:host([theme~='arrow'][position^='bottom'][start-aligned]) [part='arrow'],
|
|
56
|
-
:host([theme~='arrow'][position^='top'][start-aligned]) [part='arrow'] {
|
|
57
|
-
transform: translateX(-50%);
|
|
58
|
-
inset-inline-start: 1.5rem;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
:host([theme~='arrow'][position^='bottom'][end-aligned]) [part='arrow'],
|
|
62
|
-
:host([theme~='arrow'][position^='top'][end-aligned]) [part='arrow'] {
|
|
63
|
-
transform: translateX(50%);
|
|
64
|
-
inset-inline-end: 1.5rem;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
:host([theme~='arrow'][position^='bottom'][arrow-centered]) [part='arrow'],
|
|
68
|
-
:host([theme~='arrow'][position^='top'][arrow-centered]) [part='arrow'] {
|
|
69
|
-
transform: translateX(-50%);
|
|
70
|
-
inset-inline-start: 50%;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/* start / end position */
|
|
74
|
-
:host([theme~='arrow'][position^='start']) [part='arrow'],
|
|
75
|
-
:host([theme~='arrow'][position^='end']) [part='arrow'] {
|
|
76
|
-
border-top: var(--vaadin-popover-arrow-size) solid transparent;
|
|
77
|
-
border-bottom: var(--vaadin-popover-arrow-size) solid transparent;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
:host([theme~='arrow'][position^='start'][start-aligned]) [part='arrow'],
|
|
81
|
-
:host([theme~='arrow'][position^='end'][start-aligned]) [part='arrow'] {
|
|
82
|
-
inset-inline-start: calc(var(--vaadin-popover-arrow-size) * -1);
|
|
83
|
-
border-right: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
|
|
84
|
-
filter: drop-shadow(-2px 0 1px var(--lumo-shade-10pct));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
:host([theme~='arrow'][position^='start'][end-aligned]) [part='arrow'],
|
|
88
|
-
:host([theme~='arrow'][position^='end'][end-aligned]) [part='arrow'] {
|
|
89
|
-
inset-inline-end: calc(var(--vaadin-popover-arrow-size) * -1);
|
|
90
|
-
border-left: var(--vaadin-popover-arrow-size) solid var(--lumo-base-color);
|
|
91
|
-
filter: drop-shadow(2px 0 1px var(--lumo-shade-10pct));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
:host([theme~='arrow'][position^='start'][top-aligned]) [part='arrow'],
|
|
95
|
-
:host([theme~='arrow'][position^='end'][top-aligned]) [part='arrow'] {
|
|
96
|
-
top: 0.5rem;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
:host([theme~='arrow'][position='start'][top-aligned]) [part='arrow'],
|
|
100
|
-
:host([theme~='arrow'][position='end'][top-aligned]) [part='arrow'] {
|
|
101
|
-
top: 50%;
|
|
102
|
-
transform: translateY(-50%);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
:host([theme~='arrow'][position^='start'][bottom-aligned]) [part='arrow'],
|
|
106
|
-
:host([theme~='arrow'][position^='end'][bottom-aligned]) [part='arrow'] {
|
|
107
|
-
bottom: 0.5rem;
|
|
108
|
-
}
|
|
109
|
-
`;
|
|
110
|
-
|
|
111
|
-
registerStyles('vaadin-popover-overlay', [overlay, popoverOverlay], { moduleId: 'lumo-popover-overlay' });
|