@vaadin/tooltip 23.3.0-alpha1 → 23.3.0-alpha3
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 +7 -7
- package/src/vaadin-tooltip-overlay.js +11 -0
- package/src/vaadin-tooltip.d.ts +8 -6
- package/src/vaadin-tooltip.js +271 -175
- package/theme/lumo/vaadin-tooltip-styles.js +2 -2
- package/web-types.json +7 -7
- package/web-types.lit.json +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/tooltip",
|
|
3
|
-
"version": "23.3.0-
|
|
3
|
+
"version": "23.3.0-alpha3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@polymer/polymer": "^3.0.0",
|
|
38
|
-
"@vaadin/component-base": "23.3.0-
|
|
39
|
-
"@vaadin/vaadin-lumo-styles": "23.3.0-
|
|
40
|
-
"@vaadin/vaadin-material-styles": "23.3.0-
|
|
41
|
-
"@vaadin/vaadin-overlay": "23.3.0-
|
|
42
|
-
"@vaadin/vaadin-themable-mixin": "23.3.0-
|
|
38
|
+
"@vaadin/component-base": "23.3.0-alpha3",
|
|
39
|
+
"@vaadin/vaadin-lumo-styles": "23.3.0-alpha3",
|
|
40
|
+
"@vaadin/vaadin-material-styles": "23.3.0-alpha3",
|
|
41
|
+
"@vaadin/vaadin-overlay": "23.3.0-alpha3",
|
|
42
|
+
"@vaadin/vaadin-themable-mixin": "23.3.0-alpha3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@esm-bundle/chai": "^4.3.4",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"web-types.json",
|
|
51
51
|
"web-types.lit.json"
|
|
52
52
|
],
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "e86cd2abf3e28bade37711291331415d92c454ec"
|
|
54
54
|
}
|
|
@@ -64,6 +64,17 @@ class TooltipOverlay extends PositionMixin(OverlayElement) {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/** @protected */
|
|
68
|
+
ready() {
|
|
69
|
+
super.ready();
|
|
70
|
+
|
|
71
|
+
// When setting `manual` and `opened` attributes, the overlay is already moved to body
|
|
72
|
+
// by the time when `ready()` callback of the `vaadin-tooltip` is executed by Polymer,
|
|
73
|
+
// so querySelector() would return null. So we use this workaround to set properties.
|
|
74
|
+
this.owner = this.__dataHost;
|
|
75
|
+
this.owner._overlayElement = this;
|
|
76
|
+
}
|
|
77
|
+
|
|
67
78
|
requestContentUpdate() {
|
|
68
79
|
super.requestContentUpdate();
|
|
69
80
|
|
package/src/vaadin-tooltip.d.ts
CHANGED
|
@@ -78,14 +78,15 @@ declare class Tooltip extends ThemePropertyMixin(ElementMixin(HTMLElement)) {
|
|
|
78
78
|
static setDefaultHoverDelay(delay: number): void;
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* Object with properties passed to `
|
|
82
|
-
*
|
|
81
|
+
* Object with properties passed to `generator` and
|
|
82
|
+
* `shouldShow` functions for generating tooltip text
|
|
83
|
+
* or detecting whether to show the tooltip or not.
|
|
83
84
|
*/
|
|
84
85
|
context: Record<string, unknown>;
|
|
85
86
|
|
|
86
87
|
/**
|
|
87
88
|
* The delay in milliseconds before the tooltip
|
|
88
|
-
* is opened on focus, when not in manual mode.
|
|
89
|
+
* is opened on keyboard focus, when not in manual mode.
|
|
89
90
|
* @attr {number} focus-delay
|
|
90
91
|
*/
|
|
91
92
|
focusDelay: number;
|
|
@@ -135,10 +136,11 @@ declare class Tooltip extends ThemePropertyMixin(ElementMixin(HTMLElement)) {
|
|
|
135
136
|
/**
|
|
136
137
|
* Function used to detect whether to show the tooltip based on a condition,
|
|
137
138
|
* called every time the tooltip is about to be shown on hover and focus.
|
|
138
|
-
* The function
|
|
139
|
+
* The function takes two parameters: `target` and `context`, which contain
|
|
140
|
+
* values of the corresponding tooltip properties at the time of calling.
|
|
139
141
|
* The tooltip is only shown when the function invocation returns `true`.
|
|
140
142
|
*/
|
|
141
|
-
shouldShow: (target: HTMLElement) => boolean;
|
|
143
|
+
shouldShow: (target: HTMLElement, context?: Record<string, unknown>) => boolean;
|
|
142
144
|
|
|
143
145
|
/**
|
|
144
146
|
* Reference to the element used as a tooltip trigger.
|
|
@@ -158,7 +160,7 @@ declare class Tooltip extends ThemePropertyMixin(ElementMixin(HTMLElement)) {
|
|
|
158
160
|
* Use the `context` property to provide argument
|
|
159
161
|
* that can be passed to the generator function.
|
|
160
162
|
*/
|
|
161
|
-
|
|
163
|
+
generator: (context: Record<string, unknown>) => string;
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
declare global {
|
package/src/vaadin-tooltip.js
CHANGED
|
@@ -23,6 +23,174 @@ let warmedUp = false;
|
|
|
23
23
|
let warmUpTimeout = null;
|
|
24
24
|
let cooldownTimeout = null;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Controller for handling tooltip opened state.
|
|
28
|
+
*/
|
|
29
|
+
class TooltipStateController {
|
|
30
|
+
constructor(host) {
|
|
31
|
+
this.host = host;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Schedule opening the tooltip.
|
|
36
|
+
* @param {Object} options
|
|
37
|
+
*/
|
|
38
|
+
open(options = { immediate: false }) {
|
|
39
|
+
const { immediate, hover, focus } = options;
|
|
40
|
+
const isHover = hover && this.hoverDelay > 0;
|
|
41
|
+
const isFocus = focus && this.focusDelay > 0;
|
|
42
|
+
|
|
43
|
+
if (!immediate && (isHover || isFocus) && !this.__closeTimeout) {
|
|
44
|
+
this.__warmupTooltip(isFocus);
|
|
45
|
+
} else {
|
|
46
|
+
this.__showTooltip();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Schedule closing the tooltip.
|
|
52
|
+
* @param {boolean} immediate
|
|
53
|
+
*/
|
|
54
|
+
close(immediate) {
|
|
55
|
+
if (!immediate && this.hideDelay > 0) {
|
|
56
|
+
this.__scheduleClose();
|
|
57
|
+
} else {
|
|
58
|
+
this.__abortClose();
|
|
59
|
+
this._setOpened(false);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.__abortWarmUp();
|
|
63
|
+
|
|
64
|
+
if (warmedUp) {
|
|
65
|
+
// Re-start cooldown timer on each tooltip closing.
|
|
66
|
+
this.__abortCooldown();
|
|
67
|
+
this.__scheduleCooldown();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** @private */
|
|
72
|
+
get openedProp() {
|
|
73
|
+
return this.host.manual ? 'opened' : '_autoOpened';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** @private */
|
|
77
|
+
get focusDelay() {
|
|
78
|
+
const tooltip = this.host;
|
|
79
|
+
return tooltip.focusDelay != null && tooltip.focusDelay > 0 ? tooltip.focusDelay : defaultFocusDelay;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** @private */
|
|
83
|
+
get hoverDelay() {
|
|
84
|
+
const tooltip = this.host;
|
|
85
|
+
return tooltip.hoverDelay != null && tooltip.hoverDelay > 0 ? tooltip.hoverDelay : defaultHoverDelay;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** @private */
|
|
89
|
+
get hideDelay() {
|
|
90
|
+
const tooltip = this.host;
|
|
91
|
+
return tooltip.hideDelay != null && tooltip.hideDelay > 0 ? tooltip.hideDelay : defaultHideDelay;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @private */
|
|
95
|
+
_isOpened() {
|
|
96
|
+
return this.host[this.openedProp];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** @private */
|
|
100
|
+
_setOpened(opened) {
|
|
101
|
+
this.host[this.openedProp] = opened;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @private */
|
|
105
|
+
__flushClosingTooltips() {
|
|
106
|
+
closing.forEach((tooltip) => {
|
|
107
|
+
tooltip._stateController.close(true);
|
|
108
|
+
closing.delete(tooltip);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** @private */
|
|
113
|
+
__showTooltip() {
|
|
114
|
+
this.__abortClose();
|
|
115
|
+
this.__flushClosingTooltips();
|
|
116
|
+
|
|
117
|
+
this._setOpened(true);
|
|
118
|
+
warmedUp = true;
|
|
119
|
+
|
|
120
|
+
// Abort previously scheduled timers.
|
|
121
|
+
this.__abortWarmUp();
|
|
122
|
+
this.__abortCooldown();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** @private */
|
|
126
|
+
__warmupTooltip(isFocus) {
|
|
127
|
+
if (!this._isOpened()) {
|
|
128
|
+
// First tooltip is opened, warm up.
|
|
129
|
+
if (!warmedUp) {
|
|
130
|
+
this.__scheduleWarmUp(isFocus);
|
|
131
|
+
} else {
|
|
132
|
+
// Warmed up, show another tooltip.
|
|
133
|
+
this.__showTooltip();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** @private */
|
|
139
|
+
__abortClose() {
|
|
140
|
+
if (this.__closeTimeout) {
|
|
141
|
+
clearTimeout(this.__closeTimeout);
|
|
142
|
+
this.__closeTimeout = null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** @private */
|
|
147
|
+
__abortCooldown() {
|
|
148
|
+
if (cooldownTimeout) {
|
|
149
|
+
clearTimeout(cooldownTimeout);
|
|
150
|
+
cooldownTimeout = null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** @private */
|
|
155
|
+
__abortWarmUp() {
|
|
156
|
+
if (warmUpTimeout) {
|
|
157
|
+
clearTimeout(warmUpTimeout);
|
|
158
|
+
warmUpTimeout = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** @private */
|
|
163
|
+
__scheduleClose() {
|
|
164
|
+
if (this._isOpened()) {
|
|
165
|
+
closing.add(this.host);
|
|
166
|
+
|
|
167
|
+
this.__closeTimeout = setTimeout(() => {
|
|
168
|
+
closing.delete(this.host);
|
|
169
|
+
this.__closeTimeout = null;
|
|
170
|
+
this._setOpened(false);
|
|
171
|
+
}, this.hideDelay);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** @private */
|
|
176
|
+
__scheduleCooldown() {
|
|
177
|
+
cooldownTimeout = setTimeout(() => {
|
|
178
|
+
cooldownTimeout = null;
|
|
179
|
+
warmedUp = false;
|
|
180
|
+
}, this.hideDelay);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** @private */
|
|
184
|
+
__scheduleWarmUp(isFocus) {
|
|
185
|
+
const delay = isFocus ? this.focusDelay : this.hoverDelay;
|
|
186
|
+
warmUpTimeout = setTimeout(() => {
|
|
187
|
+
warmUpTimeout = null;
|
|
188
|
+
warmedUp = true;
|
|
189
|
+
this.__showTooltip();
|
|
190
|
+
}, delay);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
26
194
|
/**
|
|
27
195
|
* `<vaadin-tooltip>` is a Web Component for creating tooltips.
|
|
28
196
|
*
|
|
@@ -82,13 +250,14 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
82
250
|
role="tooltip"
|
|
83
251
|
renderer="[[_renderer]]"
|
|
84
252
|
theme$="[[_theme]]"
|
|
85
|
-
opened="[[__computeOpened(manual, opened, _autoOpened)]]"
|
|
253
|
+
opened="[[__computeOpened(manual, opened, _autoOpened, _isConnected)]]"
|
|
86
254
|
position-target="[[target]]"
|
|
87
|
-
position="[[
|
|
88
|
-
no-horizontal-overlap$="[[__computeNoHorizontalOverlap(
|
|
89
|
-
no-vertical-overlap$="[[__computeNoVerticalOverlap(
|
|
90
|
-
horizontal-align="[[__computeHorizontalAlign(
|
|
91
|
-
vertical-align="[[__computeVerticalAlign(
|
|
255
|
+
position="[[__effectivePosition]]"
|
|
256
|
+
no-horizontal-overlap$="[[__computeNoHorizontalOverlap(__effectivePosition)]]"
|
|
257
|
+
no-vertical-overlap$="[[__computeNoVerticalOverlap(__effectivePosition)]]"
|
|
258
|
+
horizontal-align="[[__computeHorizontalAlign(__effectivePosition)]]"
|
|
259
|
+
vertical-align="[[__computeVerticalAlign(__effectivePosition)]]"
|
|
260
|
+
on-mouseleave="__onOverlayMouseLeave"
|
|
92
261
|
modeless
|
|
93
262
|
></vaadin-tooltip-overlay>
|
|
94
263
|
`;
|
|
@@ -97,8 +266,9 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
97
266
|
static get properties() {
|
|
98
267
|
return {
|
|
99
268
|
/**
|
|
100
|
-
* Object with properties passed to `
|
|
101
|
-
*
|
|
269
|
+
* Object with properties passed to `generator` and
|
|
270
|
+
* `shouldShow` functions for generating tooltip text
|
|
271
|
+
* or detecting whether to show the tooltip or not.
|
|
102
272
|
*/
|
|
103
273
|
context: {
|
|
104
274
|
type: Object,
|
|
@@ -109,7 +279,7 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
109
279
|
|
|
110
280
|
/**
|
|
111
281
|
* The delay in milliseconds before the tooltip
|
|
112
|
-
* is opened on focus, when not in manual mode.
|
|
282
|
+
* is opened on keyboard focus, when not in manual mode.
|
|
113
283
|
* @attr {number} focus-delay
|
|
114
284
|
*/
|
|
115
285
|
focusDelay: {
|
|
@@ -171,19 +341,19 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
171
341
|
*/
|
|
172
342
|
position: {
|
|
173
343
|
type: String,
|
|
174
|
-
value: 'bottom',
|
|
175
344
|
},
|
|
176
345
|
|
|
177
346
|
/**
|
|
178
347
|
* Function used to detect whether to show the tooltip based on a condition,
|
|
179
348
|
* called every time the tooltip is about to be shown on hover and focus.
|
|
180
|
-
* The function
|
|
349
|
+
* The function takes two parameters: `target` and `context`, which contain
|
|
350
|
+
* values of the corresponding tooltip properties at the time of calling.
|
|
181
351
|
* The tooltip is only shown when the function invocation returns `true`.
|
|
182
352
|
*/
|
|
183
353
|
shouldShow: {
|
|
184
354
|
type: Object,
|
|
185
355
|
value: () => {
|
|
186
|
-
return (_target) => true;
|
|
356
|
+
return (_target, _context) => true;
|
|
187
357
|
},
|
|
188
358
|
},
|
|
189
359
|
|
|
@@ -211,7 +381,7 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
211
381
|
* Use the `context` property to provide argument
|
|
212
382
|
* that can be passed to the generator function.
|
|
213
383
|
*/
|
|
214
|
-
|
|
384
|
+
generator: {
|
|
215
385
|
type: Object,
|
|
216
386
|
},
|
|
217
387
|
|
|
@@ -225,6 +395,21 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
225
395
|
observer: '__autoOpenedChanged',
|
|
226
396
|
},
|
|
227
397
|
|
|
398
|
+
/**
|
|
399
|
+
* Default value used when `position` property is not set.
|
|
400
|
+
* @protected
|
|
401
|
+
*/
|
|
402
|
+
_position: {
|
|
403
|
+
type: String,
|
|
404
|
+
value: 'bottom',
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
/** @private */
|
|
408
|
+
__effectivePosition: {
|
|
409
|
+
type: String,
|
|
410
|
+
computed: '__computePosition(position, _position)',
|
|
411
|
+
},
|
|
412
|
+
|
|
228
413
|
/** @protected */
|
|
229
414
|
_overlayElement: Object,
|
|
230
415
|
|
|
@@ -233,11 +418,16 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
233
418
|
type: Boolean,
|
|
234
419
|
value: false,
|
|
235
420
|
},
|
|
421
|
+
|
|
422
|
+
/** @private */
|
|
423
|
+
_isConnected: {
|
|
424
|
+
type: Boolean,
|
|
425
|
+
},
|
|
236
426
|
};
|
|
237
427
|
}
|
|
238
428
|
|
|
239
429
|
static get observers() {
|
|
240
|
-
return ['
|
|
430
|
+
return ['__generatorChanged(_overlayElement, generator, context)'];
|
|
241
431
|
}
|
|
242
432
|
|
|
243
433
|
/**
|
|
@@ -289,14 +479,15 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
289
479
|
},
|
|
290
480
|
{ threshold: 1 },
|
|
291
481
|
);
|
|
482
|
+
|
|
483
|
+
this._stateController = new TooltipStateController(this);
|
|
292
484
|
}
|
|
293
485
|
|
|
294
486
|
/** @protected */
|
|
295
|
-
|
|
296
|
-
super.
|
|
487
|
+
connectedCallback() {
|
|
488
|
+
super.connectedCallback();
|
|
297
489
|
|
|
298
|
-
this.
|
|
299
|
-
this._overlayElement.owner = this;
|
|
490
|
+
this._isConnected = true;
|
|
300
491
|
}
|
|
301
492
|
|
|
302
493
|
/** @protected */
|
|
@@ -304,8 +495,9 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
304
495
|
super.disconnectedCallback();
|
|
305
496
|
|
|
306
497
|
if (this._autoOpened) {
|
|
307
|
-
this.
|
|
498
|
+
this._stateController.close(true);
|
|
308
499
|
}
|
|
500
|
+
this._isConnected = false;
|
|
309
501
|
}
|
|
310
502
|
|
|
311
503
|
/** @private */
|
|
@@ -329,13 +521,18 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
329
521
|
}
|
|
330
522
|
|
|
331
523
|
/** @private */
|
|
332
|
-
__computeOpened(manual, opened, autoOpened) {
|
|
333
|
-
return manual ? opened : autoOpened;
|
|
524
|
+
__computeOpened(manual, opened, autoOpened, connected) {
|
|
525
|
+
return connected && (manual ? opened : autoOpened);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** @private */
|
|
529
|
+
__computePosition(position, defaultPosition) {
|
|
530
|
+
return position || defaultPosition;
|
|
334
531
|
}
|
|
335
532
|
|
|
336
533
|
/** @private */
|
|
337
534
|
__tooltipRenderer(root) {
|
|
338
|
-
root.textContent = typeof this.
|
|
535
|
+
root.textContent = typeof this.generator === 'function' ? this.generator(this.context) : this.text;
|
|
339
536
|
}
|
|
340
537
|
|
|
341
538
|
/** @private */
|
|
@@ -381,7 +578,10 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
381
578
|
target.addEventListener('focusout', this.__onFocusout);
|
|
382
579
|
target.addEventListener('mousedown', this.__onMouseDown);
|
|
383
580
|
|
|
384
|
-
|
|
581
|
+
// Wait before observing to avoid Chrome issue.
|
|
582
|
+
requestAnimationFrame(() => {
|
|
583
|
+
this.__targetVisibilityObserver.observe(target);
|
|
584
|
+
});
|
|
385
585
|
|
|
386
586
|
addValueToAttribute(target, 'aria-describedby', this._uniqueId);
|
|
387
587
|
}
|
|
@@ -389,6 +589,10 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
389
589
|
|
|
390
590
|
/** @private */
|
|
391
591
|
__onFocusin(event) {
|
|
592
|
+
if (this.manual) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
|
|
392
596
|
// Only open on keyboard focus.
|
|
393
597
|
if (!isKeyboardActive()) {
|
|
394
598
|
return;
|
|
@@ -399,19 +603,23 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
399
603
|
return;
|
|
400
604
|
}
|
|
401
605
|
|
|
402
|
-
if (
|
|
606
|
+
if (!this.__isShouldShow()) {
|
|
403
607
|
return;
|
|
404
608
|
}
|
|
405
609
|
|
|
406
610
|
this.__focusInside = true;
|
|
407
611
|
|
|
408
612
|
if (!this.__isTargetHidden && (!this.__hoverInside || !this._autoOpened)) {
|
|
409
|
-
this.
|
|
613
|
+
this._stateController.open({ focus: true });
|
|
410
614
|
}
|
|
411
615
|
}
|
|
412
616
|
|
|
413
617
|
/** @private */
|
|
414
618
|
__onFocusout(event) {
|
|
619
|
+
if (this.manual) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
|
|
415
623
|
// Do not close when moving focus within a component.
|
|
416
624
|
if (this.target.contains(event.relatedTarget)) {
|
|
417
625
|
return;
|
|
@@ -420,7 +628,7 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
420
628
|
this.__focusInside = false;
|
|
421
629
|
|
|
422
630
|
if (!this.__hoverInside) {
|
|
423
|
-
this.
|
|
631
|
+
this._stateController.close(true);
|
|
424
632
|
}
|
|
425
633
|
}
|
|
426
634
|
|
|
@@ -428,18 +636,22 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
428
636
|
__onKeyDown(event) {
|
|
429
637
|
if (event.key === 'Escape') {
|
|
430
638
|
event.stopPropagation();
|
|
431
|
-
this.
|
|
639
|
+
this._stateController.close(true);
|
|
432
640
|
}
|
|
433
641
|
}
|
|
434
642
|
|
|
435
643
|
/** @private */
|
|
436
644
|
__onMouseDown() {
|
|
437
|
-
this.
|
|
645
|
+
this._stateController.close(true);
|
|
438
646
|
}
|
|
439
647
|
|
|
440
648
|
/** @private */
|
|
441
649
|
__onMouseEnter() {
|
|
442
|
-
if (
|
|
650
|
+
if (this.manual) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (!this.__isShouldShow()) {
|
|
443
655
|
return;
|
|
444
656
|
}
|
|
445
657
|
|
|
@@ -451,16 +663,34 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
451
663
|
this.__hoverInside = true;
|
|
452
664
|
|
|
453
665
|
if (!this.__isTargetHidden && (!this.__focusInside || !this._autoOpened)) {
|
|
454
|
-
this.
|
|
666
|
+
this._stateController.open({ hover: true });
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** @private */
|
|
671
|
+
__onMouseLeave(event) {
|
|
672
|
+
if (event.relatedTarget !== this._overlayElement) {
|
|
673
|
+
this.__handleMouseLeave();
|
|
455
674
|
}
|
|
456
675
|
}
|
|
457
676
|
|
|
458
677
|
/** @private */
|
|
459
|
-
|
|
678
|
+
__onOverlayMouseLeave(event) {
|
|
679
|
+
if (event.relatedTarget !== this.target) {
|
|
680
|
+
this.__handleMouseLeave();
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/** @private */
|
|
685
|
+
__handleMouseLeave() {
|
|
686
|
+
if (this.manual) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
|
|
460
690
|
this.__hoverInside = false;
|
|
461
691
|
|
|
462
692
|
if (!this.__focusInside) {
|
|
463
|
-
this.
|
|
693
|
+
this._stateController.close();
|
|
464
694
|
}
|
|
465
695
|
}
|
|
466
696
|
|
|
@@ -471,157 +701,23 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
471
701
|
|
|
472
702
|
// Open the overlay when the target becomes visible and has focus or hover.
|
|
473
703
|
if (oldHidden && isVisible && (this.__focusInside || this.__hoverInside)) {
|
|
474
|
-
this.
|
|
704
|
+
this._stateController.open({ immediate: true });
|
|
475
705
|
return;
|
|
476
706
|
}
|
|
477
707
|
|
|
478
708
|
// Close the overlay when the target is no longer fully visible.
|
|
479
709
|
if (!isVisible && this._autoOpened) {
|
|
480
|
-
this.
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* Schedule opening the tooltip.
|
|
486
|
-
* @param {boolean} immediate
|
|
487
|
-
* @protected
|
|
488
|
-
*/
|
|
489
|
-
_open(options = { immediate: false }) {
|
|
490
|
-
const { immediate, hover, focus } = options;
|
|
491
|
-
const isHover = hover && this.__getHoverDelay() > 0;
|
|
492
|
-
const isFocus = focus && this.__getFocusDelay() > 0;
|
|
493
|
-
|
|
494
|
-
if (!immediate && (isHover || isFocus) && !this.__closeTimeout) {
|
|
495
|
-
this.__warmupTooltip(isFocus);
|
|
496
|
-
} else {
|
|
497
|
-
this.__showTooltip();
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Schedule closing the tooltip.
|
|
503
|
-
* @param {boolean} immediate
|
|
504
|
-
* @protected
|
|
505
|
-
*/
|
|
506
|
-
_close(immediate) {
|
|
507
|
-
if (!immediate && this.__getHideDelay() > 0) {
|
|
508
|
-
this.__scheduleClose();
|
|
509
|
-
} else {
|
|
510
|
-
this.__abortClose();
|
|
511
|
-
this._autoOpened = false;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
this.__abortWarmUp();
|
|
515
|
-
|
|
516
|
-
if (warmedUp) {
|
|
517
|
-
// Re-start cooldown timer on each tooltip closing.
|
|
518
|
-
this.__abortCooldown();
|
|
519
|
-
this.__scheduleCooldown();
|
|
710
|
+
this._stateController.close(true);
|
|
520
711
|
}
|
|
521
712
|
}
|
|
522
713
|
|
|
523
714
|
/** @private */
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
/** @private */
|
|
529
|
-
__getHoverDelay() {
|
|
530
|
-
return this.hoverDelay != null && this.hoverDelay > 0 ? this.hoverDelay : defaultHoverDelay;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/** @private */
|
|
534
|
-
__getHideDelay() {
|
|
535
|
-
return this.hideDelay != null && this.hideDelay > 0 ? this.hideDelay : defaultHideDelay;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/** @private */
|
|
539
|
-
__flushClosingTooltips() {
|
|
540
|
-
closing.forEach((tooltip) => {
|
|
541
|
-
tooltip._close(true);
|
|
542
|
-
closing.delete(tooltip);
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
/** @private */
|
|
547
|
-
__showTooltip() {
|
|
548
|
-
this.__abortClose();
|
|
549
|
-
this.__flushClosingTooltips();
|
|
550
|
-
|
|
551
|
-
this._autoOpened = true;
|
|
552
|
-
warmedUp = true;
|
|
553
|
-
|
|
554
|
-
// Abort previously scheduled timers.
|
|
555
|
-
this.__abortWarmUp();
|
|
556
|
-
this.__abortCooldown();
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/** @private */
|
|
560
|
-
__warmupTooltip(isFocus) {
|
|
561
|
-
if (!this._autoOpened) {
|
|
562
|
-
// First tooltip is opened, warm up.
|
|
563
|
-
if (!warmedUp) {
|
|
564
|
-
this.__scheduleWarmUp(isFocus);
|
|
565
|
-
} else {
|
|
566
|
-
// Warmed up, show another tooltip.
|
|
567
|
-
this.__showTooltip();
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
/** @private */
|
|
573
|
-
__abortClose() {
|
|
574
|
-
if (this.__closeTimeout) {
|
|
575
|
-
clearTimeout(this.__closeTimeout);
|
|
576
|
-
this.__closeTimeout = null;
|
|
715
|
+
__isShouldShow() {
|
|
716
|
+
if (typeof this.shouldShow === 'function' && this.shouldShow(this.target, this.context) !== true) {
|
|
717
|
+
return false;
|
|
577
718
|
}
|
|
578
|
-
}
|
|
579
719
|
|
|
580
|
-
|
|
581
|
-
__abortCooldown() {
|
|
582
|
-
if (cooldownTimeout) {
|
|
583
|
-
clearTimeout(cooldownTimeout);
|
|
584
|
-
cooldownTimeout = null;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/** @private */
|
|
589
|
-
__abortWarmUp() {
|
|
590
|
-
if (warmUpTimeout) {
|
|
591
|
-
clearTimeout(warmUpTimeout);
|
|
592
|
-
warmUpTimeout = null;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
/** @private */
|
|
597
|
-
__scheduleClose() {
|
|
598
|
-
if (this._autoOpened) {
|
|
599
|
-
closing.add(this);
|
|
600
|
-
|
|
601
|
-
this.__closeTimeout = setTimeout(() => {
|
|
602
|
-
closing.delete(this);
|
|
603
|
-
this.__closeTimeout = null;
|
|
604
|
-
this._autoOpened = false;
|
|
605
|
-
}, this.__getHideDelay());
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
/** @private */
|
|
610
|
-
__scheduleCooldown() {
|
|
611
|
-
cooldownTimeout = setTimeout(() => {
|
|
612
|
-
cooldownTimeout = null;
|
|
613
|
-
warmedUp = false;
|
|
614
|
-
}, this.__getHideDelay());
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
/** @private */
|
|
618
|
-
__scheduleWarmUp(isFocus) {
|
|
619
|
-
const delay = isFocus ? this.__getFocusDelay() : this.__getHoverDelay();
|
|
620
|
-
warmUpTimeout = setTimeout(() => {
|
|
621
|
-
warmUpTimeout = null;
|
|
622
|
-
warmedUp = true;
|
|
623
|
-
this.__showTooltip();
|
|
624
|
-
}, delay);
|
|
720
|
+
return true;
|
|
625
721
|
}
|
|
626
722
|
|
|
627
723
|
/** @private */
|
|
@@ -632,13 +728,13 @@ class Tooltip extends ThemePropertyMixin(ElementMixin(PolymerElement)) {
|
|
|
632
728
|
}
|
|
633
729
|
|
|
634
730
|
/** @private */
|
|
635
|
-
|
|
731
|
+
__generatorChanged(overlayElement, generator, context) {
|
|
636
732
|
if (overlayElement) {
|
|
637
|
-
if (
|
|
733
|
+
if (generator !== this.__oldTextGenerator || context !== this.__oldContext) {
|
|
638
734
|
overlayElement.requestContentUpdate();
|
|
639
735
|
}
|
|
640
736
|
|
|
641
|
-
this.__oldTextGenerator =
|
|
737
|
+
this.__oldTextGenerator = generator;
|
|
642
738
|
this.__oldContext = context;
|
|
643
739
|
}
|
|
644
740
|
}
|
|
@@ -12,8 +12,8 @@ const tooltipOverlay = css`
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
[part='overlay'] {
|
|
15
|
-
background-color
|
|
16
|
-
color: var(--lumo-
|
|
15
|
+
background: var(--lumo-base-color) linear-gradient(var(--lumo-contrast-5pct), var(--lumo-contrast-5pct));
|
|
16
|
+
color: var(--lumo-body-text-color);
|
|
17
17
|
font-size: var(--lumo-font-size-xs);
|
|
18
18
|
}
|
|
19
19
|
|
package/web-types.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/tooltip",
|
|
4
|
-
"version": "23.3.0-
|
|
4
|
+
"version": "23.3.0-alpha3",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-tooltip",
|
|
11
|
-
"description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/23.3.0-
|
|
11
|
+
"description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/23.3.0-alpha3/#/elements/vaadin-overlay) documentation\nfor `<vaadin-tooltip-overlay>` parts.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-tooltip>` is\npropagated to the internal `<vaadin-tooltip-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "focus-delay",
|
|
15
|
-
"description": "The delay in milliseconds before the tooltip\nis opened on focus, when not in manual mode.",
|
|
15
|
+
"description": "The delay in milliseconds before the tooltip\nis opened on keyboard focus, when not in manual mode.",
|
|
16
16
|
"value": {
|
|
17
17
|
"type": [
|
|
18
18
|
"number",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"properties": [
|
|
115
115
|
{
|
|
116
116
|
"name": "context",
|
|
117
|
-
"description": "Object with properties passed to `
|
|
117
|
+
"description": "Object with properties passed to `generator` and\n`shouldShow` functions for generating tooltip text\nor detecting whether to show the tooltip or not.",
|
|
118
118
|
"value": {
|
|
119
119
|
"type": [
|
|
120
120
|
"Object",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"name": "focusDelay",
|
|
128
|
-
"description": "The delay in milliseconds before the tooltip\nis opened on focus, when not in manual mode.",
|
|
128
|
+
"description": "The delay in milliseconds before the tooltip\nis opened on keyboard focus, when not in manual mode.",
|
|
129
129
|
"value": {
|
|
130
130
|
"type": [
|
|
131
131
|
"number",
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
},
|
|
203
203
|
{
|
|
204
204
|
"name": "shouldShow",
|
|
205
|
-
"description": "Function used to detect whether to show the tooltip based on a condition,\ncalled every time the tooltip is about to be shown on hover and focus.\nThe function
|
|
205
|
+
"description": "Function used to detect whether to show the tooltip based on a condition,\ncalled every time the tooltip is about to be shown on hover and focus.\nThe function takes two parameters: `target` and `context`, which contain\nvalues of the corresponding tooltip properties at the time of calling.\nThe tooltip is only shown when the function invocation returns `true`.",
|
|
206
206
|
"value": {
|
|
207
207
|
"type": [
|
|
208
208
|
"Object",
|
|
@@ -234,7 +234,7 @@
|
|
|
234
234
|
}
|
|
235
235
|
},
|
|
236
236
|
{
|
|
237
|
-
"name": "
|
|
237
|
+
"name": "generator",
|
|
238
238
|
"description": "Function used to generate the tooltip content.\nWhen provided, it overrides the `text` property.\nUse the `context` property to provide argument\nthat can be passed to the generator function.",
|
|
239
239
|
"value": {
|
|
240
240
|
"type": [
|
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/tooltip",
|
|
4
|
-
"version": "23.3.0-
|
|
4
|
+
"version": "23.3.0-alpha3",
|
|
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-tooltip",
|
|
19
|
-
"description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/23.3.0-
|
|
19
|
+
"description": "`<vaadin-tooltip>` is a Web Component for creating tooltips.\n\n```html\n<button id=\"confirm\">Confirm</button>\n<vaadin-tooltip text=\"Click to save changes\" for=\"confirm\"></vaadin-tooltip>\n```\n\n### Styling\n\n`<vaadin-tooltip>` uses `<vaadin-tooltip-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/23.3.0-alpha3/#/elements/vaadin-overlay) documentation\nfor `<vaadin-tooltip-overlay>` parts.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-tooltip>` is\npropagated to the internal `<vaadin-tooltip-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-tooltip>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-tooltip-offset-top` | Used as an offset when the tooltip is aligned vertically below the target\n`--vaadin-tooltip-offset-bottom` | Used as an offset when the tooltip is aligned vertically above the target\n`--vaadin-tooltip-offset-start` | Used as an offset when the tooltip is aligned horizontally after the target\n`--vaadin-tooltip-offset-end` | Used as an offset when the tooltip is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"name": ".context",
|
|
38
|
-
"description": "Object with properties passed to `
|
|
38
|
+
"description": "Object with properties passed to `generator` and\n`shouldShow` functions for generating tooltip text\nor detecting whether to show the tooltip or not.",
|
|
39
39
|
"value": {
|
|
40
40
|
"kind": "expression"
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"name": ".focusDelay",
|
|
45
|
-
"description": "The delay in milliseconds before the tooltip\nis opened on focus, when not in manual mode.",
|
|
45
|
+
"description": "The delay in milliseconds before the tooltip\nis opened on keyboard focus, when not in manual mode.",
|
|
46
46
|
"value": {
|
|
47
47
|
"kind": "expression"
|
|
48
48
|
}
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"name": ".shouldShow",
|
|
80
|
-
"description": "Function used to detect whether to show the tooltip based on a condition,\ncalled every time the tooltip is about to be shown on hover and focus.\nThe function
|
|
80
|
+
"description": "Function used to detect whether to show the tooltip based on a condition,\ncalled every time the tooltip is about to be shown on hover and focus.\nThe function takes two parameters: `target` and `context`, which contain\nvalues of the corresponding tooltip properties at the time of calling.\nThe tooltip is only shown when the function invocation returns `true`.",
|
|
81
81
|
"value": {
|
|
82
82
|
"kind": "expression"
|
|
83
83
|
}
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
|
-
"name": ".
|
|
100
|
+
"name": ".generator",
|
|
101
101
|
"description": "Function used to generate the tooltip content.\nWhen provided, it overrides the `text` property.\nUse the `context` property to provide argument\nthat can be passed to the generator function.",
|
|
102
102
|
"value": {
|
|
103
103
|
"kind": "expression"
|