pure-web-bottom-sheet 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +560 -0
  3. package/dist/react/BottomSheet.d.ts +12 -0
  4. package/dist/react/BottomSheetDialogManager.d.ts +12 -0
  5. package/dist/react/Client.d.ts +1 -0
  6. package/dist/react/ShadowRootTemplate.d.ts +13 -0
  7. package/dist/react/index.d.ts +3 -0
  8. package/dist/react/index.js +2 -0
  9. package/dist/react/index.js.map +1 -0
  10. package/dist/react/react/BottomSheet.d.ts +12 -0
  11. package/dist/react/react/BottomSheet.js +2 -0
  12. package/dist/react/react/BottomSheet.js.map +1 -0
  13. package/dist/react/react/BottomSheetDialogManager.d.ts +12 -0
  14. package/dist/react/react/BottomSheetDialogManager.js +2 -0
  15. package/dist/react/react/BottomSheetDialogManager.js.map +1 -0
  16. package/dist/react/react/Client.d.ts +1 -0
  17. package/dist/react/react/Client.js +3 -0
  18. package/dist/react/react/Client.js.map +1 -0
  19. package/dist/react/react/ShadowRootTemplate.d.ts +13 -0
  20. package/dist/react/react/ShadowRootTemplate.js +3 -0
  21. package/dist/react/react/ShadowRootTemplate.js.map +1 -0
  22. package/dist/react/react/index.d.ts +3 -0
  23. package/dist/react/web/bottom-sheet-dialog-manager.d.ts +17 -0
  24. package/dist/react/web/bottom-sheet-dialog-manager.js +2 -0
  25. package/dist/react/web/bottom-sheet-dialog-manager.js.map +1 -0
  26. package/dist/react/web/bottom-sheet-dialog-manager.template.d.ts +1 -0
  27. package/dist/react/web/bottom-sheet-dialog-manager.template.js +2 -0
  28. package/dist/react/web/bottom-sheet-dialog-manager.template.js.map +1 -0
  29. package/dist/react/web/bottom-sheet.d.ts +47 -0
  30. package/dist/react/web/bottom-sheet.js +2 -0
  31. package/dist/react/web/bottom-sheet.js.map +1 -0
  32. package/dist/react/web/bottom-sheet.template.d.ts +1 -0
  33. package/dist/react/web/bottom-sheet.template.js +2 -0
  34. package/dist/react/web/bottom-sheet.template.js.map +1 -0
  35. package/dist/react/web/index.client.d.ts +4 -0
  36. package/dist/react/web/index.client.js +2 -0
  37. package/dist/react/web/index.client.js.map +1 -0
  38. package/dist/react/web/index.ssr.d.ts +4 -0
  39. package/dist/vue/index-fslx24KY.js +2 -0
  40. package/dist/vue/index-fslx24KY.js.map +1 -0
  41. package/dist/vue/index.client-BJCxko7x.js +2 -0
  42. package/dist/vue/index.client-BJCxko7x.js.map +1 -0
  43. package/dist/vue/index.d.ts +2 -0
  44. package/dist/vue/index.js +2 -0
  45. package/dist/vue/index.js.map +1 -0
  46. package/dist/vue/shims-vue.d.ts +9 -0
  47. package/dist/web/bottom-sheet-dialog-manager.d.ts +17 -0
  48. package/dist/web/bottom-sheet-dialog-manager.template.d.ts +1 -0
  49. package/dist/web/bottom-sheet.d.ts +47 -0
  50. package/dist/web/bottom-sheet.template.d.ts +1 -0
  51. package/dist/web/index.client.d.ts +4 -0
  52. package/dist/web/index.ssr.d.ts +4 -0
  53. package/dist/web.client.js +1 -0
  54. package/dist/web.ssr.js +1 -0
  55. package/package.json +117 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Vili Ketonen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,560 @@
