@vaadin/dialog 22.0.0-alpha10
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/LICENSE +190 -0
- package/README.md +68 -0
- package/package.json +51 -0
- package/src/vaadin-dialog-draggable-mixin.d.ts +29 -0
- package/src/vaadin-dialog-draggable-mixin.js +118 -0
- package/src/vaadin-dialog-resizable-mixin.d.ts +22 -0
- package/src/vaadin-dialog-resizable-mixin.js +250 -0
- package/src/vaadin-dialog-utils.d.ts +20 -0
- package/src/vaadin-dialog-utils.js +20 -0
- package/src/vaadin-dialog.d.ts +165 -0
- package/src/vaadin-dialog.js +351 -0
- package/theme/lumo/vaadin-dialog-styles.js +69 -0
- package/theme/lumo/vaadin-dialog.js +2 -0
- package/theme/material/vaadin-dialog-styles.js +26 -0
- package/theme/material/vaadin-dialog.js +2 -0
- package/vaadin-dialog.d.ts +1 -0
- package/vaadin-dialog.js +2 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
|
|
2
|
+
import { getMouseOrFirstTouchEvent, eventInWindow } from './vaadin-dialog-utils.js';
|
|
3
|
+
|
|
4
|
+
registerStyles(
|
|
5
|
+
'vaadin-dialog-overlay',
|
|
6
|
+
css`
|
|
7
|
+
[part='overlay'] {
|
|
8
|
+
position: relative;
|
|
9
|
+
overflow: visible;
|
|
10
|
+
max-height: 100%;
|
|
11
|
+
display: flex;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
[part='content'] {
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
height: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.resizer-container {
|
|
20
|
+
overflow: auto;
|
|
21
|
+
flex-grow: 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
[part='overlay'][style] .resizer-container {
|
|
25
|
+
min-height: 100%;
|
|
26
|
+
width: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:host(:not([resizable])) .resizer {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.resizer {
|
|
34
|
+
position: absolute;
|
|
35
|
+
height: 16px;
|
|
36
|
+
width: 16px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.resizer.edge {
|
|
40
|
+
height: 8px;
|
|
41
|
+
width: 8px;
|
|
42
|
+
top: -4px;
|
|
43
|
+
right: -4px;
|
|
44
|
+
bottom: -4px;
|
|
45
|
+
left: -4px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.resizer.edge.n {
|
|
49
|
+
width: auto;
|
|
50
|
+
bottom: auto;
|
|
51
|
+
cursor: ns-resize;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.resizer.ne {
|
|
55
|
+
top: -4px;
|
|
56
|
+
right: -4px;
|
|
57
|
+
cursor: nesw-resize;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.resizer.edge.e {
|
|
61
|
+
height: auto;
|
|
62
|
+
left: auto;
|
|
63
|
+
cursor: ew-resize;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.resizer.se {
|
|
67
|
+
bottom: -4px;
|
|
68
|
+
right: -4px;
|
|
69
|
+
cursor: nwse-resize;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.resizer.edge.s {
|
|
73
|
+
width: auto;
|
|
74
|
+
top: auto;
|
|
75
|
+
cursor: ns-resize;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.resizer.sw {
|
|
79
|
+
bottom: -4px;
|
|
80
|
+
left: -4px;
|
|
81
|
+
cursor: nesw-resize;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.resizer.edge.w {
|
|
85
|
+
height: auto;
|
|
86
|
+
right: auto;
|
|
87
|
+
cursor: ew-resize;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.resizer.nw {
|
|
91
|
+
top: -4px;
|
|
92
|
+
left: -4px;
|
|
93
|
+
cursor: nwse-resize;
|
|
94
|
+
}
|
|
95
|
+
`,
|
|
96
|
+
{ moduleId: 'vaadin-dialog-resizable-overlay-styles' }
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @polymerMixin
|
|
101
|
+
*/
|
|
102
|
+
export const DialogResizableMixin = (superClass) =>
|
|
103
|
+
class VaadinDialogResizableMixin extends superClass {
|
|
104
|
+
static get properties() {
|
|
105
|
+
return {
|
|
106
|
+
/**
|
|
107
|
+
* Set to true to enable resizing the dialog by dragging the corners and edges.
|
|
108
|
+
* @type {boolean}
|
|
109
|
+
*/
|
|
110
|
+
resizable: {
|
|
111
|
+
type: Boolean,
|
|
112
|
+
value: false,
|
|
113
|
+
reflectToAttribute: true
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** @protected */
|
|
119
|
+
ready() {
|
|
120
|
+
super.ready();
|
|
121
|
+
this._originalBounds = {};
|
|
122
|
+
this._originalMouseCoords = {};
|
|
123
|
+
this._resizeListeners = { start: {}, resize: {}, stop: {} };
|
|
124
|
+
this._addResizeListeners();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** @private */
|
|
128
|
+
_addResizeListeners() {
|
|
129
|
+
// Note: edge controls added before corners
|
|
130
|
+
['n', 'e', 's', 'w', 'nw', 'ne', 'se', 'sw'].forEach((direction) => {
|
|
131
|
+
const resizer = document.createElement('div');
|
|
132
|
+
this._resizeListeners.start[direction] = (e) => this._startResize(e, direction);
|
|
133
|
+
this._resizeListeners.resize[direction] = (e) => this._resize(e, direction);
|
|
134
|
+
this._resizeListeners.stop[direction] = () => this._stopResize(direction);
|
|
135
|
+
if (direction.length === 1) {
|
|
136
|
+
resizer.classList.add('edge');
|
|
137
|
+
}
|
|
138
|
+
resizer.classList.add('resizer');
|
|
139
|
+
resizer.classList.add(direction);
|
|
140
|
+
resizer.addEventListener('mousedown', this._resizeListeners.start[direction]);
|
|
141
|
+
resizer.addEventListener('touchstart', this._resizeListeners.start[direction]);
|
|
142
|
+
this.$.overlay.$.resizerContainer.appendChild(resizer);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {!MouseEvent | !TouchEvent} e
|
|
148
|
+
* @param {!DialogResizableDirection} direction
|
|
149
|
+
* @protected
|
|
150
|
+
*/
|
|
151
|
+
_startResize(e, direction) {
|
|
152
|
+
// Don't initiate when there's more than 1 touch (pinch zoom)
|
|
153
|
+
if (e.type === 'touchstart' && e.touches.length > 1) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (e.button === 0 || e.touches) {
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
|
|
160
|
+
this._originalBounds = this.$.overlay.getBounds();
|
|
161
|
+
const event = getMouseOrFirstTouchEvent(e);
|
|
162
|
+
this._originalMouseCoords = { top: event.pageY, left: event.pageX };
|
|
163
|
+
window.addEventListener('mousemove', this._resizeListeners.resize[direction]);
|
|
164
|
+
window.addEventListener('touchmove', this._resizeListeners.resize[direction]);
|
|
165
|
+
window.addEventListener('mouseup', this._resizeListeners.stop[direction]);
|
|
166
|
+
window.addEventListener('touchend', this._resizeListeners.stop[direction]);
|
|
167
|
+
if (this.$.overlay.$.overlay.style.position !== 'absolute') {
|
|
168
|
+
this.$.overlay.setBounds(this._originalBounds);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {!MouseEvent | !TouchEvent} e
|
|
175
|
+
* @param {!DialogResizableDirection} resizer
|
|
176
|
+
* @protected
|
|
177
|
+
*/
|
|
178
|
+
_resize(e, resizer) {
|
|
179
|
+
const event = getMouseOrFirstTouchEvent(e);
|
|
180
|
+
if (eventInWindow(event)) {
|
|
181
|
+
const minimumSize = 40;
|
|
182
|
+
resizer.split('').forEach((direction) => {
|
|
183
|
+
switch (direction) {
|
|
184
|
+
case 'n': {
|
|
185
|
+
const height = this._originalBounds.height - (event.pageY - this._originalMouseCoords.top);
|
|
186
|
+
const top = this._originalBounds.top + (event.pageY - this._originalMouseCoords.top);
|
|
187
|
+
if (height > minimumSize) {
|
|
188
|
+
this.$.overlay.setBounds({ top, height });
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
case 'e': {
|
|
193
|
+
const width = this._originalBounds.width + (event.pageX - this._originalMouseCoords.left);
|
|
194
|
+
if (width > minimumSize) {
|
|
195
|
+
this.$.overlay.setBounds({ width });
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case 's': {
|
|
200
|
+
const height = this._originalBounds.height + (event.pageY - this._originalMouseCoords.top);
|
|
201
|
+
if (height > minimumSize) {
|
|
202
|
+
this.$.overlay.setBounds({ height });
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case 'w': {
|
|
207
|
+
const width = this._originalBounds.width - (event.pageX - this._originalMouseCoords.left);
|
|
208
|
+
const left = this._originalBounds.left + (event.pageX - this._originalMouseCoords.left);
|
|
209
|
+
if (width > minimumSize) {
|
|
210
|
+
this.$.overlay.setBounds({ left, width });
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
this.$.overlay.notifyResize();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @param {!DialogResizableDirection} direction
|
|
223
|
+
* @protected
|
|
224
|
+
*/
|
|
225
|
+
_stopResize(direction) {
|
|
226
|
+
window.removeEventListener('mousemove', this._resizeListeners.resize[direction]);
|
|
227
|
+
window.removeEventListener('touchmove', this._resizeListeners.resize[direction]);
|
|
228
|
+
window.removeEventListener('mouseup', this._resizeListeners.stop[direction]);
|
|
229
|
+
window.removeEventListener('touchend', this._resizeListeners.stop[direction]);
|
|
230
|
+
this.dispatchEvent(new CustomEvent('resize', { detail: this._getResizeDimensions() }));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @return {!DialogResizeDimensions}
|
|
235
|
+
* @protected
|
|
236
|
+
*/
|
|
237
|
+
_getResizeDimensions() {
|
|
238
|
+
const scrollPosition = this.$.overlay.$.resizerContainer.scrollTop;
|
|
239
|
+
const { width, height } = getComputedStyle(this.$.overlay.$.overlay);
|
|
240
|
+
const content = this.$.overlay.$.content;
|
|
241
|
+
content.setAttribute(
|
|
242
|
+
'style',
|
|
243
|
+
'position: absolute; top: 0; right: 0; bottom: 0; left: 0; box-sizing: content-box; height: auto;'
|
|
244
|
+
);
|
|
245
|
+
const { width: contentWidth, height: contentHeight } = getComputedStyle(content);
|
|
246
|
+
content.removeAttribute('style');
|
|
247
|
+
this.$.overlay.$.resizerContainer.scrollTop = scrollPosition;
|
|
248
|
+
return { width, height, contentWidth, contentHeight };
|
|
249
|
+
}
|
|
250
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checks if the argument is a touch event and if so, returns a first touch.
|
|
9
|
+
* Otherwise, if the mouse event was passed, returns it as is.
|
|
10
|
+
*/
|
|
11
|
+
declare function getMouseOrFirstTouchEvent(e: MouseEvent | TouchEvent): MouseEvent | Touch;
|
|
12
|
+
|
|
13
|
+
export { getMouseOrFirstTouchEvent };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether a mouse or touch event is in window.
|
|
17
|
+
*/
|
|
18
|
+
declare function eventInWindow(e: MouseEvent | TouchEvent): boolean;
|
|
19
|
+
|
|
20
|
+
export { eventInWindow };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if the argument is a touch event and if so, returns a first touch.
|
|
3
|
+
* Otherwise, if the mouse event was passed, returns it as is.
|
|
4
|
+
* @param {!MouseEvent | !TouchEvent} e
|
|
5
|
+
* @return {!MouseEvent | !Touch}
|
|
6
|
+
* @protected
|
|
7
|
+
*/
|
|
8
|
+
export function getMouseOrFirstTouchEvent(e) {
|
|
9
|
+
return e.touches ? e.touches[0] : e;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether a mouse or touch event is in window.
|
|
14
|
+
* @param {!MouseEvent | !TouchEvent} e
|
|
15
|
+
* @return {boolean}
|
|
16
|
+
* @protected
|
|
17
|
+
*/
|
|
18
|
+
export function eventInWindow(e) {
|
|
19
|
+
return e.clientX >= 0 && e.clientX <= window.innerWidth && e.clientY >= 0 && e.clientY <= window.innerHeight;
|
|
20
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
7
|
+
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
8
|
+
import { DialogDraggableMixin } from './vaadin-dialog-draggable-mixin.js';
|
|
9
|
+
import { DialogResizableMixin } from './vaadin-dialog-resizable-mixin.js';
|
|
10
|
+
|
|
11
|
+
export type DialogRenderer = (root: HTMLElement, dialog?: Dialog) => void;
|
|
12
|
+
|
|
13
|
+
export type DialogResizableDirection = 'n' | 'e' | 's' | 'w' | 'nw' | 'ne' | 'se' | 'sw';
|
|
14
|
+
|
|
15
|
+
export type DialogResizeDimensions = {
|
|
16
|
+
width: string;
|
|
17
|
+
height: string;
|
|
18
|
+
contentWidth: string;
|
|
19
|
+
contentHeight: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type DialogOverlayBounds = {
|
|
23
|
+
top: number;
|
|
24
|
+
left: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type DialogOverlayBoundsParam =
|
|
30
|
+
| DialogOverlayBounds
|
|
31
|
+
| {
|
|
32
|
+
top?: string | number;
|
|
33
|
+
left?: string | number;
|
|
34
|
+
width?: string | number;
|
|
35
|
+
height?: string | number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Fired when the `opened` property changes.
|
|
40
|
+
*/
|
|
41
|
+
export type DialogOpenedChangedEvent = CustomEvent<{ value: boolean }>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fired when the dialog resize is finished.
|
|
45
|
+
*/
|
|
46
|
+
export type DialogResizeEvent = CustomEvent<DialogResizeDimensions>;
|
|
47
|
+
|
|
48
|
+
export interface DialogCustomEventMap {
|
|
49
|
+
'opened-changed': DialogOpenedChangedEvent;
|
|
50
|
+
|
|
51
|
+
resize: DialogResizeEvent;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type DialogEventMap = HTMLElementEventMap & DialogCustomEventMap;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* `<vaadin-dialog>` is a Web Component for creating customized modal dialogs.
|
|
58
|
+
*
|
|
59
|
+
* ### Rendering
|
|
60
|
+
*
|
|
61
|
+
* The content of the dialog can be populated by using the renderer callback function.
|
|
62
|
+
*
|
|
63
|
+
* The renderer function provides `root`, `dialog` arguments.
|
|
64
|
+
* Generate DOM content, append it to the `root` element and control the state
|
|
65
|
+
* of the host element by accessing `dialog`. Before generating new content,
|
|
66
|
+
* users are able to check if there is already content in `root` for reusing it.
|
|
67
|
+
*
|
|
68
|
+
* ```html
|
|
69
|
+
* <vaadin-dialog id="dialog"></vaadin-dialog>
|
|
70
|
+
* ```
|
|
71
|
+
* ```js
|
|
72
|
+
* const dialog = document.querySelector('#dialog');
|
|
73
|
+
* dialog.renderer = function(root, dialog) {
|
|
74
|
+
* root.textContent = "Sample dialog";
|
|
75
|
+
* };
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* Renderer is called on the opening of the dialog.
|
|
79
|
+
* DOM generated during the renderer call can be reused
|
|
80
|
+
* in the next renderer call and will be provided with the `root` argument.
|
|
81
|
+
* On first call it will be empty.
|
|
82
|
+
*
|
|
83
|
+
* ### Styling
|
|
84
|
+
*
|
|
85
|
+
* `<vaadin-dialog>` uses `<vaadin-dialog-overlay>` internal
|
|
86
|
+
* themable component as the actual visible dialog overlay.
|
|
87
|
+
*
|
|
88
|
+
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation.
|
|
89
|
+
* for `<vaadin-dialog-overlay>` parts.
|
|
90
|
+
*
|
|
91
|
+
* Note: the `theme` attribute value set on `<vaadin-dialog>` is
|
|
92
|
+
* propagated to the internal `<vaadin-dialog-overlay>` component.
|
|
93
|
+
*
|
|
94
|
+
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
|
|
95
|
+
*
|
|
96
|
+
* @fires {CustomEvent} resize - Fired when the dialog resize is finished.
|
|
97
|
+
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
98
|
+
*/
|
|
99
|
+
declare class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(DialogResizableMixin(HTMLElement)))) {
|
|
100
|
+
/**
|
|
101
|
+
* True if the overlay is currently displayed.
|
|
102
|
+
*/
|
|
103
|
+
opened: boolean;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Set to true to disable closing dialog on outside click
|
|
107
|
+
* @attr {boolean} no-close-on-outside-click
|
|
108
|
+
*/
|
|
109
|
+
noCloseOnOutsideClick: boolean;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Set to true to disable closing dialog on Escape press
|
|
113
|
+
* @attr {boolean} no-close-on-esc
|
|
114
|
+
*/
|
|
115
|
+
noCloseOnEsc: boolean;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Set the `aria-label` attribute for assistive technologies like
|
|
119
|
+
* screen readers. An empty string value for this property (the
|
|
120
|
+
* default) means that the `aria-label` attribute is not present.
|
|
121
|
+
*/
|
|
122
|
+
ariaLabel: string;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Custom function for rendering the content of the dialog.
|
|
126
|
+
* Receives two arguments:
|
|
127
|
+
*
|
|
128
|
+
* - `root` The root container DOM element. Append your content to it.
|
|
129
|
+
* - `dialog` The reference to the `<vaadin-dialog>` element.
|
|
130
|
+
*/
|
|
131
|
+
renderer: DialogRenderer | null | undefined;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Set to true to remove backdrop and allow click events on background elements.
|
|
135
|
+
*/
|
|
136
|
+
modeless: boolean;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Requests an update for the content of the dialog.
|
|
140
|
+
* While performing the update, it invokes the renderer passed in the `renderer` property.
|
|
141
|
+
*
|
|
142
|
+
* It is not guaranteed that the update happens immediately (synchronously) after it is requested.
|
|
143
|
+
*/
|
|
144
|
+
requestContentUpdate(): void;
|
|
145
|
+
|
|
146
|
+
addEventListener<K extends keyof DialogEventMap>(
|
|
147
|
+
type: K,
|
|
148
|
+
listener: (this: Dialog, ev: DialogEventMap[K]) => void,
|
|
149
|
+
options?: boolean | AddEventListenerOptions
|
|
150
|
+
): void;
|
|
151
|
+
|
|
152
|
+
removeEventListener<K extends keyof DialogEventMap>(
|
|
153
|
+
type: K,
|
|
154
|
+
listener: (this: Dialog, ev: DialogEventMap[K]) => void,
|
|
155
|
+
options?: boolean | EventListenerOptions
|
|
156
|
+
): void;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
declare global {
|
|
160
|
+
interface HTMLElementTagNameMap {
|
|
161
|
+
'vaadin-dialog': Dialog;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { Dialog };
|