wj-elements 0.6.0 → 0.7.0
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/dist/packages/wje-breadcrumbs/breadcrumbs.element.d.ts +1 -1
- package/dist/packages/wje-dropdown/dropdown.element.d.ts +18 -0
- package/dist/packages/wje-orgchart/orgchart.element.d.ts +15 -0
- package/dist/packages/wje-orgchart-item/orgchart-item.element.d.ts +3 -1
- package/dist/packages/wje-popup/popup.element.d.ts +48 -1
- package/dist/packages/wje-sliding-container/sliding-container.element.d.ts +360 -3
- package/dist/packages/wje-toolbar-action/toolbar-action.element.d.ts +11 -0
- package/dist/{popup.element-C8-g3WLs.js → popup.element-CwXvVFK7.js} +275 -43
- package/dist/popup.element-CwXvVFK7.js.map +1 -0
- package/dist/styles.css +0 -38
- package/dist/wje-animation.js +1 -1
- package/dist/wje-breadcrumbs.js +4 -0
- package/dist/wje-breadcrumbs.js.map +1 -1
- package/dist/wje-dropdown.js +28 -4
- package/dist/wje-dropdown.js.map +1 -1
- package/dist/wje-master.js +1 -1
- package/dist/wje-orgchart-group.js +1 -1
- package/dist/wje-orgchart-item.js +13 -4
- package/dist/wje-orgchart-item.js.map +1 -1
- package/dist/wje-orgchart.js +27 -0
- package/dist/wje-orgchart.js.map +1 -1
- package/dist/wje-popup.js +1 -1
- package/dist/wje-select.js +28 -5
- package/dist/wje-select.js.map +1 -1
- package/dist/wje-sliding-container.js +865 -14
- package/dist/wje-sliding-container.js.map +1 -1
- package/dist/wje-toolbar-action.js +25 -1
- package/dist/wje-toolbar-action.js.map +1 -1
- package/dist/wje-toolbar.js +1 -1
- package/dist/wje-tooltip.js +1 -1
- package/package.json +2 -1
- package/dist/popup.element-C8-g3WLs.js.map +0 -1
|
@@ -3,7 +3,9 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import WJElement from "./wje-element.js";
|
|
5
5
|
import { event } from "./event.js";
|
|
6
|
-
const styles = ":host {\n display: block;\n z-index: 9999;\n position: relative;\n height: 100%;\n right: unset;\n left: unset;\n .close-button {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 1000;\n }\n}\n\n:host([hide-button]) {\n .close-button {\n display: none;\n }\n}\n\n.sliding-container-wrapper {\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.native-sliding-container {\n\n position: absolute;\n width: 0;\n height: 100%;\n}\n\n.native-sliding-container-inner {\n height: 100%;\n position: absolute;\n}\n";
|
|
6
|
+
const styles = ":host {\n display: block;\n z-index: 9999;\n position: relative;\n height: 100%;\n right: unset;\n left: unset;\n .close-button {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 1000;\n }\n}\n\n:host([hide-button]) {\n .close-button {\n display: none;\n }\n}\n\n.sliding-container-backdrop {\n display: none;\n}\n\n.sliding-container-wrapper {\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.native-sliding-container {\n\n position: absolute;\n width: 0;\n height: 100%;\n}\n\n.native-sliding-container-inner {\n height: 100%;\n position: absolute;\n}\n\n.sliding-container-sheet-handle-area {\n display: none;\n}\n\n:host(.bottom-sheet) {\n inset: 0;\n pointer-events: none;\n}\n\n:host(.bottom-sheet.open) {\n pointer-events: auto;\n overscroll-behavior: contain;\n}\n\n:host(.bottom-sheet) .sliding-container-backdrop {\n display: block;\n position: fixed;\n inset: 0;\n z-index: 0;\n opacity: 0;\n pointer-events: none;\n touch-action: none;\n overscroll-behavior: none;\n background: var(--wje-sliding-container-backdrop-background, var(--wje-backdrop, rgba(0, 0, 0, .35)));\n}\n\n:host(.bottom-sheet.open) .sliding-container-backdrop {\n pointer-events: auto;\n}\n\n:host(.bottom-sheet) .sliding-container-wrapper {\n position: fixed;\n inset: 0;\n overflow: visible;\n pointer-events: none;\n z-index: 1;\n}\n\n:host(.bottom-sheet) .sliding-container-transparent {\n display: none;\n}\n\n:host(.bottom-sheet) .native-sliding-container {\n position: fixed;\n top: auto;\n height: fit-content;\n overflow: hidden;\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n overscroll-behavior: contain;\n background: var(--wje-sliding-container-background);\n box-shadow: var(--wje-sliding-container-box-shadow, var(--wje-sliding-container-shadow));\n border-radius: var(--wje-sliding-container-sheet-border-radius, var(--wje-sliding-container-border-radius) var(--wje-sliding-container-border-radius) 0 0);\n}\n\n:host(.bottom-sheet) .native-sliding-container-inner {\n position: relative;\n flex: 1 1 auto;\n min-height: 0;\n height: auto;\n max-height: inherit;\n overflow: auto;\n overscroll-behavior: contain;\n}\n\n:host(.bottom-sheet) .sliding-container-sheet-handle-area {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 var(--wje-sliding-container-sheet-handle-area-height, 24px);\n height: var(--wje-sliding-container-sheet-handle-area-height, 24px);\n cursor: ns-resize;\n pointer-events: auto;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n:host(.bottom-sheet) .sliding-container-sheet-handle {\n width: var(--wje-sliding-container-sheet-handle-width, 36px);\n height: var(--wje-sliding-container-sheet-handle-height, 2px);\n background: var(--wje-sliding-container-sheet-handle-background, var(--wje-border-color));\n border-radius: var(--wje-sliding-container-sheet-handle-radius, 999px);\n}\n";
|
|
7
|
+
let documentScrollLocks = 0;
|
|
8
|
+
let documentScrollState = null;
|
|
7
9
|
class SlidingContainer extends WJElement {
|
|
8
10
|
/**
|
|
9
11
|
* Creates an instance of SlidingContainer.
|
|
@@ -12,6 +14,183 @@ class SlidingContainer extends WJElement {
|
|
|
12
14
|
constructor() {
|
|
13
15
|
super();
|
|
14
16
|
__publicField(this, "className", "SlidingContainer");
|
|
17
|
+
/**
|
|
18
|
+
* Stops a handle interaction from dismissing the bottom sheet.
|
|
19
|
+
* @param {Event} e The interaction emitted by the resize handle.
|
|
20
|
+
*/
|
|
21
|
+
__publicField(this, "stopSheetHandleEvent", (e) => {
|
|
22
|
+
var _a;
|
|
23
|
+
if (!this.isBottomSheet()) return;
|
|
24
|
+
this._sheetIgnoreDismissUntil = Date.now() + 500;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
e.stopPropagation();
|
|
27
|
+
(_a = e.stopImmediatePropagation) == null ? void 0 : _a.call(e);
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Prevents scroll events from reaching the page behind the bottom sheet.
|
|
31
|
+
* @param {Event} e The scroll event.
|
|
32
|
+
*/
|
|
33
|
+
__publicField(this, "preventBottomSheetScroll", (e) => {
|
|
34
|
+
if (!this.isBottomSheet() || !this.classList.contains("open")) return;
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Starts mobile bottom sheet resizing.
|
|
40
|
+
* @param {PointerEvent} e The pointer event.
|
|
41
|
+
*/
|
|
42
|
+
__publicField(this, "handleSheetDragStart", (e) => {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
if (!this.sheetResizable || !this.isBottomSheet()) return;
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
e.stopPropagation();
|
|
47
|
+
(_a = e.stopImmediatePropagation) == null ? void 0 : _a.call(e);
|
|
48
|
+
this._sheetIgnoreDismissUntil = Date.now() + 500;
|
|
49
|
+
if (this._sheetDrag) return;
|
|
50
|
+
this.startSheetDrag(e.pointerId, e.clientY);
|
|
51
|
+
try {
|
|
52
|
+
(_b = this.sheetHandleArea) == null ? void 0 : _b.setPointerCapture(e.pointerId);
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
window.addEventListener("pointermove", this.handleSheetDragMove);
|
|
56
|
+
window.addEventListener("pointerup", this.handleSheetDragEnd);
|
|
57
|
+
window.addEventListener("pointercancel", this.handleSheetDragEnd);
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Starts mobile bottom sheet resizing from a touch event.
|
|
61
|
+
* @param {TouchEvent} e The touch event.
|
|
62
|
+
*/
|
|
63
|
+
__publicField(this, "handleSheetTouchStart", (e) => {
|
|
64
|
+
var _a, _b;
|
|
65
|
+
if (!this.sheetResizable || !this.isBottomSheet() || this._sheetDrag) return;
|
|
66
|
+
const touch = (_a = e.touches) == null ? void 0 : _a[0];
|
|
67
|
+
if (!touch) return;
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
e.stopPropagation();
|
|
70
|
+
(_b = e.stopImmediatePropagation) == null ? void 0 : _b.call(e);
|
|
71
|
+
this._sheetIgnoreDismissUntil = Date.now() + 500;
|
|
72
|
+
this.startSheetDrag("touch", touch.clientY);
|
|
73
|
+
window.addEventListener("touchmove", this.handleSheetTouchMove, { passive: false });
|
|
74
|
+
window.addEventListener("touchend", this.handleSheetTouchEnd, { passive: false });
|
|
75
|
+
window.addEventListener("touchcancel", this.handleSheetTouchEnd, { passive: false });
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Starts tracking a possible backdrop dismiss tap.
|
|
79
|
+
* @param {PointerEvent} e The pointer event.
|
|
80
|
+
*/
|
|
81
|
+
__publicField(this, "handleBackdropPointerStart", (e) => {
|
|
82
|
+
if (!this.isBottomSheet() || e.target !== this.backdropElement || this.isEventInsideSheet(e) || Date.now() < this._sheetIgnoreDismissUntil) {
|
|
83
|
+
this._sheetBackdropGesture = null;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
this._sheetBackdropGesture = {
|
|
87
|
+
pointerId: e.pointerId,
|
|
88
|
+
startX: e.clientX,
|
|
89
|
+
startY: e.clientY,
|
|
90
|
+
hasMoved: false
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Tracks movement during a possible backdrop dismiss tap.
|
|
95
|
+
* @param {PointerEvent} e The pointer event.
|
|
96
|
+
*/
|
|
97
|
+
__publicField(this, "handleBackdropPointerMove", (e) => {
|
|
98
|
+
if (!this._sheetBackdropGesture || e.pointerId !== this._sheetBackdropGesture.pointerId) return;
|
|
99
|
+
const distanceX = Math.abs(e.clientX - this._sheetBackdropGesture.startX);
|
|
100
|
+
const distanceY = Math.abs(e.clientY - this._sheetBackdropGesture.startY);
|
|
101
|
+
if (distanceX > 8 || distanceY > 8) {
|
|
102
|
+
this._sheetBackdropGesture.hasMoved = true;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Finishes a possible backdrop dismiss tap.
|
|
107
|
+
* @param {PointerEvent} e The pointer event.
|
|
108
|
+
*/
|
|
109
|
+
__publicField(this, "handleBackdropPointerEnd", (e) => {
|
|
110
|
+
if (!this._sheetBackdropGesture || e.pointerId !== this._sheetBackdropGesture.pointerId) return;
|
|
111
|
+
const shouldClose = !this._sheetBackdropGesture.hasMoved && e.target === this.backdropElement && !this.isEventInsideSheet(e) && Date.now() >= this._sheetIgnoreDismissUntil;
|
|
112
|
+
this._sheetBackdropGesture = null;
|
|
113
|
+
this._sheetBackdropHandledUntil = Date.now() + 350;
|
|
114
|
+
if (shouldClose) {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
this.close(e);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
/**
|
|
121
|
+
* Cancels a possible backdrop dismiss tap.
|
|
122
|
+
*/
|
|
123
|
+
__publicField(this, "handleBackdropPointerCancel", () => {
|
|
124
|
+
this._sheetBackdropGesture = null;
|
|
125
|
+
this._sheetBackdropHandledUntil = Date.now() + 350;
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Resizes the mobile bottom sheet during dragging.
|
|
129
|
+
* @param {PointerEvent} e The pointer event.
|
|
130
|
+
*/
|
|
131
|
+
__publicField(this, "handleSheetDragMove", (e) => {
|
|
132
|
+
var _a;
|
|
133
|
+
if (!this._sheetDrag || e.pointerId !== this._sheetDrag.pointerId) return;
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
(_a = e.stopImmediatePropagation) == null ? void 0 : _a.call(e);
|
|
137
|
+
this.updateSheetDrag(e.clientY);
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* Resizes the mobile bottom sheet during touch dragging.
|
|
141
|
+
* @param {TouchEvent} e The touch event.
|
|
142
|
+
*/
|
|
143
|
+
__publicField(this, "handleSheetTouchMove", (e) => {
|
|
144
|
+
var _a, _b;
|
|
145
|
+
if (!this._sheetDrag || this._sheetDrag.pointerId !== "touch") return;
|
|
146
|
+
const touch = (_a = e.touches) == null ? void 0 : _a[0];
|
|
147
|
+
if (!touch) return;
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
e.stopPropagation();
|
|
150
|
+
(_b = e.stopImmediatePropagation) == null ? void 0 : _b.call(e);
|
|
151
|
+
this.updateSheetDrag(touch.clientY);
|
|
152
|
+
});
|
|
153
|
+
/**
|
|
154
|
+
* Ends mobile bottom sheet resizing.
|
|
155
|
+
* @param {PointerEvent} e The pointer event.
|
|
156
|
+
*/
|
|
157
|
+
__publicField(this, "handleSheetDragEnd", (e) => {
|
|
158
|
+
var _a, _b, _c;
|
|
159
|
+
const hasMoved = (_a = this._sheetDrag) == null ? void 0 : _a.hasMoved;
|
|
160
|
+
if (this._sheetDrag && (e == null ? void 0 : e.pointerId) === this._sheetDrag.pointerId) {
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
e.stopPropagation();
|
|
163
|
+
(_b = e.stopImmediatePropagation) == null ? void 0 : _b.call(e);
|
|
164
|
+
try {
|
|
165
|
+
(_c = this.sheetHandleArea) == null ? void 0 : _c.releasePointerCapture(e.pointerId);
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (hasMoved) {
|
|
170
|
+
this._sheetIgnoreDismissUntil = Date.now() + 350;
|
|
171
|
+
} else {
|
|
172
|
+
this._sheetIgnoreDismissUntil = Date.now() + 500;
|
|
173
|
+
}
|
|
174
|
+
this.endSheetDrag();
|
|
175
|
+
});
|
|
176
|
+
/**
|
|
177
|
+
* Ends mobile bottom sheet resizing from a touch event.
|
|
178
|
+
* @param {TouchEvent} e The touch event.
|
|
179
|
+
*/
|
|
180
|
+
__publicField(this, "handleSheetTouchEnd", (e) => {
|
|
181
|
+
var _a;
|
|
182
|
+
if (!this._sheetDrag || this._sheetDrag.pointerId !== "touch") return;
|
|
183
|
+
const hasMoved = this._sheetDrag.hasMoved;
|
|
184
|
+
if (e.type !== "touchcancel") {
|
|
185
|
+
e.preventDefault();
|
|
186
|
+
}
|
|
187
|
+
e.stopPropagation();
|
|
188
|
+
if (e.type !== "touchcancel") {
|
|
189
|
+
(_a = e.stopImmediatePropagation) == null ? void 0 : _a.call(e);
|
|
190
|
+
}
|
|
191
|
+
this._sheetIgnoreDismissUntil = Date.now() + (hasMoved ? 350 : 700);
|
|
192
|
+
this.endSheetDrag();
|
|
193
|
+
});
|
|
15
194
|
/**
|
|
16
195
|
* Triggers the event based on the target element.
|
|
17
196
|
* If the target element is different from the last caller, it refreshes the children by calling the `open` method.
|
|
@@ -28,11 +207,19 @@ class SlidingContainer extends WJElement {
|
|
|
28
207
|
});
|
|
29
208
|
this._isOpen = false;
|
|
30
209
|
this._lastCaller = null;
|
|
210
|
+
this._sheetDrag = null;
|
|
211
|
+
this._sheetIgnoreDismissUntil = 0;
|
|
212
|
+
this._sheetBackdropGesture = null;
|
|
213
|
+
this._sheetBackdropHandledUntil = 0;
|
|
214
|
+
this._hasLockedDocumentScroll = false;
|
|
215
|
+
this._bottomSheetScopeFrame = null;
|
|
31
216
|
this._resizeObserver = new ResizeObserver((entries) => {
|
|
32
217
|
for (let entry of entries) {
|
|
33
218
|
if (entry.contentBoxSize) {
|
|
34
219
|
if (this.drawingStatus < 3) return;
|
|
35
|
-
if (this.
|
|
220
|
+
if (this.isBottomSheet()) {
|
|
221
|
+
this.checkForVariant(this.variant);
|
|
222
|
+
} else if (this.screenBreakPoint && window.innerWidth <= this.screenBreakPoint) {
|
|
36
223
|
if (this.variant !== "over") {
|
|
37
224
|
this.variant = "over";
|
|
38
225
|
} else {
|
|
@@ -155,6 +342,34 @@ class SlidingContainer extends WJElement {
|
|
|
155
342
|
set screenBreakPoint(value) {
|
|
156
343
|
this.setAttribute("screen-break-point", value);
|
|
157
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Sets mobile presentation mode.
|
|
347
|
+
* @param {string} value The mobile presentation mode.
|
|
348
|
+
*/
|
|
349
|
+
set mobilePresentation(value) {
|
|
350
|
+
this.setAttribute("mobile-presentation", value);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Gets mobile presentation mode.
|
|
354
|
+
* @returns {string|null} The mobile presentation mode.
|
|
355
|
+
*/
|
|
356
|
+
get mobilePresentation() {
|
|
357
|
+
return this.getAttribute("mobile-presentation");
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Sets the breakpoint for mobile presentation.
|
|
361
|
+
* @param {string} value The mobile breakpoint.
|
|
362
|
+
*/
|
|
363
|
+
set mobileBreakPoint(value) {
|
|
364
|
+
this.setAttribute("mobile-break-point", value);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Gets the breakpoint for mobile presentation.
|
|
368
|
+
* @returns {string} The mobile breakpoint.
|
|
369
|
+
*/
|
|
370
|
+
get mobileBreakPoint() {
|
|
371
|
+
return this.getAttribute("mobile-break-point") || "768";
|
|
372
|
+
}
|
|
158
373
|
/**
|
|
159
374
|
* Sets the duration of the animation by updating the `animation-duration` attribute.
|
|
160
375
|
* @param {string} value The duration value for the animation, specified in a format
|
|
@@ -192,6 +407,97 @@ class SlidingContainer extends WJElement {
|
|
|
192
407
|
get hasOpacity() {
|
|
193
408
|
return this.hasAttribute("has-opacity") ?? false;
|
|
194
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Determines if the bottom sheet should close when the backdrop is clicked.
|
|
412
|
+
* @returns {boolean} True if backdrop dismiss is enabled.
|
|
413
|
+
*/
|
|
414
|
+
get backdropDismiss() {
|
|
415
|
+
return this.hasAttribute("backdrop-dismiss") ?? false;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Enables resizing for the mobile bottom sheet.
|
|
419
|
+
* @returns {boolean} True if the sheet can be resized.
|
|
420
|
+
*/
|
|
421
|
+
get sheetResizable() {
|
|
422
|
+
return this.hasAttribute("sheet-resizable") ?? false;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Sets resizing for the mobile bottom sheet.
|
|
426
|
+
* @param {boolean|string} value The value to set.
|
|
427
|
+
*/
|
|
428
|
+
set sheetResizable(value) {
|
|
429
|
+
this.setAttribute("sheet-resizable", value);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Gets the mobile bottom sheet scope.
|
|
433
|
+
* @returns {string} Either 'viewport', 'container', or 'parent'.
|
|
434
|
+
*/
|
|
435
|
+
get sheetScope() {
|
|
436
|
+
return this.getAttribute("sheet-scope") || "viewport";
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Sets the mobile bottom sheet scope.
|
|
440
|
+
* @param {string} value The new boundary mode for the mobile sheet.
|
|
441
|
+
*/
|
|
442
|
+
set sheetScope(value) {
|
|
443
|
+
this.setAttribute("sheet-scope", value);
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Gets the selector used for container-scoped mobile bottom sheets.
|
|
447
|
+
* @returns {string|null} A CSS selector used to find the composed boundary ancestor.
|
|
448
|
+
*/
|
|
449
|
+
get sheetBoundary() {
|
|
450
|
+
return this.getAttribute("sheet-boundary");
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Sets the selector used for container-scoped mobile bottom sheets.
|
|
454
|
+
* @param {string} value Selector for the boundary element.
|
|
455
|
+
*/
|
|
456
|
+
set sheetBoundary(value) {
|
|
457
|
+
this.setAttribute("sheet-boundary", value);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Gets the mobile bottom sheet opening height.
|
|
461
|
+
* @returns {string|null} The opening height.
|
|
462
|
+
*/
|
|
463
|
+
get sheetHeight() {
|
|
464
|
+
return this.getAttribute("sheet-height");
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Sets the mobile bottom sheet opening height.
|
|
468
|
+
* @param {string} value The opening height.
|
|
469
|
+
*/
|
|
470
|
+
set sheetHeight(value) {
|
|
471
|
+
this.setAttribute("sheet-height", value);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Gets the minimum mobile bottom sheet height while resizing.
|
|
475
|
+
* @returns {string|null} The minimum height.
|
|
476
|
+
*/
|
|
477
|
+
get sheetMinHeight() {
|
|
478
|
+
return this.getAttribute("sheet-min-height");
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Sets the minimum mobile bottom sheet height while resizing.
|
|
482
|
+
* @param {string} value The minimum height.
|
|
483
|
+
*/
|
|
484
|
+
set sheetMinHeight(value) {
|
|
485
|
+
this.setAttribute("sheet-min-height", value);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Gets the maximum mobile bottom sheet height while resizing.
|
|
489
|
+
* @returns {string|null} The maximum height.
|
|
490
|
+
*/
|
|
491
|
+
get sheetMaxHeight() {
|
|
492
|
+
return this.getAttribute("sheet-max-height");
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Sets the maximum mobile bottom sheet height while resizing.
|
|
496
|
+
* @param {string} value The maximum height.
|
|
497
|
+
*/
|
|
498
|
+
set sheetMaxHeight(value) {
|
|
499
|
+
this.setAttribute("sheet-max-height", value);
|
|
500
|
+
}
|
|
195
501
|
/**
|
|
196
502
|
* Sets the value of the 'add-to-height' attribute.
|
|
197
503
|
* This attribute is used to modify or adjust the height dynamically.
|
|
@@ -220,7 +526,7 @@ class SlidingContainer extends WJElement {
|
|
|
220
526
|
* @returns {string[]}
|
|
221
527
|
*/
|
|
222
528
|
static get observedAttributes() {
|
|
223
|
-
return ["max-width", "max-height", "trigger", "direction", "variant", "screen-break-point", "remove-child-after-close", "animation-duration", "animation-easing", "has-opacity"];
|
|
529
|
+
return ["max-width", "max-height", "trigger", "direction", "variant", "screen-break-point", "remove-child-after-close", "animation-duration", "animation-easing", "has-opacity", "mobile-presentation", "mobile-break-point", "backdrop-dismiss", "sheet-resizable", "sheet-scope", "sheet-boundary", "sheet-height", "sheet-min-height", "sheet-max-height"];
|
|
224
530
|
}
|
|
225
531
|
/**
|
|
226
532
|
* Returns the CSS styles for the component.
|
|
@@ -244,6 +550,7 @@ class SlidingContainer extends WJElement {
|
|
|
244
550
|
var _a, _b;
|
|
245
551
|
(_a = this.animation) == null ? void 0 : _a.cancel();
|
|
246
552
|
(_b = this.nativeAnimation) == null ? void 0 : _b.cancel();
|
|
553
|
+
this.endSheetDrag();
|
|
247
554
|
document.removeEventListener(this.trigger, this.triggerEvent);
|
|
248
555
|
}
|
|
249
556
|
/**
|
|
@@ -255,44 +562,89 @@ class SlidingContainer extends WJElement {
|
|
|
255
562
|
*/
|
|
256
563
|
draw(context, store, params) {
|
|
257
564
|
let fragment = document.createDocumentFragment();
|
|
565
|
+
const isBottomSheet = this.isBottomSheet();
|
|
566
|
+
let backdrop = document.createElement("div");
|
|
567
|
+
backdrop.setAttribute("part", "backdrop");
|
|
568
|
+
backdrop.classList.add("sliding-container-backdrop");
|
|
569
|
+
if (this._isOpen && isBottomSheet) {
|
|
570
|
+
backdrop.style.opacity = "var(--wje-sliding-container-backdrop-opacity, 1)";
|
|
571
|
+
}
|
|
572
|
+
backdrop.addEventListener("wheel", this.preventBottomSheetScroll, { passive: false });
|
|
573
|
+
backdrop.addEventListener("touchmove", this.preventBottomSheetScroll, { passive: false });
|
|
574
|
+
if (this.backdropDismiss) {
|
|
575
|
+
backdrop.addEventListener("pointerdown", this.handleBackdropPointerStart);
|
|
576
|
+
backdrop.addEventListener("pointermove", this.handleBackdropPointerMove);
|
|
577
|
+
backdrop.addEventListener("pointerup", this.handleBackdropPointerEnd);
|
|
578
|
+
backdrop.addEventListener("pointercancel", this.handleBackdropPointerCancel);
|
|
579
|
+
backdrop.addEventListener("click", (e) => {
|
|
580
|
+
if (this.isEventInsideSheet(e) || Date.now() < this._sheetIgnoreDismissUntil || Date.now() < this._sheetBackdropHandledUntil) {
|
|
581
|
+
e.preventDefault();
|
|
582
|
+
e.stopPropagation();
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (e.target === backdrop) {
|
|
586
|
+
this.close(e);
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
}
|
|
258
590
|
let wrapperDiv = document.createElement("div");
|
|
259
591
|
wrapperDiv.classList.add("sliding-container-wrapper");
|
|
260
592
|
let transparentDiv = document.createElement("div");
|
|
261
593
|
transparentDiv.classList.add("sliding-container-transparent");
|
|
262
|
-
if (this._isOpen) {
|
|
594
|
+
if (this._isOpen && !isBottomSheet) {
|
|
263
595
|
transparentDiv.style.width = this.maxWidth;
|
|
264
596
|
}
|
|
265
597
|
let native = document.createElement("div");
|
|
266
598
|
native.setAttribute("part", "sliding-container");
|
|
267
599
|
native.classList.add("native-sliding-container");
|
|
268
|
-
native.style.width = 0;
|
|
600
|
+
native.style.width = isBottomSheet ? "100%" : 0;
|
|
269
601
|
if (this.hasOpacity) {
|
|
270
602
|
native.style.opacity = 0;
|
|
271
603
|
}
|
|
272
604
|
if (this._isOpen) {
|
|
273
|
-
native.style.width = this.maxWidth;
|
|
605
|
+
native.style.width = isBottomSheet ? "100%" : this.maxWidth;
|
|
606
|
+
if (isBottomSheet) {
|
|
607
|
+
native.style.transform = "translateY(0)";
|
|
608
|
+
}
|
|
274
609
|
if (this.hasOpacity) {
|
|
275
610
|
native.style.opacity = 1;
|
|
276
611
|
}
|
|
612
|
+
} else if (isBottomSheet) {
|
|
613
|
+
native.style.transform = "translateY(100%)";
|
|
277
614
|
}
|
|
278
|
-
if (
|
|
615
|
+
if (isBottomSheet) {
|
|
616
|
+
native.style.left = 0;
|
|
617
|
+
native.style.right = 0;
|
|
618
|
+
native.style.bottom = 0;
|
|
619
|
+
native.style.maxHeight = this.maxHeight;
|
|
620
|
+
} else if (this.direction === "right") {
|
|
279
621
|
native.style.right = 0;
|
|
280
622
|
} else {
|
|
281
623
|
native.style.left = 0;
|
|
282
624
|
}
|
|
283
|
-
let slot = document.createElement("slot");
|
|
284
625
|
const nativeInner = document.createElement("div");
|
|
285
626
|
nativeInner.classList.add("native-sliding-container-inner");
|
|
286
|
-
nativeInner.style.width = this.maxWidth;
|
|
627
|
+
nativeInner.style.width = isBottomSheet ? "100%" : this.maxWidth;
|
|
628
|
+
if (isBottomSheet) {
|
|
629
|
+
nativeInner.style.maxHeight = this.maxHeight;
|
|
630
|
+
}
|
|
631
|
+
let slot = document.createElement("slot");
|
|
632
|
+
this.sheetHandleArea = null;
|
|
287
633
|
nativeInner.append(slot);
|
|
288
634
|
nativeInner.append(this.htmlCloseButton());
|
|
635
|
+
if (this.sheetResizable) {
|
|
636
|
+
native.append(this.htmlSheetHandle());
|
|
637
|
+
}
|
|
289
638
|
native.append(nativeInner);
|
|
290
639
|
wrapperDiv.append(transparentDiv);
|
|
291
640
|
wrapperDiv.append(native);
|
|
641
|
+
fragment.append(backdrop);
|
|
292
642
|
fragment.append(wrapperDiv);
|
|
643
|
+
this.backdropElement = backdrop;
|
|
293
644
|
this.transparentDiv = transparentDiv;
|
|
294
645
|
this.wrapperDiv = wrapperDiv;
|
|
295
646
|
this.nativeElement = native;
|
|
647
|
+
this.nativeInner = nativeInner;
|
|
296
648
|
return fragment;
|
|
297
649
|
}
|
|
298
650
|
/**
|
|
@@ -304,11 +656,18 @@ class SlidingContainer extends WJElement {
|
|
|
304
656
|
afterDraw() {
|
|
305
657
|
this.syncAria();
|
|
306
658
|
document.addEventListener(this.trigger, this.triggerEvent);
|
|
307
|
-
if (this.screenBreakPoint && window.innerWidth <= this.screenBreakPoint) {
|
|
659
|
+
if (!this.isBottomSheet() && this.screenBreakPoint && window.innerWidth <= this.screenBreakPoint) {
|
|
308
660
|
this.variant = "over";
|
|
309
661
|
}
|
|
310
662
|
this.checkForVariant(this.variant);
|
|
311
663
|
}
|
|
664
|
+
/**
|
|
665
|
+
* Returns whether the mobile bottom sheet presentation is active.
|
|
666
|
+
* @returns {boolean}
|
|
667
|
+
*/
|
|
668
|
+
isBottomSheet() {
|
|
669
|
+
return this.mobilePresentation === "bottom-sheet" && window.innerWidth <= +this.mobileBreakPoint;
|
|
670
|
+
}
|
|
312
671
|
/**
|
|
313
672
|
* Sync ARIA attributes on host.
|
|
314
673
|
*/
|
|
@@ -341,6 +700,28 @@ class SlidingContainer extends WJElement {
|
|
|
341
700
|
});
|
|
342
701
|
return closeButton;
|
|
343
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Creates the mobile bottom sheet resize handle.
|
|
705
|
+
* @returns {HTMLElement} The resize handle element.
|
|
706
|
+
*/
|
|
707
|
+
htmlSheetHandle() {
|
|
708
|
+
const handleArea = document.createElement("div");
|
|
709
|
+
handleArea.setAttribute("part", "sheet-handle-area");
|
|
710
|
+
handleArea.setAttribute("role", "separator");
|
|
711
|
+
handleArea.setAttribute("aria-orientation", "horizontal");
|
|
712
|
+
handleArea.classList.add("sliding-container-sheet-handle-area");
|
|
713
|
+
const handle = document.createElement("div");
|
|
714
|
+
handle.setAttribute("part", "sheet-handle");
|
|
715
|
+
handle.classList.add("sliding-container-sheet-handle");
|
|
716
|
+
handleArea.append(handle);
|
|
717
|
+
handleArea.addEventListener("pointerdown", this.handleSheetDragStart, { capture: true });
|
|
718
|
+
handleArea.addEventListener("touchstart", this.handleSheetTouchStart, { capture: true, passive: false });
|
|
719
|
+
handleArea.addEventListener("click", this.stopSheetHandleEvent, { capture: true });
|
|
720
|
+
handleArea.addEventListener("mousedown", this.stopSheetHandleEvent, { capture: true });
|
|
721
|
+
handleArea.addEventListener("mouseup", this.stopSheetHandleEvent, { capture: true });
|
|
722
|
+
this.sheetHandleArea = handleArea;
|
|
723
|
+
return handleArea;
|
|
724
|
+
}
|
|
344
725
|
/**
|
|
345
726
|
* Retrieves the parent element of the current element.
|
|
346
727
|
* If the parent element is not found, it attempts to find the root host element.
|
|
@@ -353,6 +734,108 @@ class SlidingContainer extends WJElement {
|
|
|
353
734
|
}
|
|
354
735
|
return parentElement;
|
|
355
736
|
}
|
|
737
|
+
/**
|
|
738
|
+
* Finds the closest element across shadow DOM boundaries.
|
|
739
|
+
* @param {string} selector The selector to match.
|
|
740
|
+
* @returns {Element|null} The matched composed ancestor.
|
|
741
|
+
*/
|
|
742
|
+
getClosestComposedElement(selector) {
|
|
743
|
+
var _a;
|
|
744
|
+
let currentElement = this;
|
|
745
|
+
while (currentElement) {
|
|
746
|
+
let matches = false;
|
|
747
|
+
try {
|
|
748
|
+
matches = currentElement instanceof Element && currentElement.matches(selector);
|
|
749
|
+
} catch {
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
if (matches) {
|
|
753
|
+
return currentElement;
|
|
754
|
+
}
|
|
755
|
+
if (currentElement.parentElement) {
|
|
756
|
+
currentElement = currentElement.parentElement;
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
const root = (_a = currentElement.getRootNode) == null ? void 0 : _a.call(currentElement);
|
|
760
|
+
currentElement = root instanceof ShadowRoot ? root.host : null;
|
|
761
|
+
}
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Returns the viewport frame.
|
|
766
|
+
* @returns {{top: number, left: number, right: number, bottom: number, width: number, height: number}}
|
|
767
|
+
*/
|
|
768
|
+
getViewportFrame() {
|
|
769
|
+
return {
|
|
770
|
+
top: 0,
|
|
771
|
+
left: 0,
|
|
772
|
+
right: window.innerWidth,
|
|
773
|
+
bottom: window.innerHeight,
|
|
774
|
+
width: window.innerWidth,
|
|
775
|
+
height: window.innerHeight
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Returns the element that bounds the mobile bottom sheet.
|
|
780
|
+
* @returns {Element|null} The scope element, or null for viewport scope.
|
|
781
|
+
*/
|
|
782
|
+
getBottomSheetScopeElement() {
|
|
783
|
+
if (this.sheetScope === "viewport") return null;
|
|
784
|
+
if (this.sheetScope === "parent") return this.getParentElement();
|
|
785
|
+
if (this.sheetBoundary) return this.getClosestComposedElement(this.sheetBoundary);
|
|
786
|
+
return this.getParentElement();
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Returns the frame used by the mobile bottom sheet.
|
|
790
|
+
* @returns {{top: number, left: number, right: number, bottom: number, width: number, height: number}}
|
|
791
|
+
*/
|
|
792
|
+
getBottomSheetScopeFrame() {
|
|
793
|
+
const scopeElement = this.getBottomSheetScopeElement();
|
|
794
|
+
if (!scopeElement) return this.getViewportFrame();
|
|
795
|
+
const rect = scopeElement.getBoundingClientRect();
|
|
796
|
+
const top = Math.max(rect.top, 0);
|
|
797
|
+
const left = Math.max(rect.left, 0);
|
|
798
|
+
const right = Math.min(rect.right, window.innerWidth);
|
|
799
|
+
const bottom = Math.min(rect.bottom, window.innerHeight);
|
|
800
|
+
const width = right - left;
|
|
801
|
+
const height = bottom - top;
|
|
802
|
+
if (width <= 0 || height <= 0) {
|
|
803
|
+
return this.getViewportFrame();
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
top,
|
|
807
|
+
left,
|
|
808
|
+
right,
|
|
809
|
+
bottom,
|
|
810
|
+
width,
|
|
811
|
+
height
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Applies a fixed frame to a bottom sheet layer.
|
|
816
|
+
* @param {HTMLElement|SlidingContainer} element The element to update.
|
|
817
|
+
* @param {object} frame The frame to apply.
|
|
818
|
+
*/
|
|
819
|
+
setBottomSheetLayerFrame(element, frame) {
|
|
820
|
+
element.style.top = frame.top + "px";
|
|
821
|
+
element.style.left = frame.left + "px";
|
|
822
|
+
element.style.right = "auto";
|
|
823
|
+
element.style.bottom = "auto";
|
|
824
|
+
element.style.width = frame.width + "px";
|
|
825
|
+
element.style.height = frame.height + "px";
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Removes fixed frame styles from a bottom sheet layer.
|
|
829
|
+
* @param {HTMLElement|SlidingContainer} element The element to reset.
|
|
830
|
+
*/
|
|
831
|
+
resetBottomSheetLayerFrame(element) {
|
|
832
|
+
element == null ? void 0 : element.style.removeProperty("top");
|
|
833
|
+
element == null ? void 0 : element.style.removeProperty("left");
|
|
834
|
+
element == null ? void 0 : element.style.removeProperty("right");
|
|
835
|
+
element == null ? void 0 : element.style.removeProperty("bottom");
|
|
836
|
+
element == null ? void 0 : element.style.removeProperty("width");
|
|
837
|
+
element == null ? void 0 : element.style.removeProperty("height");
|
|
838
|
+
}
|
|
356
839
|
/**
|
|
357
840
|
* Adjusts the position and dimensions of the current element based on the specified variant.
|
|
358
841
|
*
|
|
@@ -362,6 +845,11 @@ class SlidingContainer extends WJElement {
|
|
|
362
845
|
* @returns {void} No value is returned, the method modifies the element's style properties directly.
|
|
363
846
|
*/
|
|
364
847
|
checkForVariant(variant) {
|
|
848
|
+
if (this.isBottomSheet()) {
|
|
849
|
+
this.setBottomSheetVariant();
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
this.resetBottomSheetVariant();
|
|
365
853
|
if (variant === "over") {
|
|
366
854
|
this.style.position = "fixed";
|
|
367
855
|
let computentStyleOfParent = window.getComputedStyle(this.getParentElement());
|
|
@@ -390,6 +878,286 @@ class SlidingContainer extends WJElement {
|
|
|
390
878
|
}
|
|
391
879
|
}
|
|
392
880
|
}
|
|
881
|
+
/**
|
|
882
|
+
* Applies the mobile bottom sheet layout.
|
|
883
|
+
*/
|
|
884
|
+
setBottomSheetVariant() {
|
|
885
|
+
const scopeFrame = this.getBottomSheetScopeFrame();
|
|
886
|
+
this._bottomSheetScopeFrame = scopeFrame;
|
|
887
|
+
this.classList.add("bottom-sheet");
|
|
888
|
+
this.style.position = "fixed";
|
|
889
|
+
this.setBottomSheetLayerFrame(this, scopeFrame);
|
|
890
|
+
this.setBottomSheetLayerFrame(this.backdropElement, scopeFrame);
|
|
891
|
+
this.setBottomSheetLayerFrame(this.wrapperDiv, scopeFrame);
|
|
892
|
+
this.wrapperDiv.style.height = "100%";
|
|
893
|
+
this.transparentDiv.style.width = 0;
|
|
894
|
+
this.nativeElement.style.left = scopeFrame.left + "px";
|
|
895
|
+
this.nativeElement.style.right = "auto";
|
|
896
|
+
this.nativeElement.style.bottom = window.innerHeight - scopeFrame.bottom + "px";
|
|
897
|
+
this.nativeElement.style.top = "auto";
|
|
898
|
+
this.nativeElement.style.width = scopeFrame.width + "px";
|
|
899
|
+
if (this._sheetDrag) {
|
|
900
|
+
this.nativeElement.style.maxHeight = this.getSheetMaxHeightInPixels() + "px";
|
|
901
|
+
} else {
|
|
902
|
+
this.setSheetHeight();
|
|
903
|
+
}
|
|
904
|
+
this.setBottomSheetVisualState(this.classList.contains("open"));
|
|
905
|
+
this.nativeInner.style.width = "100%";
|
|
906
|
+
this.nativeInner.style.maxHeight = this.nativeElement.style.maxHeight;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Removes layout styles managed by the mobile bottom sheet mode.
|
|
910
|
+
*/
|
|
911
|
+
resetBottomSheetVariant() {
|
|
912
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
913
|
+
if (!this.classList.contains("bottom-sheet")) return;
|
|
914
|
+
this.classList.remove("bottom-sheet");
|
|
915
|
+
this.style.removeProperty("position");
|
|
916
|
+
this.resetBottomSheetLayerFrame(this);
|
|
917
|
+
this.resetBottomSheetLayerFrame(this.backdropElement);
|
|
918
|
+
this.resetBottomSheetLayerFrame(this.wrapperDiv);
|
|
919
|
+
if (this.transparentDiv) {
|
|
920
|
+
this.transparentDiv.style.width = this._isOpen ? this.maxWidth : 0;
|
|
921
|
+
}
|
|
922
|
+
(_a = this.nativeElement) == null ? void 0 : _a.style.removeProperty("left");
|
|
923
|
+
(_b = this.nativeElement) == null ? void 0 : _b.style.removeProperty("right");
|
|
924
|
+
(_c = this.nativeElement) == null ? void 0 : _c.style.removeProperty("bottom");
|
|
925
|
+
(_d = this.nativeElement) == null ? void 0 : _d.style.removeProperty("top");
|
|
926
|
+
(_e = this.nativeElement) == null ? void 0 : _e.style.removeProperty("height");
|
|
927
|
+
(_f = this.nativeElement) == null ? void 0 : _f.style.removeProperty("max-height");
|
|
928
|
+
(_g = this.nativeElement) == null ? void 0 : _g.style.removeProperty("transform");
|
|
929
|
+
if (this.nativeElement) {
|
|
930
|
+
if (this.direction === "right") {
|
|
931
|
+
this.nativeElement.style.right = 0;
|
|
932
|
+
} else {
|
|
933
|
+
this.nativeElement.style.left = 0;
|
|
934
|
+
}
|
|
935
|
+
this.nativeElement.style.width = this._isOpen ? this.maxWidth : 0;
|
|
936
|
+
}
|
|
937
|
+
(_h = this.nativeInner) == null ? void 0 : _h.style.removeProperty("max-height");
|
|
938
|
+
if (this.nativeInner) {
|
|
939
|
+
this.nativeInner.style.width = this.maxWidth;
|
|
940
|
+
}
|
|
941
|
+
(_i = this.backdropElement) == null ? void 0 : _i.style.removeProperty("opacity");
|
|
942
|
+
this._bottomSheetScopeFrame = null;
|
|
943
|
+
this.endSheetDrag();
|
|
944
|
+
this.unlockDocumentScroll();
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Applies the current visual open or closed state to the mobile bottom sheet.
|
|
948
|
+
* @param {boolean} isOpen True when the sheet should be visible.
|
|
949
|
+
*/
|
|
950
|
+
setBottomSheetVisualState(isOpen) {
|
|
951
|
+
this.nativeElement.style.transform = isOpen ? "translateY(0)" : "translateY(100%)";
|
|
952
|
+
if (this.hasOpacity) {
|
|
953
|
+
this.nativeElement.style.opacity = isOpen ? 1 : 0;
|
|
954
|
+
}
|
|
955
|
+
this.backdropElement.style.opacity = isOpen ? "var(--wje-sliding-container-backdrop-opacity, 1)" : 0;
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Gets the CSS height limit used for the mobile bottom sheet.
|
|
959
|
+
* @returns {string} The CSS max height.
|
|
960
|
+
*/
|
|
961
|
+
getSheetMaxHeight() {
|
|
962
|
+
return this.sheetMaxHeight || this.maxHeight;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Applies the configured bottom sheet opening height.
|
|
966
|
+
*/
|
|
967
|
+
setSheetHeight() {
|
|
968
|
+
const maxHeightInPixels = this.getSheetMaxHeightInPixels();
|
|
969
|
+
this.nativeElement.style.maxHeight = maxHeightInPixels + "px";
|
|
970
|
+
if (!this.sheetHeight) {
|
|
971
|
+
this.nativeElement.style.removeProperty("height");
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const minHeight = Math.min(this.getSheetMinHeightInPixels(), maxHeightInPixels);
|
|
975
|
+
const height = this.resolveCssHeight(this.sheetHeight, maxHeightInPixels);
|
|
976
|
+
const clampedHeight = this.clamp(height, minHeight, maxHeightInPixels);
|
|
977
|
+
this.nativeElement.style.height = clampedHeight + "px";
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Resolves the sheet minimum height in pixels.
|
|
981
|
+
* @returns {number} The minimum height.
|
|
982
|
+
*/
|
|
983
|
+
getSheetMinHeightInPixels() {
|
|
984
|
+
const availableHeight = this.getBottomSheetAvailableHeight();
|
|
985
|
+
return Math.min(
|
|
986
|
+
this.resolveCssHeight(this.sheetMinHeight || "30vh", availableHeight * 0.3),
|
|
987
|
+
availableHeight
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Resolves the sheet maximum height in pixels.
|
|
992
|
+
* @returns {number} The maximum height.
|
|
993
|
+
*/
|
|
994
|
+
getSheetMaxHeightInPixels() {
|
|
995
|
+
const availableHeight = this.getBottomSheetAvailableHeight();
|
|
996
|
+
return Math.min(
|
|
997
|
+
this.resolveCssHeight(this.getSheetMaxHeight(), availableHeight * 0.9),
|
|
998
|
+
availableHeight
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Returns available height for the bottom sheet scope.
|
|
1003
|
+
* @returns {number} Pixel height that can be used inside the current sheet frame.
|
|
1004
|
+
*/
|
|
1005
|
+
getBottomSheetAvailableHeight() {
|
|
1006
|
+
var _a;
|
|
1007
|
+
return ((_a = this._bottomSheetScopeFrame) == null ? void 0 : _a.height) || this.getBottomSheetScopeFrame().height || window.innerHeight;
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Resolves a CSS height value against the viewport.
|
|
1011
|
+
* @param {string} value The configured sheet height.
|
|
1012
|
+
* @param {number} fallback The fallback height in pixels.
|
|
1013
|
+
* @returns {number} The resolved height.
|
|
1014
|
+
*/
|
|
1015
|
+
resolveCssHeight(value, fallback) {
|
|
1016
|
+
if (!value || value === "auto") return fallback;
|
|
1017
|
+
const normalizedValue = `${value}`.trim();
|
|
1018
|
+
const parsedValue = Number.parseFloat(normalizedValue);
|
|
1019
|
+
if (Number.isNaN(parsedValue)) return fallback;
|
|
1020
|
+
if (normalizedValue.endsWith("px")) return parsedValue;
|
|
1021
|
+
if (normalizedValue.endsWith("vh")) return window.innerHeight * parsedValue / 100;
|
|
1022
|
+
if (normalizedValue.endsWith("vw")) return window.innerWidth * parsedValue / 100;
|
|
1023
|
+
if (normalizedValue.endsWith("%")) return window.innerHeight * parsedValue / 100;
|
|
1024
|
+
if (/^-?\d+(\.\d+)?$/.test(normalizedValue)) return parsedValue;
|
|
1025
|
+
return fallback;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Clamps a number between min and max.
|
|
1029
|
+
* @param {number} value The measured height.
|
|
1030
|
+
* @param {number} min The minimum.
|
|
1031
|
+
* @param {number} max The maximum.
|
|
1032
|
+
* @returns {number} The clamped value.
|
|
1033
|
+
*/
|
|
1034
|
+
clamp(value, min, max) {
|
|
1035
|
+
return Math.min(Math.max(value, min), max);
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Checks whether an event came from the resize handle.
|
|
1039
|
+
* @param {Event} e The event to check.
|
|
1040
|
+
* @returns {boolean} True when the event belongs to the resize handle.
|
|
1041
|
+
*/
|
|
1042
|
+
isSheetHandleEvent(e) {
|
|
1043
|
+
if (!(e == null ? void 0 : e.composedPath)) return false;
|
|
1044
|
+
return e.composedPath().includes(this.sheetHandleArea);
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Checks whether an event happened inside the visible bottom sheet.
|
|
1048
|
+
* @param {Event} e The event to check.
|
|
1049
|
+
* @returns {boolean} True when the event coordinates are inside the sheet.
|
|
1050
|
+
*/
|
|
1051
|
+
isEventInsideSheet(e) {
|
|
1052
|
+
if (!this.nativeElement || typeof (e == null ? void 0 : e.clientX) !== "number" || typeof (e == null ? void 0 : e.clientY) !== "number") return false;
|
|
1053
|
+
const rect = this.nativeElement.getBoundingClientRect();
|
|
1054
|
+
return e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Prevents the page behind the mobile bottom sheet from scrolling.
|
|
1058
|
+
*/
|
|
1059
|
+
lockDocumentScroll() {
|
|
1060
|
+
if (!this.isBottomSheet() || this.sheetScope !== "viewport" || this._hasLockedDocumentScroll) return;
|
|
1061
|
+
if (documentScrollLocks === 0) {
|
|
1062
|
+
documentScrollState = {
|
|
1063
|
+
bodyOverflow: document.body.style.overflow,
|
|
1064
|
+
documentOverflow: document.documentElement.style.overflow,
|
|
1065
|
+
bodyOverscrollBehavior: document.body.style.overscrollBehavior,
|
|
1066
|
+
documentOverscrollBehavior: document.documentElement.style.overscrollBehavior,
|
|
1067
|
+
bodyPosition: document.body.style.position,
|
|
1068
|
+
bodyTop: document.body.style.top,
|
|
1069
|
+
bodyLeft: document.body.style.left,
|
|
1070
|
+
bodyRight: document.body.style.right,
|
|
1071
|
+
bodyWidth: document.body.style.width,
|
|
1072
|
+
scrollX: window.scrollX,
|
|
1073
|
+
scrollY: window.scrollY
|
|
1074
|
+
};
|
|
1075
|
+
document.body.style.overflow = "hidden";
|
|
1076
|
+
document.documentElement.style.overflow = "hidden";
|
|
1077
|
+
document.body.style.overscrollBehavior = "none";
|
|
1078
|
+
document.documentElement.style.overscrollBehavior = "none";
|
|
1079
|
+
document.body.style.position = "fixed";
|
|
1080
|
+
document.body.style.top = `-${documentScrollState.scrollY}px`;
|
|
1081
|
+
document.body.style.left = `-${documentScrollState.scrollX}px`;
|
|
1082
|
+
document.body.style.right = "0";
|
|
1083
|
+
document.body.style.width = "100%";
|
|
1084
|
+
}
|
|
1085
|
+
documentScrollLocks++;
|
|
1086
|
+
this._hasLockedDocumentScroll = true;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Restores page scrolling after the mobile bottom sheet is closed.
|
|
1090
|
+
*/
|
|
1091
|
+
unlockDocumentScroll() {
|
|
1092
|
+
if (!this._hasLockedDocumentScroll) return;
|
|
1093
|
+
documentScrollLocks = Math.max(documentScrollLocks - 1, 0);
|
|
1094
|
+
this._hasLockedDocumentScroll = false;
|
|
1095
|
+
if (documentScrollLocks > 0 || !documentScrollState) return;
|
|
1096
|
+
document.body.style.overflow = documentScrollState.bodyOverflow;
|
|
1097
|
+
document.documentElement.style.overflow = documentScrollState.documentOverflow;
|
|
1098
|
+
document.body.style.overscrollBehavior = documentScrollState.bodyOverscrollBehavior;
|
|
1099
|
+
document.documentElement.style.overscrollBehavior = documentScrollState.documentOverscrollBehavior;
|
|
1100
|
+
document.body.style.position = documentScrollState.bodyPosition;
|
|
1101
|
+
document.body.style.top = documentScrollState.bodyTop;
|
|
1102
|
+
document.body.style.left = documentScrollState.bodyLeft;
|
|
1103
|
+
document.body.style.right = documentScrollState.bodyRight;
|
|
1104
|
+
document.body.style.width = documentScrollState.bodyWidth;
|
|
1105
|
+
window.scrollTo(documentScrollState.scrollX, documentScrollState.scrollY);
|
|
1106
|
+
documentScrollState = null;
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Stores the initial drag state for the mobile bottom sheet.
|
|
1110
|
+
* @param {number|string} pointerId The pointer identifier.
|
|
1111
|
+
* @param {number} startY The starting Y coordinate.
|
|
1112
|
+
*/
|
|
1113
|
+
startSheetDrag(pointerId, startY) {
|
|
1114
|
+
var _a, _b;
|
|
1115
|
+
if (this.classList.contains("open")) {
|
|
1116
|
+
this.setBottomSheetVisualState(true);
|
|
1117
|
+
}
|
|
1118
|
+
(_a = this.animation) == null ? void 0 : _a.cancel();
|
|
1119
|
+
(_b = this.nativeAnimation) == null ? void 0 : _b.cancel();
|
|
1120
|
+
this.animation = null;
|
|
1121
|
+
this.nativeAnimation = null;
|
|
1122
|
+
const fallbackHeight = this.resolveCssHeight(this.sheetHeight, window.innerHeight * 0.5);
|
|
1123
|
+
const currentHeight = this.nativeElement.getBoundingClientRect().height || fallbackHeight;
|
|
1124
|
+
this._sheetDrag = {
|
|
1125
|
+
pointerId,
|
|
1126
|
+
startY,
|
|
1127
|
+
startHeight: currentHeight,
|
|
1128
|
+
minHeight: this.getSheetMinHeightInPixels(),
|
|
1129
|
+
maxHeight: this.getSheetMaxHeightInPixels(),
|
|
1130
|
+
hasMoved: false
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Applies a new height while the bottom sheet is being dragged.
|
|
1135
|
+
* @param {number} clientY The current Y coordinate.
|
|
1136
|
+
*/
|
|
1137
|
+
updateSheetDrag(clientY) {
|
|
1138
|
+
const distance = this._sheetDrag.startY - clientY;
|
|
1139
|
+
if (Math.abs(distance) > 3) {
|
|
1140
|
+
this._sheetDrag.hasMoved = true;
|
|
1141
|
+
}
|
|
1142
|
+
const height = this.clamp(
|
|
1143
|
+
this._sheetDrag.startHeight + distance,
|
|
1144
|
+
this._sheetDrag.minHeight,
|
|
1145
|
+
this._sheetDrag.maxHeight
|
|
1146
|
+
);
|
|
1147
|
+
this.nativeElement.style.height = height + "px";
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Cleans up mobile bottom sheet resizing listeners.
|
|
1151
|
+
*/
|
|
1152
|
+
endSheetDrag() {
|
|
1153
|
+
window.removeEventListener("pointermove", this.handleSheetDragMove);
|
|
1154
|
+
window.removeEventListener("pointerup", this.handleSheetDragEnd);
|
|
1155
|
+
window.removeEventListener("pointercancel", this.handleSheetDragEnd);
|
|
1156
|
+
window.removeEventListener("touchmove", this.handleSheetTouchMove);
|
|
1157
|
+
window.removeEventListener("touchend", this.handleSheetTouchEnd);
|
|
1158
|
+
window.removeEventListener("touchcancel", this.handleSheetTouchEnd);
|
|
1159
|
+
this._sheetDrag = null;
|
|
1160
|
+
}
|
|
393
1161
|
/**
|
|
394
1162
|
* Executes before the element is opened.
|
|
395
1163
|
*/
|
|
@@ -431,6 +1199,9 @@ class SlidingContainer extends WJElement {
|
|
|
431
1199
|
direction: "normal",
|
|
432
1200
|
easing: this.animationEasing
|
|
433
1201
|
};
|
|
1202
|
+
if (this.isBottomSheet()) {
|
|
1203
|
+
return this.doAnimateBottomSheetTransition(options);
|
|
1204
|
+
}
|
|
434
1205
|
if (this.animation && ((_b = (_a = this.animation) == null ? void 0 : _a.effect) == null ? void 0 : _b.target) !== this.transparentDiv) {
|
|
435
1206
|
this.animation.cancel();
|
|
436
1207
|
this.animation = null;
|
|
@@ -500,13 +1271,74 @@ class SlidingContainer extends WJElement {
|
|
|
500
1271
|
);
|
|
501
1272
|
}
|
|
502
1273
|
}
|
|
503
|
-
return new Promise((resolve
|
|
1274
|
+
return new Promise((resolve) => {
|
|
504
1275
|
this.animation.onfinish = () => {
|
|
505
1276
|
this._isOpen = !this._isOpen;
|
|
506
1277
|
resolve();
|
|
507
1278
|
};
|
|
508
1279
|
});
|
|
509
1280
|
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Animates the mobile bottom sheet and its backdrop.
|
|
1283
|
+
* @param {object} options Web Animation options.
|
|
1284
|
+
* @returns {Promise<void>}
|
|
1285
|
+
*/
|
|
1286
|
+
doAnimateBottomSheetTransition(options) {
|
|
1287
|
+
var _a, _b, _c, _d;
|
|
1288
|
+
const shouldOpen = !this._isOpen;
|
|
1289
|
+
const closedBackdrop = {
|
|
1290
|
+
opacity: 0
|
|
1291
|
+
};
|
|
1292
|
+
const openBackdrop = {
|
|
1293
|
+
opacity: "var(--wje-sliding-container-backdrop-opacity, 1)"
|
|
1294
|
+
};
|
|
1295
|
+
const closedSheet = {
|
|
1296
|
+
...this.hasOpacity ? { opacity: 0 } : {},
|
|
1297
|
+
transform: "translateY(100%)"
|
|
1298
|
+
};
|
|
1299
|
+
const openSheet = {
|
|
1300
|
+
...this.hasOpacity ? { opacity: 1 } : {},
|
|
1301
|
+
transform: "translateY(0)"
|
|
1302
|
+
};
|
|
1303
|
+
if (this.animation && ((_b = (_a = this.animation) == null ? void 0 : _a.effect) == null ? void 0 : _b.target) !== this.backdropElement) {
|
|
1304
|
+
this.animation.cancel();
|
|
1305
|
+
this.animation = null;
|
|
1306
|
+
}
|
|
1307
|
+
if (this.nativeAnimation && ((_d = (_c = this.nativeAnimation) == null ? void 0 : _c.effect) == null ? void 0 : _d.target) !== this.nativeElement) {
|
|
1308
|
+
this.nativeAnimation.cancel();
|
|
1309
|
+
this.nativeAnimation = null;
|
|
1310
|
+
}
|
|
1311
|
+
if (shouldOpen) {
|
|
1312
|
+
if (this.animation && this.nativeAnimation) {
|
|
1313
|
+
this.animation.reverse();
|
|
1314
|
+
this.nativeAnimation.reverse();
|
|
1315
|
+
} else {
|
|
1316
|
+
this.animation = this.backdropElement.animate([closedBackdrop, openBackdrop], options);
|
|
1317
|
+
this.nativeAnimation = this.nativeElement.animate([closedSheet, openSheet], options);
|
|
1318
|
+
}
|
|
1319
|
+
} else {
|
|
1320
|
+
if (this.animation && this.nativeAnimation) {
|
|
1321
|
+
this.animation.reverse();
|
|
1322
|
+
this.nativeAnimation.reverse();
|
|
1323
|
+
} else {
|
|
1324
|
+
this.animation = this.backdropElement.animate([openBackdrop, closedBackdrop], options);
|
|
1325
|
+
this.nativeAnimation = this.nativeElement.animate([openSheet, closedSheet], options);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
return new Promise((resolve) => {
|
|
1329
|
+
let isFinished = false;
|
|
1330
|
+
const finish = () => {
|
|
1331
|
+
if (isFinished) return;
|
|
1332
|
+
isFinished = true;
|
|
1333
|
+
this._isOpen = shouldOpen;
|
|
1334
|
+
this.classList.toggle("open", shouldOpen);
|
|
1335
|
+
this.setBottomSheetVisualState(shouldOpen);
|
|
1336
|
+
resolve();
|
|
1337
|
+
};
|
|
1338
|
+
this.nativeAnimation.onfinish = finish;
|
|
1339
|
+
this.nativeAnimation.oncancel = finish;
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
510
1342
|
/**
|
|
511
1343
|
* Opens the sliding container by performing necessary preparatory and transitional operations.
|
|
512
1344
|
* @param {Event} e The event that triggered the open operation.
|
|
@@ -518,6 +1350,7 @@ class SlidingContainer extends WJElement {
|
|
|
518
1350
|
this.classList.add("open");
|
|
519
1351
|
event.dispatchCustomEvent(this, "wje-sliding-container:beforeOpen");
|
|
520
1352
|
this.checkForVariant(this.variant);
|
|
1353
|
+
this.lockDocumentScroll();
|
|
521
1354
|
await this.doAnimateTransition();
|
|
522
1355
|
this.syncAria();
|
|
523
1356
|
await Promise.resolve(this.afterOpen(e)).then(() => {
|
|
@@ -532,12 +1365,20 @@ class SlidingContainer extends WJElement {
|
|
|
532
1365
|
* @returns {Promise<void>} A promise that resolves when the closing operation, including animations and child element removal, is completed.
|
|
533
1366
|
*/
|
|
534
1367
|
async close(e) {
|
|
1368
|
+
if (this.isBottomSheet() && e instanceof Event && (this.isSheetHandleEvent(e) || e.target === this.backdropElement && Date.now() < this._sheetIgnoreDismissUntil)) {
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
535
1371
|
await Promise.resolve(this.beforeClose(e)).then(async () => {
|
|
536
1372
|
if (this._isOpen) {
|
|
537
1373
|
this.classList.remove("open");
|
|
538
1374
|
event.dispatchCustomEvent(this, "wje-sliding-container:beforeClose");
|
|
539
|
-
await this.doAnimateTransition()
|
|
1375
|
+
await this.doAnimateTransition().catch(() => {
|
|
1376
|
+
if (this.isBottomSheet()) {
|
|
1377
|
+
this.setBottomSheetClosedState();
|
|
1378
|
+
}
|
|
1379
|
+
});
|
|
540
1380
|
this.syncAria();
|
|
1381
|
+
this.unlockDocumentScroll();
|
|
541
1382
|
await Promise.resolve(this.afterClose(e)).then(() => {
|
|
542
1383
|
if (this.removeChildAfterClose) {
|
|
543
1384
|
this.childNodes.forEach((child) => {
|
|
@@ -549,6 +1390,14 @@ class SlidingContainer extends WJElement {
|
|
|
549
1390
|
}
|
|
550
1391
|
});
|
|
551
1392
|
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Forces the closed visual state for the mobile bottom sheet.
|
|
1395
|
+
*/
|
|
1396
|
+
setBottomSheetClosedState() {
|
|
1397
|
+
this._isOpen = false;
|
|
1398
|
+
this.classList.remove("open");
|
|
1399
|
+
this.setBottomSheetVisualState(false);
|
|
1400
|
+
}
|
|
552
1401
|
/**
|
|
553
1402
|
* Toggles the state between open and closed.
|
|
554
1403
|
* @param {Event} e The event object triggering the toggle.
|
|
@@ -556,9 +1405,9 @@ class SlidingContainer extends WJElement {
|
|
|
556
1405
|
*/
|
|
557
1406
|
async toggle(e) {
|
|
558
1407
|
if (this._isOpen) {
|
|
559
|
-
await this.close(
|
|
1408
|
+
await this.close(e);
|
|
560
1409
|
} else {
|
|
561
|
-
await this.open(
|
|
1410
|
+
await this.open(e);
|
|
562
1411
|
}
|
|
563
1412
|
}
|
|
564
1413
|
/**
|
|
@@ -568,6 +1417,8 @@ class SlidingContainer extends WJElement {
|
|
|
568
1417
|
*/
|
|
569
1418
|
componentCleanup() {
|
|
570
1419
|
var _a;
|
|
1420
|
+
this.endSheetDrag();
|
|
1421
|
+
this.unlockDocumentScroll();
|
|
571
1422
|
(_a = this._resizeObserver) == null ? void 0 : _a.disconnect();
|
|
572
1423
|
this._resizeObserver = null;
|
|
573
1424
|
}
|