@surdeddd/bottom-sheet 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{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/index.cjs
CHANGED
|
@@ -270,18 +270,25 @@ var SnapResolver = class {
|
|
|
270
270
|
__publicField(this, "resolved", []);
|
|
271
271
|
__publicField(this, "maxAxisSize", 0);
|
|
272
272
|
__publicField(this, "rangeCache", null);
|
|
273
|
+
__publicField(this, "notified", false);
|
|
273
274
|
this.raw = raw;
|
|
274
275
|
this.allowedIds = allowed ?? raw.map((p) => p.id);
|
|
275
276
|
this.recompute();
|
|
276
277
|
}
|
|
277
278
|
recompute() {
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
const measure = this.measureFit;
|
|
280
|
+
let measured;
|
|
281
|
+
const measureOnce = measure ? () => measured ?? (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";
|
|
@@ -1149,6 +1297,9 @@ var ScrimController = class {
|
|
|
1149
1297
|
const s = this.screenComponent.style;
|
|
1150
1298
|
s.opacity = "";
|
|
1151
1299
|
s.display = "";
|
|
1300
|
+
s.position = "";
|
|
1301
|
+
s.inset = "";
|
|
1302
|
+
s.pointerEvents = "";
|
|
1152
1303
|
}
|
|
1153
1304
|
if (this.backdrop) {
|
|
1154
1305
|
this.backdrop.style.opacity = "";
|
|
@@ -1397,7 +1548,12 @@ var AnimationRunner = class {
|
|
|
1397
1548
|
this.currentSpring?.cancel();
|
|
1398
1549
|
}
|
|
1399
1550
|
async animateTo(target, velocityPxPerMs) {
|
|
1400
|
-
if (target === this.getSize())
|
|
1551
|
+
if (target === this.getSize()) {
|
|
1552
|
+
if (!this.isAnimating && !this.isDragging()) {
|
|
1553
|
+
this.element.style.willChange = "";
|
|
1554
|
+
}
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1401
1557
|
this.currentTween?.cancel();
|
|
1402
1558
|
this.currentSpring?.cancel();
|
|
1403
1559
|
this.getRootEl()?.setAttribute("data-animating", "true");
|
|
@@ -1405,7 +1561,7 @@ var AnimationRunner = class {
|
|
|
1405
1561
|
if (this.reducedMotion) {
|
|
1406
1562
|
this.applySizeFn(target);
|
|
1407
1563
|
this.getRootEl()?.removeAttribute("data-animating");
|
|
1408
|
-
if (!this.isDragging()) this.element.style.willChange = "
|
|
1564
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1409
1565
|
return;
|
|
1410
1566
|
}
|
|
1411
1567
|
if (this.animationKind === "spring") {
|
|
@@ -1433,7 +1589,7 @@ var AnimationRunner = class {
|
|
|
1433
1589
|
}
|
|
1434
1590
|
if (!this.isAnimating) {
|
|
1435
1591
|
this.getRootEl()?.removeAttribute("data-animating");
|
|
1436
|
-
if (!this.isDragging()) this.element.style.willChange = "
|
|
1592
|
+
if (!this.isDragging()) this.element.style.willChange = "";
|
|
1437
1593
|
}
|
|
1438
1594
|
}
|
|
1439
1595
|
destroy() {
|
|
@@ -1464,9 +1620,35 @@ var isVisible = (el) => {
|
|
|
1464
1620
|
}
|
|
1465
1621
|
return el.offsetParent !== null;
|
|
1466
1622
|
};
|
|
1467
|
-
var
|
|
1623
|
+
var collectFocusables = (root) => {
|
|
1624
|
+
const out = Array.from(root.querySelectorAll(FOCUSABLE));
|
|
1625
|
+
if (typeof HTMLSlotElement !== "undefined") {
|
|
1626
|
+
for (const slot of Array.from(root.querySelectorAll("slot"))) {
|
|
1627
|
+
for (const assigned of slot.assignedElements()) {
|
|
1628
|
+
if (assigned.matches(FOCUSABLE)) out.push(assigned);
|
|
1629
|
+
out.push(...collectFocusables(assigned));
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
return out;
|
|
1634
|
+
};
|
|
1635
|
+
var focusables = (root) => collectFocusables(root).filter(
|
|
1468
1636
|
(el) => !el.hasAttribute("inert") && isVisible(el) && !el.matches("[aria-hidden='true']")
|
|
1469
1637
|
);
|
|
1638
|
+
var containsComposed = (container, node) => {
|
|
1639
|
+
let n = node;
|
|
1640
|
+
while (n) {
|
|
1641
|
+
if (n === container) return true;
|
|
1642
|
+
const slot = n.assignedSlot;
|
|
1643
|
+
if (slot) {
|
|
1644
|
+
n = slot;
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
const parent = n.parentNode;
|
|
1648
|
+
n = parent instanceof ShadowRoot ? parent.host : parent;
|
|
1649
|
+
}
|
|
1650
|
+
return false;
|
|
1651
|
+
};
|
|
1470
1652
|
var trapStack = [];
|
|
1471
1653
|
var installFocusTrap = (container, options = {}) => {
|
|
1472
1654
|
if (typeof document === "undefined") return () => {
|
|
@@ -1476,7 +1658,13 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1476
1658
|
const isActive = () => trapStack[trapStack.length - 1] === token;
|
|
1477
1659
|
const previouslyFocused = document.activeElement;
|
|
1478
1660
|
const focusInitial = () => {
|
|
1479
|
-
const
|
|
1661
|
+
const spec = options.initialFocus;
|
|
1662
|
+
if (spec === false) {
|
|
1663
|
+
if (!container.hasAttribute("tabindex")) container.tabIndex = -1;
|
|
1664
|
+
container.focus({ preventScroll: true });
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
const initial = typeof spec === "string" ? container.querySelector(spec) : spec ?? focusables(container)[0] ?? container;
|
|
1480
1668
|
initial?.focus({ preventScroll: true });
|
|
1481
1669
|
};
|
|
1482
1670
|
focusInitial();
|
|
@@ -1506,7 +1694,7 @@ var installFocusTrap = (container, options = {}) => {
|
|
|
1506
1694
|
const handleFocusIn = (e) => {
|
|
1507
1695
|
if (!isActive()) return;
|
|
1508
1696
|
const target = e.target;
|
|
1509
|
-
if (target && !container
|
|
1697
|
+
if (target && !containsComposed(container, target)) {
|
|
1510
1698
|
const list = focusables(container);
|
|
1511
1699
|
list[0]?.focus({ preventScroll: true });
|
|
1512
1700
|
}
|
|
@@ -1543,8 +1731,14 @@ var lockBodyScroll = () => {
|
|
|
1543
1731
|
position: body.style.position,
|
|
1544
1732
|
top: body.style.top,
|
|
1545
1733
|
width: body.style.width,
|
|
1734
|
+
paddingRight: body.style.paddingRight,
|
|
1546
1735
|
scrollY: window.scrollY
|
|
1547
1736
|
};
|
|
1737
|
+
const scrollbarGap = window.innerWidth - document.documentElement.clientWidth;
|
|
1738
|
+
if (scrollbarGap > 0) {
|
|
1739
|
+
const current = parseFloat(getComputedStyle(body).paddingRight) || 0;
|
|
1740
|
+
body.style.paddingRight = `${current + scrollbarGap}px`;
|
|
1741
|
+
}
|
|
1548
1742
|
body.style.overflow = "hidden";
|
|
1549
1743
|
body.style.position = "fixed";
|
|
1550
1744
|
body.style.top = `-${savedStyles.scrollY}px`;
|
|
@@ -1562,6 +1756,7 @@ var lockBodyScroll = () => {
|
|
|
1562
1756
|
body.style.position = savedStyles.position;
|
|
1563
1757
|
body.style.top = savedStyles.top;
|
|
1564
1758
|
body.style.width = savedStyles.width;
|
|
1759
|
+
body.style.paddingRight = savedStyles.paddingRight;
|
|
1565
1760
|
window.scrollTo(0, savedStyles.scrollY);
|
|
1566
1761
|
savedStyles = null;
|
|
1567
1762
|
}
|
|
@@ -1774,12 +1969,14 @@ var installGestures = (handle, mode, callbacks) => {
|
|
|
1774
1969
|
handle.addEventListener("pointermove", onPointerMove);
|
|
1775
1970
|
handle.addEventListener("pointerup", finishGesture);
|
|
1776
1971
|
handle.addEventListener("pointercancel", onPointerCancel);
|
|
1972
|
+
const prevTouchAction = handle.style.touchAction;
|
|
1777
1973
|
handle.style.touchAction = isAxisVertical(mode) ? "pan-x" : "pan-y";
|
|
1778
1974
|
return () => {
|
|
1779
1975
|
handle.removeEventListener("pointerdown", onPointerDown);
|
|
1780
1976
|
handle.removeEventListener("pointermove", onPointerMove);
|
|
1781
1977
|
handle.removeEventListener("pointerup", finishGesture);
|
|
1782
1978
|
handle.removeEventListener("pointercancel", onPointerCancel);
|
|
1979
|
+
handle.style.touchAction = prevTouchAction;
|
|
1783
1980
|
if (activePointerId !== null && handle.hasPointerCapture(activePointerId)) {
|
|
1784
1981
|
handle.releasePointerCapture(activePointerId);
|
|
1785
1982
|
}
|
|
@@ -1907,7 +2104,7 @@ var GestureController = class {
|
|
|
1907
2104
|
this.isDragging_ = false;
|
|
1908
2105
|
this.keyboardDismissed = false;
|
|
1909
2106
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1910
|
-
this.deps.element.style.willChange = "
|
|
2107
|
+
this.deps.element.style.willChange = "";
|
|
1911
2108
|
}
|
|
1912
2109
|
};
|
|
1913
2110
|
|
|
@@ -2306,8 +2503,7 @@ function resolveEngineOptions(opts, extras) {
|
|
|
2306
2503
|
};
|
|
2307
2504
|
}
|
|
2308
2505
|
|
|
2309
|
-
// src/core/
|
|
2310
|
-
var HAPTIC_DURATION_MS = 8;
|
|
2506
|
+
// src/core/primitives/teardown-stack.ts
|
|
2311
2507
|
var TeardownStack = class {
|
|
2312
2508
|
constructor() {
|
|
2313
2509
|
__publicField(this, "fns", []);
|
|
@@ -2327,6 +2523,9 @@ var TeardownStack = class {
|
|
|
2327
2523
|
}
|
|
2328
2524
|
}
|
|
2329
2525
|
};
|
|
2526
|
+
|
|
2527
|
+
// src/core/BottomSheetEngine.ts
|
|
2528
|
+
var HAPTIC_DURATION_MS = 8;
|
|
2330
2529
|
var BottomSheetEngine = class {
|
|
2331
2530
|
constructor(opts) {
|
|
2332
2531
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
@@ -2351,6 +2550,7 @@ var BottomSheetEngine = class {
|
|
|
2351
2550
|
__publicField(this, "disableDragFlag");
|
|
2352
2551
|
__publicField(this, "closeOnRouteChange");
|
|
2353
2552
|
__publicField(this, "maxHeightCap");
|
|
2553
|
+
__publicField(this, "maxHeightRaw");
|
|
2354
2554
|
__publicField(this, "snapPointsRaw");
|
|
2355
2555
|
__publicField(this, "snaps");
|
|
2356
2556
|
__publicField(this, "activeId");
|
|
@@ -2386,6 +2586,7 @@ var BottomSheetEngine = class {
|
|
|
2386
2586
|
__publicField(this, "detachScrimStages", null);
|
|
2387
2587
|
__publicField(this, "stackEffectEnabled", false);
|
|
2388
2588
|
__publicField(this, "stackEffectPrimed", false);
|
|
2589
|
+
__publicField(this, "fitDeps");
|
|
2389
2590
|
__publicField(this, "transformTemplate");
|
|
2390
2591
|
const resolved = resolveEngineOptions(opts, {
|
|
2391
2592
|
shouldApplyInertSiblings: () => {
|
|
@@ -2458,12 +2659,19 @@ var BottomSheetEngine = class {
|
|
|
2458
2659
|
}
|
|
2459
2660
|
this.activeId = resolved.initialId;
|
|
2460
2661
|
auditVhUsage(this.snapPointsRaw);
|
|
2662
|
+
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
2461
2663
|
this.rootEl = this.element.closest(".bs-root");
|
|
2664
|
+
this.fitDeps = {
|
|
2665
|
+
element: this.element,
|
|
2666
|
+
scrollContainer: this.scrollContainer,
|
|
2667
|
+
mode: this.mode,
|
|
2668
|
+
getMaxHeightCap: () => this.maxHeightCap
|
|
2669
|
+
};
|
|
2462
2670
|
this.snaps = new SnapResolver(
|
|
2463
2671
|
this.snapPointsRaw,
|
|
2464
2672
|
resolved.initialAllowed,
|
|
2465
2673
|
this.mode,
|
|
2466
|
-
() => this.
|
|
2674
|
+
() => measureFitSize(this.fitDeps),
|
|
2467
2675
|
(maxAxisSize) => {
|
|
2468
2676
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2469
2677
|
}
|
|
@@ -2497,7 +2705,18 @@ var BottomSheetEngine = class {
|
|
|
2497
2705
|
io.observe(this.element);
|
|
2498
2706
|
this.teardowns.add(() => io.disconnect());
|
|
2499
2707
|
}
|
|
2500
|
-
this.
|
|
2708
|
+
this.teardowns.add(
|
|
2709
|
+
installFitObserver({
|
|
2710
|
+
handle: this.handle,
|
|
2711
|
+
scrollContainer: this.scrollContainer,
|
|
2712
|
+
hasFitSnap: () => this.snapPointsRaw.some(
|
|
2713
|
+
(p) => p.size === "fit" || p.size === "content"
|
|
2714
|
+
),
|
|
2715
|
+
isDestroyed: () => this.destroyed,
|
|
2716
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2717
|
+
recompute: () => this.recompute()
|
|
2718
|
+
})
|
|
2719
|
+
);
|
|
2501
2720
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2502
2721
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2503
2722
|
this.applyAutoAriaLabelledBy();
|
|
@@ -2648,27 +2867,33 @@ var BottomSheetEngine = class {
|
|
|
2648
2867
|
} else {
|
|
2649
2868
|
await this.animation.animateTo(target.size, velocityPxPerMs);
|
|
2650
2869
|
}
|
|
2651
|
-
this.opening = false;
|
|
2652
2870
|
externalSignal?.removeEventListener("abort", onExternalAbort);
|
|
2653
2871
|
if (signal.aborted) return;
|
|
2654
|
-
this.
|
|
2872
|
+
this.opening = false;
|
|
2873
|
+
this.completeSnap(id, target.size, previousSize, wasClosed, false);
|
|
2874
|
+
}
|
|
2875
|
+
completeSnap(id, targetSize, previousSize, wasClosed, withHaptic) {
|
|
2876
|
+
this.scrollCache.restore(id, previousSize, targetSize);
|
|
2655
2877
|
this.updateAriaSlider();
|
|
2656
2878
|
this.emit("snap", {
|
|
2657
2879
|
id,
|
|
2658
2880
|
size: this.size,
|
|
2659
2881
|
progress: this.computeProgress(this.size)
|
|
2660
2882
|
});
|
|
2661
|
-
if (
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2883
|
+
if (withHaptic) this.haptic();
|
|
2884
|
+
if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
|
|
2885
|
+
if (targetSize === 0) this.emitCloseSequence();
|
|
2886
|
+
}
|
|
2887
|
+
emitOpenSequence(id) {
|
|
2888
|
+
this.emit("open", { id });
|
|
2889
|
+
this.handleOpen();
|
|
2890
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
2891
|
+
this.emit("opened", { id });
|
|
2892
|
+
}
|
|
2893
|
+
emitCloseSequence() {
|
|
2894
|
+
this.emit("close", void 0);
|
|
2895
|
+
this.handleClose();
|
|
2896
|
+
this.emit("closed", void 0);
|
|
2672
2897
|
}
|
|
2673
2898
|
async dragTo(targetSize, velocityOrOpts = 0) {
|
|
2674
2899
|
if (this.destroyed) return;
|
|
@@ -2689,19 +2914,31 @@ var BottomSheetEngine = class {
|
|
|
2689
2914
|
}
|
|
2690
2915
|
open(id) {
|
|
2691
2916
|
if (this.destroyed) return Promise.resolve();
|
|
2692
|
-
const target = id ?? this.snaps.getAllowedIds().find((a) => a
|
|
2917
|
+
const target = id ?? this.snaps.getAllowedIds().find((a) => (this.snaps.findById(a)?.size ?? 0) > 0) ?? this.activeId;
|
|
2693
2918
|
return this.snapTo(target);
|
|
2694
2919
|
}
|
|
2695
2920
|
close(reason = "programmatic") {
|
|
2696
2921
|
if (this.destroyed) return Promise.resolve();
|
|
2697
2922
|
if (this.disableCloseFlag) return Promise.resolve();
|
|
2698
2923
|
if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
|
|
2699
|
-
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
|
|
2924
|
+
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];
|
|
2700
2925
|
return this.snapTo(closedId ?? this.activeId);
|
|
2701
2926
|
}
|
|
2702
2927
|
canDismiss() {
|
|
2703
2928
|
return !this.persistent && !this.disableCloseFlag && !this.destroyed;
|
|
2704
2929
|
}
|
|
2930
|
+
setPersistent(value) {
|
|
2931
|
+
if (this.destroyed) return;
|
|
2932
|
+
this.persistent = value;
|
|
2933
|
+
}
|
|
2934
|
+
setDisableClose(value) {
|
|
2935
|
+
if (this.destroyed) return;
|
|
2936
|
+
this.disableCloseFlag = value;
|
|
2937
|
+
}
|
|
2938
|
+
setDisableDrag(value) {
|
|
2939
|
+
if (this.destroyed) return;
|
|
2940
|
+
this.disableDragFlag = value;
|
|
2941
|
+
}
|
|
2705
2942
|
isTop() {
|
|
2706
2943
|
return this.isTopSheet;
|
|
2707
2944
|
}
|
|
@@ -2738,18 +2975,23 @@ var BottomSheetEngine = class {
|
|
|
2738
2975
|
axis === "height" ? "max-height" : "max-width",
|
|
2739
2976
|
value
|
|
2740
2977
|
);
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2751
|
-
this.recompute();
|
|
2978
|
+
this.maxHeightRaw = h;
|
|
2979
|
+
this.resolveMaxHeightCap();
|
|
2980
|
+
this.recompute();
|
|
2981
|
+
}
|
|
2982
|
+
resolveMaxHeightCap() {
|
|
2983
|
+
const raw = this.maxHeightRaw;
|
|
2984
|
+
if (raw === void 0) {
|
|
2985
|
+
this.maxHeightCap = void 0;
|
|
2986
|
+
return;
|
|
2752
2987
|
}
|
|
2988
|
+
if (typeof raw === "number") {
|
|
2989
|
+
this.maxHeightCap = raw;
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2992
|
+
if (typeof window === "undefined") return;
|
|
2993
|
+
const measured = resolveSnap(raw, this.mode);
|
|
2994
|
+
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2753
2995
|
}
|
|
2754
2996
|
clampToMaxHeight() {
|
|
2755
2997
|
if (this.maxHeightCap === void 0) return;
|
|
@@ -2880,6 +3122,7 @@ var BottomSheetEngine = class {
|
|
|
2880
3122
|
this.newCycle();
|
|
2881
3123
|
this.snapPointsRaw = points;
|
|
2882
3124
|
auditVhUsage(points);
|
|
3125
|
+
this.auditDuplicateSnapIds(points);
|
|
2883
3126
|
this.snaps.setRaw(points);
|
|
2884
3127
|
if (allowed) this.snaps.setAllowedIds(allowed);
|
|
2885
3128
|
this.scrollCache.clear();
|
|
@@ -2892,6 +3135,7 @@ var BottomSheetEngine = class {
|
|
|
2892
3135
|
}
|
|
2893
3136
|
recompute() {
|
|
2894
3137
|
if (this.destroyed) return;
|
|
3138
|
+
this.resolveMaxHeightCap();
|
|
2895
3139
|
this.snaps.recompute();
|
|
2896
3140
|
this.clampToMaxHeight();
|
|
2897
3141
|
this.scrim.invalidateOpacityCache();
|
|
@@ -2903,129 +3147,6 @@ var BottomSheetEngine = class {
|
|
|
2903
3147
|
this.updateAriaSlider();
|
|
2904
3148
|
}
|
|
2905
3149
|
}
|
|
2906
|
-
contentTargets() {
|
|
2907
|
-
const scroller = this.scrollContainer;
|
|
2908
|
-
if (!scroller) return [];
|
|
2909
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2910
|
-
const out = [];
|
|
2911
|
-
for (const child of Array.from(scroller.children)) {
|
|
2912
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
2913
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
2914
|
-
} else {
|
|
2915
|
-
out.push(child);
|
|
2916
|
-
}
|
|
2917
|
-
}
|
|
2918
|
-
return out;
|
|
2919
|
-
}
|
|
2920
|
-
measureSheetNatural(vertical) {
|
|
2921
|
-
const el = this.element;
|
|
2922
|
-
const content = this.scrollContainer;
|
|
2923
|
-
if (!content) {
|
|
2924
|
-
return vertical ? el.offsetHeight : el.offsetWidth;
|
|
2925
|
-
}
|
|
2926
|
-
const axis = vertical ? "height" : "width";
|
|
2927
|
-
const sheetStyle = el.style;
|
|
2928
|
-
const cs = content.style;
|
|
2929
|
-
const prevSheet = sheetStyle[axis];
|
|
2930
|
-
const prevFlex = cs.flex;
|
|
2931
|
-
const prevContent = vertical ? cs.height : cs.width;
|
|
2932
|
-
sheetStyle[axis] = "auto";
|
|
2933
|
-
cs.flex = "none";
|
|
2934
|
-
if (vertical) cs.height = "auto";
|
|
2935
|
-
else cs.width = "auto";
|
|
2936
|
-
const poked = vertical ? el.offsetHeight : el.offsetWidth;
|
|
2937
|
-
const contentBox = vertical ? content.clientHeight : content.clientWidth;
|
|
2938
|
-
const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
|
|
2939
|
-
const natural = Math.max(poked, poked - contentBox + contentScroll);
|
|
2940
|
-
sheetStyle[axis] = prevSheet;
|
|
2941
|
-
cs.flex = prevFlex;
|
|
2942
|
-
if (vertical) cs.height = prevContent;
|
|
2943
|
-
else cs.width = prevContent;
|
|
2944
|
-
return natural;
|
|
2945
|
-
}
|
|
2946
|
-
measureFitSize() {
|
|
2947
|
-
const vertical = layoutAxis(this.mode) === "height";
|
|
2948
|
-
const natural = this.measureSheetNatural(vertical);
|
|
2949
|
-
const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
|
|
2950
|
-
if (typeof window === "undefined") return capped;
|
|
2951
|
-
const viewport = this.containingExtent(vertical);
|
|
2952
|
-
return viewport > 0 ? Math.min(capped, viewport) : capped;
|
|
2953
|
-
}
|
|
2954
|
-
// The fit cap is the sheet's containing block, not always the window: a
|
|
2955
|
-
// position:fixed sheet nested under a transform/filter/will-change ancestor
|
|
2956
|
-
// is clipped to that ancestor, so capping by window.innerHeight oversizes the
|
|
2957
|
-
// sheet and the content/footer get clipped. offsetParent resolves to that
|
|
2958
|
-
// ancestor when present, and is null (→ viewport) for a plain fixed sheet.
|
|
2959
|
-
containingExtent(vertical) {
|
|
2960
|
-
const op = this.element.offsetParent;
|
|
2961
|
-
if (op && op !== document.body && op !== document.documentElement) {
|
|
2962
|
-
return vertical ? op.clientHeight : op.clientWidth;
|
|
2963
|
-
}
|
|
2964
|
-
return vertical ? window.innerHeight : window.innerWidth;
|
|
2965
|
-
}
|
|
2966
|
-
installFitObserver() {
|
|
2967
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
2968
|
-
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2969
|
-
return;
|
|
2970
|
-
let raf = 0;
|
|
2971
|
-
const schedule = () => {
|
|
2972
|
-
if (raf) return;
|
|
2973
|
-
raf = requestAnimationFrame(() => {
|
|
2974
|
-
raf = 0;
|
|
2975
|
-
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2976
|
-
this.recompute();
|
|
2977
|
-
});
|
|
2978
|
-
};
|
|
2979
|
-
const ro = new ResizeObserver(schedule);
|
|
2980
|
-
ro.observe(this.handle);
|
|
2981
|
-
const scroller = this.scrollContainer;
|
|
2982
|
-
const observed = /* @__PURE__ */ new Set();
|
|
2983
|
-
const slots = /* @__PURE__ */ new Set();
|
|
2984
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2985
|
-
const onSlotChange = () => resync();
|
|
2986
|
-
const trackSlots = () => {
|
|
2987
|
-
if (!scroller || !hasSlot) return;
|
|
2988
|
-
for (const child of Array.from(scroller.children)) {
|
|
2989
|
-
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
2990
|
-
child.addEventListener("slotchange", onSlotChange);
|
|
2991
|
-
slots.add(child);
|
|
2992
|
-
}
|
|
2993
|
-
}
|
|
2994
|
-
};
|
|
2995
|
-
const resync = () => {
|
|
2996
|
-
trackSlots();
|
|
2997
|
-
const targets = this.contentTargets();
|
|
2998
|
-
for (const el of observed) {
|
|
2999
|
-
if (!targets.includes(el)) {
|
|
3000
|
-
ro.unobserve(el);
|
|
3001
|
-
observed.delete(el);
|
|
3002
|
-
}
|
|
3003
|
-
}
|
|
3004
|
-
for (const el of targets) {
|
|
3005
|
-
if (!observed.has(el)) {
|
|
3006
|
-
ro.observe(el);
|
|
3007
|
-
observed.add(el);
|
|
3008
|
-
}
|
|
3009
|
-
}
|
|
3010
|
-
schedule();
|
|
3011
|
-
};
|
|
3012
|
-
let mo;
|
|
3013
|
-
if (scroller) {
|
|
3014
|
-
resync();
|
|
3015
|
-
if (typeof MutationObserver !== "undefined") {
|
|
3016
|
-
mo = new MutationObserver(resync);
|
|
3017
|
-
mo.observe(scroller, { childList: true });
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
this.teardowns.add(() => {
|
|
3021
|
-
ro.disconnect();
|
|
3022
|
-
mo?.disconnect();
|
|
3023
|
-
for (const slot of slots) {
|
|
3024
|
-
slot.removeEventListener("slotchange", onSlotChange);
|
|
3025
|
-
}
|
|
3026
|
-
if (raf) cancelAnimationFrame(raf);
|
|
3027
|
-
});
|
|
3028
|
-
}
|
|
3029
3150
|
destroy() {
|
|
3030
3151
|
this.destroyed = true;
|
|
3031
3152
|
this.opening = false;
|
|
@@ -3043,9 +3164,10 @@ var BottomSheetEngine = class {
|
|
|
3043
3164
|
this.backdrop.style.opacity = "";
|
|
3044
3165
|
this.backdrop.style.pointerEvents = "";
|
|
3045
3166
|
}
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3167
|
+
for (const host of [this.anchorHost, this.scrimParent, this.rootEl]) {
|
|
3168
|
+
if (!host) continue;
|
|
3169
|
+
host.style.removeProperty("--bs-size");
|
|
3170
|
+
host.style.removeProperty("--bs-progress");
|
|
3049
3171
|
}
|
|
3050
3172
|
if (this.screenComponent) {
|
|
3051
3173
|
this.screenComponent.style.opacity = "";
|
|
@@ -3059,6 +3181,7 @@ var BottomSheetEngine = class {
|
|
|
3059
3181
|
}
|
|
3060
3182
|
newCycle() {
|
|
3061
3183
|
this.allowOvershoot = false;
|
|
3184
|
+
this.opening = false;
|
|
3062
3185
|
this.currentAbort.abort();
|
|
3063
3186
|
this.currentAbort = new AbortController();
|
|
3064
3187
|
return this.currentAbort.signal;
|
|
@@ -3114,8 +3237,14 @@ var BottomSheetEngine = class {
|
|
|
3114
3237
|
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3115
3238
|
}
|
|
3116
3239
|
recomputeSnaps() {
|
|
3240
|
+
this.resolveMaxHeightCap();
|
|
3241
|
+
this.snaps.setRaw(this.snapPointsRaw);
|
|
3242
|
+
this.clampToMaxHeight();
|
|
3243
|
+
this.scrim.invalidateOpacityCache();
|
|
3244
|
+
}
|
|
3245
|
+
auditDuplicateSnapIds(points) {
|
|
3117
3246
|
const seen = /* @__PURE__ */ new Set();
|
|
3118
|
-
for (const p of
|
|
3247
|
+
for (const p of points) {
|
|
3119
3248
|
if (seen.has(p.id)) {
|
|
3120
3249
|
console.warn(
|
|
3121
3250
|
`[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
|
|
@@ -3123,9 +3252,6 @@ var BottomSheetEngine = class {
|
|
|
3123
3252
|
}
|
|
3124
3253
|
seen.add(p.id);
|
|
3125
3254
|
}
|
|
3126
|
-
this.snaps.setRaw(this.snapPointsRaw);
|
|
3127
|
-
this.clampToMaxHeight();
|
|
3128
|
-
this.scrim.invalidateOpacityCache();
|
|
3129
3255
|
}
|
|
3130
3256
|
getAllowedRange() {
|
|
3131
3257
|
return this.snaps.getAllowedRange();
|
|
@@ -3313,9 +3439,15 @@ var BottomSheetEngine = class {
|
|
|
3313
3439
|
flickVelocity: this.flickVelocity,
|
|
3314
3440
|
dragThreshold: this.dragThreshold
|
|
3315
3441
|
});
|
|
3316
|
-
if (!target)
|
|
3442
|
+
if (!target) {
|
|
3443
|
+
this.clearWillChangeIfIdle();
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3317
3446
|
const previousId = this.activeId;
|
|
3318
|
-
if (target.id === previousId && target.size === this.size)
|
|
3447
|
+
if (target.id === previousId && target.size === this.size) {
|
|
3448
|
+
this.clearWillChangeIfIdle();
|
|
3449
|
+
return;
|
|
3450
|
+
}
|
|
3319
3451
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
3320
3452
|
const restore = this.snaps.findById(previousId);
|
|
3321
3453
|
if (restore) {
|
|
@@ -3338,27 +3470,19 @@ var BottomSheetEngine = class {
|
|
|
3338
3470
|
if (signal.aborted) return;
|
|
3339
3471
|
this.allowOvershoot = false;
|
|
3340
3472
|
this.opening = false;
|
|
3341
|
-
this.
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
this.haptic();
|
|
3349
|
-
if (previousSnapSize === 0 && target.size > 0) {
|
|
3350
|
-
this.emit("open", { id: target.id });
|
|
3351
|
-
this.handleOpen();
|
|
3352
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3353
|
-
this.emit("opened", { id: target.id });
|
|
3354
|
-
}
|
|
3355
|
-
if (target.size === 0) {
|
|
3356
|
-
this.emit("close", void 0);
|
|
3357
|
-
this.handleClose();
|
|
3358
|
-
this.emit("closed", void 0);
|
|
3359
|
-
}
|
|
3473
|
+
this.completeSnap(
|
|
3474
|
+
target.id,
|
|
3475
|
+
target.size,
|
|
3476
|
+
previousSize,
|
|
3477
|
+
previousSnapSize === 0,
|
|
3478
|
+
true
|
|
3479
|
+
);
|
|
3360
3480
|
});
|
|
3361
3481
|
}
|
|
3482
|
+
clearWillChangeIfIdle() {
|
|
3483
|
+
if (this.animation.isAnimating || this.gesture?.isDragging) return;
|
|
3484
|
+
this.element.style.willChange = "";
|
|
3485
|
+
}
|
|
3362
3486
|
haptic() {
|
|
3363
3487
|
if (typeof navigator !== "undefined" && "vibrate" in navigator) {
|
|
3364
3488
|
try {
|
|
@@ -3439,14 +3563,9 @@ var BottomSheetEngine = class {
|
|
|
3439
3563
|
progress: this.computeProgress(this.size)
|
|
3440
3564
|
});
|
|
3441
3565
|
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3442
|
-
this.
|
|
3443
|
-
this.handleOpen();
|
|
3444
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3445
|
-
this.emit("opened", { id: target.id });
|
|
3566
|
+
this.emitOpenSequence(target.id);
|
|
3446
3567
|
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3447
|
-
this.
|
|
3448
|
-
this.handleClose();
|
|
3449
|
-
this.emit("closed", void 0);
|
|
3568
|
+
this.emitCloseSequence();
|
|
3450
3569
|
}
|
|
3451
3570
|
}
|
|
3452
3571
|
handleClose() {
|
|
@@ -3482,6 +3601,95 @@ var createSheetManager = (initial = {}) => {
|
|
|
3482
3601
|
};
|
|
3483
3602
|
};
|
|
3484
3603
|
|
|
3604
|
+
// src/core/primitives/overlay-transforms.ts
|
|
3605
|
+
var closedTransform = (edge) => CLOSED_TRANSFORM[edge];
|
|
3606
|
+
var closedTransformFor = (edge, animation, peekPx) => {
|
|
3607
|
+
switch (animation) {
|
|
3608
|
+
case "fade":
|
|
3609
|
+
return "translate3d(0, 0, 0)";
|
|
3610
|
+
case "scale":
|
|
3611
|
+
return "translate3d(0, 0, 0) scale(0.94)";
|
|
3612
|
+
case "slide":
|
|
3613
|
+
default:
|
|
3614
|
+
if (peekPx !== void 0 && edge === "bottom") {
|
|
3615
|
+
return `translate3d(0, calc(100% - ${peekPx}px), 0)`;
|
|
3616
|
+
}
|
|
3617
|
+
return closedTransform(edge);
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
var openTransformFor = (animation) => animation === "scale" ? "translate3d(0, 0, 0) scale(1)" : "translate3d(0, 0, 0)";
|
|
3621
|
+
|
|
3622
|
+
// src/core/features/overlay-swipe.ts
|
|
3623
|
+
function installOverlaySwipe(deps) {
|
|
3624
|
+
const el = deps.element;
|
|
3625
|
+
const edge = deps.edge;
|
|
3626
|
+
const isVertical = edge === "bottom" || edge === "top";
|
|
3627
|
+
const sign = edge === "bottom" || edge === "right" ? 1 : -1;
|
|
3628
|
+
const SLOP = 8;
|
|
3629
|
+
let startX = 0;
|
|
3630
|
+
let startY = 0;
|
|
3631
|
+
let startT = 0;
|
|
3632
|
+
let tracking = false;
|
|
3633
|
+
let dragging = false;
|
|
3634
|
+
let pointerId = null;
|
|
3635
|
+
const previousTouchAction = el.style.touchAction;
|
|
3636
|
+
el.style.touchAction = isVertical ? "pan-x" : "pan-y";
|
|
3637
|
+
const onDown = (e) => {
|
|
3638
|
+
if (e.button !== void 0 && e.button !== 0) return;
|
|
3639
|
+
pointerId = e.pointerId;
|
|
3640
|
+
startX = e.clientX;
|
|
3641
|
+
startY = e.clientY;
|
|
3642
|
+
startT = performance.now();
|
|
3643
|
+
tracking = true;
|
|
3644
|
+
dragging = false;
|
|
3645
|
+
};
|
|
3646
|
+
const onMove = (e) => {
|
|
3647
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
3648
|
+
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
3649
|
+
if (!dragging) {
|
|
3650
|
+
if (Math.abs(delta) < SLOP) return;
|
|
3651
|
+
dragging = true;
|
|
3652
|
+
el.style.transition = "none";
|
|
3653
|
+
try {
|
|
3654
|
+
el.setPointerCapture(e.pointerId);
|
|
3655
|
+
} catch {
|
|
3656
|
+
}
|
|
3657
|
+
}
|
|
3658
|
+
const offset = Math.max(0, sign * delta);
|
|
3659
|
+
el.style.transform = isVertical ? `translate3d(0, ${sign * offset}px, 0)` : `translate3d(${sign * offset}px, 0, 0)`;
|
|
3660
|
+
};
|
|
3661
|
+
const finish = (e) => {
|
|
3662
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
3663
|
+
tracking = false;
|
|
3664
|
+
pointerId = null;
|
|
3665
|
+
if (!dragging) return;
|
|
3666
|
+
dragging = false;
|
|
3667
|
+
const dt = performance.now() - startT || 1;
|
|
3668
|
+
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
3669
|
+
const offset = Math.max(0, sign * delta);
|
|
3670
|
+
const velocity = sign * delta / dt;
|
|
3671
|
+
const size = isVertical ? el.offsetHeight : el.offsetWidth;
|
|
3672
|
+
const past = offset > size * deps.getThreshold() || velocity > deps.getVelocityThreshold();
|
|
3673
|
+
el.style.transition = deps.getExitTransition();
|
|
3674
|
+
if (past) {
|
|
3675
|
+
deps.close();
|
|
3676
|
+
} else {
|
|
3677
|
+
el.style.transform = deps.getOpenTransform();
|
|
3678
|
+
}
|
|
3679
|
+
};
|
|
3680
|
+
el.addEventListener("pointerdown", onDown);
|
|
3681
|
+
el.addEventListener("pointermove", onMove);
|
|
3682
|
+
el.addEventListener("pointerup", finish);
|
|
3683
|
+
el.addEventListener("pointercancel", finish);
|
|
3684
|
+
return () => {
|
|
3685
|
+
el.style.touchAction = previousTouchAction;
|
|
3686
|
+
el.removeEventListener("pointerdown", onDown);
|
|
3687
|
+
el.removeEventListener("pointermove", onMove);
|
|
3688
|
+
el.removeEventListener("pointerup", finish);
|
|
3689
|
+
el.removeEventListener("pointercancel", finish);
|
|
3690
|
+
};
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3485
3693
|
// src/core/overlay.ts
|
|
3486
3694
|
var OVERLAY_PRESETS = Object.freeze({
|
|
3487
3695
|
sheet: Object.freeze({
|
|
@@ -3513,22 +3721,6 @@ var OVERLAY_PRESETS = Object.freeze({
|
|
|
3513
3721
|
swipeToClose: false
|
|
3514
3722
|
})
|
|
3515
3723
|
});
|
|
3516
|
-
var closedTransform = (edge) => CLOSED_TRANSFORM[edge];
|
|
3517
|
-
var closedTransformFor = (edge, animation, peekPx) => {
|
|
3518
|
-
switch (animation) {
|
|
3519
|
-
case "fade":
|
|
3520
|
-
return "translate3d(0, 0, 0)";
|
|
3521
|
-
case "scale":
|
|
3522
|
-
return "translate3d(0, 0, 0) scale(0.94)";
|
|
3523
|
-
case "slide":
|
|
3524
|
-
default:
|
|
3525
|
-
if (peekPx !== void 0 && edge === "bottom") {
|
|
3526
|
-
return `translate3d(0, calc(100% - ${peekPx}px), 0)`;
|
|
3527
|
-
}
|
|
3528
|
-
return closedTransform(edge);
|
|
3529
|
-
}
|
|
3530
|
-
};
|
|
3531
|
-
var openTransformFor = (animation) => animation === "scale" ? "translate3d(0, 0, 0) scale(1)" : "translate3d(0, 0, 0)";
|
|
3532
3724
|
var OverlayEngine = class {
|
|
3533
3725
|
constructor(opts) {
|
|
3534
3726
|
__publicField(this, "id", nextInstanceId("ovl"));
|
|
@@ -3661,6 +3853,7 @@ var OverlayEngine = class {
|
|
|
3661
3853
|
if (this.backdrop) {
|
|
3662
3854
|
this.backdrop.style.transition = `opacity ${dur}ms ease-out`;
|
|
3663
3855
|
}
|
|
3856
|
+
this.setWillChange(true);
|
|
3664
3857
|
const cycle = ++this.cycleNonce;
|
|
3665
3858
|
return new Promise((resolve) => {
|
|
3666
3859
|
requestAnimationFrame(() => {
|
|
@@ -3683,6 +3876,7 @@ var OverlayEngine = class {
|
|
|
3683
3876
|
this.releaseInteractiveListeners();
|
|
3684
3877
|
this.isOpen_ = false;
|
|
3685
3878
|
this.isAnimating_ = false;
|
|
3879
|
+
this.setWillChange(false);
|
|
3686
3880
|
this.element.style.transform = closedTransformFor(
|
|
3687
3881
|
this.edge,
|
|
3688
3882
|
this.enterAnimation,
|
|
@@ -3713,6 +3907,7 @@ var OverlayEngine = class {
|
|
|
3713
3907
|
).then(() => {
|
|
3714
3908
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3715
3909
|
this.isAnimating_ = false;
|
|
3910
|
+
this.setWillChange(false);
|
|
3716
3911
|
this.element.setAttribute("data-state", "open");
|
|
3717
3912
|
this.emit("open", void 0);
|
|
3718
3913
|
this.onOpenCb?.();
|
|
@@ -3736,6 +3931,7 @@ var OverlayEngine = class {
|
|
|
3736
3931
|
if (this.backdrop) {
|
|
3737
3932
|
this.backdrop.style.transition = `opacity ${dur}ms ease-in`;
|
|
3738
3933
|
}
|
|
3934
|
+
this.setWillChange(true);
|
|
3739
3935
|
const cycle = ++this.cycleNonce;
|
|
3740
3936
|
return new Promise((resolve) => {
|
|
3741
3937
|
requestAnimationFrame(() => {
|
|
@@ -3761,6 +3957,7 @@ var OverlayEngine = class {
|
|
|
3761
3957
|
).then(() => {
|
|
3762
3958
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3763
3959
|
this.isAnimating_ = false;
|
|
3960
|
+
this.setWillChange(false);
|
|
3764
3961
|
if (this.peekPx === void 0) {
|
|
3765
3962
|
this.element.setAttribute("hidden", "");
|
|
3766
3963
|
}
|
|
@@ -3783,6 +3980,7 @@ var OverlayEngine = class {
|
|
|
3783
3980
|
this.destroyed = true;
|
|
3784
3981
|
this.cycleNonce++;
|
|
3785
3982
|
this.bus.clear();
|
|
3983
|
+
this.setWillChange(false);
|
|
3786
3984
|
this.releaseInteractiveListeners();
|
|
3787
3985
|
this.releaseStackEntry?.();
|
|
3788
3986
|
this.releaseStackEntry = null;
|
|
@@ -4008,7 +4206,6 @@ var OverlayEngine = class {
|
|
|
4008
4206
|
this.originalNextSibling = null;
|
|
4009
4207
|
}
|
|
4010
4208
|
applyClosedStyles() {
|
|
4011
|
-
this.element.style.willChange = "transform, opacity";
|
|
4012
4209
|
this.element.style.transform = closedTransformFor(
|
|
4013
4210
|
this.edge,
|
|
4014
4211
|
this.enterAnimation,
|
|
@@ -4022,7 +4219,12 @@ var OverlayEngine = class {
|
|
|
4022
4219
|
if (this.backdrop) {
|
|
4023
4220
|
this.backdrop.style.opacity = "0";
|
|
4024
4221
|
this.backdrop.style.pointerEvents = "none";
|
|
4025
|
-
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
setWillChange(on) {
|
|
4225
|
+
this.element.style.willChange = on ? "transform, opacity" : "";
|
|
4226
|
+
if (this.backdrop) {
|
|
4227
|
+
this.backdrop.style.willChange = on ? "opacity" : "";
|
|
4026
4228
|
}
|
|
4027
4229
|
}
|
|
4028
4230
|
awaitTransition(cycle, property = "transform") {
|
|
@@ -4108,73 +4310,15 @@ var OverlayEngine = class {
|
|
|
4108
4310
|
this.lifecycle.release();
|
|
4109
4311
|
}
|
|
4110
4312
|
installSwipeToClose() {
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
let dragging = false;
|
|
4121
|
-
let pointerId = null;
|
|
4122
|
-
const previousTouchAction = el.style.touchAction;
|
|
4123
|
-
el.style.touchAction = isVertical ? "pan-x" : "pan-y";
|
|
4124
|
-
const onDown = (e) => {
|
|
4125
|
-
if (e.button !== void 0 && e.button !== 0) return;
|
|
4126
|
-
pointerId = e.pointerId;
|
|
4127
|
-
startX = e.clientX;
|
|
4128
|
-
startY = e.clientY;
|
|
4129
|
-
startT = performance.now();
|
|
4130
|
-
tracking = true;
|
|
4131
|
-
dragging = false;
|
|
4132
|
-
};
|
|
4133
|
-
const onMove = (e) => {
|
|
4134
|
-
if (!tracking || e.pointerId !== pointerId) return;
|
|
4135
|
-
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
4136
|
-
if (!dragging) {
|
|
4137
|
-
if (Math.abs(delta) < SLOP) return;
|
|
4138
|
-
dragging = true;
|
|
4139
|
-
el.style.transition = "none";
|
|
4140
|
-
try {
|
|
4141
|
-
el.setPointerCapture(e.pointerId);
|
|
4142
|
-
} catch {
|
|
4143
|
-
}
|
|
4144
|
-
}
|
|
4145
|
-
const offset = Math.max(0, sign * delta);
|
|
4146
|
-
el.style.transform = isVertical ? `translate3d(0, ${sign * offset}px, 0)` : `translate3d(${sign * offset}px, 0, 0)`;
|
|
4147
|
-
};
|
|
4148
|
-
const finish = (e) => {
|
|
4149
|
-
if (!tracking || e.pointerId !== pointerId) return;
|
|
4150
|
-
tracking = false;
|
|
4151
|
-
pointerId = null;
|
|
4152
|
-
if (!dragging) return;
|
|
4153
|
-
dragging = false;
|
|
4154
|
-
const dt = performance.now() - startT || 1;
|
|
4155
|
-
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
4156
|
-
const offset = Math.max(0, sign * delta);
|
|
4157
|
-
const velocity = sign * delta / dt;
|
|
4158
|
-
const size = isVertical ? el.offsetHeight : el.offsetWidth;
|
|
4159
|
-
const past = offset > size * this.swipeThreshold || velocity > this.swipeVelocityThreshold;
|
|
4160
|
-
el.style.transition = `transform ${this.effectiveDuration()}ms ${this.exitEasing}`;
|
|
4161
|
-
if (past) {
|
|
4162
|
-
void this.close("swipe");
|
|
4163
|
-
} else {
|
|
4164
|
-
el.style.transform = openTransformFor(this.enterAnimation);
|
|
4165
|
-
}
|
|
4166
|
-
};
|
|
4167
|
-
el.addEventListener("pointerdown", onDown);
|
|
4168
|
-
el.addEventListener("pointermove", onMove);
|
|
4169
|
-
el.addEventListener("pointerup", finish);
|
|
4170
|
-
el.addEventListener("pointercancel", finish);
|
|
4171
|
-
return () => {
|
|
4172
|
-
el.style.touchAction = previousTouchAction;
|
|
4173
|
-
el.removeEventListener("pointerdown", onDown);
|
|
4174
|
-
el.removeEventListener("pointermove", onMove);
|
|
4175
|
-
el.removeEventListener("pointerup", finish);
|
|
4176
|
-
el.removeEventListener("pointercancel", finish);
|
|
4177
|
-
};
|
|
4313
|
+
return installOverlaySwipe({
|
|
4314
|
+
element: this.element,
|
|
4315
|
+
edge: this.edge,
|
|
4316
|
+
getThreshold: () => this.swipeThreshold,
|
|
4317
|
+
getVelocityThreshold: () => this.swipeVelocityThreshold,
|
|
4318
|
+
getExitTransition: () => `transform ${this.effectiveDuration()}ms ${this.exitEasing}`,
|
|
4319
|
+
getOpenTransform: () => openTransformFor(this.enterAnimation),
|
|
4320
|
+
close: () => void this.close("swipe")
|
|
4321
|
+
});
|
|
4178
4322
|
}
|
|
4179
4323
|
registerInStack() {
|
|
4180
4324
|
this.releaseStackEntry = sheetStack.push({
|