1
+ # pure-web-bottom-sheet
2
+
3
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/viliket/pure-web-bottom-sheet/blob/main/LICENSE)
4
+
5
+ A lightweight, framework-agnostic bottom sheet component leveraging [CSS scroll snap](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll_snap)
6
+ and implemented as a [Web Component](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements).
7
+ Its key features include:
8
+
9
+ - **Native scroll-driven sheet movement and snap points** - uses the browser’s own
10
+ scroll mechanics instead of JavaScript-driven animations to adjust the sheet position
11
+ through CSS scroll snapping
12
+ - **Near Zero-JavaScript** operation on modern browsers - core functionality is
13
+ pure CSS
14
+ - **Framework-agnostic** - works with any framework or vanilla HTML
15
+ - **Easy customization** with a simple API
16
+ - **Accessibility** through native elements ([Dialog](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog)
17
+ or [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API))
18
+ supporting touch, keyboard, or mouse scrolling
19
+ - **Server-side rendering (SSR) compatible** with declarative Shadow DOM support
20
+ - **Cross-browser support** - tested on Chrome, Safari, and Firefox (desktop and
21
+ mobile)
22
+
23
+ The component uses CSS scroll snap and [CSS scroll-driven animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations)
24
+ for its core functionality. It uses minimal JavaScript for backward compatibility
25
+ and optional features, such as swipe-to-dismiss. Relying on browser-driven scrolling
26
+ physics ensures a native-like feel across different browsers and a performant implementation
27
+ by not relying on JavaScript-driven animation logic.
28
+
29
+ For server-side rendering or static site generation, the component includes [declarative Shadow DOM](https://web.dev/articles/declarative-shadow-dom)
30
+ templates to avoid flash of unstyled content (FOUC) when displaying the bottom sheet
31
+ initially open on page load.
32
+
33
+ https://github.com/user-attachments/assets/d25beef6-7256-4b7c-93ca-7605f73045b8
34
+
35
+ ## 📦 Installation
36
+
37
+ ```sh
38
+ npm install pure-web-bottom-sheet
39
+ ```
40
+
41
+ ## 💻 Usage
42
+
43
+ ### Vanilla HTML
44
+
45
+ <details>
46
+ <summary><strong>#️⃣ Example code - plain non-dismissible bottom sheet</strong></summary>
47
+
48
+ ```html
49
+ <!doctype html>
50
+ <html>
51
+ <head>
52
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
53
+ <title>Vanilla HTML example</title>
54
+ </head>
55
+ <body>
56
+ <bottom-sheet tabindex="0">
57
+ <!-- Snap points -->
58
+ <div slot="snap" style="--snap: 25%"></div>
59
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
60
+ <div slot="snap" style="--snap: 75%"></div>
61
+
62
+ <div slot="header">
63
+ <h2>Custom header</h2>
64
+ </div>
65
+ <div slot="footer">
66
+ <h2>Custom footer</h2>
67
+ </div>
68
+
69
+ <p>Custom content</p>
70
+ </bottom-sheet>
71
+
72
+ <script type="module">
73
+ import { BottomSheet } from "./path/to/pure-web-bottom-sheet";
74
+ customElements.define("bottom-sheet", BottomSheet);
75
+ </script>
76
+ </body>
77
+ </html>
78
+ ```
79
+
80
+ </details>
81
+
82
+ <details>
83
+ <summary><strong>#️⃣ Example code - modal bottom sheet with dialog integration</strong></summary>
84
+
85
+ ```html
86
+ <!doctype html>
87
+ <html>
88
+ <head>
89
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
90
+ <title>Vanilla HTML example</title>
91
+ </head>
92
+ <body>
93
+ <bottom-sheet-dialog-manager>
94
+ <dialog id="bottom-sheet-dialog">
95
+ <bottom-sheet swipe-to-dismiss tabindex="0">
96
+ <!-- Snap points -->
97
+ <div slot="snap" style="--snap: 25%"></div>
98
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
99
+ <div slot="snap" style="--snap: 75%"></div>
100
+
101
+ <div slot="header">
102
+ <h2>Custom header</h2>
103
+ </div>
104
+ <div slot="footer">
105
+ <h2>Custom footer</h2>
106
+ </div>
107
+
108
+ <p>Custom content</p>
109
+ </bottom-sheet>
110
+ </dialog>
111
+ </bottom-sheet-dialog-manager>
112
+
113
+ <button id="show-button">Open bottom sheet</button>
114
+
115
+ <script type="module">
116
+ import { registerSheetElements } from "./path/to/pure-web-bottom-sheet";
117
+ registerSheetElements();
118
+
119
+ document.getElementById("show-button").addEventListener("click", () => {
120
+ document.getElementById("bottom-sheet-dialog").showModal();
121
+ });
122
+ </script>
123
+ </body>
124
+ </html>
125
+ ```
126
+
127
+ </details>
128
+
129
+ ### Astro
130
+
131
+ <details>
132
+ <summary><strong>#️⃣ Example code - plain non-dismissible bottom sheet</strong></summary>
133
+
134
+ ```astro
135
+ ---
136
+ import { bottomSheetTemplate } from "pure-web-bottom-sheet/ssr";
137
+ ---
138
+
139
+ <bottom-sheet tabindex="0">
140
+ {/* Declarative shadow DOM for SSR support (optional) */}
141
+ <template shadowrootmode="open">
142
+ <Fragment set:html={bottomSheetTemplate} />
143
+ </template>
144
+
145
+ {/* Snap points */}
146
+ <div slot="snap" style="--snap: 25%"></div>
147
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
148
+ <div slot="snap" style="--snap: 75%"></div>
149
+
150
+ <div slot="header">
151
+ <h2>Custom header</h2>
152
+ </div>
153
+ <div slot="footer">
154
+ <h2>Custom footer</h2>
155
+ </div>
156
+
157
+ Custom content
158
+ </bottom-sheet>
159
+
160
+ <script>
161
+ import { BottomSheet } from "pure-web-bottom-sheet";
162
+ customElements.define("bottom-sheet", BottomSheet);
163
+ </script>
164
+ ```
165
+
166
+ </details>
167
+
168
+ <details>
169
+ <summary><strong>#️⃣ Example code - modal bottom sheet with dialog integration</strong></summary>
170
+
171
+ ```astro
172
+ ---
173
+ import { bottomSheetTemplate } from "pure-web-bottom-sheet/ssr";
174
+ ---
175
+
176
+ <bottom-sheet-dialog-manager>
177
+ <dialog id="bottom-sheet-dialog">
178
+ <bottom-sheet swipe-to-dismiss tabindex="0">
179
+ {/* Declarative shadow DOM for SSR support (optional) */}
180
+ <template shadowrootmode="open">
181
+ <Fragment set:html={bottomSheetTemplate} />
182
+ </template>
183
+
184
+ <!-- Snap points -->
185
+ <div slot="snap" style="--snap: 25%"></div>
186
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
187
+ <div slot="snap" style="--snap: 75%"></div>
188
+
189
+ <div slot="header">
190
+ <h2>Custom header</h2>
191
+ </div>
192
+ <div slot="footer">
193
+ <h2>Custom footer</h2>
194
+ </div>
195
+
196
+ <p>Custom content</p>
197
+ </bottom-sheet>
198
+ </dialog>
199
+ </bottom-sheet-dialog-manager>
200
+
201
+ <button id="show-button">Open bottom sheet</button>
202
+
203
+ <script type="module">
204
+ import { registerSheetElements } from "pure-web-bottom-sheet";
205
+ registerSheetElements();
206
+
207
+ document.getElementById("show-button").addEventListener("click", () => {
208
+ document.getElementById("bottom-sheet-dialog").showModal();
209
+ });
210
+ </script>
211
+ ```
212
+
213
+ </details>
214
+
215
+ ### React
216
+
217
+ For React, the library provides wrapper components to make it easier to use the
218
+ component and provide SSR support out of the box.
219
+
220
+ <details>
221
+ <summary><strong>#️⃣ Example code - plain non-dismissible bottom sheet</strong></summary>
222
+
223
+ ```tsx
224
+ import { BottomSheet } from "pure-web-bottom-sheet/react";
225
+
226
+ function Example() {
227
+ return (
228
+ <BottomSheet tabIndex={0}>
229
+ <div slot="snap" style={{ "--snap": "25%" }} />
230
+ <div slot="snap" style={{ "--snap": "50%" }} className="initial" />
231
+ <div slot="snap" style={{ "--snap": "75%" }} />
232
+
233
+ <div slot="header">
234
+ <h2>Custom header</h2>
235
+ </div>
236
+ <div slot="footer">
237
+ <h2>Custom footer</h2>
238
+ </div>
239
+
240
+ <p>Custom content</p>
241
+ </BottomSheet>
242
+ );
243
+ }
244
+ ```
245
+
246
+ </details>
247
+
248
+ <details>
249
+ <summary><strong>#️⃣ Example code - modal bottom sheet with dialog integration</strong></summary>
250
+
251
+ ```tsx
252
+ import {
253
+ BottomSheet,
254
+ BottomSheetDialogManager,
255
+ } from "pure-web-bottom-sheet/react";
256
+
257
+ import { useRef } from "react";
258
+
259
+ function Example() {
260
+ const dialog = useRef<HTMLDialogElement | null>(null);
261
+
262
+ return (
263
+ <section>
264
+ <p>
265
+ <button onClick={() => dialog.current?.showModal()}>
266
+ Open as modal
267
+ </button>
268
+ <button onClick={() => dialog.current?.show()}>
269
+ Open as non-modal
270
+ </button>
271
+ </p>
272
+ <BottomSheetDialogManager>
273
+ <dialog ref={dialog}>
274
+ <BottomSheet swipe-to-dismiss tabIndex={0}>
275
+ <div slot="snap" style={{ "--snap": "25%" }} />
276
+ <div slot="snap" style={{ "--snap": "50%" }} className="initial" />
277
+ <div slot="snap" style={{ "--snap": "75%" }} />
278
+ <div slot="header">
279
+ <h2>Custom header</h2>
280
+ </div>
281
+ <div slot="footer">
282
+ <h2>Custom footer</h2>
283
+ </div>
284
+ <DummyContent />
285
+ </BottomSheet>
286
+ </dialog>
287
+ </BottomSheetDialogManager>
288
+ </section>
289
+ );
290
+ }
291
+ ```
292
+
293
+ </details>
294
+
295
+ ### Vue
296
+
297
+ Similarly, for Vue, the library provides wrapper components to make it easier to
298
+ use the component and provide SSR support out of the box.
299
+
300
+ <details>
301
+ <summary><strong>#️⃣ Example code - plain non-dismissible bottom sheet</strong></summary>
302
+
303
+ ```vue
304
+ <template>
305
+ <VBottomSheet tabindex="0">
306
+ <div slot="snap" style="--snap: 25%"></div>
307
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
308
+ <div slot="snap" style="--snap: 75%"></div>
309
+
310
+ <div slot="header">
311
+ <h2>Custom header</h2>
312
+ </div>
313
+ <div slot="footer">
314
+ <h2>Custom footer</h2>
315
+ </div>
316
+
317
+ Custom content
318
+ </VBottomSheet>
319
+ </template>
320
+ <script setup>
321
+ import { VBottomSheet } from "pure-web-bottom-sheet/vue";
322
+ </script>
323
+ ```
324
+
325
+ </details>
326
+
327
+ <details>
328
+ <summary><strong>#️⃣ Example code - modal bottom sheet with dialog integration</strong></summary>
329
+
330
+ ```vue
331
+ <template>
332
+ <section>
333
+ <p>
334
+ <button @click="dialog.showModal()">Open as modal</button>
335
+ <button @click="dialog.show()">Open as non-modal</button>
336
+ </p>
337
+ <VBottomSheetDialogManager>
338
+ <dialog ref="bottom-sheet-dialog">
339
+ <VBottomSheet class="example" swipe-to-dismiss tabindex="0">
340
+ <div slot="header">
341
+ <h2>Custom header</h2>
342
+ </div>
343
+ <div slot="footer">
344
+ <h2>Custom footer</h2>
345
+ </div>
346
+ <div slot="snap" style="--snap: 25%"></div>
347
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
348
+ <div slot="snap" style="--snap: 75%"></div>
349
+ <DummyContent />
350
+ </VBottomSheet>
351
+ </dialog>
352
+ </VBottomSheetDialogManager>
353
+ </section>
354
+ </template>
355
+ <script setup>
356
+ import {
357
+ VBottomSheet,
358
+ VBottomSheetDialogManager,
359
+ } from "pure-web-bottom-sheet/vue";
360
+
361
+ const dialog = useTemplateRef("bottom-sheet-dialog");
362
+ </script>
363
+ ```
364
+
365
+ </details>
366
+
367
+ ## ▶️ Demos
368
+
369
+ See [examples](./examples).
370
+
371
+ ## 📄 API reference
372
+
373
+ ### `<bottom-sheet>`: The bottom sheet element
374
+
375
+ The `<bottom-sheet>` element can be used as a standalone component, optionally
376
+ with the HTML Popover API (see the _Examples_ section below), or together with
377
+ a dialog element (see `<bottom-sheet-dialog-manager>` element in the following
378
+ section). When used without a dialog wrapper element or without the HTML Popover
379
+ API, the bottom sheet is non-dismissable. This approach can be useful, e.g., when
380
+ using the bottom sheet as an overlay that should always remain visible.
381
+
382
+ #### Example composition
383
+
384
+ ```html
385
+ <bottom-sheet>
386
+ <!-- Snap points -->
387
+ <div slot="snap" style="--snap: 25%"></div>
388
+ <div slot="snap" style="--snap: 50%" class="initial"></div>
389
+ <div slot="snap" style="--snap: 75%"></div>
390
+
391
+ <!-- Custom header -->
392
+ <div slot="header">
393
+ <h2>Custom header</h2>
394
+ </div>
395
+
396
+ <!-- Custom footer -->
397
+ <div slot="footer">
398
+ <h2>Custom footer</h2>
399
+ </div>
400
+
401
+ <!-- Custom content (default slot) -->
402
+ Custom content
403
+ </bottom-sheet>
404
+ ```
405
+
406
+ #### Attributes
407
+
408
+ - **`content-height`**
409
+ Specifies that the sheet's maximum height is based on the height of its contents.
410
+ By default, when this attribute is not set, the sheet's maximum height is based
411
+ on the `--sheet-max-height` property (see below)
412
+ > ℹ️ **Note**: Not applicable when using the `nested-scroll` attribute
413
+ - **`nested-scroll`**
414
+ Specifies whether the bottom sheet acts as a scrollable container that allows
415
+ scrolling its contents independent of the bottom sheet's snap position
416
+ - **`nested-scroll-optimization`**
417
+ Specifies that the bottom sheet uses resize optimization for the nested scroll
418
+ mode to avoid reflows during sheet resizing. Only relevant when `nested-scroll`
419
+ is also true. Not relevant for `expand-to-scroll` mode since it already avoids
420
+ reflows.
421
+ > ℹ️ **Note**: This attribute is experimental.
422
+ - **`expand-to-scroll`**
423
+ Specifies that the content of the bottom sheet can only be scrolled after the
424
+ bottom sheet has been expanded to its full height
425
+ > ℹ️ **Note**: Only applicable when `nested-scroll` attribute is also set
426
+ - **`swipe-to-dismiss`**
427
+ Specifies that the bottom sheet can be swiped down to dismiss, and it will have
428
+ a snap point on the bottom to snap to close it
429
+ > ℹ️ **Note**: Only relevant when either:
430
+ >
431
+ > - the `<bottom-sheet>` is placed inside a `<dialog>` wrapped
432
+ > in `bottom-sheet-dialog-manager` element
433
+ > - using the Popover API (`popover` attribute on the bottom-sheet).
434
+
435
+ #### Slots
436
+
437
+ - **Default slot**
438
+ Defines the main content of the bottom sheet.
439
+ - **`snap`** (optional)
440
+ Defines snap points for positioning the bottom sheet. If not specified, the bottom
441
+ sheet will have a single snap point `--snap: 100%` (maximum
442
+ height). Note that when the `<bottom-sheet>` has the `swipe-to-dismiss` attribute
443
+ set, it also has a snap point at the bottom of the viewport to allow swiping down
444
+ to dismiss it.
445
+ Each snap point element should:
446
+ - Be assigned to this slot
447
+ - Specify the `--snap` custom property to set to the wanted offset from the viewport
448
+ top. For instance, `<div slot="snap" style="--snap: 50vh"></div>` creates a
449
+ snap point at 50vh from the bottom of the viewport (vertical center), and
450
+ a snap point with `--snap: 25vh` would position the sheet at 25vh from the viewport
451
+ bottom. You may use any CSS length units, such as `px`, `vh` (based on viewport
452
+ height), or `%` (based on sheet max height).
453
+ - Optionally specify the class `initial` to make the bottom sheet
454
+ initially snap to that point each time it is opened. Note that
455
+ only a single snap point should specify this class.
456
+ - **`header`** (optional)
457
+ Optional header content that is displayed at the top of the bottom sheet.
458
+ - **`footer`** (optional)
459
+ Optional content that is displayed at the bottom of the bottom sheet.
460
+
461
+ #### CSS custom properties
462
+
463
+ - **`--sheet-max-height`**
464
+ Controls the maximum height of the bottom sheet.
465
+ E.g., `--sheet-max-height: 50dvh;` means that the dialog max height is half of
466
+ the dynamic viewport height, and `--sheet-max-height: 100dvh;` means that the dialog max height is the full dynamic viewport height
467
+ - **`--sheet-background`**
468
+ Specifies the `background` property of the bottom sheet
469
+ - **`--sheet-border-radius`**
470
+ Specifies the border radius of the bottom sheet
471
+
472
+ #### Events
473
+
474
+ - **`snap-position-change`** - type: `CustomEvent<{ snapPosition: string; }>`
475
+ Notifies that the sheet snap position has changed. Positions: `"0"` indicates
476
+ a fully expanded position, `"2"` indicates a fully collapsed (closed) position,
477
+ and `"1"` indicates an intermediate position.
478
+
479
+ ### `<bottom-sheet-dialog-manager>`: A utility element for the native `<dialog>` element to use the `<bottom-sheet>` element as a dialog
480
+
481
+ The `<bottom-sheet-dialog-manager>` element is used when the bottom sheet should
482
+ act as a modal that can be opened and closed. This element should have
483
+ a single native `dialog` element as its child, which itself should have a single
484
+ `bottom-sheet` element as its child. The purpose of the `<bottom-sheet-dialog-manager>`
485
+ is to provide additional CSS styles to the native `dialog` element, and to handle
486
+ closing the dialog when clicking on the backdrop, and to implement the swipe-to-dismiss
487
+ functionality.
488
+
489
+ Example HTML structure:
490
+
491
+ ```html
492
+ <bottom-sheet-dialog-manager>
493
+ <dialog id="my-dialog">
494
+ <!--
495
+ Remember to specify `swipe-to-dismiss` attribute to allow the manager to
496
+ close the dialog when the bottom sheet is snapped to bottom of the viewport.
497
+
498
+ Specify `tabindex="0"` when you want the bottom sheet element itself to be
499
+ focusable. If set, it will appear in the tab order even if it has other focusable
500
+ content.
501
+ -->
502
+ <bottom-sheet swipe-to-dismiss tabindex="0">
503
+ <!-- Bottom sheet contents -->
504
+ </bottom-sheet>
505
+ </dialog>
506
+ </bottom-sheet-dialog-manager>
507
+
508
+ <button>Show the dialog</button>
509
+
510
+ <script>
511
+ import { registerSheetElements } from "pure-web-bottom-sheet";
512
+ registerSheetElements();
513
+
514
+ const dialog = document.getElementById("my-dialog");
515
+ const showButton = document.querySelector(
516
+ "bottom-sheet-dialog-manager + button",
517
+ );
518
+ showButton.addEventListener("click", () => {
519
+ dialog.showModal();
520
+ });
521
+ </script>
522
+ ```
523
+
524
+ ## 🎨 Customization
525
+
526
+ The bottom sheet exposes all its relevant parts to allow adding custom styles or
527
+ overriding the default styles.
528
+
529
+ Here are the relevant CSS selectors for the sheet customization:
530
+
531
+ - **`bottom-sheet`**
532
+ - **`bottom-sheet::part(sheet)`**
533
+ - **`bottom-sheet::part(handle)`**
534
+ - **`bottom-sheet::part(content)`**
535
+ - **`bottom-sheet::part(header)`**
536
+ - **`bottom-sheet::part(footer)`**
537
+
538
+ ## 🧑‍💻 Development
539
+
540
+ 1. Install the dependencies by running `npm install`
541
+ 2. Build the library by running `npm run build`
542
+ 3. Build the production build of the library by running `npm run build:prod`
543
+
544
+ Launch Astro examples:
545
+
546
+ ```sh
547
+ npm run dev -w examples/astro
548
+ ```
549
+
550
+ Launch React/Next.js examples:
551
+
552
+ ```sh
553
+ npm run dev -w examples/react-nextjs
554
+ ```
555
+
556
+ Launch Vue/Nuxt examples:
557
+
558
+ ```sh
559
+ npm run dev -w examples/vue-nuxt
560
+ ```
@@ -0,0 +1,12 @@
1
+ import { BottomSheet as BottomSheetElement } from '../web/index.ssr';
2
+ type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;
3
+ export type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & ElementProps<I>;
4
+ declare module "react/jsx-runtime" {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ "bottom-sheet": WebComponentProps<BottomSheetElement>;
8
+ }
9
+ }
10
+ }
11
+ export default function BottomSheet({ children, ...props }: WebComponentProps<BottomSheetElement>): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,12 @@
1
+ import { BottomSheetDialogManager as BottomSheetDialogManagerElement } from '../web/index.ssr';
2
+ type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;
3
+ export type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<React.HTMLAttributes<I>, I> & ElementProps<I>;
4
+ declare module "react/jsx-runtime" {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ "bottom-sheet-dialog-manager": WebComponentProps<BottomSheetDialogManagerElement>;
8
+ }
9
+ }
10
+ }
11
+ export default function BottomSheetDialogManager({ children, ...props }: WebComponentProps<BottomSheetDialogManagerElement>): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1 @@
1
+ export default function Client(): null;
@@ -0,0 +1,13 @@
1
+ declare module "react/jsx-runtime" {
2
+ namespace JSX {
3
+ interface IntrinsicElements {
4
+ template: React.HTMLAttributes<HTMLTemplateElement> & {
5
+ shadowrootmode?: ShadowRootMode;
6
+ shadowrootdelegatesfocus?: string;
7
+ };
8
+ }
9
+ }
10
+ }
11
+ export default function Template({ html }: {
12
+ html: string;
13
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,3 @@
1
+ import { default as BottomSheet } from './BottomSheet';
2
+ import { default as BottomSheetDialogManager } from './BottomSheetDialogManager';
3
+ export { BottomSheet, BottomSheetDialogManager };
@@ -0,0 +1,2 @@
1
+ export{default as BottomSheet}from"./react/BottomSheet.js";export{default as BottomSheetDialogManager}from"./react/BottomSheetDialogManager.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { BottomSheet as BottomSheetElement } from "../web/index.ssr";
2
+ type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;
3
+ export type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & ElementProps<I>;
4
+ declare module "react/jsx-runtime" {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ "bottom-sheet": WebComponentProps<BottomSheetElement>;
8
+ }
9
+ }
10
+ }
11
+ export default function BottomSheet({ children, ...props }: WebComponentProps<BottomSheetElement>): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,2 @@
1
+ import{jsxs as t,Fragment as e,jsx as r}from"react/jsx-runtime";import{template as o}from"../web/bottom-sheet.template.js";import m from"./Client.js";import i from"./ShadowRootTemplate.js";function n({children:n,...s}){return t(e,{children:[t("bottom-sheet",{...s,suppressHydrationWarning:!0,children:[r(i,{html:o}),n]}),r(m,{})]})}export{n as default};
2
+ //# sourceMappingURL=BottomSheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheet.js","sources":["../../../../src/react/BottomSheet.tsx"],"sourcesContent":["import {\r\n bottomSheetTemplate,\r\n BottomSheet as BottomSheetElement,\r\n} from \"../web/index.ssr\";\r\nimport Client from \"./Client\";\r\nimport ShadowRootTemplate from \"./ShadowRootTemplate\";\r\n\r\ntype ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;\r\nexport type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<\r\n React.HTMLAttributes<HTMLElement>,\r\n HTMLElement\r\n> &\r\n ElementProps<I>;\r\n\r\ndeclare module \"react/jsx-runtime\" {\r\n namespace JSX {\r\n interface IntrinsicElements {\r\n \"bottom-sheet\": WebComponentProps<BottomSheetElement>;\r\n }\r\n }\r\n}\r\n\r\nexport default function BottomSheet({\r\n children,\r\n ...props\r\n}: WebComponentProps<BottomSheetElement>) {\r\n return (\r\n <>\r\n <bottom-sheet\r\n {...props}\r\n // Need to use `suppressHydrationWarning` to avoid hydration mismatch\r\n // because the bottom-sheet component updates its `data-sheet-snap-position`\r\n // attribute during the initial render, which is not reflected in the\r\n // server-rendered HTML.\r\n suppressHydrationWarning\r\n >\r\n {<ShadowRootTemplate html={bottomSheetTemplate} />}\r\n {children}\r\n </bottom-sheet>\r\n <Client />\r\n </>\r\n );\r\n}\r\n"],"names":["BottomSheet","children","props","_jsxs","_Fragment","suppressHydrationWarning","_jsx","ShadowRootTemplate","html","bottomSheetTemplate","Client"],"mappings":"6LAsBc,SAAUA,GAAYC,SAClCA,KACGC,IAEH,OACEC,EAAAC,EAAA,CAAAH,SAAA,CACEE,EAAA,eAAA,IACMD,EAKJG,sCAECC,EAACC,EAAkB,CAACC,KAAMC,IAC1BR,KAEHK,EAACI,EAAM,CAAA,KAGb"}
@@ -0,0 +1,12 @@
1
+ import { BottomSheetDialogManager as BottomSheetDialogManagerElement } from "../web/index.ssr";
2
+ type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;
3
+ export type WebComponentProps<I extends HTMLElement> = React.DetailedHTMLProps<React.HTMLAttributes<I>, I> & ElementProps<I>;
4
+ declare module "react/jsx-runtime" {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ "bottom-sheet-dialog-manager": WebComponentProps<BottomSheetDialogManagerElement>;
8
+ }
9
+ }
10
+ }
11
+ export default function BottomSheetDialogManager({ children, ...props }: WebComponentProps<BottomSheetDialogManagerElement>): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,2 @@
1
+ import{jsxs as t,Fragment as e,jsx as o}from"react/jsx-runtime";import{template as r}from"../web/bottom-sheet-dialog-manager.template.js";import m from"./Client.js";import a from"./ShadowRootTemplate.js";function i({children:i,...l}){return t(e,{children:[t("bottom-sheet-dialog-manager",{...l,children:[o(a,{html:r}),i]}),o(m,{})]})}export{i as default};
2
+ //# sourceMappingURL=BottomSheetDialogManager.js.map