@duskmoon-dev/el-bottom-sheet 0.4.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.
@@ -0,0 +1,425 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // src/index.ts
30
+ var exports_src = {};
31
+ __export(exports_src, {
32
+ register: () => register,
33
+ ElDmBottomSheet: () => ElDmBottomSheet
34
+ });
35
+ module.exports = __toCommonJS(exports_src);
36
+
37
+ // src/el-dm-bottom-sheet.ts
38
+ var import_el_core = require("@duskmoon-dev/el-core");
39
+ var styles = import_el_core.css`
40
+ :host {
41
+ display: contents;
42
+ }
43
+
44
+ :host([hidden]) {
45
+ display: none !important;
46
+ }
47
+
48
+ .bottom-sheet-wrapper {
49
+ position: fixed;
50
+ inset: 0;
51
+ z-index: 1000;
52
+ pointer-events: none;
53
+ }
54
+
55
+ .bottom-sheet-wrapper.open {
56
+ pointer-events: auto;
57
+ }
58
+
59
+ .bottom-sheet-backdrop {
60
+ position: absolute;
61
+ inset: 0;
62
+ background-color: rgba(0, 0, 0, 0.5);
63
+ opacity: 0;
64
+ transition: opacity 300ms ease;
65
+ }
66
+
67
+ .bottom-sheet-wrapper.open .bottom-sheet-backdrop {
68
+ opacity: 1;
69
+ }
70
+
71
+ .bottom-sheet {
72
+ position: absolute;
73
+ bottom: 0;
74
+ left: 0;
75
+ right: 0;
76
+ display: flex;
77
+ flex-direction: column;
78
+ max-height: 100vh;
79
+ max-height: 100dvh;
80
+ background-color: var(--color-surface);
81
+ border-radius: 1rem 1rem 0 0;
82
+ box-shadow: 0 -4px 20px rgb(0 0 0 / 0.15);
83
+ transform: translateY(100%);
84
+ transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1);
85
+ touch-action: none;
86
+ will-change: transform;
87
+ pointer-events: auto;
88
+ }
89
+
90
+ .bottom-sheet-wrapper.open .bottom-sheet {
91
+ transform: translateY(0);
92
+ }
93
+
94
+ .bottom-sheet.dragging {
95
+ transition: none;
96
+ }
97
+
98
+ .bottom-sheet-handle-area {
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ padding: 0.75rem 0;
103
+ cursor: grab;
104
+ touch-action: none;
105
+ }
106
+
107
+ .bottom-sheet-handle-area:active {
108
+ cursor: grabbing;
109
+ }
110
+
111
+ .bottom-sheet-handle {
112
+ width: 2.5rem;
113
+ height: 0.25rem;
114
+ background-color: var(--color-outline);
115
+ border-radius: 0.125rem;
116
+ transition: background-color 150ms ease;
117
+ }
118
+
119
+ .bottom-sheet-handle-area:hover .bottom-sheet-handle {
120
+ background-color: var(--color-outline-variant, var(--color-outline));
121
+ }
122
+
123
+ .bottom-sheet-header {
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: space-between;
127
+ padding: 0 1rem 0.75rem;
128
+ border-bottom: 1px solid var(--color-outline);
129
+ }
130
+
131
+ .bottom-sheet-header:empty {
132
+ display: none;
133
+ }
134
+
135
+ .bottom-sheet-content {
136
+ flex: 1;
137
+ padding: 1rem;
138
+ overflow-y: auto;
139
+ overscroll-behavior: contain;
140
+ }
141
+
142
+ /* Focus trap indicator for modal */
143
+ .bottom-sheet:focus-visible {
144
+ outline: 2px solid var(--color-primary);
145
+ outline-offset: -2px;
146
+ }
147
+
148
+ /* Safe area padding for notched devices */
149
+ @supports (padding-bottom: env(safe-area-inset-bottom)) {
150
+ .bottom-sheet-content {
151
+ padding-bottom: calc(1rem + env(safe-area-inset-bottom));
152
+ }
153
+ }
154
+ `;
155
+
156
+ class ElDmBottomSheet extends import_el_core.BaseElement {
157
+ static properties = {
158
+ open: { type: Boolean, reflect: true },
159
+ modal: { type: Boolean, reflect: true },
160
+ persistent: { type: Boolean, reflect: true },
161
+ snapPoints: { type: String, reflect: true, attribute: "snap-points" }
162
+ };
163
+ _startY = 0;
164
+ _currentY = 0;
165
+ _sheetHeight = 0;
166
+ _isDragging = false;
167
+ _parsedSnapPoints = [];
168
+ _currentSnapIndex = -1;
169
+ _focusableElements = [];
170
+ _previouslyFocused = null;
171
+ constructor() {
172
+ super();
173
+ this.attachStyles(styles);
174
+ }
175
+ connectedCallback() {
176
+ super.connectedCallback?.();
177
+ this._parseSnapPoints();
178
+ }
179
+ _parseSnapPoints() {
180
+ if (!this.snapPoints) {
181
+ this._parsedSnapPoints = [100];
182
+ return;
183
+ }
184
+ this._parsedSnapPoints = this.snapPoints.split(",").map((point) => {
185
+ const trimmed = point.trim();
186
+ if (trimmed.endsWith("%")) {
187
+ return parseFloat(trimmed);
188
+ }
189
+ return parseFloat(trimmed);
190
+ }).filter((point) => !isNaN(point) && point > 0 && point <= 100).sort((a, b) => a - b);
191
+ if (this._parsedSnapPoints.length === 0) {
192
+ this._parsedSnapPoints = [100];
193
+ }
194
+ }
195
+ _handleBackdropClick = (event) => {
196
+ if (!this.persistent && event.target === event.currentTarget) {
197
+ this.hide();
198
+ }
199
+ };
200
+ _handleKeyDown = (event) => {
201
+ if (event.key === "Escape" && !this.persistent) {
202
+ this.hide();
203
+ return;
204
+ }
205
+ if (this.modal && event.key === "Tab") {
206
+ this._trapFocus(event);
207
+ }
208
+ };
209
+ _trapFocus(event) {
210
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
211
+ if (!sheet)
212
+ return;
213
+ this._focusableElements = Array.from(sheet.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'));
214
+ const slotContent = this.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
215
+ this._focusableElements.push(...Array.from(slotContent));
216
+ if (this._focusableElements.length === 0)
217
+ return;
218
+ const firstFocusable = this._focusableElements[0];
219
+ const lastFocusable = this._focusableElements[this._focusableElements.length - 1];
220
+ if (event.shiftKey && document.activeElement === firstFocusable) {
221
+ event.preventDefault();
222
+ lastFocusable.focus();
223
+ } else if (!event.shiftKey && document.activeElement === lastFocusable) {
224
+ event.preventDefault();
225
+ firstFocusable.focus();
226
+ }
227
+ }
228
+ _handleTouchStart = (event) => {
229
+ const touch = event.touches[0];
230
+ this._startY = touch.clientY;
231
+ this._isDragging = true;
232
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
233
+ if (sheet) {
234
+ this._sheetHeight = sheet.getBoundingClientRect().height;
235
+ sheet.classList.add("dragging");
236
+ }
237
+ };
238
+ _handleTouchMove = (event) => {
239
+ if (!this._isDragging)
240
+ return;
241
+ const touch = event.touches[0];
242
+ this._currentY = touch.clientY;
243
+ const deltaY = this._currentY - this._startY;
244
+ if (deltaY > 0) {
245
+ event.preventDefault();
246
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
247
+ if (sheet) {
248
+ sheet.style.transform = `translateY(${deltaY}px)`;
249
+ }
250
+ }
251
+ };
252
+ _handleTouchEnd = () => {
253
+ if (!this._isDragging)
254
+ return;
255
+ this._isDragging = false;
256
+ const deltaY = this._currentY - this._startY;
257
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
258
+ if (sheet) {
259
+ sheet.classList.remove("dragging");
260
+ sheet.style.transform = "";
261
+ }
262
+ const threshold = this._sheetHeight * 0.25;
263
+ if (!this.persistent && deltaY > threshold) {
264
+ this.hide();
265
+ } else if (this._parsedSnapPoints.length > 1) {
266
+ this._snapToNearestPoint(deltaY);
267
+ }
268
+ this._startY = 0;
269
+ this._currentY = 0;
270
+ };
271
+ _handleMouseDown = (event) => {
272
+ this._startY = event.clientY;
273
+ this._isDragging = true;
274
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
275
+ if (sheet) {
276
+ this._sheetHeight = sheet.getBoundingClientRect().height;
277
+ sheet.classList.add("dragging");
278
+ }
279
+ document.addEventListener("mousemove", this._handleMouseMove);
280
+ document.addEventListener("mouseup", this._handleMouseUp);
281
+ };
282
+ _handleMouseMove = (event) => {
283
+ if (!this._isDragging)
284
+ return;
285
+ this._currentY = event.clientY;
286
+ const deltaY = this._currentY - this._startY;
287
+ if (deltaY > 0) {
288
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
289
+ if (sheet) {
290
+ sheet.style.transform = `translateY(${deltaY}px)`;
291
+ }
292
+ }
293
+ };
294
+ _handleMouseUp = () => {
295
+ if (!this._isDragging)
296
+ return;
297
+ this._isDragging = false;
298
+ const deltaY = this._currentY - this._startY;
299
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
300
+ if (sheet) {
301
+ sheet.classList.remove("dragging");
302
+ sheet.style.transform = "";
303
+ }
304
+ document.removeEventListener("mousemove", this._handleMouseMove);
305
+ document.removeEventListener("mouseup", this._handleMouseUp);
306
+ const threshold = this._sheetHeight * 0.25;
307
+ if (!this.persistent && deltaY > threshold) {
308
+ this.hide();
309
+ } else if (this._parsedSnapPoints.length > 1) {
310
+ this._snapToNearestPoint(deltaY);
311
+ }
312
+ this._startY = 0;
313
+ this._currentY = 0;
314
+ };
315
+ _snapToNearestPoint(deltaY) {
316
+ const currentHeightPercent = (this._sheetHeight - deltaY) / window.innerHeight * 100;
317
+ let nearestIndex = 0;
318
+ let nearestDistance = Math.abs(this._parsedSnapPoints[0] - currentHeightPercent);
319
+ for (let i = 1;i < this._parsedSnapPoints.length; i++) {
320
+ const distance = Math.abs(this._parsedSnapPoints[i] - currentHeightPercent);
321
+ if (distance < nearestDistance) {
322
+ nearestDistance = distance;
323
+ nearestIndex = i;
324
+ }
325
+ }
326
+ if (nearestIndex !== this._currentSnapIndex) {
327
+ this._currentSnapIndex = nearestIndex;
328
+ const snapHeight = this._parsedSnapPoints[nearestIndex];
329
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
330
+ if (sheet) {
331
+ sheet.style.height = `${snapHeight}vh`;
332
+ }
333
+ this.emit("snap", {
334
+ height: `${snapHeight}%`,
335
+ index: nearestIndex
336
+ });
337
+ }
338
+ }
339
+ show() {
340
+ this._parseSnapPoints();
341
+ this._previouslyFocused = document.activeElement;
342
+ this.open = true;
343
+ document.addEventListener("keydown", this._handleKeyDown);
344
+ document.body.style.overflow = "hidden";
345
+ if (this._parsedSnapPoints.length > 0) {
346
+ this._currentSnapIndex = this._parsedSnapPoints.length - 1;
347
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
348
+ if (sheet) {
349
+ sheet.style.height = `${this._parsedSnapPoints[this._currentSnapIndex]}vh`;
350
+ }
351
+ }
352
+ this.emit("open");
353
+ if (this.modal) {
354
+ requestAnimationFrame(() => {
355
+ const sheet = this.shadowRoot?.querySelector(".bottom-sheet");
356
+ sheet?.focus();
357
+ });
358
+ }
359
+ }
360
+ hide() {
361
+ this.open = false;
362
+ document.removeEventListener("keydown", this._handleKeyDown);
363
+ document.body.style.overflow = "";
364
+ this.emit("close");
365
+ if (this._previouslyFocused) {
366
+ this._previouslyFocused.focus();
367
+ this._previouslyFocused = null;
368
+ }
369
+ }
370
+ disconnectedCallback() {
371
+ super.disconnectedCallback?.();
372
+ document.removeEventListener("keydown", this._handleKeyDown);
373
+ document.removeEventListener("mousemove", this._handleMouseMove);
374
+ document.removeEventListener("mouseup", this._handleMouseUp);
375
+ document.body.style.overflow = "";
376
+ }
377
+ render() {
378
+ return `
379
+ <div class="bottom-sheet-wrapper ${this.open ? "open" : ""}" part="wrapper">
380
+ ${this.modal ? '<div class="bottom-sheet-backdrop" part="backdrop"></div>' : ""}
381
+ <div
382
+ class="bottom-sheet"
383
+ role="dialog"
384
+ aria-modal="${this.modal ? "true" : "false"}"
385
+ tabindex="-1"
386
+ part="sheet"
387
+ >
388
+ <div class="bottom-sheet-handle-area" part="handle-area">
389
+ <div class="bottom-sheet-handle" part="handle"></div>
390
+ </div>
391
+ <div class="bottom-sheet-header" part="header">
392
+ <slot name="header"></slot>
393
+ </div>
394
+ <div class="bottom-sheet-content" part="content">
395
+ <slot></slot>
396
+ </div>
397
+ </div>
398
+ </div>
399
+ `;
400
+ }
401
+ update() {
402
+ super.update();
403
+ const backdrop = this.shadowRoot?.querySelector(".bottom-sheet-backdrop");
404
+ backdrop?.addEventListener("click", this._handleBackdropClick);
405
+ const handleArea = this.shadowRoot?.querySelector(".bottom-sheet-handle-area");
406
+ handleArea?.addEventListener("touchstart", this._handleTouchStart, {
407
+ passive: false
408
+ });
409
+ handleArea?.addEventListener("touchmove", this._handleTouchMove, {
410
+ passive: false
411
+ });
412
+ handleArea?.addEventListener("touchend", this._handleTouchEnd);
413
+ handleArea?.addEventListener("mousedown", this._handleMouseDown);
414
+ }
415
+ }
416
+
417
+ // src/index.ts
418
+ function register() {
419
+ if (!customElements.get("el-dm-bottom-sheet")) {
420
+ customElements.define("el-dm-bottom-sheet", ElDmBottomSheet);
421
+ }
422
+ }
423
+
424
+ //# debugId=F0E78987FED4EAE464756E2164756E21
425
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/el-dm-bottom-sheet.ts", "../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * DuskMoon Bottom Sheet Element\n *\n * A mobile bottom panel/sheet component for displaying content that slides up from the bottom.\n * Supports snap points, swipe gestures, and modal mode.\n *\n * @element el-dm-bottom-sheet\n *\n * @attr {boolean} open - Whether the bottom sheet is open\n * @attr {boolean} modal - Whether to show backdrop and trap focus\n * @attr {boolean} persistent - Prevent dismiss by outside click or swipe down\n * @attr {string} snap-points - Comma-separated list of snap point heights (e.g., \"25%,50%,100%\")\n *\n * @slot - Default slot for sheet content\n * @slot header - Header content above the drag handle\n *\n * @csspart sheet - The sheet container\n * @csspart backdrop - The backdrop overlay (modal mode)\n * @csspart handle - The drag handle\n * @csspart content - The content wrapper\n * @csspart header - The header section\n *\n * @fires open - Fired when sheet opens\n * @fires close - Fired when sheet closes\n * @fires snap - Fired when sheet snaps to a point, detail contains { height, index }\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\n\nconst styles = css`\n :host {\n display: contents;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n .bottom-sheet-wrapper {\n position: fixed;\n inset: 0;\n z-index: 1000;\n pointer-events: none;\n }\n\n .bottom-sheet-wrapper.open {\n pointer-events: auto;\n }\n\n .bottom-sheet-backdrop {\n position: absolute;\n inset: 0;\n background-color: rgba(0, 0, 0, 0.5);\n opacity: 0;\n transition: opacity 300ms ease;\n }\n\n .bottom-sheet-wrapper.open .bottom-sheet-backdrop {\n opacity: 1;\n }\n\n .bottom-sheet {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n flex-direction: column;\n max-height: 100vh;\n max-height: 100dvh;\n background-color: var(--color-surface);\n border-radius: 1rem 1rem 0 0;\n box-shadow: 0 -4px 20px rgb(0 0 0 / 0.15);\n transform: translateY(100%);\n transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1);\n touch-action: none;\n will-change: transform;\n pointer-events: auto;\n }\n\n .bottom-sheet-wrapper.open .bottom-sheet {\n transform: translateY(0);\n }\n\n .bottom-sheet.dragging {\n transition: none;\n }\n\n .bottom-sheet-handle-area {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.75rem 0;\n cursor: grab;\n touch-action: none;\n }\n\n .bottom-sheet-handle-area:active {\n cursor: grabbing;\n }\n\n .bottom-sheet-handle {\n width: 2.5rem;\n height: 0.25rem;\n background-color: var(--color-outline);\n border-radius: 0.125rem;\n transition: background-color 150ms ease;\n }\n\n .bottom-sheet-handle-area:hover .bottom-sheet-handle {\n background-color: var(--color-outline-variant, var(--color-outline));\n }\n\n .bottom-sheet-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 1rem 0.75rem;\n border-bottom: 1px solid var(--color-outline);\n }\n\n .bottom-sheet-header:empty {\n display: none;\n }\n\n .bottom-sheet-content {\n flex: 1;\n padding: 1rem;\n overflow-y: auto;\n overscroll-behavior: contain;\n }\n\n /* Focus trap indicator for modal */\n .bottom-sheet:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: -2px;\n }\n\n /* Safe area padding for notched devices */\n @supports (padding-bottom: env(safe-area-inset-bottom)) {\n .bottom-sheet-content {\n padding-bottom: calc(1rem + env(safe-area-inset-bottom));\n }\n }\n`;\n\ninterface SnapEvent {\n height: string;\n index: number;\n}\n\nexport class ElDmBottomSheet extends BaseElement {\n static properties = {\n open: { type: Boolean, reflect: true },\n modal: { type: Boolean, reflect: true },\n persistent: { type: Boolean, reflect: true },\n snapPoints: { type: String, reflect: true, attribute: 'snap-points' },\n };\n\n declare open: boolean;\n declare modal: boolean;\n declare persistent: boolean;\n declare snapPoints: string;\n\n private _startY = 0;\n private _currentY = 0;\n private _sheetHeight = 0;\n private _isDragging = false;\n private _parsedSnapPoints: number[] = [];\n private _currentSnapIndex = -1;\n private _focusableElements: HTMLElement[] = [];\n private _previouslyFocused: HTMLElement | null = null;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n connectedCallback(): void {\n super.connectedCallback?.();\n this._parseSnapPoints();\n }\n\n private _parseSnapPoints(): void {\n if (!this.snapPoints) {\n this._parsedSnapPoints = [100];\n return;\n }\n\n this._parsedSnapPoints = this.snapPoints\n .split(',')\n .map((point) => {\n const trimmed = point.trim();\n if (trimmed.endsWith('%')) {\n return parseFloat(trimmed);\n }\n return parseFloat(trimmed);\n })\n .filter((point) => !isNaN(point) && point > 0 && point <= 100)\n .sort((a, b) => a - b);\n\n if (this._parsedSnapPoints.length === 0) {\n this._parsedSnapPoints = [100];\n }\n }\n\n private _handleBackdropClick = (event: Event): void => {\n if (!this.persistent && event.target === event.currentTarget) {\n this.hide();\n }\n };\n\n private _handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape' && !this.persistent) {\n this.hide();\n return;\n }\n\n if (this.modal && event.key === 'Tab') {\n this._trapFocus(event);\n }\n };\n\n private _trapFocus(event: KeyboardEvent): void {\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (!sheet) return;\n\n this._focusableElements = Array.from(\n sheet.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n\n const slotContent = this.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n this._focusableElements.push(...Array.from(slotContent));\n\n if (this._focusableElements.length === 0) return;\n\n const firstFocusable = this._focusableElements[0];\n const lastFocusable = this._focusableElements[this._focusableElements.length - 1];\n\n if (event.shiftKey && document.activeElement === firstFocusable) {\n event.preventDefault();\n lastFocusable.focus();\n } else if (!event.shiftKey && document.activeElement === lastFocusable) {\n event.preventDefault();\n firstFocusable.focus();\n }\n }\n\n private _handleTouchStart = (event: TouchEvent): void => {\n const touch = event.touches[0];\n this._startY = touch.clientY;\n this._isDragging = true;\n\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n this._sheetHeight = sheet.getBoundingClientRect().height;\n sheet.classList.add('dragging');\n }\n };\n\n private _handleTouchMove = (event: TouchEvent): void => {\n if (!this._isDragging) return;\n\n const touch = event.touches[0];\n this._currentY = touch.clientY;\n const deltaY = this._currentY - this._startY;\n\n if (deltaY > 0) {\n event.preventDefault();\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n sheet.style.transform = `translateY(${deltaY}px)`;\n }\n }\n };\n\n private _handleTouchEnd = (): void => {\n if (!this._isDragging) return;\n\n this._isDragging = false;\n const deltaY = this._currentY - this._startY;\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n\n if (sheet) {\n sheet.classList.remove('dragging');\n sheet.style.transform = '';\n }\n\n const threshold = this._sheetHeight * 0.25;\n\n if (!this.persistent && deltaY > threshold) {\n this.hide();\n } else if (this._parsedSnapPoints.length > 1) {\n this._snapToNearestPoint(deltaY);\n }\n\n this._startY = 0;\n this._currentY = 0;\n };\n\n private _handleMouseDown = (event: MouseEvent): void => {\n this._startY = event.clientY;\n this._isDragging = true;\n\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n this._sheetHeight = sheet.getBoundingClientRect().height;\n sheet.classList.add('dragging');\n }\n\n document.addEventListener('mousemove', this._handleMouseMove);\n document.addEventListener('mouseup', this._handleMouseUp);\n };\n\n private _handleMouseMove = (event: MouseEvent): void => {\n if (!this._isDragging) return;\n\n this._currentY = event.clientY;\n const deltaY = this._currentY - this._startY;\n\n if (deltaY > 0) {\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n sheet.style.transform = `translateY(${deltaY}px)`;\n }\n }\n };\n\n private _handleMouseUp = (): void => {\n if (!this._isDragging) return;\n\n this._isDragging = false;\n const deltaY = this._currentY - this._startY;\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n\n if (sheet) {\n sheet.classList.remove('dragging');\n sheet.style.transform = '';\n }\n\n document.removeEventListener('mousemove', this._handleMouseMove);\n document.removeEventListener('mouseup', this._handleMouseUp);\n\n const threshold = this._sheetHeight * 0.25;\n\n if (!this.persistent && deltaY > threshold) {\n this.hide();\n } else if (this._parsedSnapPoints.length > 1) {\n this._snapToNearestPoint(deltaY);\n }\n\n this._startY = 0;\n this._currentY = 0;\n };\n\n private _snapToNearestPoint(deltaY: number): void {\n const currentHeightPercent = ((this._sheetHeight - deltaY) / window.innerHeight) * 100;\n\n let nearestIndex = 0;\n let nearestDistance = Math.abs(this._parsedSnapPoints[0] - currentHeightPercent);\n\n for (let i = 1; i < this._parsedSnapPoints.length; i++) {\n const distance = Math.abs(this._parsedSnapPoints[i] - currentHeightPercent);\n if (distance < nearestDistance) {\n nearestDistance = distance;\n nearestIndex = i;\n }\n }\n\n if (nearestIndex !== this._currentSnapIndex) {\n this._currentSnapIndex = nearestIndex;\n const snapHeight = this._parsedSnapPoints[nearestIndex];\n\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n sheet.style.height = `${snapHeight}vh`;\n }\n\n this.emit<SnapEvent>('snap', {\n height: `${snapHeight}%`,\n index: nearestIndex,\n });\n }\n }\n\n show(): void {\n this._parseSnapPoints();\n this._previouslyFocused = document.activeElement as HTMLElement;\n this.open = true;\n document.addEventListener('keydown', this._handleKeyDown);\n document.body.style.overflow = 'hidden';\n\n if (this._parsedSnapPoints.length > 0) {\n this._currentSnapIndex = this._parsedSnapPoints.length - 1;\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n if (sheet) {\n sheet.style.height = `${this._parsedSnapPoints[this._currentSnapIndex]}vh`;\n }\n }\n\n this.emit('open');\n\n if (this.modal) {\n requestAnimationFrame(() => {\n const sheet = this.shadowRoot?.querySelector('.bottom-sheet') as HTMLElement;\n sheet?.focus();\n });\n }\n }\n\n hide(): void {\n this.open = false;\n document.removeEventListener('keydown', this._handleKeyDown);\n document.body.style.overflow = '';\n\n this.emit('close');\n\n if (this._previouslyFocused) {\n this._previouslyFocused.focus();\n this._previouslyFocused = null;\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback?.();\n document.removeEventListener('keydown', this._handleKeyDown);\n document.removeEventListener('mousemove', this._handleMouseMove);\n document.removeEventListener('mouseup', this._handleMouseUp);\n document.body.style.overflow = '';\n }\n\n render(): string {\n return `\n <div class=\"bottom-sheet-wrapper ${this.open ? 'open' : ''}\" part=\"wrapper\">\n ${this.modal ? '<div class=\"bottom-sheet-backdrop\" part=\"backdrop\"></div>' : ''}\n <div\n class=\"bottom-sheet\"\n role=\"dialog\"\n aria-modal=\"${this.modal ? 'true' : 'false'}\"\n tabindex=\"-1\"\n part=\"sheet\"\n >\n <div class=\"bottom-sheet-handle-area\" part=\"handle-area\">\n <div class=\"bottom-sheet-handle\" part=\"handle\"></div>\n </div>\n <div class=\"bottom-sheet-header\" part=\"header\">\n <slot name=\"header\"></slot>\n </div>\n <div class=\"bottom-sheet-content\" part=\"content\">\n <slot></slot>\n </div>\n </div>\n </div>\n `;\n }\n\n update(): void {\n super.update();\n\n const backdrop = this.shadowRoot?.querySelector('.bottom-sheet-backdrop');\n backdrop?.addEventListener('click', this._handleBackdropClick);\n\n const handleArea = this.shadowRoot?.querySelector('.bottom-sheet-handle-area');\n handleArea?.addEventListener('touchstart', this._handleTouchStart as EventListener, {\n passive: false,\n });\n handleArea?.addEventListener('touchmove', this._handleTouchMove as EventListener, {\n passive: false,\n });\n handleArea?.addEventListener('touchend', this._handleTouchEnd);\n handleArea?.addEventListener('mousedown', this._handleMouseDown as EventListener);\n }\n}\n",
6
+ "import { ElDmBottomSheet } from './el-dm-bottom-sheet.js';\n\nexport { ElDmBottomSheet };\n\nexport function register(): void {\n if (!customElements.get('el-dm-bottom-sheet')) {\n customElements.define('el-dm-bottom-sheet', ElDmBottomSheet);\n }\n}\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "F0E78987FED4EAE464756E2164756E21",
10
+ "names": []
11
+ }