@surdeddd/bottom-sheet 0.10.0 → 0.12.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/README.md +52 -35
- package/dist/{BottomSheetEngine-DzsIwD28.d.cts → BottomSheetEngine-D6oiEfZ4.d.cts} +1 -0
- package/dist/{BottomSheetEngine-DRjCU73e.d.ts → BottomSheetEngine-Dhy0X_e9.d.ts} +1 -0
- package/dist/element.cjs +250 -136
- package/dist/element.d.cts +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +250 -136
- package/dist/index.cjs +257 -164
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +257 -164
- package/dist/integrations/formik.d.cts +1 -1
- package/dist/integrations/formik.d.ts +1 -1
- package/dist/integrations/react-hook-form.d.cts +1 -1
- package/dist/integrations/react-hook-form.d.ts +1 -1
- package/dist/overlay.cjs +161 -33
- package/dist/overlay.d.cts +1 -3
- package/dist/overlay.d.ts +1 -3
- package/dist/overlay.js +161 -33
- package/dist/preact.d.cts +1 -1
- package/dist/preact.d.ts +1 -1
- package/dist/qwik.cjs +240 -131
- package/dist/qwik.d.cts +2 -2
- package/dist/qwik.d.ts +2 -2
- package/dist/qwik.js +240 -131
- package/dist/react.cjs +257 -164
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +257 -164
- package/dist/solid.cjs +240 -131
- package/dist/solid.d.cts +1 -0
- package/dist/solid.d.ts +1 -0
- package/dist/solid.js +240 -131
- package/dist/solid.source.jsx +240 -131
- package/dist/svelte-core.cjs +240 -131
- package/dist/svelte-core.js +240 -131
- package/dist/svelte.cjs +252 -143
- package/dist/svelte.js +252 -143
- package/dist/vue.cjs +240 -131
- package/dist/vue.js +240 -131
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> Universal, headless bottom-sheet engine. **One core, eight adapters, GPU-accelerated, fully tested.**
|
|
4
4
|
|
|
5
|
-

|
|
6
|
+

|
|
7
7
|

|
|
8
8
|

