@vaadin/notification 24.6.0-alpha3 → 24.6.0-alpha5
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 +10 -9
- package/src/vaadin-lit-notification.js +129 -0
- package/src/vaadin-notification-mixin.d.ts +90 -0
- package/src/vaadin-notification-mixin.js +434 -0
- package/src/vaadin-notification-styles.js +71 -0
- package/src/vaadin-notification.d.ts +14 -79
- package/src/vaadin-notification.js +15 -468
- package/theme/lumo/vaadin-lit-notification.d.ts +2 -0
- package/theme/lumo/vaadin-lit-notification.js +2 -0
- package/theme/material/vaadin-lit-notification.d.ts +2 -0
- package/theme/material/vaadin-lit-notification.js +2 -0
- package/vaadin-lit-notification.d.ts +1 -0
- package/vaadin-lit-notification.js +2 -0
- package/web-types.json +1 -1
- package/web-types.lit.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/notification",
|
|
3
|
-
"version": "24.6.0-
|
|
3
|
+
"version": "24.6.0-alpha5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,17 +37,18 @@
|
|
|
37
37
|
"polymer"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
40
41
|
"@polymer/polymer": "^3.0.0",
|
|
41
|
-
"@vaadin/component-base": "24.6.0-
|
|
42
|
-
"@vaadin/lit-renderer": "24.6.0-
|
|
43
|
-
"@vaadin/vaadin-lumo-styles": "24.6.0-
|
|
44
|
-
"@vaadin/vaadin-material-styles": "24.6.0-
|
|
45
|
-
"@vaadin/vaadin-themable-mixin": "24.6.0-
|
|
42
|
+
"@vaadin/component-base": "24.6.0-alpha5",
|
|
43
|
+
"@vaadin/lit-renderer": "24.6.0-alpha5",
|
|
44
|
+
"@vaadin/vaadin-lumo-styles": "24.6.0-alpha5",
|
|
45
|
+
"@vaadin/vaadin-material-styles": "24.6.0-alpha5",
|
|
46
|
+
"@vaadin/vaadin-themable-mixin": "24.6.0-alpha5",
|
|
46
47
|
"lit": "^3.0.0"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
|
-
"@vaadin/button": "24.6.0-
|
|
50
|
-
"@vaadin/chai-plugins": "24.6.0-
|
|
50
|
+
"@vaadin/button": "24.6.0-alpha5",
|
|
51
|
+
"@vaadin/chai-plugins": "24.6.0-alpha5",
|
|
51
52
|
"@vaadin/testing-helpers": "^1.0.0",
|
|
52
53
|
"sinon": "^18.0.0"
|
|
53
54
|
},
|
|
@@ -55,5 +56,5 @@
|
|
|
55
56
|
"web-types.json",
|
|
56
57
|
"web-types.lit.json"
|
|
57
58
|
],
|
|
58
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "cbfa46fe276f254dcaa99a622710d56df7f0a539"
|
|
59
60
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2017 - 2024 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css, html, LitElement } from 'lit';
|
|
7
|
+
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
|
+
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
9
|
+
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
|
+
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
11
|
+
import { NotificationContainerMixin, NotificationMixin } from './vaadin-notification-mixin.js';
|
|
12
|
+
import { notificationCardStyles, notificationContainerStyles } from './vaadin-notification-styles.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An element used internally by `<vaadin-notification>`. Not intended to be used separately.
|
|
16
|
+
*
|
|
17
|
+
* @customElement
|
|
18
|
+
* @extends HTMLElement
|
|
19
|
+
* @mixes NotificationContainerMixin
|
|
20
|
+
* @mixes ElementMixin
|
|
21
|
+
* @mixes ThemableMixin
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
class NotificationContainer extends NotificationContainerMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
25
|
+
static get styles() {
|
|
26
|
+
return notificationContainerStyles;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
return html`
|
|
31
|
+
<div region="top-stretch"><slot name="top-stretch"></slot></div>
|
|
32
|
+
<div region-group="top">
|
|
33
|
+
<div region="top-start"><slot name="top-start"></slot></div>
|
|
34
|
+
<div region="top-center"><slot name="top-center"></slot></div>
|
|
35
|
+
<div region="top-end"><slot name="top-end"></slot></div>
|
|
36
|
+
</div>
|
|
37
|
+
<div region="middle"><slot name="middle"></slot></div>
|
|
38
|
+
<div region-group="bottom">
|
|
39
|
+
<div region="bottom-start"><slot name="bottom-start"></slot></div>
|
|
40
|
+
<div region="bottom-center"><slot name="bottom-center"></slot></div>
|
|
41
|
+
<div region="bottom-end"><slot name="bottom-end"></slot></div>
|
|
42
|
+
</div>
|
|
43
|
+
<div region="bottom-stretch"><slot name="bottom-stretch"></slot></div>
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static get is() {
|
|
48
|
+
return 'vaadin-notification-container';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* An element used internally by `<vaadin-notification>`. Not intended to be used separately.
|
|
54
|
+
*
|
|
55
|
+
* @customElement
|
|
56
|
+
* @extends HTMLElement
|
|
57
|
+
* @mixes ThemableMixin
|
|
58
|
+
* @mixes ElementMixin
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
class NotificationCard extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))) {
|
|
62
|
+
static get styles() {
|
|
63
|
+
return notificationCardStyles;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
render() {
|
|
67
|
+
return html`
|
|
68
|
+
<div part="overlay">
|
|
69
|
+
<div part="content">
|
|
70
|
+
<slot></slot>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static get is() {
|
|
77
|
+
return 'vaadin-notification-card';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @protected */
|
|
81
|
+
ready() {
|
|
82
|
+
super.ready();
|
|
83
|
+
this.setAttribute('role', 'alert');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* LitElement based version of `<vaadin-notification>` web component.
|
|
89
|
+
*
|
|
90
|
+
* ## Disclaimer
|
|
91
|
+
*
|
|
92
|
+
* This component is an experiment and not yet a part of Vaadin platform.
|
|
93
|
+
* There is no ETA regarding specific Vaadin version where it'll land.
|
|
94
|
+
* Feel free to try this code in your apps as per Apache 2.0 license.
|
|
95
|
+
*/
|
|
96
|
+
class Notification extends NotificationMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
97
|
+
static get styles() {
|
|
98
|
+
return css`
|
|
99
|
+
:host {
|
|
100
|
+
display: none !important;
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
return html`
|
|
107
|
+
<vaadin-notification-card
|
|
108
|
+
theme="${this._theme || ''}"
|
|
109
|
+
aria-live="${this.__computeAriaLive(this.assertive)}"
|
|
110
|
+
></vaadin-notification-card>
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static get is() {
|
|
115
|
+
return 'vaadin-notification';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Fired when the notification is closed.
|
|
120
|
+
*
|
|
121
|
+
* @event closed
|
|
122
|
+
*/
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
defineCustomElement(NotificationContainer);
|
|
126
|
+
defineCustomElement(NotificationCard);
|
|
127
|
+
defineCustomElement(Notification);
|
|
128
|
+
|
|
129
|
+
export { Notification };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
2
|
+
import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin';
|
|
3
|
+
import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin';
|
|
4
|
+
import type { Notification } from './vaadin-notification.js';
|
|
5
|
+
|
|
6
|
+
export type NotificationPosition =
|
|
7
|
+
| 'bottom-center'
|
|
8
|
+
| 'bottom-end'
|
|
9
|
+
| 'bottom-start'
|
|
10
|
+
| 'bottom-stretch'
|
|
11
|
+
| 'middle'
|
|
12
|
+
| 'top-center'
|
|
13
|
+
| 'top-end'
|
|
14
|
+
| 'top-start'
|
|
15
|
+
| 'top-stretch';
|
|
16
|
+
|
|
17
|
+
export type NotificationRenderer = (root: HTMLElement, notification: Notification) => void;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A mixin providing common notification container functionality.
|
|
21
|
+
*/
|
|
22
|
+
export declare function NotificationContainerMixin<T>(base: T): Constructor<NotificationContainerMixinClass> & T;
|
|
23
|
+
|
|
24
|
+
export declare class NotificationContainerMixinClass {
|
|
25
|
+
/**
|
|
26
|
+
* True when the container is opened
|
|
27
|
+
*/
|
|
28
|
+
opened: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A mixin providing common notification functionality.
|
|
33
|
+
*/
|
|
34
|
+
export declare function NotificationMixin<T>(
|
|
35
|
+
base: T,
|
|
36
|
+
): Constructor<NotificationMixinClass> & Constructor<ThemePropertyMixinClass> & Constructor<OverlayClassMixinClass> & T;
|
|
37
|
+
|
|
38
|
+
export declare class NotificationMixinClass {
|
|
39
|
+
/**
|
|
40
|
+
* When true, the notification card has `aria-live` attribute set to
|
|
41
|
+
* `assertive` instead of `polite`. This makes screen readers announce
|
|
42
|
+
* the notification content immediately when it appears.
|
|
43
|
+
*/
|
|
44
|
+
assertive: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The duration in milliseconds to show the notification.
|
|
48
|
+
* Set to `0` or a negative number to disable the notification auto-closing.
|
|
49
|
+
*/
|
|
50
|
+
duration: number;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* True if the notification is currently displayed.
|
|
54
|
+
*/
|
|
55
|
+
opened: boolean;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Alignment of the notification in the viewport
|
|
59
|
+
* Valid values are `top-stretch|top-start|top-center|top-end|middle|bottom-start|bottom-center|bottom-end|bottom-stretch`
|
|
60
|
+
*/
|
|
61
|
+
position: NotificationPosition;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Custom function for rendering the content of the notification.
|
|
65
|
+
* Receives two arguments:
|
|
66
|
+
*
|
|
67
|
+
* - `root` The `<vaadin-notification-card>` DOM element. Append
|
|
68
|
+
* your content to it.
|
|
69
|
+
* - `notification` The reference to the `<vaadin-notification>` element.
|
|
70
|
+
*/
|
|
71
|
+
renderer: NotificationRenderer | undefined;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Requests an update for the content of the notification.
|
|
75
|
+
* While performing the update, it invokes the renderer passed in the `renderer` property.
|
|
76
|
+
*
|
|
77
|
+
* It is not guaranteed that the update happens immediately (synchronously) after it is requested.
|
|
78
|
+
*/
|
|
79
|
+
requestContentUpdate(): void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Opens the notification.
|
|
83
|
+
*/
|
|
84
|
+
open(): void;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Closes the notification.
|
|
88
|
+
*/
|
|
89
|
+
close(): void;
|
|
90
|
+
}
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2017 - 2024 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { render } from 'lit';
|
|
7
|
+
import { isTemplateResult } from 'lit/directive-helpers.js';
|
|
8
|
+
import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
|
|
9
|
+
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
10
|
+
import { processTemplates } from '@vaadin/component-base/src/templates.js';
|
|
11
|
+
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A mixin providing common notification container functionality.
|
|
15
|
+
*
|
|
16
|
+
* @polymerMixin
|
|
17
|
+
*/
|
|
18
|
+
export const NotificationContainerMixin = (superClass) =>
|
|
19
|
+
class extends superClass {
|
|
20
|
+
static get properties() {
|
|
21
|
+
return {
|
|
22
|
+
/**
|
|
23
|
+
* True when the container is opened
|
|
24
|
+
* @type {boolean}
|
|
25
|
+
*/
|
|
26
|
+
opened: {
|
|
27
|
+
type: Boolean,
|
|
28
|
+
value: false,
|
|
29
|
+
sync: true,
|
|
30
|
+
observer: '_openedChanged',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
|
|
38
|
+
this._boundVaadinOverlayClose = this._onVaadinOverlayClose.bind(this);
|
|
39
|
+
if (isIOS) {
|
|
40
|
+
this._boundIosResizeListener = () => this._detectIosNavbar();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** @private */
|
|
45
|
+
_openedChanged(opened) {
|
|
46
|
+
if (opened) {
|
|
47
|
+
document.body.appendChild(this);
|
|
48
|
+
document.addEventListener('vaadin-overlay-close', this._boundVaadinOverlayClose);
|
|
49
|
+
if (this._boundIosResizeListener) {
|
|
50
|
+
this._detectIosNavbar();
|
|
51
|
+
window.addEventListener('resize', this._boundIosResizeListener);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
document.body.removeChild(this);
|
|
55
|
+
document.removeEventListener('vaadin-overlay-close', this._boundVaadinOverlayClose);
|
|
56
|
+
if (this._boundIosResizeListener) {
|
|
57
|
+
window.removeEventListener('resize', this._boundIosResizeListener);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @private */
|
|
63
|
+
_detectIosNavbar() {
|
|
64
|
+
const innerHeight = window.innerHeight;
|
|
65
|
+
const innerWidth = window.innerWidth;
|
|
66
|
+
const landscape = innerWidth > innerHeight;
|
|
67
|
+
const clientHeight = document.documentElement.clientHeight;
|
|
68
|
+
if (landscape && clientHeight > innerHeight) {
|
|
69
|
+
this.style.bottom = `${clientHeight - innerHeight}px`;
|
|
70
|
+
} else {
|
|
71
|
+
this.style.bottom = '0';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** @private */
|
|
76
|
+
_onVaadinOverlayClose(event) {
|
|
77
|
+
// Notifications are a separate overlay mechanism from vaadin-overlay, and
|
|
78
|
+
// interacting with them should not close modal overlays
|
|
79
|
+
const sourceEvent = event.detail.sourceEvent;
|
|
80
|
+
const isFromNotification = sourceEvent && sourceEvent.composedPath().indexOf(this) >= 0;
|
|
81
|
+
if (isFromNotification) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* A mixin providing common notification functionality.
|
|
89
|
+
*
|
|
90
|
+
* @polymerMixin
|
|
91
|
+
* @mixes OverlayClassMixin
|
|
92
|
+
* @mixes ThemePropertyMixin
|
|
93
|
+
*/
|
|
94
|
+
export const NotificationMixin = (superClass) =>
|
|
95
|
+
class extends ThemePropertyMixin(OverlayClassMixin(superClass)) {
|
|
96
|
+
static get properties() {
|
|
97
|
+
return {
|
|
98
|
+
/**
|
|
99
|
+
* When true, the notification card has `aria-live` attribute set to
|
|
100
|
+
* `assertive` instead of `polite`. This makes screen readers announce
|
|
101
|
+
* the notification content immediately when it appears.
|
|
102
|
+
*/
|
|
103
|
+
assertive: {
|
|
104
|
+
type: Boolean,
|
|
105
|
+
value: false,
|
|
106
|
+
sync: true,
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The duration in milliseconds to show the notification.
|
|
111
|
+
* Set to `0` or a negative number to disable the notification auto-closing.
|
|
112
|
+
* @type {number}
|
|
113
|
+
*/
|
|
114
|
+
duration: {
|
|
115
|
+
type: Number,
|
|
116
|
+
value: 5000,
|
|
117
|
+
sync: true,
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* True if the notification is currently displayed.
|
|
122
|
+
* @type {boolean}
|
|
123
|
+
*/
|
|
124
|
+
opened: {
|
|
125
|
+
type: Boolean,
|
|
126
|
+
value: false,
|
|
127
|
+
notify: true,
|
|
128
|
+
sync: true,
|
|
129
|
+
observer: '_openedChanged',
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Alignment of the notification in the viewport
|
|
134
|
+
* Valid values are `top-stretch|top-start|top-center|top-end|middle|bottom-start|bottom-center|bottom-end|bottom-stretch`
|
|
135
|
+
* @type {!NotificationPosition}
|
|
136
|
+
*/
|
|
137
|
+
position: {
|
|
138
|
+
type: String,
|
|
139
|
+
value: 'bottom-start',
|
|
140
|
+
observer: '_positionChanged',
|
|
141
|
+
sync: true,
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Custom function for rendering the content of the notification.
|
|
146
|
+
* Receives two arguments:
|
|
147
|
+
*
|
|
148
|
+
* - `root` The `<vaadin-notification-card>` DOM element. Append
|
|
149
|
+
* your content to it.
|
|
150
|
+
* - `notification` The reference to the `<vaadin-notification>` element.
|
|
151
|
+
* @type {!NotificationRenderer | undefined}
|
|
152
|
+
*/
|
|
153
|
+
renderer: {
|
|
154
|
+
type: Function,
|
|
155
|
+
sync: true,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static get observers() {
|
|
161
|
+
return ['_durationChanged(duration, opened)', '_rendererChanged(renderer, opened, _overlayElement)'];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Shows a notification with the given content.
|
|
166
|
+
* By default, positions the notification at `bottom-start` and uses a 5 second duration.
|
|
167
|
+
* An options object can be passed to configure the notification.
|
|
168
|
+
* The options object has the following structure:
|
|
169
|
+
*
|
|
170
|
+
* ```
|
|
171
|
+
* {
|
|
172
|
+
* assertive?: boolean
|
|
173
|
+
* position?: string
|
|
174
|
+
* duration?: number
|
|
175
|
+
* theme?: string
|
|
176
|
+
* }
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* See the individual documentation for:
|
|
180
|
+
* - [`assertive`](#/elements/vaadin-notification#property-assertive)
|
|
181
|
+
* - [`position`](#/elements/vaadin-notification#property-position)
|
|
182
|
+
* - [`duration`](#/elements/vaadin-notification#property-duration)
|
|
183
|
+
*
|
|
184
|
+
* @param contents the contents to show, either as a string or a Lit template.
|
|
185
|
+
* @param options optional options for customizing the notification.
|
|
186
|
+
*/
|
|
187
|
+
static show(contents, options) {
|
|
188
|
+
const Notification = customElements.get('vaadin-notification');
|
|
189
|
+
if (isTemplateResult(contents)) {
|
|
190
|
+
return Notification._createAndShowNotification((root) => {
|
|
191
|
+
render(contents, root);
|
|
192
|
+
}, options);
|
|
193
|
+
}
|
|
194
|
+
return Notification._createAndShowNotification((root) => {
|
|
195
|
+
root.innerText = contents;
|
|
196
|
+
}, options);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** @private */
|
|
200
|
+
static _createAndShowNotification(renderer, options) {
|
|
201
|
+
const notification = document.createElement('vaadin-notification');
|
|
202
|
+
if (options && Number.isFinite(options.duration)) {
|
|
203
|
+
notification.duration = options.duration;
|
|
204
|
+
}
|
|
205
|
+
if (options && options.position) {
|
|
206
|
+
notification.position = options.position;
|
|
207
|
+
}
|
|
208
|
+
if (options && options.assertive) {
|
|
209
|
+
notification.assertive = options.assertive;
|
|
210
|
+
}
|
|
211
|
+
if (options && options.theme) {
|
|
212
|
+
notification.setAttribute('theme', options.theme);
|
|
213
|
+
}
|
|
214
|
+
notification.renderer = renderer;
|
|
215
|
+
document.body.appendChild(notification);
|
|
216
|
+
notification.opened = true;
|
|
217
|
+
|
|
218
|
+
notification.addEventListener('opened-changed', (e) => {
|
|
219
|
+
if (!e.detail.value) {
|
|
220
|
+
notification.remove();
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return notification;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** @private */
|
|
228
|
+
get _container() {
|
|
229
|
+
if (!Notification._container) {
|
|
230
|
+
Notification._container = document.createElement('vaadin-notification-container');
|
|
231
|
+
document.body.appendChild(Notification._container);
|
|
232
|
+
}
|
|
233
|
+
return Notification._container;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** @protected */
|
|
237
|
+
get _card() {
|
|
238
|
+
return this._overlayElement;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** @protected */
|
|
242
|
+
ready() {
|
|
243
|
+
super.ready();
|
|
244
|
+
|
|
245
|
+
this._overlayElement = this.shadowRoot.querySelector('vaadin-notification-card');
|
|
246
|
+
|
|
247
|
+
processTemplates(this);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** @protected */
|
|
251
|
+
disconnectedCallback() {
|
|
252
|
+
super.disconnectedCallback();
|
|
253
|
+
queueMicrotask(() => {
|
|
254
|
+
if (!this.isConnected) {
|
|
255
|
+
this.opened = false;
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Requests an update for the content of the notification.
|
|
262
|
+
* While performing the update, it invokes the renderer passed in the `renderer` property.
|
|
263
|
+
*
|
|
264
|
+
* It is not guaranteed that the update happens immediately (synchronously) after it is requested.
|
|
265
|
+
*/
|
|
266
|
+
requestContentUpdate() {
|
|
267
|
+
if (!this.renderer) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.renderer(this._card, this);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** @private */
|
|
275
|
+
__computeAriaLive(assertive) {
|
|
276
|
+
return assertive ? 'assertive' : 'polite';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** @private */
|
|
280
|
+
_rendererChanged(renderer, opened, card) {
|
|
281
|
+
if (!card) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const rendererChanged = this._oldRenderer !== renderer;
|
|
286
|
+
this._oldRenderer = renderer;
|
|
287
|
+
|
|
288
|
+
if (rendererChanged) {
|
|
289
|
+
card.innerHTML = '';
|
|
290
|
+
// Whenever a Lit-based renderer is used, it assigns a Lit part to the node it was rendered into.
|
|
291
|
+
// When clearing the rendered content, this part needs to be manually disposed of.
|
|
292
|
+
// Otherwise, using a Lit-based renderer on the same node will throw an exception or render nothing afterward.
|
|
293
|
+
delete card._$litPart$;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (opened) {
|
|
297
|
+
if (!this._didAnimateNotificationAppend) {
|
|
298
|
+
this._animatedAppendNotificationCard();
|
|
299
|
+
}
|
|
300
|
+
this.requestContentUpdate();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Opens the notification.
|
|
306
|
+
*/
|
|
307
|
+
open() {
|
|
308
|
+
this.opened = true;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Closes the notification.
|
|
313
|
+
*/
|
|
314
|
+
close() {
|
|
315
|
+
this.opened = false;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/** @private */
|
|
319
|
+
_openedChanged(opened) {
|
|
320
|
+
if (opened) {
|
|
321
|
+
this._container.opened = true;
|
|
322
|
+
this._animatedAppendNotificationCard();
|
|
323
|
+
} else if (this._card) {
|
|
324
|
+
this._closeNotificationCard();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** @private */
|
|
329
|
+
__cleanUpOpeningClosingState() {
|
|
330
|
+
this._card.removeAttribute('opening');
|
|
331
|
+
this._card.removeAttribute('closing');
|
|
332
|
+
this._card.removeEventListener('animationend', this.__animationEndListener);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** @private */
|
|
336
|
+
_animatedAppendNotificationCard() {
|
|
337
|
+
if (this._card) {
|
|
338
|
+
this.__cleanUpOpeningClosingState();
|
|
339
|
+
|
|
340
|
+
this._card.setAttribute('opening', '');
|
|
341
|
+
this._appendNotificationCard();
|
|
342
|
+
this.__animationEndListener = () => this.__cleanUpOpeningClosingState();
|
|
343
|
+
this._card.addEventListener('animationend', this.__animationEndListener);
|
|
344
|
+
this._didAnimateNotificationAppend = true;
|
|
345
|
+
} else {
|
|
346
|
+
this._didAnimateNotificationAppend = false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** @private */
|
|
351
|
+
_appendNotificationCard() {
|
|
352
|
+
if (!this._card) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (this._container.performUpdate) {
|
|
357
|
+
this._container.performUpdate();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (!this._container.shadowRoot.querySelector(`slot[name="${this.position}"]`)) {
|
|
361
|
+
console.warn(`Invalid alignment parameter provided: position=${this.position}`);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this._card.slot = this.position;
|
|
366
|
+
if (this._container.firstElementChild && /top/u.test(this.position)) {
|
|
367
|
+
this._container.insertBefore(this._card, this._container.firstElementChild);
|
|
368
|
+
} else {
|
|
369
|
+
this._container.appendChild(this._card);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** @private */
|
|
374
|
+
_removeNotificationCard() {
|
|
375
|
+
if (!this._card) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (this._card.parentNode) {
|
|
380
|
+
this._card.parentNode.removeChild(this._card);
|
|
381
|
+
}
|
|
382
|
+
this._card.removeAttribute('closing');
|
|
383
|
+
this._container.opened = Boolean(this._container.firstElementChild);
|
|
384
|
+
this.dispatchEvent(new CustomEvent('closed'));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** @private */
|
|
388
|
+
_closeNotificationCard() {
|
|
389
|
+
if (this._durationTimeoutId) {
|
|
390
|
+
clearTimeout(this._durationTimeoutId);
|
|
391
|
+
}
|
|
392
|
+
this._animatedRemoveNotificationCard();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** @private */
|
|
396
|
+
_animatedRemoveNotificationCard() {
|
|
397
|
+
this.__cleanUpOpeningClosingState();
|
|
398
|
+
|
|
399
|
+
this._card.setAttribute('closing', '');
|
|
400
|
+
const name = getComputedStyle(this._card).getPropertyValue('animation-name');
|
|
401
|
+
if (name && name !== 'none') {
|
|
402
|
+
this.__animationEndListener = () => {
|
|
403
|
+
this._removeNotificationCard();
|
|
404
|
+
this.__cleanUpOpeningClosingState();
|
|
405
|
+
};
|
|
406
|
+
this._card.addEventListener('animationend', this.__animationEndListener);
|
|
407
|
+
} else {
|
|
408
|
+
this._removeNotificationCard();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/** @private */
|
|
413
|
+
_positionChanged() {
|
|
414
|
+
if (this.opened) {
|
|
415
|
+
this._animatedAppendNotificationCard();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** @private */
|
|
420
|
+
_durationChanged(duration, opened) {
|
|
421
|
+
if (opened) {
|
|
422
|
+
clearTimeout(this._durationTimeoutId);
|
|
423
|
+
if (duration > 0) {
|
|
424
|
+
this._durationTimeoutId = setTimeout(() => this.close(), duration);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Fired when the notification is closed.
|
|
431
|
+
*
|
|
432
|
+
* @event closed
|
|
433
|
+
*/
|
|
434
|
+
};
|