@surdeddd/bottom-sheet 0.8.2 → 0.9.1
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/{BottomSheetEngine-7BDK2OWX.d.cts → BottomSheetEngine-BcyruNP1.d.cts} +12 -6
- package/dist/{BottomSheetEngine-BFTb0-4Z.d.ts → BottomSheetEngine-CBRcBwV-.d.ts} +12 -6
- package/dist/element.cjs +530 -349
- package/dist/element.d.cts +2 -1
- package/dist/element.d.ts +2 -1
- package/dist/element.iife.global.js +2 -2
- package/dist/element.js +530 -349
- package/dist/index.cjs +438 -294
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +438 -294
- 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 +160 -96
- package/dist/overlay.d.cts +2 -0
- package/dist/overlay.d.ts +2 -0
- package/dist/overlay.js +160 -96
- package/dist/preact.d.cts +1 -1
- package/dist/preact.d.ts +1 -1
- package/dist/qwik.cjs +387 -211
- package/dist/qwik.d.cts +4 -3
- package/dist/qwik.d.ts +4 -3
- package/dist/qwik.js +387 -211
- package/dist/react.cjs +472 -296
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +472 -296
- package/dist/solid.cjs +417 -215
- package/dist/solid.d.cts +21 -7
- package/dist/solid.d.ts +21 -7
- package/dist/solid.js +417 -215
- package/dist/solid.source.jsx +412 -209
- package/dist/svelte-core.cjs +328 -209
- package/dist/svelte-core.js +328 -209
- package/dist/svelte-src/BottomSheet.svelte +56 -0
- package/dist/svelte.cjs +365 -210
- package/dist/svelte.d.cts +4 -0
- package/dist/svelte.d.ts +4 -0
- package/dist/svelte.js +365 -210
- package/dist/vue.cjs +358 -211
- package/dist/vue.d.cts +6 -0
- package/dist/vue.d.ts +6 -0
- package/dist/vue.js +358 -211
- package/package.json +6 -6
package/dist/solid.source.jsx
CHANGED
|
@@ -274,14 +274,21 @@ var SnapResolver = class {
|
|
|
274
274
|
resolved = [];
|
|
275
275
|
maxAxisSize = 0;
|
|
276
276
|
rangeCache = null;
|
|
277
|
+
notified = false;
|
|
277
278
|
recompute() {
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
const measure = this.measureFit;
|
|
280
|
+
let measured;
|
|
281
|
+
const measureOnce = measure ? () => measured ??= measure() : void 0;
|
|
282
|
+
this.resolved = resolveSnapList(this.raw, this.mode, measureOnce);
|
|
283
|
+
const nextMax = this.resolved.reduce(
|
|
280
284
|
(m, s) => s.size > m ? s.size : m,
|
|
281
285
|
0
|
|
282
286
|
);
|
|
283
287
|
this.rangeCache = null;
|
|
284
|
-
this.
|
|
288
|
+
const changed = nextMax !== this.maxAxisSize || !this.notified;
|
|
289
|
+
this.maxAxisSize = nextMax;
|
|
290
|
+
this.notified = true;
|
|
291
|
+
if (changed) this.onMaxAxisSizeChange?.(this.maxAxisSize);
|
|
285
292
|
}
|
|
286
293
|
setRaw(raw) {
|
|
287
294
|
this.raw = raw;
|
|
@@ -434,7 +441,10 @@ var ensureHandler = () => {
|
|
|
434
441
|
target.consumed = true;
|
|
435
442
|
const idx = closers.indexOf(target);
|
|
436
443
|
if (idx !== -1) closers.splice(idx, 1);
|
|
437
|
-
target
|
|
444
|
+
const settled = target;
|
|
445
|
+
void Promise.resolve(settled.close()).then(() => {
|
|
446
|
+
if (settled.isOpen()) settled.restore();
|
|
447
|
+
});
|
|
438
448
|
});
|
|
439
449
|
};
|
|
440
450
|
var programmaticBack = () => {
|
|
@@ -470,16 +480,7 @@ function installRoute(deps) {
|
|
|
470
480
|
pushed = false;
|
|
471
481
|
}
|
|
472
482
|
};
|
|
473
|
-
const
|
|
474
|
-
if (closer) return;
|
|
475
|
-
closer = {
|
|
476
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
477
|
-
isTop: () => deps.isTopSheet(),
|
|
478
|
-
close: () => void deps.close(),
|
|
479
|
-
consumed: false
|
|
480
|
-
};
|
|
481
|
-
ensureHandler();
|
|
482
|
-
closers.push(closer);
|
|
483
|
+
const pushEntry = () => {
|
|
483
484
|
try {
|
|
484
485
|
if (deps.routedTo !== void 0) {
|
|
485
486
|
history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
|
|
@@ -491,6 +492,25 @@ function installRoute(deps) {
|
|
|
491
492
|
pushed = false;
|
|
492
493
|
}
|
|
493
494
|
};
|
|
495
|
+
const onOpen = () => {
|
|
496
|
+
if (closer) return;
|
|
497
|
+
const self = {
|
|
498
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
499
|
+
isTop: () => deps.isTopSheet(),
|
|
500
|
+
close: () => deps.close(),
|
|
501
|
+
restore: () => {
|
|
502
|
+
if (deps.isDestroyed() || closer !== self) return;
|
|
503
|
+
self.consumed = false;
|
|
504
|
+
if (!closers.includes(self)) closers.push(self);
|
|
505
|
+
pushEntry();
|
|
506
|
+
},
|
|
507
|
+
consumed: false
|
|
508
|
+
};
|
|
509
|
+
closer = self;
|
|
510
|
+
ensureHandler();
|
|
511
|
+
closers.push(self);
|
|
512
|
+
pushEntry();
|
|
513
|
+
};
|
|
494
514
|
const unsubscribeOpen = deps.on("open", onOpen);
|
|
495
515
|
const unsubscribeClose = deps.on("close", teardownEntry);
|
|
496
516
|
if (deps.getSize() > 0) onOpen();
|
|
@@ -537,11 +557,13 @@ var CONTENT_PULL_THRESHOLD = 60;
|
|
|
537
557
|
function installContentSwipe(deps) {
|
|
538
558
|
const { container } = deps;
|
|
539
559
|
let startY = 0;
|
|
560
|
+
let startScrollTop = 0;
|
|
540
561
|
let moved = false;
|
|
541
562
|
const onTouchStart = (e) => {
|
|
542
563
|
const t = e.touches[0];
|
|
543
564
|
if (!t) return;
|
|
544
565
|
startY = t.clientY;
|
|
566
|
+
startScrollTop = container.scrollTop;
|
|
545
567
|
moved = false;
|
|
546
568
|
};
|
|
547
569
|
const onTouchMove = (e) => {
|
|
@@ -552,6 +574,7 @@ function installContentSwipe(deps) {
|
|
|
552
574
|
const onTouchEnd = (e) => {
|
|
553
575
|
if (!moved) return;
|
|
554
576
|
if (deps.isDragging() || deps.isAnimating()) return;
|
|
577
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
555
578
|
const t = e.changedTouches[0];
|
|
556
579
|
if (!t) return;
|
|
557
580
|
const deltaY = t.clientY - startY;
|
|
@@ -663,6 +686,131 @@ function installResizeObserver(deps) {
|
|
|
663
686
|
};
|
|
664
687
|
}
|
|
665
688
|
|
|
689
|
+
// src/core/features/fit-observer.ts
|
|
690
|
+
var contentTargets = (scroller) => {
|
|
691
|
+
if (!scroller) return [];
|
|
692
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
693
|
+
const out = [];
|
|
694
|
+
for (const child of Array.from(scroller.children)) {
|
|
695
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
696
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
697
|
+
} else {
|
|
698
|
+
out.push(child);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return out;
|
|
702
|
+
};
|
|
703
|
+
function installFitObserver(deps) {
|
|
704
|
+
if (typeof ResizeObserver === "undefined") return () => {
|
|
705
|
+
};
|
|
706
|
+
if (!deps.hasFitSnap()) return () => {
|
|
707
|
+
};
|
|
708
|
+
let raf = 0;
|
|
709
|
+
const schedule = () => {
|
|
710
|
+
if (raf) return;
|
|
711
|
+
raf = requestAnimationFrame(() => {
|
|
712
|
+
raf = 0;
|
|
713
|
+
if (deps.isDestroyed() || deps.isDragging()) return;
|
|
714
|
+
deps.recompute();
|
|
715
|
+
});
|
|
716
|
+
};
|
|
717
|
+
const ro = new ResizeObserver(schedule);
|
|
718
|
+
ro.observe(deps.handle);
|
|
719
|
+
const scroller = deps.scrollContainer;
|
|
720
|
+
const observed = /* @__PURE__ */ new Set();
|
|
721
|
+
const slots = /* @__PURE__ */ new Set();
|
|
722
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
723
|
+
const onSlotChange = () => resync();
|
|
724
|
+
const trackSlots = () => {
|
|
725
|
+
if (!scroller || !hasSlot) return;
|
|
726
|
+
for (const child of Array.from(scroller.children)) {
|
|
727
|
+
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
728
|
+
child.addEventListener("slotchange", onSlotChange);
|
|
729
|
+
slots.add(child);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
const resync = () => {
|
|
734
|
+
trackSlots();
|
|
735
|
+
const targets = contentTargets(scroller);
|
|
736
|
+
for (const el of observed) {
|
|
737
|
+
if (!targets.includes(el)) {
|
|
738
|
+
ro.unobserve(el);
|
|
739
|
+
observed.delete(el);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
for (const el of targets) {
|
|
743
|
+
if (!observed.has(el)) {
|
|
744
|
+
ro.observe(el);
|
|
745
|
+
observed.add(el);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
schedule();
|
|
749
|
+
};
|
|
750
|
+
let mo;
|
|
751
|
+
if (scroller) {
|
|
752
|
+
resync();
|
|
753
|
+
if (typeof MutationObserver !== "undefined") {
|
|
754
|
+
mo = new MutationObserver(resync);
|
|
755
|
+
mo.observe(scroller, { childList: true });
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return () => {
|
|
759
|
+
ro.disconnect();
|
|
760
|
+
mo?.disconnect();
|
|
761
|
+
for (const slot of slots) {
|
|
762
|
+
slot.removeEventListener("slotchange", onSlotChange);
|
|
763
|
+
}
|
|
764
|
+
if (raf) cancelAnimationFrame(raf);
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/core/features/fit-measurement.ts
|
|
769
|
+
var measureSheetNatural = (element, content, vertical) => {
|
|
770
|
+
if (!content) {
|
|
771
|
+
return vertical ? element.offsetHeight : element.offsetWidth;
|
|
772
|
+
}
|
|
773
|
+
const axis = vertical ? "height" : "width";
|
|
774
|
+
const sheetStyle = element.style;
|
|
775
|
+
const cs = content.style;
|
|
776
|
+
const prevSheet = sheetStyle[axis];
|
|
777
|
+
const prevFlex = cs.flex;
|
|
778
|
+
const prevContent = vertical ? cs.height : cs.width;
|
|
779
|
+
sheetStyle[axis] = "auto";
|
|
780
|
+
cs.flex = "none";
|
|
781
|
+
if (vertical) cs.height = "auto";
|
|
782
|
+
else cs.width = "auto";
|
|
783
|
+
const poked = vertical ? element.offsetHeight : element.offsetWidth;
|
|
784
|
+
const contentBox = vertical ? content.clientHeight : content.clientWidth;
|
|
785
|
+
const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
|
|
786
|
+
const natural = Math.max(poked, poked - contentBox + contentScroll);
|
|
787
|
+
sheetStyle[axis] = prevSheet;
|
|
788
|
+
cs.flex = prevFlex;
|
|
789
|
+
if (vertical) cs.height = prevContent;
|
|
790
|
+
else cs.width = prevContent;
|
|
791
|
+
return natural;
|
|
792
|
+
};
|
|
793
|
+
var containingExtent = (element, vertical) => {
|
|
794
|
+
const op = element.offsetParent;
|
|
795
|
+
if (op && op !== document.body && op !== document.documentElement) {
|
|
796
|
+
return vertical ? op.clientHeight : op.clientWidth;
|
|
797
|
+
}
|
|
798
|
+
return vertical ? window.innerHeight : window.innerWidth;
|
|
799
|
+
};
|
|
800
|
+
var measureFitSize = (deps) => {
|
|
801
|
+
const vertical = layoutAxis(deps.mode) === "height";
|
|
802
|
+
const natural = measureSheetNatural(
|
|
803
|
+
deps.element,
|
|
804
|
+
deps.scrollContainer,
|
|
805
|
+
vertical
|
|
806
|
+
);
|
|
807
|
+
const cap = deps.getMaxHeightCap();
|
|
808
|
+
const capped = cap !== void 0 ? Math.min(natural, cap) : natural;
|
|
809
|
+
if (typeof window === "undefined") return capped;
|
|
810
|
+
const viewport = containingExtent(deps.element, vertical);
|
|
811
|
+
return viewport > 0 ? Math.min(capped, viewport) : capped;
|
|
812
|
+
};
|
|
813
|
+
|
|
666
814
|
// src/core/features/slider-keyboard.ts
|
|
667
815
|
function installSliderKeyboard(deps) {
|
|
668
816
|
const isVerticalAxis = deps.mode === "bottom" || deps.mode === "top";
|
|
@@ -1147,6 +1295,9 @@ var ScrimController = class {
|
|
|
1147
1295
|
const s = this.screenComponent.style;
|
|
1148
1296
|
s.opacity = "";
|
|
1149
1297
|
s.display = "";
|
|
1298
|
+
s.position = "";
|
|
1299
|
+
s.inset = "";
|
|
1300
|
+
s.pointerEvents = "";
|
|
1150
1301
|
}
|
|
1151
1302
|
if (this.backdrop) {
|
|
1152
1303
|
this.backdrop.style.opacity = "";
|
|
@@ -1395,7 +1546,12 @@ var AnimationRunner = class {
|
|
|
1395
1546
|
this.currentSpring?.cancel();
|
|
1396
1547
|
}
|
|
1397
1548
|
async animateTo(target, velocityPxPerMs) {
|
|
1398
|
-
if (target === this.getSize())
|
|
1549
|
+
if (target === this.getSize()) {
|
|
1550
|
+
if (!this.isAnimating && !this.isDragging()) {
|
|
1551
|
+
this.element.style.willChange = "";
|
|
1552
|
+
}
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1399
1555
|
this.currentTween?.cancel();
|
|
1400
1556
|
this.currentSpring?.cancel();
|
|
1401
1557
|
this.getRootEl()?.setAttribute("data-animating", "true");
|
|
@@ -1403,7 +1559,7 @@ var AnimationRunner = class {
|
|
|
1403
1559
|
if (this.reducedMotion) {
|
|
1404
1560
|
this.applySizeFn(target);
|
|
1405
1561
|
this.getRootEl()?.removeAttribute("data-animating");
|
|
1406
|
-
if (!this.isDragging()) this.element.style.willChange = "
|
|
1562
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1407
1563
|
return;
|
|
1408
1564
|
}
|
|
1409
1565
|
if (this.animationKind === "spring") {
|
|
@@ -1431,7 +1587,7 @@ var AnimationRunner = class {
|
|
|
1431
1587
|
}
|
|
1432
1588
|
if (!this.isAnimating) {
|
|
1433
1589
|
this.getRootEl()?.removeAttribute("data-animating");
|
|
1434
|
-
if (!this.isDragging()) this.element.style.willChange = "
|
|
1590
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1435
1591
|
}
|
|
1436
1592
|
}
|
|
1437
1593
|
destroy() {
|
|
@@ -1462,9 +1618,35 @@ var isVisible = (el) => {
|
|
|
1462
1618
|
}
|
|
1463
1619
|
return el.offsetParent !== null;
|
|
1464
1620
|
};
|
|
1465
|
-
var
|
|
1621
|
+
var collectFocusables = (root) => {
|
|
1622
|
+
const out = Array.from(root.querySelectorAll(FOCUSABLE));
|
|
1623
|
+
if (typeof HTMLSlotElement !== "undefined") {
|
|
1624
|
+
for (const slot of Array.from(root.querySelectorAll("slot"))) {
|
|
1625
|
+
for (const assigned of slot.assignedElements()) {
|
|
1626
|
+
if (assigned.matches(FOCUSABLE)) out.push(assigned);
|
|
1627
|
+
out.push(...collectFocusables(assigned));
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
return out;
|
|
1632
|
+
};
|
|
1633
|
+
var focusables = (root) => collectFocusables(root).filter(
|
|
1466
1634
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1467
1635
|
);
|
|
1636
|
+
var containsComposed = (container, node) => {
|
|
1637
|
+
let n = node;
|
|
1638
|
+
while (n) {
|
|
1639
|
+
if (n === container) return true;
|
|
1640
|
+
const slot = n.assignedSlot;
|
|
1641
|
+
if (slot) {
|
|
1642
|
+
n = slot;
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
const parent = n.parentNode;
|
|
1646
|
+
n = parent instanceof ShadowRoot ? parent.host : parent;
|
|
1647
|
+
}
|
|
1648
|
+
return false;
|
|
1649
|
+
};
|
|
1468
1650
|
var trapStack = [];
|
|
1469
1651
|
var installFocusTrap = (container, options = {}) => {
|
|
1470
1652
|
if (typeof document === "undefined") return () => {
|
|
@@ -1474,7 +1656,13 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1474
1656
|
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1475
1657
|
const previouslyFocused = document.activeElement;
|
|
1476
1658
|
const focusInitial = () => {
|
|
1477
|
-
const
|
|
1659
|
+
const spec = options.initialFocus;
|
|
1660
|
+
if (spec === false) {
|
|
1661
|
+
if (!container.hasAttribute("tabindex")) container.tabIndex = -1;
|
|
1662
|
+
container.focus({ preventScroll: true });
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
const initial = typeof spec === "string" ? container.querySelector(spec) : spec ?? focusables(container)[0] ?? container;
|
|
1478
1666
|
initial?.focus({ preventScroll: true });
|
|
1479
1667
|
};
|
|
1480
1668
|
focusInitial();
|
|
@@ -1504,7 +1692,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1504
1692
|
const handleFocusIn = (e) => {
|
|
1505
1693
|
if (!isActive()) return;
|
|
1506
1694
|
const target = e.target;
|
|
1507
|
-
if (target && !container
|
|
1695
|
+
if (target && !containsComposed(container, target)) {
|
|
1508
1696
|
const list = focusables(container);
|
|
1509
1697
|
list[0]?.focus({ preventScroll: true });
|
|
1510
1698
|
}
|
|
@@ -1541,8 +1729,14 @@ var lockBodyScroll = () => {
|
|
|
1541
1729
|
position: body.style.position,
|
|
1542
1730
|
top: body.style.top,
|
|
1543
1731
|
width: body.style.width,
|
|
1732
|
+
paddingRight: body.style.paddingRight,
|
|
1544
1733
|
scrollY: window.scrollY
|
|
1545
1734
|
};
|
|
1735
|
+
const scrollbarGap = window.innerWidth - document.documentElement.clientWidth;
|
|
1736
|
+
if (scrollbarGap > 0) {
|
|
1737
|
+
const current = parseFloat(getComputedStyle(body).paddingRight) || 0;
|
|
1738
|
+
body.style.paddingRight = `${current + scrollbarGap}px`;
|
|
1739
|
+
}
|
|
1546
1740
|
body.style.overflow = "hidden";
|
|
1547
1741
|
body.style.position = "fixed";
|
|
1548
1742
|
body.style.top = `-${savedStyles.scrollY}px`;
|
|
@@ -1560,6 +1754,7 @@ var lockBodyScroll = () => {
|
|
|
1560
1754
|
body.style.position = savedStyles.position;
|
|
1561
1755
|
body.style.top = savedStyles.top;
|
|
1562
1756
|
body.style.width = savedStyles.width;
|
|
1757
|
+
body.style.paddingRight = savedStyles.paddingRight;
|
|
1563
1758
|
window.scrollTo(0, savedStyles.scrollY);
|
|
1564
1759
|
savedStyles = null;
|
|
1565
1760
|
}
|
|
@@ -1772,12 +1967,14 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1772
1967
|
handle.addEventListener("pointermove", onPointerMove);
|
|
1773
1968
|
handle.addEventListener("pointerup", finishGesture);
|
|
1774
1969
|
handle.addEventListener("pointercancel", onPointerCancel);
|
|
1970
|
+
const prevTouchAction = handle.style.touchAction;
|
|
1775
1971
|
handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
|
|
1776
1972
|
return () => {
|
|
1777
1973
|
handle.removeEventListener("pointerdown", onPointerDown);
|
|
1778
1974
|
handle.removeEventListener("pointermove", onPointerMove);
|
|
1779
1975
|
handle.removeEventListener("pointerup", finishGesture);
|
|
1780
1976
|
handle.removeEventListener("pointercancel", onPointerCancel);
|
|
1977
|
+
handle.style.touchAction = prevTouchAction;
|
|
1781
1978
|
if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
|
|
1782
1979
|
handle.releasePointerCapture(activePointerId);
|
|
1783
1980
|
}
|
|
@@ -1904,7 +2101,7 @@ var GestureController = class {
|
|
|
1904
2101
|
this.isDragging_ = false;
|
|
1905
2102
|
this.keyboardDismissed = false;
|
|
1906
2103
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1907
|
-
this.deps.element.style.willChange = "
|
|
2104
|
+
this.deps.element.style.willChange = "";
|
|
1908
2105
|
}
|
|
1909
2106
|
};
|
|
1910
2107
|
|
|
@@ -2304,8 +2501,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2304
2501
|
};
|
|
2305
2502
|
}
|
|
2306
2503
|
|
|
2307
|
-
// src/core/
|
|
2308
|
-
var HAPTIC_DURATION_MS = 8;
|
|
2504
|
+
// src/core/primitives/teardown-stack.ts
|
|
2309
2505
|
var TeardownStack = class {
|
|
2310
2506
|
fns = [];
|
|
2311
2507
|
add(fn) {
|
|
@@ -2323,6 +2519,9 @@ var TeardownStack = class {
|
|
|
2323
2519
|
}
|
|
2324
2520
|
}
|
|
2325
2521
|
};
|
|
2522
|
+
|
|
2523
|
+
// src/core/BottomSheetEngine.ts
|
|
2524
|
+
var HAPTIC_DURATION_MS = 8;
|
|
2326
2525
|
var BottomSheetEngine = class {
|
|
2327
2526
|
id = nextInstanceId("bs");
|
|
2328
2527
|
element;
|
|
@@ -2346,6 +2545,7 @@ var BottomSheetEngine = class {
|
|
|
2346
2545
|
disableDragFlag;
|
|
2347
2546
|
closeOnRouteChange;
|
|
2348
2547
|
maxHeightCap;
|
|
2548
|
+
maxHeightRaw;
|
|
2349
2549
|
snapPointsRaw;
|
|
2350
2550
|
snaps;
|
|
2351
2551
|
activeId;
|
|
@@ -2381,6 +2581,7 @@ var BottomSheetEngine = class {
|
|
|
2381
2581
|
detachScrimStages = null;
|
|
2382
2582
|
stackEffectEnabled = false;
|
|
2383
2583
|
stackEffectPrimed = false;
|
|
2584
|
+
fitDeps;
|
|
2384
2585
|
transformTemplate;
|
|
2385
2586
|
constructor(opts) {
|
|
2386
2587
|
const resolved = resolveEngineOptions(opts, {
|
|
@@ -2454,12 +2655,19 @@ var BottomSheetEngine = class {
|
|
|
2454
2655
|
}
|
|
2455
2656
|
this.activeId = resolved.initialId;
|
|
2456
2657
|
auditVhUsage(this.snapPointsRaw);
|
|
2658
|
+
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
2457
2659
|
this.rootEl = this.element.closest(".bs-root");
|
|
2660
|
+
this.fitDeps = {
|
|
2661
|
+
element: this.element,
|
|
2662
|
+
scrollContainer: this.scrollContainer,
|
|
2663
|
+
mode: this.mode,
|
|
2664
|
+
getMaxHeightCap: () => this.maxHeightCap
|
|
2665
|
+
};
|
|
2458
2666
|
this.snaps = new SnapResolver(
|
|
2459
2667
|
this.snapPointsRaw,
|
|
2460
2668
|
resolved.initialAllowed,
|
|
2461
2669
|
this.mode,
|
|
2462
|
-
() => this.
|
|
2670
|
+
() => measureFitSize(this.fitDeps),
|
|
2463
2671
|
(maxAxisSize) => {
|
|
2464
2672
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2465
2673
|
}
|
|
@@ -2493,7 +2701,18 @@ var BottomSheetEngine = class {
|
|
|
2493
2701
|
io.observe(this.element);
|
|
2494
2702
|
this.teardowns.add(() => io.disconnect());
|
|
2495
2703
|
}
|
|
2496
|
-
this.
|
|
2704
|
+
this.teardowns.add(
|
|
2705
|
+
installFitObserver({
|
|
2706
|
+
handle: this.handle,
|
|
2707
|
+
scrollContainer: this.scrollContainer,
|
|
2708
|
+
hasFitSnap: () => this.snapPointsRaw.some(
|
|
2709
|
+
(p) => p.size === "fit" || p.size === "content"
|
|
2710
|
+
),
|
|
2711
|
+
isDestroyed: () => this.destroyed,
|
|
2712
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2713
|
+
recompute: () => this.recompute()
|
|
2714
|
+
})
|
|
2715
|
+
);
|
|
2497
2716
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2498
2717
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2499
2718
|
this.applyAutoAriaLabelledBy();
|
|
@@ -2644,27 +2863,33 @@ var BottomSheetEngine = class {
|
|
|
2644
2863
|
} else {
|
|
2645
2864
|
await this.animation.animateTo(target.size, velocityPxPerMs);
|
|
2646
2865
|
}
|
|
2647
|
-
this.opening = false;
|
|
2648
2866
|
externalSignal?.removeEventListener("abort", onExternalAbort);
|
|
2649
2867
|
if (signal.aborted) return;
|
|
2650
|
-
this.
|
|
2868
|
+
this.opening = false;
|
|
2869
|
+
this.completeSnap(id, target.size, previousSize, wasClosed, false);
|
|
2870
|
+
}
|
|
2871
|
+
completeSnap(id, targetSize, previousSize, wasClosed, withHaptic) {
|
|
2872
|
+
this.scrollCache.restore(id, previousSize, targetSize);
|
|
2651
2873
|
this.updateAriaSlider();
|
|
2652
2874
|
this.emit("snap", {
|
|
2653
2875
|
id,
|
|
2654
2876
|
size: this.size,
|
|
2655
2877
|
progress: this.computeProgress(this.size)
|
|
2656
2878
|
});
|
|
2657
|
-
if (
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
}
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2879
|
+
if (withHaptic) this.haptic();
|
|
2880
|
+
if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
|
|
2881
|
+
if (targetSize === 0) this.emitCloseSequence();
|
|
2882
|
+
}
|
|
2883
|
+
emitOpenSequence(id) {
|
|
2884
|
+
this.emit("open", { id });
|
|
2885
|
+
this.handleOpen();
|
|
2886
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
2887
|
+
this.emit("opened", { id });
|
|
2888
|
+
}
|
|
2889
|
+
emitCloseSequence() {
|
|
2890
|
+
this.emit("close", void 0);
|
|
2891
|
+
this.handleClose();
|
|
2892
|
+
this.emit("closed", void 0);
|
|
2668
2893
|
}
|
|
2669
2894
|
async dragTo(targetSize, velocityOrOpts = 0) {
|
|
2670
2895
|
if (this.destroyed) return;
|
|
@@ -2685,19 +2910,31 @@ var BottomSheetEngine = class {
|
|
|
2685
2910
|
}
|
|
2686
2911
|
open(id) {
|
|
2687
2912
|
if (this.destroyed) return Promise.resolve();
|
|
2688
|
-
const target = id ?? this.snaps.getAllowedIds().find((a) => a
|
|
2913
|
+
const target = id ?? this.snaps.getAllowedIds().find((a) => (this.snaps.findById(a)?.size ?? 0) > 0) ?? this.activeId;
|
|
2689
2914
|
return this.snapTo(target);
|
|
2690
2915
|
}
|
|
2691
2916
|
close(reason = "programmatic") {
|
|
2692
2917
|
if (this.destroyed) return Promise.resolve();
|
|
2693
2918
|
if (this.disableCloseFlag) return Promise.resolve();
|
|
2694
2919
|
if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
|
|
2695
|
-
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
|
|
2920
|
+
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds().find((a) => this.snaps.findById(a)?.size === 0) ?? this.snaps.getAllowedIds()[0];
|
|
2696
2921
|
return this.snapTo(closedId ?? this.activeId);
|
|
2697
2922
|
}
|
|
2698
2923
|
canDismiss() {
|
|
2699
2924
|
return !this.persistent && !this.disableCloseFlag && !this.destroyed;
|
|
2700
2925
|
}
|
|
2926
|
+
setPersistent(value) {
|
|
2927
|
+
if (this.destroyed) return;
|
|
2928
|
+
this.persistent = value;
|
|
2929
|
+
}
|
|
2930
|
+
setDisableClose(value) {
|
|
2931
|
+
if (this.destroyed) return;
|
|
2932
|
+
this.disableCloseFlag = value;
|
|
2933
|
+
}
|
|
2934
|
+
setDisableDrag(value) {
|
|
2935
|
+
if (this.destroyed) return;
|
|
2936
|
+
this.disableDragFlag = value;
|
|
2937
|
+
}
|
|
2701
2938
|
isTop() {
|
|
2702
2939
|
return this.isTopSheet;
|
|
2703
2940
|
}
|
|
@@ -2734,18 +2971,23 @@ var BottomSheetEngine = class {
|
|
|
2734
2971
|
axis === "height" ? "max-height" : "max-width",
|
|
2735
2972
|
value
|
|
2736
2973
|
);
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2747
|
-
this.recompute();
|
|
2974
|
+
this.maxHeightRaw = h;
|
|
2975
|
+
this.resolveMaxHeightCap();
|
|
2976
|
+
this.recompute();
|
|
2977
|
+
}
|
|
2978
|
+
resolveMaxHeightCap() {
|
|
2979
|
+
const raw = this.maxHeightRaw;
|
|
2980
|
+
if (raw === void 0) {
|
|
2981
|
+
this.maxHeightCap = void 0;
|
|
2982
|
+
return;
|
|
2748
2983
|
}
|
|
2984
|
+
if (typeof raw === "number") {
|
|
2985
|
+
this.maxHeightCap = raw;
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
if (typeof window === "undefined") return;
|
|
2989
|
+
const measured = resolveSnap(raw, this.mode);
|
|
2990
|
+
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2749
2991
|
}
|
|
2750
2992
|
clampToMaxHeight() {
|
|
2751
2993
|
if (this.maxHeightCap === void 0) return;
|
|
@@ -2876,6 +3118,7 @@ var BottomSheetEngine = class {
|
|
|
2876
3118
|
this.newCycle();
|
|
2877
3119
|
this.snapPointsRaw = points;
|
|
2878
3120
|
auditVhUsage(points);
|
|
3121
|
+
this.auditDuplicateSnapIds(points);
|
|
2879
3122
|
this.snaps.setRaw(points);
|
|
2880
3123
|
if (allowed) this.snaps.setAllowedIds(allowed);
|
|
2881
3124
|
this.scrollCache.clear();
|
|
@@ -2888,6 +3131,7 @@ var BottomSheetEngine = class {
|
|
|
2888
3131
|
}
|
|
2889
3132
|
recompute() {
|
|
2890
3133
|
if (this.destroyed) return;
|
|
3134
|
+
this.resolveMaxHeightCap();
|
|
2891
3135
|
this.snaps.recompute();
|
|
2892
3136
|
this.clampToMaxHeight();
|
|
2893
3137
|
this.scrim.invalidateOpacityCache();
|
|
@@ -2899,129 +3143,6 @@ var BottomSheetEngine = class {
|
|
|
2899
3143
|
this.updateAriaSlider();
|
|
2900
3144
|
}
|
|
2901
3145
|
}
|
|
2902
|
-
contentTargets() {
|
|
2903
|
-
const scroller = this.scrollContainer;
|
|
2904
|
-
if (!scroller) return [];
|
|
2905
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2906
|
-
const out = [];
|
|
2907
|
-
for (const child of Array.from(scroller.children)) {
|
|
2908
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
2909
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
2910
|
-
} else {
|
|
2911
|
-
out.push(child);
|
|
2912
|
-
}
|
|
2913
|
-
}
|
|
2914
|
-
return out;
|
|
2915
|
-
}
|
|
2916
|
-
measureSheetNatural(vertical) {
|
|
2917
|
-
const el = this.element;
|
|
2918
|
-
const content = this.scrollContainer;
|
|
2919
|
-
if (!content) {
|
|
2920
|
-
return vertical ? el.offsetHeight : el.offsetWidth;
|
|
2921
|
-
}
|
|
2922
|
-
const axis = vertical ? "height" : "width";
|
|
2923
|
-
const sheetStyle = el.style;
|
|
2924
|
-
const cs = content.style;
|
|
2925
|
-
const prevSheet = sheetStyle[axis];
|
|
2926
|
-
const prevFlex = cs.flex;
|
|
2927
|
-
const prevContent = vertical ? cs.height : cs.width;
|
|
2928
|
-
sheetStyle[axis] = "auto";
|
|
2929
|
-
cs.flex = "none";
|
|
2930
|
-
if (vertical) cs.height = "auto";
|
|
2931
|
-
else cs.width = "auto";
|
|
2932
|
-
const poked = vertical ? el.offsetHeight : el.offsetWidth;
|
|
2933
|
-
const contentBox = vertical ? content.clientHeight : content.clientWidth;
|
|
2934
|
-
const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
|
|
2935
|
-
const natural = Math.max(poked, poked - contentBox + contentScroll);
|
|
2936
|
-
sheetStyle[axis] = prevSheet;
|
|
2937
|
-
cs.flex = prevFlex;
|
|
2938
|
-
if (vertical) cs.height = prevContent;
|
|
2939
|
-
else cs.width = prevContent;
|
|
2940
|
-
return natural;
|
|
2941
|
-
}
|
|
2942
|
-
measureFitSize() {
|
|
2943
|
-
const vertical = layoutAxis(this.mode) === "height";
|
|
2944
|
-
const natural = this.measureSheetNatural(vertical);
|
|
2945
|
-
const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
|
|
2946
|
-
if (typeof window === "undefined") return capped;
|
|
2947
|
-
const viewport = this.containingExtent(vertical);
|
|
2948
|
-
return viewport > 0 ? Math.min(capped, viewport) : capped;
|
|
2949
|
-
}
|
|
2950
|
-
// The fit cap is the sheet's containing block, not always the window: a
|
|
2951
|
-
// position:fixed sheet nested under a transform/filter/will-change ancestor
|
|
2952
|
-
// is clipped to that ancestor, so capping by window.innerHeight oversizes the
|
|
2953
|
-
// sheet and the content/footer get clipped. offsetParent resolves to that
|
|
2954
|
-
// ancestor when present, and is null (→ viewport) for a plain fixed sheet.
|
|
2955
|
-
containingExtent(vertical) {
|
|
2956
|
-
const op = this.element.offsetParent;
|
|
2957
|
-
if (op && op !== document.body && op !== document.documentElement) {
|
|
2958
|
-
return vertical ? op.clientHeight : op.clientWidth;
|
|
2959
|
-
}
|
|
2960
|
-
return vertical ? window.innerHeight : window.innerWidth;
|
|
2961
|
-
}
|
|
2962
|
-
installFitObserver() {
|
|
2963
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
2964
|
-
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2965
|
-
return;
|
|
2966
|
-
let raf = 0;
|
|
2967
|
-
const schedule = () => {
|
|
2968
|
-
if (raf) return;
|
|
2969
|
-
raf = requestAnimationFrame(() => {
|
|
2970
|
-
raf = 0;
|
|
2971
|
-
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2972
|
-
this.recompute();
|
|
2973
|
-
});
|
|
2974
|
-
};
|
|
2975
|
-
const ro = new ResizeObserver(schedule);
|
|
2976
|
-
ro.observe(this.handle);
|
|
2977
|
-
const scroller = this.scrollContainer;
|
|
2978
|
-
const observed = /* @__PURE__ */ new Set();
|
|
2979
|
-
const slots = /* @__PURE__ */ new Set();
|
|
2980
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2981
|
-
const onSlotChange = () => resync();
|
|
2982
|
-
const trackSlots = () => {
|
|
2983
|
-
if (!scroller || !hasSlot) return;
|
|
2984
|
-
for (const child of Array.from(scroller.children)) {
|
|
2985
|
-
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
2986
|
-
child.addEventListener("slotchange", onSlotChange);
|
|
2987
|
-
slots.add(child);
|
|
2988
|
-
}
|
|
2989
|
-
}
|
|
2990
|
-
};
|
|
2991
|
-
const resync = () => {
|
|
2992
|
-
trackSlots();
|
|
2993
|
-
const targets = this.contentTargets();
|
|
2994
|
-
for (const el of observed) {
|
|
2995
|
-
if (!targets.includes(el)) {
|
|
2996
|
-
ro.unobserve(el);
|
|
2997
|
-
observed.delete(el);
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
for (const el of targets) {
|
|
3001
|
-
if (!observed.has(el)) {
|
|
3002
|
-
ro.observe(el);
|
|
3003
|
-
observed.add(el);
|
|
3004
|
-
}
|
|
3005
|
-
}
|
|
3006
|
-
schedule();
|
|
3007
|
-
};
|
|
3008
|
-
let mo;
|
|
3009
|
-
if (scroller) {
|
|
3010
|
-
resync();
|
|
3011
|
-
if (typeof MutationObserver !== "undefined") {
|
|
3012
|
-
mo = new MutationObserver(resync);
|
|
3013
|
-
mo.observe(scroller, { childList: true });
|
|
3014
|
-
}
|
|
3015
|
-
}
|
|
3016
|
-
this.teardowns.add(() => {
|
|
3017
|
-
ro.disconnect();
|
|
3018
|
-
mo?.disconnect();
|
|
3019
|
-
for (const slot of slots) {
|
|
3020
|
-
slot.removeEventListener("slotchange", onSlotChange);
|
|
3021
|
-
}
|
|
3022
|
-
if (raf) cancelAnimationFrame(raf);
|
|
3023
|
-
});
|
|
3024
|
-
}
|
|
3025
3146
|
destroy() {
|
|
3026
3147
|
this.destroyed = true;
|
|
3027
3148
|
this.opening = false;
|
|
@@ -3039,9 +3160,10 @@ var BottomSheetEngine = class {
|
|
|
3039
3160
|
this.backdrop.style.opacity = "";
|
|
3040
3161
|
this.backdrop.style.pointerEvents = "";
|
|
3041
3162
|
}
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3163
|
+
for (const host of [this.anchorHost, this.scrimParent, this.rootEl]) {
|
|
3164
|
+
if (!host) continue;
|
|
3165
|
+
host.style.removeProperty("--bs-size");
|
|
3166
|
+
host.style.removeProperty("--bs-progress");
|
|
3045
3167
|
}
|
|
3046
3168
|
if (this.screenComponent) {
|
|
3047
3169
|
this.screenComponent.style.opacity = "";
|
|
@@ -3055,6 +3177,7 @@ var BottomSheetEngine = class {
|
|
|
3055
3177
|
}
|
|
3056
3178
|
newCycle() {
|
|
3057
3179
|
this.allowOvershoot = false;
|
|
3180
|
+
this.opening = false;
|
|
3058
3181
|
this.currentAbort.abort();
|
|
3059
3182
|
this.currentAbort = new AbortController();
|
|
3060
3183
|
return this.currentAbort.signal;
|
|
@@ -3110,8 +3233,14 @@ var BottomSheetEngine = class {
|
|
|
3110
3233
|
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3111
3234
|
}
|
|
3112
3235
|
recomputeSnaps() {
|
|
3236
|
+
this.resolveMaxHeightCap();
|
|
3237
|
+
this.snaps.setRaw(this.snapPointsRaw);
|
|
3238
|
+
this.clampToMaxHeight();
|
|
3239
|
+
this.scrim.invalidateOpacityCache();
|
|
3240
|
+
}
|
|
3241
|
+
auditDuplicateSnapIds(points) {
|
|
3113
3242
|
const seen = /* @__PURE__ */ new Set();
|
|
3114
|
-
for (const p of
|
|
3243
|
+
for (const p of points) {
|
|
3115
3244
|
if (seen.has(p.id)) {
|
|
3116
3245
|
console.warn(
|
|
3117
3246
|
`[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
|
|
@@ -3119,9 +3248,6 @@ var BottomSheetEngine = class {
|
|
|
3119
3248
|
}
|
|
3120
3249
|
seen.add(p.id);
|
|
3121
3250
|
}
|
|
3122
|
-
this.snaps.setRaw(this.snapPointsRaw);
|
|
3123
|
-
this.clampToMaxHeight();
|
|
3124
|
-
this.scrim.invalidateOpacityCache();
|
|
3125
3251
|
}
|
|
3126
3252
|
getAllowedRange() {
|
|
3127
3253
|
return this.snaps.getAllowedRange();
|
|
@@ -3309,9 +3435,15 @@ var BottomSheetEngine = class {
|
|
|
3309
3435
|
flickVelocity: this.flickVelocity,
|
|
3310
3436
|
dragThreshold: this.dragThreshold
|
|
3311
3437
|
});
|
|
3312
|
-
if (!target)
|
|
3438
|
+
if (!target) {
|
|
3439
|
+
this.clearWillChangeIfIdle();
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3313
3442
|
const previousId = this.activeId;
|
|
3314
|
-
if (target.id === previousId && target.size === this.size)
|
|
3443
|
+
if (target.id === previousId && target.size === this.size) {
|
|
3444
|
+
this.clearWillChangeIfIdle();
|
|
3445
|
+
return;
|
|
3446
|
+
}
|
|
3315
3447
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
3316
3448
|
const restore = this.snaps.findById(previousId);
|
|
3317
3449
|
if (restore) {
|
|
@@ -3334,27 +3466,19 @@ var BottomSheetEngine = class {
|
|
|
3334
3466
|
if (signal.aborted) return;
|
|
3335
3467
|
this.allowOvershoot = false;
|
|
3336
3468
|
this.opening = false;
|
|
3337
|
-
this.
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
this.haptic();
|
|
3345
|
-
if (previousSnapSize === 0 && target.size > 0) {
|
|
3346
|
-
this.emit("open", { id: target.id });
|
|
3347
|
-
this.handleOpen();
|
|
3348
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3349
|
-
this.emit("opened", { id: target.id });
|
|
3350
|
-
}
|
|
3351
|
-
if (target.size === 0) {
|
|
3352
|
-
this.emit("close", void 0);
|
|
3353
|
-
this.handleClose();
|
|
3354
|
-
this.emit("closed", void 0);
|
|
3355
|
-
}
|
|
3469
|
+
this.completeSnap(
|
|
3470
|
+
target.id,
|
|
3471
|
+
target.size,
|
|
3472
|
+
previousSize,
|
|
3473
|
+
previousSnapSize === 0,
|
|
3474
|
+
true
|
|
3475
|
+
);
|
|
3356
3476
|
});
|
|
3357
3477
|
}
|
|
3478
|
+
clearWillChangeIfIdle() {
|
|
3479
|
+
if (this.animation.isAnimating || this.gesture?.isDragging) return;
|
|
3480
|
+
this.element.style.willChange = "";
|
|
3481
|
+
}
|
|
3358
3482
|
haptic() {
|
|
3359
3483
|
if (typeof navigator !== "undefined" && "vibrate" in navigator) {
|
|
3360
3484
|
try {
|
|
@@ -3435,14 +3559,9 @@ var BottomSheetEngine = class {
|
|
|
3435
3559
|
progress: this.computeProgress(this.size)
|
|
3436
3560
|
});
|
|
3437
3561
|
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3438
|
-
this.
|
|
3439
|
-
this.handleOpen();
|
|
3440
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3441
|
-
this.emit("opened", { id: target.id });
|
|
3562
|
+
this.emitOpenSequence(target.id);
|
|
3442
3563
|
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3443
|
-
this.
|
|
3444
|
-
this.handleClose();
|
|
3445
|
-
this.emit("closed", void 0);
|
|
3564
|
+
this.emitCloseSequence();
|
|
3446
3565
|
}
|
|
3447
3566
|
}
|
|
3448
3567
|
handleClose() {
|
|
@@ -3452,6 +3571,38 @@ var BottomSheetEngine = class {
|
|
|
3452
3571
|
}
|
|
3453
3572
|
};
|
|
3454
3573
|
|
|
3574
|
+
// src/core/features/teleport.ts
|
|
3575
|
+
var resolveTeleportTarget = (target) => {
|
|
3576
|
+
if (!target) return null;
|
|
3577
|
+
if (typeof target !== "string") return target;
|
|
3578
|
+
if (typeof document === "undefined") return null;
|
|
3579
|
+
if (target === "body") return document.body;
|
|
3580
|
+
return document.querySelector(target);
|
|
3581
|
+
};
|
|
3582
|
+
var teleportElements = (els, target) => {
|
|
3583
|
+
const records = [];
|
|
3584
|
+
for (const el of els) {
|
|
3585
|
+
if (!el || el.parentNode === target) continue;
|
|
3586
|
+
records.push({ el, parent: el.parentNode, next: el.nextSibling });
|
|
3587
|
+
target.appendChild(el);
|
|
3588
|
+
}
|
|
3589
|
+
return () => {
|
|
3590
|
+
for (let i = records.length - 1; i >= 0; i--) {
|
|
3591
|
+
const { el, parent, next } = records[i];
|
|
3592
|
+
if (parent && parent.isConnected) {
|
|
3593
|
+
const before = next && next.parentNode === parent ? next : null;
|
|
3594
|
+
try {
|
|
3595
|
+
parent.insertBefore(el, before);
|
|
3596
|
+
} catch {
|
|
3597
|
+
el.parentNode?.removeChild(el);
|
|
3598
|
+
}
|
|
3599
|
+
} else {
|
|
3600
|
+
el.parentNode?.removeChild(el);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
};
|
|
3604
|
+
};
|
|
3605
|
+
|
|
3455
3606
|
// src/solid/index.tsx
|
|
3456
3607
|
var BottomSheet = (props) => {
|
|
3457
3608
|
let sheetEl;
|
|
@@ -3468,6 +3619,7 @@ var BottomSheet = (props) => {
|
|
|
3468
3619
|
progress: 0
|
|
3469
3620
|
});
|
|
3470
3621
|
let engine = null;
|
|
3622
|
+
let restoreTeleport = null;
|
|
3471
3623
|
onMount(() => {
|
|
3472
3624
|
if (!sheetEl) return;
|
|
3473
3625
|
const engineOpts = {
|
|
@@ -3494,10 +3646,18 @@ var BottomSheet = (props) => {
|
|
|
3494
3646
|
disableClose: props.disableClose,
|
|
3495
3647
|
disableDrag: props.disableDrag,
|
|
3496
3648
|
closeOnRouteChange: props.closeOnRouteChange,
|
|
3649
|
+
stackEffect: props.stackEffect,
|
|
3497
3650
|
returnFocusTo: props.returnFocusTo
|
|
3498
3651
|
};
|
|
3499
3652
|
engine = new BottomSheetEngine(engineOpts);
|
|
3500
3653
|
props.engineRef?.(engine);
|
|
3654
|
+
const teleportTarget = props.teleport === false ? null : resolveTeleportTarget(props.teleportTo);
|
|
3655
|
+
if (teleportTarget) {
|
|
3656
|
+
restoreTeleport = teleportElements(
|
|
3657
|
+
[backdropEl, scrimEl, sheetEl],
|
|
3658
|
+
teleportTarget
|
|
3659
|
+
);
|
|
3660
|
+
}
|
|
3501
3661
|
const sync = () => {
|
|
3502
3662
|
if (!engine) return;
|
|
3503
3663
|
const s = engine.state;
|
|
@@ -3509,6 +3669,7 @@ var BottomSheet = (props) => {
|
|
|
3509
3669
|
sync();
|
|
3510
3670
|
props.onSnap?.(payload.id);
|
|
3511
3671
|
});
|
|
3672
|
+
engine.on("before-snap", (payload) => props.onBeforeSnap?.(payload));
|
|
3512
3673
|
engine.on("dragstart", sync);
|
|
3513
3674
|
engine.on("dragend", sync);
|
|
3514
3675
|
if (props.backdrop !== false && props.closeOnBackdrop !== false && backdropEl) {
|
|
@@ -3522,6 +3683,8 @@ var BottomSheet = (props) => {
|
|
|
3522
3683
|
}
|
|
3523
3684
|
});
|
|
3524
3685
|
onCleanup(() => {
|
|
3686
|
+
restoreTeleport?.();
|
|
3687
|
+
restoreTeleport = null;
|
|
3525
3688
|
engine?.destroy();
|
|
3526
3689
|
engine = null;
|
|
3527
3690
|
props.engineRef?.(null);
|
|
@@ -3549,6 +3712,36 @@ var BottomSheet = (props) => {
|
|
|
3549
3712
|
{ defer: true }
|
|
3550
3713
|
)
|
|
3551
3714
|
);
|
|
3715
|
+
createEffect(
|
|
3716
|
+
on(
|
|
3717
|
+
() => props.persistent,
|
|
3718
|
+
(value, prev) => {
|
|
3719
|
+
if (!engine || prev === void 0 || value === void 0) return;
|
|
3720
|
+
engine.setPersistent(value);
|
|
3721
|
+
},
|
|
3722
|
+
{ defer: true }
|
|
3723
|
+
)
|
|
3724
|
+
);
|
|
3725
|
+
createEffect(
|
|
3726
|
+
on(
|
|
3727
|
+
() => props.disableClose,
|
|
3728
|
+
(value, prev) => {
|
|
3729
|
+
if (!engine || prev === void 0 || value === void 0) return;
|
|
3730
|
+
engine.setDisableClose(value);
|
|
3731
|
+
},
|
|
3732
|
+
{ defer: true }
|
|
3733
|
+
)
|
|
3734
|
+
);
|
|
3735
|
+
createEffect(
|
|
3736
|
+
on(
|
|
3737
|
+
() => props.disableDrag,
|
|
3738
|
+
(value, prev) => {
|
|
3739
|
+
if (!engine || prev === void 0 || value === void 0) return;
|
|
3740
|
+
engine.setDisableDrag(value);
|
|
3741
|
+
},
|
|
3742
|
+
{ defer: true }
|
|
3743
|
+
)
|
|
3744
|
+
);
|
|
3552
3745
|
const showBackdrop = createMemo(() => props.backdrop !== false);
|
|
3553
3746
|
const mode = createMemo(() => props.mode ?? "bottom");
|
|
3554
3747
|
const ariaLabel = createMemo(() => props.ariaLabel ?? "Bottom sheet");
|
|
@@ -3592,6 +3785,16 @@ var BottomSheet = (props) => {
|
|
|
3592
3785
|
{state().activeId}
|
|
3593
3786
|
</span>
|
|
3594
3787
|
</section>
|
|
3788
|
+
<Show when={props.leftButton}>
|
|
3789
|
+
<div class="bs-button-slot" data-side="left" data-mode={mode()}>
|
|
3790
|
+
{props.leftButton}
|
|
3791
|
+
</div>
|
|
3792
|
+
</Show>
|
|
3793
|
+
<Show when={props.rightButton}>
|
|
3794
|
+
<div class="bs-button-slot" data-side="right" data-mode={mode()}>
|
|
3795
|
+
{props.rightButton}
|
|
3796
|
+
</div>
|
|
3797
|
+
</Show>
|
|
3595
3798
|
</div>;
|
|
3596
3799
|
};
|
|
3597
3800
|
export {
|