|
|
9
9
|
|
|
@@ -14,40 +14,41 @@ stacking — and the exact same engine behind every adapter.
|
|
|
14
14
|
## 🚀 [Live demo → bottom-sheet-demo.vercel.app](https://bottom-sheet-demo.vercel.app)
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
17
|
-
<
|
|
17
|
+
<picture>
|
|
18
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/screenshots/sheet-dark.png" />
|
|
19
|
+
<img src="docs/screenshots/sheet-light.png" alt="bottom sheet at a mid snap point over a dimmed page" width="420" />
|
|
20
|
+
</picture>
|
|
18
21
|
</p>
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
<p align="center">
|
|
24
|
+
<img src="https://raw.githubusercontent.com/Surdeddd/BottomSheet/main/docs/gifs/01-drag-to-close.gif" alt="drag to close — spring physics" width="380" />
|
|
25
|
+
</p>
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
│ focus trap · scroll lock · stack │
|
|
26
|
-
└────────────┬──────────────────────────┘
|
|
27
|
-
│
|
|
28
|
-
┌──────┬──────┬──────┬──────┬──────┬─────────────┬─────────┐
|
|
29
|
-
▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
|
|
30
|
-
React Vue 3 Svelte Solid Lit Web Comp. Vanilla Angular
|
|
31
|
-
(recipe)
|
|
32
|
-
```
|
|
27
|
+
<p align="center">
|
|
28
|
+
<img src="docs/assets/architecture.svg" alt="One engine core feeding eight adapters — React, Preact, Vue 3, Svelte, Solid, Qwik, Web Component and Vanilla — plus a standalone /overlay subpath" width="720" />
|
|
29
|
+
</p>
|
|
33
30
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
31
|
+
## What it does
|
|
32
|
+
|
|
33
|
+
Every item below is verifiable in this repo's `src/`:
|
|
34
|
+
|
|
35
|
+
- **8 build targets** — React, Preact, Vue 3, Svelte 5, Solid, Qwik, Web
|
|
36
|
+
Component (Lit-compatible `<bottom-sheet>`) and the vanilla core, plus an
|
|
37
|
+
`/overlay` subpath (standalone slide-up panel).
|
|
38
|
+
- **4 axes** — `bottom`, `top`, `left`, `right` (via `mode`).
|
|
39
|
+
- **Spring physics with velocity carry**, plus pointer-type-aware tuning
|
|
40
|
+
(separate touch / mouse / pen drag thresholds).
|
|
41
|
+
- **Hardware-back interception** on Android — opt-in via `closeOnBack`.
|
|
42
|
+
- **`env(safe-area-inset-*)`-aware padding** so action rows clear the home
|
|
43
|
+
indicator.
|
|
44
|
+
- **WCAG 2.1 AA keyboard slider** — Arrow/Home/End/Esc stepping, focus trap
|
|
45
|
+
with restore.
|
|
46
|
+
- **Multi-sheet stacking** plus a typed sheet-manager registry.
|
|
47
|
+
- **Cancelable `before-snap` / `before-close`** — veto a transition
|
|
48
|
+
synchronously.
|
|
49
|
+
- Backed by 500+ unit tests across the suite and ~200 Playwright e2e runs
|
|
50
|
+
across three browser engines (`mobile-chrome` / `mobile-safari` /
|
|
51
|
+
`firefox`).
|
|
51
52
|
|
|
52
53
|
## Install
|
|
53
54
|
|
|
@@ -316,6 +317,14 @@ engine.depth(); // open sheets above this one
|
|
|
316
317
|
engine.destroy(); // remove listeners + cancel animation
|
|
317
318
|
```
|
|
318
319
|
|
|
320
|
+
`initial` starts the sheet **born open** at any snap whose size resolves `> 0`
|
|
321
|
+
(no `open` / `opened` event fires — there is no transition to announce). Calling
|
|
322
|
+
`open()` / `snapTo()` **synchronously in the mount tick is safe** — no
|
|
323
|
+
`requestAnimationFrame` / `nextTick` delay is needed, including `fit` / `content`
|
|
324
|
+
and teleported sheets. A sheet mounted hidden (`display:none` ancestor) heals
|
|
325
|
+
and emits its open sequence once on reveal. See
|
|
326
|
+
[Architecture → Opening at construction](docs/ARCHITECTURE.md).
|
|
327
|
+
|
|
319
328
|
### Scrim runtime API
|
|
320
329
|
|
|
321
330
|
The scrim is the dim layer behind/around the sheet (`screenComponent`). All
|
|
@@ -407,6 +416,14 @@ element — drive any CSS animation from drag without touching JS:
|
|
|
407
416
|
}
|
|
408
417
|
```
|
|
409
418
|
|
|
419
|
+
> **z-index is engine-owned.** The stack controller rewrites inline `z-index` on
|
|
420
|
+
> `.bs-sheet`, `.bs-backdrop` and anchor wrappers on every stack change (base
|
|
421
|
+
> `100`, step `10` per depth), so a value you set is overwritten and races the
|
|
422
|
+
> stack. To position the sheet layer against app UI, move the container
|
|
423
|
+
> (teleport target / `.bs-root` parent) or change the open order — don't style
|
|
424
|
+
> `z-index` on bs-managed elements. See
|
|
425
|
+
> [Architecture → z-index & the sheet stack](docs/ARCHITECTURE.md).
|
|
426
|
+
|
|
410
427
|
### Scrim, blur & high contrast
|
|
411
428
|
|
|
412
429
|
| Token | Default | Region |
|
|
@@ -456,19 +473,19 @@ npm run demo
|
|
|
456
473
|
# http://localhost:5173
|
|
457
474
|
```
|
|
458
475
|
|
|
459
|
-
The editorial demo showcases
|
|
476
|
+
The editorial demo showcases the adapters, every gesture, every mode
|
|
460
477
|
(`bottom · top · left · right · overlay`), and live engine readouts (active
|
|
461
478
|
snap, progress, velocity, FPS). EN/RU and light/dark toggles in the corner.
|
|
462
479
|
|
|
463
480
|
## Testing
|
|
464
481
|
|
|
465
482
|
```bash
|
|
466
|
-
npm test #
|
|
483
|
+
npm test # 500+ unit tests via vitest + happy-dom
|
|
467
484
|
npx playwright test # e2e via Playwright on mobile-Chrome / mobile-Safari / Firefox
|
|
468
485
|
npm run typecheck # TypeScript --noEmit
|
|
469
486
|
```
|
|
470
487
|
|
|
471
|
-
CI runs all three across Node 20/22 on every PR and tag.
|
|
488
|
+
CI runs all three across Node 20.19 / 22 on every PR and tag.
|
|
472
489
|
|
|
473
490
|
## Contributing
|
|
474
491
|
|
package/dist/element.cjs
CHANGED
|
@@ -504,6 +504,206 @@ var init_linked_sheets = __esm({
|
|
|
504
504
|
}
|
|
505
505
|
});
|
|
506
506
|
|
|
507
|
+
// src/core/features/history-coordinator.ts
|
|
508
|
+
function onPopState() {
|
|
509
|
+
if (suppress > 0) {
|
|
510
|
+
suppress -= 1;
|
|
511
|
+
const rebrand = pendingRebrand;
|
|
512
|
+
pendingRebrand = null;
|
|
513
|
+
if (rebrand) rebrand();
|
|
514
|
+
maybeTeardownListener();
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
if (entries.length === 0) {
|
|
518
|
+
notifyRouteChange();
|
|
519
|
+
maybeTeardownListener();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
let target = null;
|
|
523
|
+
let targetIdx = -1;
|
|
524
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
525
|
+
const entry = entries[i];
|
|
526
|
+
if (!entry.surface.isOpen()) continue;
|
|
527
|
+
if (!target) {
|
|
528
|
+
target = entry;
|
|
529
|
+
targetIdx = i;
|
|
530
|
+
}
|
|
531
|
+
if (entry.surface.isTop()) {
|
|
532
|
+
target = entry;
|
|
533
|
+
targetIdx = i;
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (!target) {
|
|
538
|
+
const removed = entries.pop();
|
|
539
|
+
if (removed) removed.live = false;
|
|
540
|
+
maybeTeardownListener();
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
target.live = false;
|
|
544
|
+
entries.splice(targetIdx, 1);
|
|
545
|
+
const settled = target;
|
|
546
|
+
void Promise.resolve(settled.surface.close()).then(() => {
|
|
547
|
+
if (settled.surface.isOpen()) restore(settled);
|
|
548
|
+
});
|
|
549
|
+
maybeTeardownListener();
|
|
550
|
+
}
|
|
551
|
+
function restore(entry) {
|
|
552
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
553
|
+
entry.live = true;
|
|
554
|
+
runInternal(() => {
|
|
555
|
+
try {
|
|
556
|
+
history.pushState(brandMarker(entry.surface), "", entry.surface.url);
|
|
557
|
+
} catch {
|
|
558
|
+
entry.live = false;
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
if (entry.live) {
|
|
562
|
+
entries.push(entry);
|
|
563
|
+
ensureListener();
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function pushBackMarker(surface) {
|
|
567
|
+
const entry = { surface, priorUrl: void 0, live: false };
|
|
568
|
+
if (!hasWindow() || !hasHistory()) {
|
|
569
|
+
return entry;
|
|
570
|
+
}
|
|
571
|
+
entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
|
|
572
|
+
runInternal(() => {
|
|
573
|
+
try {
|
|
574
|
+
history.pushState(brandMarker(surface), "", surface.url);
|
|
575
|
+
entry.live = true;
|
|
576
|
+
} catch {
|
|
577
|
+
entry.live = false;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
if (entry.live) {
|
|
581
|
+
entries.push(entry);
|
|
582
|
+
ensureListener();
|
|
583
|
+
}
|
|
584
|
+
return entry;
|
|
585
|
+
}
|
|
586
|
+
function popBackMarker(handle) {
|
|
587
|
+
if (!hasWindow() || !hasHistory()) return;
|
|
588
|
+
const entry = handle;
|
|
589
|
+
const idx = entries.indexOf(entry);
|
|
590
|
+
if (idx === -1 || !entry.live) return;
|
|
591
|
+
const last = entries.length - 1;
|
|
592
|
+
entry.live = false;
|
|
593
|
+
entries.splice(idx, 1);
|
|
594
|
+
if (idx !== last) {
|
|
595
|
+
const rebrandSurface = entries[entries.length - 1].surface;
|
|
596
|
+
const rebrandUrl = entry.priorUrl;
|
|
597
|
+
pendingRebrand = () => {
|
|
598
|
+
runInternal(() => {
|
|
599
|
+
history.replaceState(
|
|
600
|
+
brandMarker(rebrandSurface),
|
|
601
|
+
"",
|
|
602
|
+
rebrandUrl !== void 0 ? rebrandUrl : location.href
|
|
603
|
+
);
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
suppress += 1;
|
|
608
|
+
runInternal(() => {
|
|
609
|
+
try {
|
|
610
|
+
history.back();
|
|
611
|
+
} catch {
|
|
612
|
+
suppress = Math.max(0, suppress - 1);
|
|
613
|
+
pendingRebrand = null;
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
maybeTeardownListener();
|
|
617
|
+
}
|
|
618
|
+
function subscribeRouteChange(fn) {
|
|
619
|
+
if (!hasWindow() || !hasHistory()) return () => {
|
|
620
|
+
};
|
|
621
|
+
subscribers.add(fn);
|
|
622
|
+
if (subscribers.size === 1) installPatch();
|
|
623
|
+
ensureListener();
|
|
624
|
+
return () => {
|
|
625
|
+
if (!subscribers.has(fn)) return;
|
|
626
|
+
subscribers.delete(fn);
|
|
627
|
+
if (subscribers.size === 0) removePatch();
|
|
628
|
+
maybeTeardownListener();
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
var entries, subscribers, suppress, internalDepth, pendingRebrand, listenerInstalled, patchInstalled, origPushState, origReplaceState, patchedPushState, patchedReplaceState, hasWindow, hasHistory, brandMarker, runInternal, notifyRouteChange, ensureListener, maybeTeardownListener, installPatch, removePatch;
|
|
632
|
+
var init_history_coordinator = __esm({
|
|
633
|
+
"src/core/features/history-coordinator.ts"() {
|
|
634
|
+
entries = [];
|
|
635
|
+
subscribers = /* @__PURE__ */ new Set();
|
|
636
|
+
suppress = 0;
|
|
637
|
+
internalDepth = 0;
|
|
638
|
+
pendingRebrand = null;
|
|
639
|
+
listenerInstalled = false;
|
|
640
|
+
patchInstalled = false;
|
|
641
|
+
origPushState = null;
|
|
642
|
+
origReplaceState = null;
|
|
643
|
+
patchedPushState = null;
|
|
644
|
+
patchedReplaceState = null;
|
|
645
|
+
hasWindow = () => typeof window !== "undefined";
|
|
646
|
+
hasHistory = () => typeof history !== "undefined";
|
|
647
|
+
brandMarker = (surface) => ({
|
|
648
|
+
...surface.markerState(),
|
|
649
|
+
__bs: true
|
|
650
|
+
});
|
|
651
|
+
runInternal = (fn) => {
|
|
652
|
+
internalDepth += 1;
|
|
653
|
+
try {
|
|
654
|
+
fn();
|
|
655
|
+
} finally {
|
|
656
|
+
internalDepth -= 1;
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
notifyRouteChange = () => {
|
|
660
|
+
const snapshot = Array.from(subscribers);
|
|
661
|
+
for (const fn of snapshot) fn();
|
|
662
|
+
};
|
|
663
|
+
ensureListener = () => {
|
|
664
|
+
if (listenerInstalled || !hasWindow()) return;
|
|
665
|
+
window.addEventListener("popstate", onPopState);
|
|
666
|
+
listenerInstalled = true;
|
|
667
|
+
};
|
|
668
|
+
maybeTeardownListener = () => {
|
|
669
|
+
if (!listenerInstalled) return;
|
|
670
|
+
if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
|
|
671
|
+
if (hasWindow()) window.removeEventListener("popstate", onPopState);
|
|
672
|
+
listenerInstalled = false;
|
|
673
|
+
};
|
|
674
|
+
installPatch = () => {
|
|
675
|
+
if (patchInstalled || !hasHistory()) return;
|
|
676
|
+
origPushState = history.pushState;
|
|
677
|
+
origReplaceState = history.replaceState;
|
|
678
|
+
patchedPushState = function(...args) {
|
|
679
|
+
origPushState.apply(this, args);
|
|
680
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
681
|
+
};
|
|
682
|
+
patchedReplaceState = function(...args) {
|
|
683
|
+
origReplaceState.apply(this, args);
|
|
684
|
+
if (internalDepth === 0) notifyRouteChange();
|
|
685
|
+
};
|
|
686
|
+
history.pushState = patchedPushState;
|
|
687
|
+
history.replaceState = patchedReplaceState;
|
|
688
|
+
patchInstalled = true;
|
|
689
|
+
};
|
|
690
|
+
removePatch = () => {
|
|
691
|
+
if (!patchInstalled) return;
|
|
692
|
+
if (history.pushState === patchedPushState && origPushState) {
|
|
693
|
+
history.pushState = origPushState;
|
|
694
|
+
}
|
|
695
|
+
if (history.replaceState === patchedReplaceState && origReplaceState) {
|
|
696
|
+
history.replaceState = origReplaceState;
|
|
697
|
+
}
|
|
698
|
+
origPushState = null;
|
|
699
|
+
origReplaceState = null;
|
|
700
|
+
patchedPushState = null;
|
|
701
|
+
patchedReplaceState = null;
|
|
702
|
+
patchInstalled = false;
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
|
|
507
707
|
// src/core/features/route.ts
|
|
508
708
|
function installRoute(deps) {
|
|
509
709
|
if (typeof window === "undefined") {
|
|
@@ -514,135 +714,43 @@ function installRoute(deps) {
|
|
|
514
714
|
return () => {
|
|
515
715
|
};
|
|
516
716
|
}
|
|
517
|
-
let
|
|
518
|
-
let closer = null;
|
|
519
|
-
const teardownEntry = () => {
|
|
520
|
-
if (closer) {
|
|
521
|
-
const idx = closers.indexOf(closer);
|
|
522
|
-
if (idx !== -1) closers.splice(idx, 1);
|
|
523
|
-
}
|
|
524
|
-
const wasConsumed = closer?.consumed ?? false;
|
|
525
|
-
closer = null;
|
|
526
|
-
if (pushed && !wasConsumed) {
|
|
527
|
-
pushed = false;
|
|
528
|
-
programmaticBack();
|
|
529
|
-
} else {
|
|
530
|
-
pushed = false;
|
|
531
|
-
}
|
|
532
|
-
};
|
|
533
|
-
const pushEntry = () => {
|
|
534
|
-
try {
|
|
535
|
-
if (deps.routedTo !== void 0) {
|
|
536
|
-
history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
|
|
537
|
-
} else {
|
|
538
|
-
history.pushState({ __bsSheet: deps.sheetId }, "");
|
|
539
|
-
}
|
|
540
|
-
pushed = true;
|
|
541
|
-
} catch {
|
|
542
|
-
pushed = false;
|
|
543
|
-
}
|
|
544
|
-
};
|
|
717
|
+
let handle = null;
|
|
545
718
|
const onOpen = () => {
|
|
546
|
-
if (
|
|
547
|
-
|
|
719
|
+
if (handle) return;
|
|
720
|
+
handle = pushBackMarker({
|
|
548
721
|
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
549
|
-
isTop:
|
|
550
|
-
close:
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
closer = self;
|
|
560
|
-
ensureHandler();
|
|
561
|
-
closers.push(self);
|
|
562
|
-
pushEntry();
|
|
722
|
+
isTop: deps.isTopSheet,
|
|
723
|
+
close: deps.close,
|
|
724
|
+
markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
|
|
725
|
+
url: deps.routedTo
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
const onClose = () => {
|
|
729
|
+
if (!handle) return;
|
|
730
|
+
popBackMarker(handle);
|
|
731
|
+
handle = null;
|
|
563
732
|
};
|
|
564
733
|
const unsubscribeOpen = deps.on("open", onOpen);
|
|
565
|
-
const unsubscribeClose = deps.on("close",
|
|
734
|
+
const unsubscribeClose = deps.on("close", onClose);
|
|
566
735
|
if (deps.getSize() > 0) onOpen();
|
|
567
736
|
return () => {
|
|
568
737
|
unsubscribeOpen();
|
|
569
738
|
unsubscribeClose();
|
|
570
|
-
|
|
739
|
+
if (handle) {
|
|
740
|
+
popBackMarker(handle);
|
|
741
|
+
handle = null;
|
|
742
|
+
}
|
|
571
743
|
};
|
|
572
744
|
}
|
|
573
745
|
function installRouteChange(deps) {
|
|
574
|
-
|
|
575
|
-
return () => {
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
const onChange = () => {
|
|
746
|
+
return subscribeRouteChange(() => {
|
|
579
747
|
if (deps.isDestroyed() || deps.getSize() <= 0) return;
|
|
580
748
|
void deps.close();
|
|
581
|
-
};
|
|
582
|
-
const wrap = (key) => {
|
|
583
|
-
const original = history[key];
|
|
584
|
-
const patched = function(...args) {
|
|
585
|
-
original.apply(this, args);
|
|
586
|
-
onChange();
|
|
587
|
-
};
|
|
588
|
-
history[key] = patched;
|
|
589
|
-
return () => {
|
|
590
|
-
if (history[key] === patched) {
|
|
591
|
-
history[key] = original;
|
|
592
|
-
}
|
|
593
|
-
};
|
|
594
|
-
};
|
|
595
|
-
window.addEventListener("popstate", onChange);
|
|
596
|
-
const restorePush = wrap("pushState");
|
|
597
|
-
const restoreReplace = wrap("replaceState");
|
|
598
|
-
return () => {
|
|
599
|
-
window.removeEventListener("popstate", onChange);
|
|
600
|
-
restorePush();
|
|
601
|
-
restoreReplace();
|
|
602
|
-
};
|
|
749
|
+
});
|
|
603
750
|
}
|
|
604
|
-
var closers, handlerInstalled, suppress, ensureHandler, programmaticBack;
|
|
605
751
|
var init_route = __esm({
|
|
606
752
|
"src/core/features/route.ts"() {
|
|
607
|
-
|
|
608
|
-
handlerInstalled = false;
|
|
609
|
-
suppress = 0;
|
|
610
|
-
ensureHandler = () => {
|
|
611
|
-
if (handlerInstalled || typeof window === "undefined") return;
|
|
612
|
-
handlerInstalled = true;
|
|
613
|
-
window.addEventListener("popstate", () => {
|
|
614
|
-
if (suppress > 0) {
|
|
615
|
-
suppress -= 1;
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
let target = null;
|
|
619
|
-
for (let i = closers.length - 1; i >= 0; i -= 1) {
|
|
620
|
-
const c = closers[i];
|
|
621
|
-
if (!c.isOpen()) continue;
|
|
622
|
-
if (!target) target = c;
|
|
623
|
-
if (c.isTop()) {
|
|
624
|
-
target = c;
|
|
625
|
-
break;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
if (!target) return;
|
|
629
|
-
target.consumed = true;
|
|
630
|
-
const idx = closers.indexOf(target);
|
|
631
|
-
if (idx !== -1) closers.splice(idx, 1);
|
|
632
|
-
const settled = target;
|
|
633
|
-
void Promise.resolve(settled.close()).then(() => {
|
|
634
|
-
if (settled.isOpen()) settled.restore();
|
|
635
|
-
});
|
|
636
|
-
});
|
|
637
|
-
};
|
|
638
|
-
programmaticBack = () => {
|
|
639
|
-
suppress += 1;
|
|
640
|
-
try {
|
|
641
|
-
history.back();
|
|
642
|
-
} catch {
|
|
643
|
-
suppress = Math.max(0, suppress - 1);
|
|
644
|
-
}
|
|
645
|
-
};
|
|
753
|
+
init_history_coordinator();
|
|
646
754
|
}
|
|
647
755
|
});
|
|
648
756
|
|
|
@@ -942,11 +1050,15 @@ var init_fit_measurement = __esm({
|
|
|
942
1050
|
"src/core/features/fit-measurement.ts"() {
|
|
943
1051
|
init_transform();
|
|
944
1052
|
measureSheetNatural = (element, content, vertical) => {
|
|
945
|
-
if (!content) {
|
|
946
|
-
return vertical ? element.offsetHeight : element.offsetWidth;
|
|
947
|
-
}
|
|
948
1053
|
const axis = vertical ? "height" : "width";
|
|
949
1054
|
const sheetStyle = element.style;
|
|
1055
|
+
if (!content) {
|
|
1056
|
+
const prev = sheetStyle[axis];
|
|
1057
|
+
sheetStyle[axis] = "auto";
|
|
1058
|
+
const poked2 = vertical ? element.offsetHeight : element.offsetWidth;
|
|
1059
|
+
sheetStyle[axis] = prev;
|
|
1060
|
+
return poked2;
|
|
1061
|
+
}
|
|
950
1062
|
const cs = content.style;
|
|
951
1063
|
const prevSheet = sheetStyle[axis];
|
|
952
1064
|
const prevFlex = cs.flex;
|
|
@@ -2640,7 +2752,7 @@ var init_sheet_anchors = __esm({
|
|
|
2640
2752
|
// src/core/features/scrim-stages.ts
|
|
2641
2753
|
function installScrimStages(deps, opts) {
|
|
2642
2754
|
const doc = deps.host.ownerDocument;
|
|
2643
|
-
const
|
|
2755
|
+
const entries2 = opts.stages.map((def) => {
|
|
2644
2756
|
const wrapper = doc.createElement("div");
|
|
2645
2757
|
wrapper.className = "bs-scrim-stage";
|
|
2646
2758
|
const ws = wrapper.style;
|
|
@@ -2661,9 +2773,9 @@ function installScrimStages(deps, opts) {
|
|
|
2661
2773
|
const resolveActive = () => {
|
|
2662
2774
|
const state = deps.getState();
|
|
2663
2775
|
if (state.size === 0) {
|
|
2664
|
-
return
|
|
2776
|
+
return entries2.find((e) => matchesId(e.def, state.activeId)) ?? null;
|
|
2665
2777
|
}
|
|
2666
|
-
return
|
|
2778
|
+
return entries2.find((e) => matchesId(e.def, state.activeId)) ?? entries2.find((e) => matchesRange(e.def, state.progress)) ?? null;
|
|
2667
2779
|
};
|
|
2668
2780
|
const hide = (entry, animate) => {
|
|
2669
2781
|
entry.inFlight?.cancel();
|
|
@@ -2712,13 +2824,13 @@ function installScrimStages(deps, opts) {
|
|
|
2712
2824
|
deps.on("open", () => update(true)),
|
|
2713
2825
|
deps.on("close", () => update(true))
|
|
2714
2826
|
];
|
|
2715
|
-
if (
|
|
2827
|
+
if (entries2.some((e) => e.def.forRange)) {
|
|
2716
2828
|
offs.push(deps.on("progress", () => update(true)));
|
|
2717
2829
|
}
|
|
2718
2830
|
update(false);
|
|
2719
2831
|
return () => {
|
|
2720
2832
|
offs.forEach((off) => off());
|
|
2721
|
-
for (const entry of
|
|
2833
|
+
for (const entry of entries2) {
|
|
2722
2834
|
entry.inFlight?.cancel();
|
|
2723
2835
|
entry.inFlight = null;
|
|
2724
2836
|
if (entry.wrapper.parentNode) {
|
|
@@ -3038,17 +3150,12 @@ var init_BottomSheetEngine = __esm({
|
|
|
3038
3150
|
this.attach();
|
|
3039
3151
|
this.registerInStack();
|
|
3040
3152
|
if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
|
|
3041
|
-
const io = new IntersectionObserver((
|
|
3042
|
-
for (const entry of
|
|
3153
|
+
const io = new IntersectionObserver((entries2) => {
|
|
3154
|
+
for (const entry of entries2) {
|
|
3043
3155
|
if (!entry.isIntersecting) continue;
|
|
3044
3156
|
if (this.destroyed) return;
|
|
3045
3157
|
this.snaps.recompute();
|
|
3046
|
-
|
|
3047
|
-
if (current) {
|
|
3048
|
-
this.size = current.size;
|
|
3049
|
-
this.applySize(this.size);
|
|
3050
|
-
this.updateAriaSlider();
|
|
3051
|
-
}
|
|
3158
|
+
this.healActiveSnap();
|
|
3052
3159
|
io.disconnect();
|
|
3053
3160
|
return;
|
|
3054
3161
|
}
|
|
@@ -3212,6 +3319,8 @@ var init_BottomSheetEngine = __esm({
|
|
|
3212
3319
|
const vt = document.startViewTransition(() => {
|
|
3213
3320
|
this.applySize(target.size);
|
|
3214
3321
|
});
|
|
3322
|
+
vt.ready?.catch(() => {
|
|
3323
|
+
});
|
|
3215
3324
|
this.currentViewTransition = vt;
|
|
3216
3325
|
try {
|
|
3217
3326
|
await vt.finished;
|
|
@@ -3463,11 +3572,16 @@ var init_BottomSheetEngine = __esm({
|
|
|
3463
3572
|
this.maxHeight.clampTo();
|
|
3464
3573
|
this.scrim.invalidateOpacityCache();
|
|
3465
3574
|
if (this.gesture?.isDragging) return;
|
|
3575
|
+
this.healActiveSnap();
|
|
3576
|
+
}
|
|
3577
|
+
healActiveSnap() {
|
|
3466
3578
|
const current = this.snaps.findById(this.activeId);
|
|
3467
|
-
if (current)
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3579
|
+
if (!current) return;
|
|
3580
|
+
this.size = current.size;
|
|
3581
|
+
this.applySize(this.size);
|
|
3582
|
+
this.updateAriaSlider();
|
|
3583
|
+
if (this.size > 0 && !this.lifecycle.isInstalled && !this.opening && !this.animation.isAnimating) {
|
|
3584
|
+
this.emitOpenSequence(this.activeId);
|
|
3471
3585
|
}
|
|
3472
3586
|
}
|
|
3473
3587
|
destroy() {
|
|
@@ -3756,9 +3870,9 @@ var init_BottomSheetEngine = __esm({
|
|
|
3756
3870
|
return;
|
|
3757
3871
|
}
|
|
3758
3872
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
3759
|
-
const
|
|
3760
|
-
if (
|
|
3761
|
-
void this.animation.animateTo(
|
|
3873
|
+
const restore2 = this.snaps.findById(previousId);
|
|
3874
|
+
if (restore2) {
|
|
3875
|
+
void this.animation.animateTo(restore2.size, 0);
|
|
3762
3876
|
}
|
|
3763
3877
|
return;
|
|
3764
3878
|
}
|
package/dist/element.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BottomSheetEngine, C as CloseReason, A as AnchorOptions, S as ScrimStagesOptions, E as EngineState } from './BottomSheetEngine-
|
|
1
|
+
import { B as BottomSheetEngine, C as CloseReason, A as AnchorOptions, S as ScrimStagesOptions, E as EngineState } from './BottomSheetEngine-D6oiEfZ4.cjs';
|
|
2
2
|
import './transform-jVfAikE9.cjs';
|
|
3
3
|
|
|
4
4
|
declare const BaseHTMLElement: typeof HTMLElement;
|
package/dist/element.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BottomSheetEngine, C as CloseReason, A as AnchorOptions, S as ScrimStagesOptions, E as EngineState } from './BottomSheetEngine-
|
|
1
|
+
import { B as BottomSheetEngine, C as CloseReason, A as AnchorOptions, S as ScrimStagesOptions, E as EngineState } from './BottomSheetEngine-Dhy0X_e9.js';
|
|
2
2
|
import './transform-jVfAikE9.js';
|
|
3
3
|
|
|
4
4
|
declare const BaseHTMLElement: typeof HTMLElement;
|