@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.js
CHANGED
|
@@ -268,18 +268,25 @@ var SnapResolver = class {
|
|
|
268
268
|
__publicField(this, "resolved", []);
|
|
269
269
|
__publicField(this, "maxAxisSize", 0);
|
|
270
270
|
__publicField(this, "rangeCache", null);
|
|
271
|
+
__publicField(this, "notified", false);
|
|
271
272
|
this.raw = raw;
|
|
272
273
|
this.allowedIds = allowed ?? raw.map((p) => p.id);
|
|
273
274
|
this.recompute();
|
|
274
275
|
}
|
|
275
276
|
recompute() {
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
const measure = this.measureFit;
|
|
278
|
+
let measured;
|
|
279
|
+
const measureOnce = measure ? () => measured ?? (measured = measure()) : void 0;
|
|
280
|
+
this.resolved = resolveSnapList(this.raw, this.mode, measureOnce);
|
|
281
|
+
const nextMax = this.resolved.reduce(
|
|
278
282
|
(m, s) => s.size > m ? s.size : m,
|
|
279
283
|
0
|
|
280
284
|
);
|
|
281
285
|
this.rangeCache = null;
|
|
282
|
-
this.
|
|
286
|
+
const changed = nextMax !== this.maxAxisSize || !this.notified;
|
|
287
|
+
this.maxAxisSize = nextMax;
|
|
288
|
+
this.notified = true;
|
|
289
|
+
if (changed) this.onMaxAxisSizeChange?.(this.maxAxisSize);
|
|
283
290
|
}
|
|
284
291
|
setRaw(raw) {
|
|
285
292
|
this.raw = raw;
|
|
@@ -432,7 +439,10 @@ var ensureHandler = () => {
|
|
|
432
439
|
target.consumed = true;
|
|
433
440
|
const idx = closers.indexOf(target);
|
|
434
441
|
if (idx !== -1) closers.splice(idx, 1);
|
|
435
|
-
target
|
|
442
|
+
const settled = target;
|
|
443
|
+
void Promise.resolve(settled.close()).then(() => {
|
|
444
|
+
if (settled.isOpen()) settled.restore();
|
|
445
|
+
});
|
|
436
446
|
});
|
|
437
447
|
};
|
|
438
448
|
var programmaticBack = () => {
|
|
@@ -468,16 +478,7 @@ function installRoute(deps) {
|
|
|
468
478
|
pushed = false;
|
|
469
479
|
}
|
|
470
480
|
};
|
|
471
|
-
const
|
|
472
|
-
if (closer) return;
|
|
473
|
-
closer = {
|
|
474
|
-
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
475
|
-
isTop: () => deps.isTopSheet(),
|
|
476
|
-
close: () => void deps.close(),
|
|
477
|
-
consumed: false
|
|
478
|
-
};
|
|
479
|
-
ensureHandler();
|
|
480
|
-
closers.push(closer);
|
|
481
|
+
const pushEntry = () => {
|
|
481
482
|
try {
|
|
482
483
|
if (deps.routedTo !== void 0) {
|
|
483
484
|
history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
|
|
@@ -489,6 +490,25 @@ function installRoute(deps) {
|
|
|
489
490
|
pushed = false;
|
|
490
491
|
}
|
|
491
492
|
};
|
|
493
|
+
const onOpen = () => {
|
|
494
|
+
if (closer) return;
|
|
495
|
+
const self = {
|
|
496
|
+
isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
|
|
497
|
+
isTop: () => deps.isTopSheet(),
|
|
498
|
+
close: () => deps.close(),
|
|
499
|
+
restore: () => {
|
|
500
|
+
if (deps.isDestroyed() || closer !== self) return;
|
|
501
|
+
self.consumed = false;
|
|
502
|
+
if (!closers.includes(self)) closers.push(self);
|
|
503
|
+
pushEntry();
|
|
504
|
+
},
|
|
505
|
+
consumed: false
|
|
506
|
+
};
|
|
507
|
+
closer = self;
|
|
508
|
+
ensureHandler();
|
|
509
|
+
closers.push(self);
|
|
510
|
+
pushEntry();
|
|
511
|
+
};
|
|
492
512
|
const unsubscribeOpen = deps.on("open", onOpen);
|
|
493
513
|
const unsubscribeClose = deps.on("close", teardownEntry);
|
|
494
514
|
if (deps.getSize() > 0) onOpen();
|
|
@@ -535,11 +555,13 @@ var CONTENT_PULL_THRESHOLD = 60;
|
|
|
535
555
|
function installContentSwipe(deps) {
|
|
536
556
|
const { container } = deps;
|
|
537
557
|
let startY = 0;
|
|
558
|
+
let startScrollTop = 0;
|
|
538
559
|
let moved = false;
|
|
539
560
|
const onTouchStart = (e) => {
|
|
540
561
|
const t = e.touches[0];
|
|
541
562
|
if (!t) return;
|
|
542
563
|
startY = t.clientY;
|
|
564
|
+
startScrollTop = container.scrollTop;
|
|
543
565
|
moved = false;
|
|
544
566
|
};
|
|
545
567
|
const onTouchMove = (e) => {
|
|
@@ -550,6 +572,7 @@ function installContentSwipe(deps) {
|
|
|
550
572
|
const onTouchEnd = (e) => {
|
|
551
573
|
if (!moved) return;
|
|
552
574
|
if (deps.isDragging() || deps.isAnimating()) return;
|
|
575
|
+
if (container.scrollTop !== startScrollTop) return;
|
|
553
576
|
const t = e.changedTouches[0];
|
|
554
577
|
if (!t) return;
|
|
555
578
|
const deltaY = t.clientY - startY;
|
|
@@ -661,6 +684,131 @@ function installResizeObserver(deps) {
|
|
|
661
684
|
};
|
|
662
685
|
}
|
|
663
686
|
|
|
687
|
+
// src/core/features/fit-observer.ts
|
|
688
|
+
var contentTargets = (scroller) => {
|
|
689
|
+
if (!scroller) return [];
|
|
690
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
691
|
+
const out = [];
|
|
692
|
+
for (const child of Array.from(scroller.children)) {
|
|
693
|
+
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
694
|
+
for (const el of child.assignedElements()) out.push(el);
|
|
695
|
+
} else {
|
|
696
|
+
out.push(child);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return out;
|
|
700
|
+
};
|
|
701
|
+
function installFitObserver(deps) {
|
|
702
|
+
if (typeof ResizeObserver === "undefined") return () => {
|
|
703
|
+
};
|
|
704
|
+
if (!deps.hasFitSnap()) return () => {
|
|
705
|
+
};
|
|
706
|
+
let raf = 0;
|
|
707
|
+
const schedule = () => {
|
|
708
|
+
if (raf) return;
|
|
709
|
+
raf = requestAnimationFrame(() => {
|
|
710
|
+
raf = 0;
|
|
711
|
+
if (deps.isDestroyed() || deps.isDragging()) return;
|
|
712
|
+
deps.recompute();
|
|
713
|
+
});
|
|
714
|
+
};
|
|
715
|
+
const ro = new ResizeObserver(schedule);
|
|
716
|
+
ro.observe(deps.handle);
|
|
717
|
+
const scroller = deps.scrollContainer;
|
|
718
|
+
const observed = /* @__PURE__ */ new Set();
|
|
719
|
+
const slots = /* @__PURE__ */ new Set();
|
|
720
|
+
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
721
|
+
const onSlotChange = () => resync();
|
|
722
|
+
const trackSlots = () => {
|
|
723
|
+
if (!scroller || !hasSlot) return;
|
|
724
|
+
for (const child of Array.from(scroller.children)) {
|
|
725
|
+
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
726
|
+
child.addEventListener("slotchange", onSlotChange);
|
|
727
|
+
slots.add(child);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
const resync = () => {
|
|
732
|
+
trackSlots();
|
|
733
|
+
const targets = contentTargets(scroller);
|
|
734
|
+
for (const el of observed) {
|
|
735
|
+
if (!targets.includes(el)) {
|
|
736
|
+
ro.unobserve(el);
|
|
737
|
+
observed.delete(el);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
for (const el of targets) {
|
|
741
|
+
if (!observed.has(el)) {
|
|
742
|
+
ro.observe(el);
|
|
743
|
+
observed.add(el);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
schedule();
|
|
747
|
+
};
|
|
748
|
+
let mo;
|
|
749
|
+
if (scroller) {
|
|
750
|
+
resync();
|
|
751
|
+
if (typeof MutationObserver !== "undefined") {
|
|
752
|
+
mo = new MutationObserver(resync);
|
|
753
|
+
mo.observe(scroller, { childList: true });
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return () => {
|
|
757
|
+
ro.disconnect();
|
|
758
|
+
mo?.disconnect();
|
|
759
|
+
for (const slot of slots) {
|
|
760
|
+
slot.removeEventListener("slotchange", onSlotChange);
|
|
761
|
+
}
|
|
762
|
+
if (raf) cancelAnimationFrame(raf);
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/core/features/fit-measurement.ts
|
|
767
|
+
var measureSheetNatural = (element, content, vertical) => {
|
|
768
|
+
if (!content) {
|
|
769
|
+
return vertical ? element.offsetHeight : element.offsetWidth;
|
|
770
|
+
}
|
|
771
|
+
const axis = vertical ? "height" : "width";
|
|
772
|
+
const sheetStyle = element.style;
|
|
773
|
+
const cs = content.style;
|
|
774
|
+
const prevSheet = sheetStyle[axis];
|
|
775
|
+
const prevFlex = cs.flex;
|
|
776
|
+
const prevContent = vertical ? cs.height : cs.width;
|
|
777
|
+
sheetStyle[axis] = "auto";
|
|
778
|
+
cs.flex = "none";
|
|
779
|
+
if (vertical) cs.height = "auto";
|
|
780
|
+
else cs.width = "auto";
|
|
781
|
+
const poked = vertical ? element.offsetHeight : element.offsetWidth;
|
|
782
|
+
const contentBox = vertical ? content.clientHeight : content.clientWidth;
|
|
783
|
+
const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
|
|
784
|
+
const natural = Math.max(poked, poked - contentBox + contentScroll);
|
|
785
|
+
sheetStyle[axis] = prevSheet;
|
|
786
|
+
cs.flex = prevFlex;
|
|
787
|
+
if (vertical) cs.height = prevContent;
|
|
788
|
+
else cs.width = prevContent;
|
|
789
|
+
return natural;
|
|
790
|
+
};
|
|
791
|
+
var containingExtent = (element, vertical) => {
|
|
792
|
+
const op = element.offsetParent;
|
|
793
|
+
if (op && op !== document.body && op !== document.documentElement) {
|
|
794
|
+
return vertical ? op.clientHeight : op.clientWidth;
|
|
795
|
+
}
|
|
796
|
+
return vertical ? window.innerHeight : window.innerWidth;
|
|
797
|
+
};
|
|
798
|
+
var measureFitSize = (deps) => {
|
|
799
|
+
const vertical = layoutAxis(deps.mode) === "height";
|
|
800
|
+
const natural = measureSheetNatural(
|
|
801
|
+
deps.element,
|
|
802
|
+
deps.scrollContainer,
|
|
803
|
+
vertical
|
|
804
|
+
);
|
|
805
|
+
const cap = deps.getMaxHeightCap();
|
|
806
|
+
const capped = cap !== void 0 ? Math.min(natural, cap) : natural;
|
|
807
|
+
if (typeof window === "undefined") return capped;
|
|
808
|
+
const viewport = containingExtent(deps.element, vertical);
|
|
809
|
+
return viewport > 0 ? Math.min(capped, viewport) : capped;
|
|
810
|
+
};
|
|
811
|
+
|
|
664
812
|
// src/core/features/slider-keyboard.ts
|
|
665
813
|
function installSliderKeyboard(deps) {
|
|
666
814
|
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
|
}
|
|
@@ -1905,7 +2102,7 @@ var GestureController = class {
|
|
|
1905
2102
|
this.isDragging_ = false;
|
|
1906
2103
|
this.keyboardDismissed = false;
|
|
1907
2104
|
this.deps.getRoot()?.removeAttribute("data-dragging");
|
|
1908
|
-
this.deps.element.style.willChange = "
|
|
2105
|
+
this.deps.element.style.willChange = "";
|
|
1909
2106
|
}
|
|
1910
2107
|
};
|
|
1911
2108
|
|
|
@@ -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
|
constructor() {
|
|
2311
2507
|
__publicField(this, "fns", []);
|
|
@@ -2325,6 +2521,9 @@ var TeardownStack = class {
|
|
|
2325
2521
|
}
|
|
2326
2522
|
}
|
|
2327
2523
|
};
|
|
2524
|
+
|
|
2525
|
+
// src/core/BottomSheetEngine.ts
|
|
2526
|
+
var HAPTIC_DURATION_MS = 8;
|
|
2328
2527
|
var BottomSheetEngine = class {
|
|
2329
2528
|
constructor(opts) {
|
|
2330
2529
|
__publicField(this, "id", nextInstanceId("bs"));
|
|
@@ -2349,6 +2548,7 @@ var BottomSheetEngine = class {
|
|
|
2349
2548
|
__publicField(this, "disableDragFlag");
|
|
2350
2549
|
__publicField(this, "closeOnRouteChange");
|
|
2351
2550
|
__publicField(this, "maxHeightCap");
|
|
2551
|
+
__publicField(this, "maxHeightRaw");
|
|
2352
2552
|
__publicField(this, "snapPointsRaw");
|
|
2353
2553
|
__publicField(this, "snaps");
|
|
2354
2554
|
__publicField(this, "activeId");
|
|
@@ -2384,6 +2584,7 @@ var BottomSheetEngine = class {
|
|
|
2384
2584
|
__publicField(this, "detachScrimStages", null);
|
|
2385
2585
|
__publicField(this, "stackEffectEnabled", false);
|
|
2386
2586
|
__publicField(this, "stackEffectPrimed", false);
|
|
2587
|
+
__publicField(this, "fitDeps");
|
|
2387
2588
|
__publicField(this, "transformTemplate");
|
|
2388
2589
|
const resolved = resolveEngineOptions(opts, {
|
|
2389
2590
|
shouldApplyInertSiblings: () => {
|
|
@@ -2456,12 +2657,19 @@ var BottomSheetEngine = class {
|
|
|
2456
2657
|
}
|
|
2457
2658
|
this.activeId = resolved.initialId;
|
|
2458
2659
|
auditVhUsage(this.snapPointsRaw);
|
|
2660
|
+
this.auditDuplicateSnapIds(this.snapPointsRaw);
|
|
2459
2661
|
this.rootEl = this.element.closest(".bs-root");
|
|
2662
|
+
this.fitDeps = {
|
|
2663
|
+
element: this.element,
|
|
2664
|
+
scrollContainer: this.scrollContainer,
|
|
2665
|
+
mode: this.mode,
|
|
2666
|
+
getMaxHeightCap: () => this.maxHeightCap
|
|
2667
|
+
};
|
|
2460
2668
|
this.snaps = new SnapResolver(
|
|
2461
2669
|
this.snapPointsRaw,
|
|
2462
2670
|
resolved.initialAllowed,
|
|
2463
2671
|
this.mode,
|
|
2464
|
-
() => this.
|
|
2672
|
+
() => measureFitSize(this.fitDeps),
|
|
2465
2673
|
(maxAxisSize) => {
|
|
2466
2674
|
this.element.style[layoutAxis(this.mode)] = `${maxAxisSize}px`;
|
|
2467
2675
|
}
|
|
@@ -2495,7 +2703,18 @@ var BottomSheetEngine = class {
|
|
|
2495
2703
|
io.observe(this.element);
|
|
2496
2704
|
this.teardowns.add(() => io.disconnect());
|
|
2497
2705
|
}
|
|
2498
|
-
this.
|
|
2706
|
+
this.teardowns.add(
|
|
2707
|
+
installFitObserver({
|
|
2708
|
+
handle: this.handle,
|
|
2709
|
+
scrollContainer: this.scrollContainer,
|
|
2710
|
+
hasFitSnap: () => this.snapPointsRaw.some(
|
|
2711
|
+
(p) => p.size === "fit" || p.size === "content"
|
|
2712
|
+
),
|
|
2713
|
+
isDestroyed: () => this.destroyed,
|
|
2714
|
+
isDragging: () => this.gesture?.isDragging ?? false,
|
|
2715
|
+
recompute: () => this.recompute()
|
|
2716
|
+
})
|
|
2717
|
+
);
|
|
2499
2718
|
if (resolved.radius !== void 0) this.setRadius(resolved.radius);
|
|
2500
2719
|
if (resolved.maxHeight !== void 0) this.setMaxHeight(resolved.maxHeight);
|
|
2501
2720
|
this.applyAutoAriaLabelledBy();
|
|
@@ -2646,27 +2865,33 @@ var BottomSheetEngine = class {
|
|
|
2646
2865
|
} else {
|
|
2647
2866
|
await this.animation.animateTo(target.size, velocityPxPerMs);
|
|
2648
2867
|
}
|
|
2649
|
-
this.opening = false;
|
|
2650
2868
|
externalSignal?.removeEventListener("abort", onExternalAbort);
|
|
2651
2869
|
if (signal.aborted) return;
|
|
2652
|
-
this.
|
|
2870
|
+
this.opening = false;
|
|
2871
|
+
this.completeSnap(id, target.size, previousSize, wasClosed, false);
|
|
2872
|
+
}
|
|
2873
|
+
completeSnap(id, targetSize, previousSize, wasClosed, withHaptic) {
|
|
2874
|
+
this.scrollCache.restore(id, previousSize, targetSize);
|
|
2653
2875
|
this.updateAriaSlider();
|
|
2654
2876
|
this.emit("snap", {
|
|
2655
2877
|
id,
|
|
2656
2878
|
size: this.size,
|
|
2657
2879
|
progress: this.computeProgress(this.size)
|
|
2658
2880
|
});
|
|
2659
|
-
if (
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
}
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2881
|
+
if (withHaptic) this.haptic();
|
|
2882
|
+
if (wasClosed && targetSize > 0) this.emitOpenSequence(id);
|
|
2883
|
+
if (targetSize === 0) this.emitCloseSequence();
|
|
2884
|
+
}
|
|
2885
|
+
emitOpenSequence(id) {
|
|
2886
|
+
this.emit("open", { id });
|
|
2887
|
+
this.handleOpen();
|
|
2888
|
+
notifyLinkedSheets(this.linkedSheets, this);
|
|
2889
|
+
this.emit("opened", { id });
|
|
2890
|
+
}
|
|
2891
|
+
emitCloseSequence() {
|
|
2892
|
+
this.emit("close", void 0);
|
|
2893
|
+
this.handleClose();
|
|
2894
|
+
this.emit("closed", void 0);
|
|
2670
2895
|
}
|
|
2671
2896
|
async dragTo(targetSize, velocityOrOpts = 0) {
|
|
2672
2897
|
if (this.destroyed) return;
|
|
@@ -2687,19 +2912,31 @@ var BottomSheetEngine = class {
|
|
|
2687
2912
|
}
|
|
2688
2913
|
open(id) {
|
|
2689
2914
|
if (this.destroyed) return Promise.resolve();
|
|
2690
|
-
const target = id ?? this.snaps.getAllowedIds().find((a) => a
|
|
2915
|
+
const target = id ?? this.snaps.getAllowedIds().find((a) => (this.snaps.findById(a)?.size ?? 0) > 0) ?? this.activeId;
|
|
2691
2916
|
return this.snapTo(target);
|
|
2692
2917
|
}
|
|
2693
2918
|
close(reason = "programmatic") {
|
|
2694
2919
|
if (this.destroyed) return Promise.resolve();
|
|
2695
2920
|
if (this.disableCloseFlag) return Promise.resolve();
|
|
2696
2921
|
if (this.size > 0 && this.emitBeforeClose(reason)) return Promise.resolve();
|
|
2697
|
-
const closedId = this.snapPointsRaw.find((p) => p.id === "closed")?.id ?? this.snaps.getAllowedIds()[0];
|
|
2922
|
+
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];
|
|
2698
2923
|
return this.snapTo(closedId ?? this.activeId);
|
|
2699
2924
|
}
|
|
2700
2925
|
canDismiss() {
|
|
2701
2926
|
return !this.persistent && !this.disableCloseFlag && !this.destroyed;
|
|
2702
2927
|
}
|
|
2928
|
+
setPersistent(value) {
|
|
2929
|
+
if (this.destroyed) return;
|
|
2930
|
+
this.persistent = value;
|
|
2931
|
+
}
|
|
2932
|
+
setDisableClose(value) {
|
|
2933
|
+
if (this.destroyed) return;
|
|
2934
|
+
this.disableCloseFlag = value;
|
|
2935
|
+
}
|
|
2936
|
+
setDisableDrag(value) {
|
|
2937
|
+
if (this.destroyed) return;
|
|
2938
|
+
this.disableDragFlag = value;
|
|
2939
|
+
}
|
|
2703
2940
|
isTop() {
|
|
2704
2941
|
return this.isTopSheet;
|
|
2705
2942
|
}
|
|
@@ -2736,18 +2973,23 @@ var BottomSheetEngine = class {
|
|
|
2736
2973
|
axis === "height" ? "max-height" : "max-width",
|
|
2737
2974
|
value
|
|
2738
2975
|
);
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2749
|
-
this.recompute();
|
|
2976
|
+
this.maxHeightRaw = h;
|
|
2977
|
+
this.resolveMaxHeightCap();
|
|
2978
|
+
this.recompute();
|
|
2979
|
+
}
|
|
2980
|
+
resolveMaxHeightCap() {
|
|
2981
|
+
const raw = this.maxHeightRaw;
|
|
2982
|
+
if (raw === void 0) {
|
|
2983
|
+
this.maxHeightCap = void 0;
|
|
2984
|
+
return;
|
|
2750
2985
|
}
|
|
2986
|
+
if (typeof raw === "number") {
|
|
2987
|
+
this.maxHeightCap = raw;
|
|
2988
|
+
return;
|
|
2989
|
+
}
|
|
2990
|
+
if (typeof window === "undefined") return;
|
|
2991
|
+
const measured = resolveSnap(raw, this.mode);
|
|
2992
|
+
this.maxHeightCap = measured > 0 ? measured : void 0;
|
|
2751
2993
|
}
|
|
2752
2994
|
clampToMaxHeight() {
|
|
2753
2995
|
if (this.maxHeightCap === void 0) return;
|
|
@@ -2878,6 +3120,7 @@ var BottomSheetEngine = class {
|
|
|
2878
3120
|
this.newCycle();
|
|
2879
3121
|
this.snapPointsRaw = points;
|
|
2880
3122
|
auditVhUsage(points);
|
|
3123
|
+
this.auditDuplicateSnapIds(points);
|
|
2881
3124
|
this.snaps.setRaw(points);
|
|
2882
3125
|
if (allowed) this.snaps.setAllowedIds(allowed);
|
|
2883
3126
|
this.scrollCache.clear();
|
|
@@ -2890,6 +3133,7 @@ var BottomSheetEngine = class {
|
|
|
2890
3133
|
}
|
|
2891
3134
|
recompute() {
|
|
2892
3135
|
if (this.destroyed) return;
|
|
3136
|
+
this.resolveMaxHeightCap();
|
|
2893
3137
|
this.snaps.recompute();
|
|
2894
3138
|
this.clampToMaxHeight();
|
|
2895
3139
|
this.scrim.invalidateOpacityCache();
|
|
@@ -2901,129 +3145,6 @@ var BottomSheetEngine = class {
|
|
|
2901
3145
|
this.updateAriaSlider();
|
|
2902
3146
|
}
|
|
2903
3147
|
}
|
|
2904
|
-
contentTargets() {
|
|
2905
|
-
const scroller = this.scrollContainer;
|
|
2906
|
-
if (!scroller) return [];
|
|
2907
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2908
|
-
const out = [];
|
|
2909
|
-
for (const child of Array.from(scroller.children)) {
|
|
2910
|
-
if (hasSlot && child instanceof HTMLSlotElement) {
|
|
2911
|
-
for (const el of child.assignedElements()) out.push(el);
|
|
2912
|
-
} else {
|
|
2913
|
-
out.push(child);
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
return out;
|
|
2917
|
-
}
|
|
2918
|
-
measureSheetNatural(vertical) {
|
|
2919
|
-
const el = this.element;
|
|
2920
|
-
const content = this.scrollContainer;
|
|
2921
|
-
if (!content) {
|
|
2922
|
-
return vertical ? el.offsetHeight : el.offsetWidth;
|
|
2923
|
-
}
|
|
2924
|
-
const axis = vertical ? "height" : "width";
|
|
2925
|
-
const sheetStyle = el.style;
|
|
2926
|
-
const cs = content.style;
|
|
2927
|
-
const prevSheet = sheetStyle[axis];
|
|
2928
|
-
const prevFlex = cs.flex;
|
|
2929
|
-
const prevContent = vertical ? cs.height : cs.width;
|
|
2930
|
-
sheetStyle[axis] = "auto";
|
|
2931
|
-
cs.flex = "none";
|
|
2932
|
-
if (vertical) cs.height = "auto";
|
|
2933
|
-
else cs.width = "auto";
|
|
2934
|
-
const poked = vertical ? el.offsetHeight : el.offsetWidth;
|
|
2935
|
-
const contentBox = vertical ? content.clientHeight : content.clientWidth;
|
|
2936
|
-
const contentScroll = vertical ? content.scrollHeight : content.scrollWidth;
|
|
2937
|
-
const natural = Math.max(poked, poked - contentBox + contentScroll);
|
|
2938
|
-
sheetStyle[axis] = prevSheet;
|
|
2939
|
-
cs.flex = prevFlex;
|
|
2940
|
-
if (vertical) cs.height = prevContent;
|
|
2941
|
-
else cs.width = prevContent;
|
|
2942
|
-
return natural;
|
|
2943
|
-
}
|
|
2944
|
-
measureFitSize() {
|
|
2945
|
-
const vertical = layoutAxis(this.mode) === "height";
|
|
2946
|
-
const natural = this.measureSheetNatural(vertical);
|
|
2947
|
-
const capped = this.maxHeightCap !== void 0 ? Math.min(natural, this.maxHeightCap) : natural;
|
|
2948
|
-
if (typeof window === "undefined") return capped;
|
|
2949
|
-
const viewport = this.containingExtent(vertical);
|
|
2950
|
-
return viewport > 0 ? Math.min(capped, viewport) : capped;
|
|
2951
|
-
}
|
|
2952
|
-
// The fit cap is the sheet's containing block, not always the window: a
|
|
2953
|
-
// position:fixed sheet nested under a transform/filter/will-change ancestor
|
|
2954
|
-
// is clipped to that ancestor, so capping by window.innerHeight oversizes the
|
|
2955
|
-
// sheet and the content/footer get clipped. offsetParent resolves to that
|
|
2956
|
-
// ancestor when present, and is null (→ viewport) for a plain fixed sheet.
|
|
2957
|
-
containingExtent(vertical) {
|
|
2958
|
-
const op = this.element.offsetParent;
|
|
2959
|
-
if (op && op !== document.body && op !== document.documentElement) {
|
|
2960
|
-
return vertical ? op.clientHeight : op.clientWidth;
|
|
2961
|
-
}
|
|
2962
|
-
return vertical ? window.innerHeight : window.innerWidth;
|
|
2963
|
-
}
|
|
2964
|
-
installFitObserver() {
|
|
2965
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
2966
|
-
if (!this.snapPointsRaw.some((p) => p.size === "fit" || p.size === "content"))
|
|
2967
|
-
return;
|
|
2968
|
-
let raf = 0;
|
|
2969
|
-
const schedule = () => {
|
|
2970
|
-
if (raf) return;
|
|
2971
|
-
raf = requestAnimationFrame(() => {
|
|
2972
|
-
raf = 0;
|
|
2973
|
-
if (this.destroyed || this.gesture?.isDragging) return;
|
|
2974
|
-
this.recompute();
|
|
2975
|
-
});
|
|
2976
|
-
};
|
|
2977
|
-
const ro = new ResizeObserver(schedule);
|
|
2978
|
-
ro.observe(this.handle);
|
|
2979
|
-
const scroller = this.scrollContainer;
|
|
2980
|
-
const observed = /* @__PURE__ */ new Set();
|
|
2981
|
-
const slots = /* @__PURE__ */ new Set();
|
|
2982
|
-
const hasSlot = typeof HTMLSlotElement !== "undefined";
|
|
2983
|
-
const onSlotChange = () => resync();
|
|
2984
|
-
const trackSlots = () => {
|
|
2985
|
-
if (!scroller || !hasSlot) return;
|
|
2986
|
-
for (const child of Array.from(scroller.children)) {
|
|
2987
|
-
if (child instanceof HTMLSlotElement && !slots.has(child)) {
|
|
2988
|
-
child.addEventListener("slotchange", onSlotChange);
|
|
2989
|
-
slots.add(child);
|
|
2990
|
-
}
|
|
2991
|
-
}
|
|
2992
|
-
};
|
|
2993
|
-
const resync = () => {
|
|
2994
|
-
trackSlots();
|
|
2995
|
-
const targets = this.contentTargets();
|
|
2996
|
-
for (const el of observed) {
|
|
2997
|
-
if (!targets.includes(el)) {
|
|
2998
|
-
ro.unobserve(el);
|
|
2999
|
-
observed.delete(el);
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3002
|
-
for (const el of targets) {
|
|
3003
|
-
if (!observed.has(el)) {
|
|
3004
|
-
ro.observe(el);
|
|
3005
|
-
observed.add(el);
|
|
3006
|
-
}
|
|
3007
|
-
}
|
|
3008
|
-
schedule();
|
|
3009
|
-
};
|
|
3010
|
-
let mo;
|
|
3011
|
-
if (scroller) {
|
|
3012
|
-
resync();
|
|
3013
|
-
if (typeof MutationObserver !== "undefined") {
|
|
3014
|
-
mo = new MutationObserver(resync);
|
|
3015
|
-
mo.observe(scroller, { childList: true });
|
|
3016
|
-
}
|
|
3017
|
-
}
|
|
3018
|
-
this.teardowns.add(() => {
|
|
3019
|
-
ro.disconnect();
|
|
3020
|
-
mo?.disconnect();
|
|
3021
|
-
for (const slot of slots) {
|
|
3022
|
-
slot.removeEventListener("slotchange", onSlotChange);
|
|
3023
|
-
}
|
|
3024
|
-
if (raf) cancelAnimationFrame(raf);
|
|
3025
|
-
});
|
|
3026
|
-
}
|
|
3027
3148
|
destroy() {
|
|
3028
3149
|
this.destroyed = true;
|
|
3029
3150
|
this.opening = false;
|
|
@@ -3041,9 +3162,10 @@ var BottomSheetEngine = class {
|
|
|
3041
3162
|
this.backdrop.style.opacity = "";
|
|
3042
3163
|
this.backdrop.style.pointerEvents = "";
|
|
3043
3164
|
}
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3165
|
+
for (const host of [this.anchorHost, this.scrimParent, this.rootEl]) {
|
|
3166
|
+
if (!host) continue;
|
|
3167
|
+
host.style.removeProperty("--bs-size");
|
|
3168
|
+
host.style.removeProperty("--bs-progress");
|
|
3047
3169
|
}
|
|
3048
3170
|
if (this.screenComponent) {
|
|
3049
3171
|
this.screenComponent.style.opacity = "";
|
|
@@ -3057,6 +3179,7 @@ var BottomSheetEngine = class {
|
|
|
3057
3179
|
}
|
|
3058
3180
|
newCycle() {
|
|
3059
3181
|
this.allowOvershoot = false;
|
|
3182
|
+
this.opening = false;
|
|
3060
3183
|
this.currentAbort.abort();
|
|
3061
3184
|
this.currentAbort = new AbortController();
|
|
3062
3185
|
return this.currentAbort.signal;
|
|
@@ -3112,8 +3235,14 @@ var BottomSheetEngine = class {
|
|
|
3112
3235
|
this.element.setAttribute("aria-labelledby", titled.id);
|
|
3113
3236
|
}
|
|
3114
3237
|
recomputeSnaps() {
|
|
3238
|
+
this.resolveMaxHeightCap();
|
|
3239
|
+
this.snaps.setRaw(this.snapPointsRaw);
|
|
3240
|
+
this.clampToMaxHeight();
|
|
3241
|
+
this.scrim.invalidateOpacityCache();
|
|
3242
|
+
}
|
|
3243
|
+
auditDuplicateSnapIds(points) {
|
|
3115
3244
|
const seen = /* @__PURE__ */ new Set();
|
|
3116
|
-
for (const p of
|
|
3245
|
+
for (const p of points) {
|
|
3117
3246
|
if (seen.has(p.id)) {
|
|
3118
3247
|
console.warn(
|
|
3119
3248
|
`[BottomSheet] duplicate snap id "${p.id}" \u2014 only the first occurrence is reachable.`
|
|
@@ -3121,9 +3250,6 @@ var BottomSheetEngine = class {
|
|
|
3121
3250
|
}
|
|
3122
3251
|
seen.add(p.id);
|
|
3123
3252
|
}
|
|
3124
|
-
this.snaps.setRaw(this.snapPointsRaw);
|
|
3125
|
-
this.clampToMaxHeight();
|
|
3126
|
-
this.scrim.invalidateOpacityCache();
|
|
3127
3253
|
}
|
|
3128
3254
|
getAllowedRange() {
|
|
3129
3255
|
return this.snaps.getAllowedRange();
|
|
@@ -3311,9 +3437,15 @@ var BottomSheetEngine = class {
|
|
|
3311
3437
|
flickVelocity: this.flickVelocity,
|
|
3312
3438
|
dragThreshold: this.dragThreshold
|
|
3313
3439
|
});
|
|
3314
|
-
if (!target)
|
|
3440
|
+
if (!target) {
|
|
3441
|
+
this.clearWillChangeIfIdle();
|
|
3442
|
+
return;
|
|
3443
|
+
}
|
|
3315
3444
|
const previousId = this.activeId;
|
|
3316
|
-
if (target.id === previousId && target.size === this.size)
|
|
3445
|
+
if (target.id === previousId && target.size === this.size) {
|
|
3446
|
+
this.clearWillChangeIfIdle();
|
|
3447
|
+
return;
|
|
3448
|
+
}
|
|
3317
3449
|
if (this.emitBeforeSnap(target, previousId)) {
|
|
3318
3450
|
const restore = this.snaps.findById(previousId);
|
|
3319
3451
|
if (restore) {
|
|
@@ -3336,27 +3468,19 @@ var BottomSheetEngine = class {
|
|
|
3336
3468
|
if (signal.aborted) return;
|
|
3337
3469
|
this.allowOvershoot = false;
|
|
3338
3470
|
this.opening = false;
|
|
3339
|
-
this.
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
this.haptic();
|
|
3347
|
-
if (previousSnapSize === 0 && target.size > 0) {
|
|
3348
|
-
this.emit("open", { id: target.id });
|
|
3349
|
-
this.handleOpen();
|
|
3350
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3351
|
-
this.emit("opened", { id: target.id });
|
|
3352
|
-
}
|
|
3353
|
-
if (target.size === 0) {
|
|
3354
|
-
this.emit("close", void 0);
|
|
3355
|
-
this.handleClose();
|
|
3356
|
-
this.emit("closed", void 0);
|
|
3357
|
-
}
|
|
3471
|
+
this.completeSnap(
|
|
3472
|
+
target.id,
|
|
3473
|
+
target.size,
|
|
3474
|
+
previousSize,
|
|
3475
|
+
previousSnapSize === 0,
|
|
3476
|
+
true
|
|
3477
|
+
);
|
|
3358
3478
|
});
|
|
3359
3479
|
}
|
|
3480
|
+
clearWillChangeIfIdle() {
|
|
3481
|
+
if (this.animation.isAnimating || this.gesture?.isDragging) return;
|
|
3482
|
+
this.element.style.willChange = "";
|
|
3483
|
+
}
|
|
3360
3484
|
haptic() {
|
|
3361
3485
|
if (typeof navigator !== "undefined" && "vibrate" in navigator) {
|
|
3362
3486
|
try {
|
|
@@ -3437,14 +3561,9 @@ var BottomSheetEngine = class {
|
|
|
3437
3561
|
progress: this.computeProgress(this.size)
|
|
3438
3562
|
});
|
|
3439
3563
|
if (target.size > 0 && !this.lifecycle.isInstalled) {
|
|
3440
|
-
this.
|
|
3441
|
-
this.handleOpen();
|
|
3442
|
-
notifyLinkedSheets(this.linkedSheets, this);
|
|
3443
|
-
this.emit("opened", { id: target.id });
|
|
3564
|
+
this.emitOpenSequence(target.id);
|
|
3444
3565
|
} else if (target.size === 0 && this.lifecycle.isInstalled) {
|
|
3445
|
-
this.
|
|
3446
|
-
this.handleClose();
|
|
3447
|
-
this.emit("closed", void 0);
|
|
3566
|
+
this.emitCloseSequence();
|
|
3448
3567
|
}
|
|
3449
3568
|
}
|
|
3450
3569
|
handleClose() {
|
|
@@ -3480,6 +3599,95 @@ var createSheetManager = (initial = {}) => {
|
|
|
3480
3599
|
};
|
|
3481
3600
|
};
|
|
3482
3601
|
|
|
3602
|
+
// src/core/primitives/overlay-transforms.ts
|
|
3603
|
+
var closedTransform = (edge) => CLOSED_TRANSFORM[edge];
|
|
3604
|
+
var closedTransformFor = (edge, animation, peekPx) => {
|
|
3605
|
+
switch (animation) {
|
|
3606
|
+
case "fade":
|
|
3607
|
+
return "translate3d(0, 0, 0)";
|
|
3608
|
+
case "scale":
|
|
3609
|
+
return "translate3d(0, 0, 0) scale(0.94)";
|
|
3610
|
+
case "slide":
|
|
3611
|
+
default:
|
|
3612
|
+
if (peekPx !== void 0 && edge === "bottom") {
|
|
3613
|
+
return `translate3d(0, calc(100% - ${peekPx}px), 0)`;
|
|
3614
|
+
}
|
|
3615
|
+
return closedTransform(edge);
|
|
3616
|
+
}
|
|
3617
|
+
};
|
|
3618
|
+
var openTransformFor = (animation) => animation === "scale" ? "translate3d(0, 0, 0) scale(1)" : "translate3d(0, 0, 0)";
|
|
3619
|
+
|
|
3620
|
+
// src/core/features/overlay-swipe.ts
|
|
3621
|
+
function installOverlaySwipe(deps) {
|
|
3622
|
+
const el = deps.element;
|
|
3623
|
+
const edge = deps.edge;
|
|
3624
|
+
const isVertical = edge === "bottom" || edge === "top";
|
|
3625
|
+
const sign = edge === "bottom" || edge === "right" ? 1 : -1;
|
|
3626
|
+
const SLOP = 8;
|
|
3627
|
+
let startX = 0;
|
|
3628
|
+
let startY = 0;
|
|
3629
|
+
let startT = 0;
|
|
3630
|
+
let tracking = false;
|
|
3631
|
+
let dragging = false;
|
|
3632
|
+
let pointerId = null;
|
|
3633
|
+
const previousTouchAction = el.style.touchAction;
|
|
3634
|
+
el.style.touchAction = isVertical ? "pan-x" : "pan-y";
|
|
3635
|
+
const onDown = (e) => {
|
|
3636
|
+
if (e.button !== void 0 && e.button !== 0) return;
|
|
3637
|
+
pointerId = e.pointerId;
|
|
3638
|
+
startX = e.clientX;
|
|
3639
|
+
startY = e.clientY;
|
|
3640
|
+
startT = performance.now();
|
|
3641
|
+
tracking = true;
|
|
3642
|
+
dragging = false;
|
|
3643
|
+
};
|
|
3644
|
+
const onMove = (e) => {
|
|
3645
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
3646
|
+
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
3647
|
+
if (!dragging) {
|
|
3648
|
+
if (Math.abs(delta) < SLOP) return;
|
|
3649
|
+
dragging = true;
|
|
3650
|
+
el.style.transition = "none";
|
|
3651
|
+
try {
|
|
3652
|
+
el.setPointerCapture(e.pointerId);
|
|
3653
|
+
} catch {
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
const offset = Math.max(0, sign * delta);
|
|
3657
|
+
el.style.transform = isVertical ? `translate3d(0, ${sign * offset}px, 0)` : `translate3d(${sign * offset}px, 0, 0)`;
|
|
3658
|
+
};
|
|
3659
|
+
const finish = (e) => {
|
|
3660
|
+
if (!tracking || e.pointerId !== pointerId) return;
|
|
3661
|
+
tracking = false;
|
|
3662
|
+
pointerId = null;
|
|
3663
|
+
if (!dragging) return;
|
|
3664
|
+
dragging = false;
|
|
3665
|
+
const dt = performance.now() - startT || 1;
|
|
3666
|
+
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
3667
|
+
const offset = Math.max(0, sign * delta);
|
|
3668
|
+
const velocity = sign * delta / dt;
|
|
3669
|
+
const size = isVertical ? el.offsetHeight : el.offsetWidth;
|
|
3670
|
+
const past = offset > size * deps.getThreshold() || velocity > deps.getVelocityThreshold();
|
|
3671
|
+
el.style.transition = deps.getExitTransition();
|
|
3672
|
+
if (past) {
|
|
3673
|
+
deps.close();
|
|
3674
|
+
} else {
|
|
3675
|
+
el.style.transform = deps.getOpenTransform();
|
|
3676
|
+
}
|
|
3677
|
+
};
|
|
3678
|
+
el.addEventListener("pointerdown", onDown);
|
|
3679
|
+
el.addEventListener("pointermove", onMove);
|
|
3680
|
+
el.addEventListener("pointerup", finish);
|
|
3681
|
+
el.addEventListener("pointercancel", finish);
|
|
3682
|
+
return () => {
|
|
3683
|
+
el.style.touchAction = previousTouchAction;
|
|
3684
|
+
el.removeEventListener("pointerdown", onDown);
|
|
3685
|
+
el.removeEventListener("pointermove", onMove);
|
|
3686
|
+
el.removeEventListener("pointerup", finish);
|
|
3687
|
+
el.removeEventListener("pointercancel", finish);
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3483
3691
|
// src/core/overlay.ts
|
|
3484
3692
|
var OVERLAY_PRESETS = Object.freeze({
|
|
3485
3693
|
sheet: Object.freeze({
|
|
@@ -3511,22 +3719,6 @@ var OVERLAY_PRESETS = Object.freeze({
|
|
|
3511
3719
|
swipeToClose: false
|
|
3512
3720
|
})
|
|
3513
3721
|
});
|
|
3514
|
-
var closedTransform = (edge) => CLOSED_TRANSFORM[edge];
|
|
3515
|
-
var closedTransformFor = (edge, animation, peekPx) => {
|
|
3516
|
-
switch (animation) {
|
|
3517
|
-
case "fade":
|
|
3518
|
-
return "translate3d(0, 0, 0)";
|
|
3519
|
-
case "scale":
|
|
3520
|
-
return "translate3d(0, 0, 0) scale(0.94)";
|
|
3521
|
-
case "slide":
|
|
3522
|
-
default:
|
|
3523
|
-
if (peekPx !== void 0 && edge === "bottom") {
|
|
3524
|
-
return `translate3d(0, calc(100% - ${peekPx}px), 0)`;
|
|
3525
|
-
}
|
|
3526
|
-
return closedTransform(edge);
|
|
3527
|
-
}
|
|
3528
|
-
};
|
|
3529
|
-
var openTransformFor = (animation) => animation === "scale" ? "translate3d(0, 0, 0) scale(1)" : "translate3d(0, 0, 0)";
|
|
3530
3722
|
var OverlayEngine = class {
|
|
3531
3723
|
constructor(opts) {
|
|
3532
3724
|
__publicField(this, "id", nextInstanceId("ovl"));
|
|
@@ -3659,6 +3851,7 @@ var OverlayEngine = class {
|
|
|
3659
3851
|
if (this.backdrop) {
|
|
3660
3852
|
this.backdrop.style.transition = `opacity ${dur}ms ease-out`;
|
|
3661
3853
|
}
|
|
3854
|
+
this.setWillChange(true);
|
|
3662
3855
|
const cycle = ++this.cycleNonce;
|
|
3663
3856
|
return new Promise((resolve) => {
|
|
3664
3857
|
requestAnimationFrame(() => {
|
|
@@ -3681,6 +3874,7 @@ var OverlayEngine = class {
|
|
|
3681
3874
|
this.releaseInteractiveListeners();
|
|
3682
3875
|
this.isOpen_ = false;
|
|
3683
3876
|
this.isAnimating_ = false;
|
|
3877
|
+
this.setWillChange(false);
|
|
3684
3878
|
this.element.style.transform = closedTransformFor(
|
|
3685
3879
|
this.edge,
|
|
3686
3880
|
this.enterAnimation,
|
|
@@ -3711,6 +3905,7 @@ var OverlayEngine = class {
|
|
|
3711
3905
|
).then(() => {
|
|
3712
3906
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3713
3907
|
this.isAnimating_ = false;
|
|
3908
|
+
this.setWillChange(false);
|
|
3714
3909
|
this.element.setAttribute("data-state", "open");
|
|
3715
3910
|
this.emit("open", void 0);
|
|
3716
3911
|
this.onOpenCb?.();
|
|
@@ -3734,6 +3929,7 @@ var OverlayEngine = class {
|
|
|
3734
3929
|
if (this.backdrop) {
|
|
3735
3930
|
this.backdrop.style.transition = `opacity ${dur}ms ease-in`;
|
|
3736
3931
|
}
|
|
3932
|
+
this.setWillChange(true);
|
|
3737
3933
|
const cycle = ++this.cycleNonce;
|
|
3738
3934
|
return new Promise((resolve) => {
|
|
3739
3935
|
requestAnimationFrame(() => {
|
|
@@ -3759,6 +3955,7 @@ var OverlayEngine = class {
|
|
|
3759
3955
|
).then(() => {
|
|
3760
3956
|
if (this.destroyed || cycle !== this.cycleNonce) return resolve();
|
|
3761
3957
|
this.isAnimating_ = false;
|
|
3958
|
+
this.setWillChange(false);
|
|
3762
3959
|
if (this.peekPx === void 0) {
|
|
3763
3960
|
this.element.setAttribute("hidden", "");
|
|
3764
3961
|
}
|
|
@@ -3781,6 +3978,7 @@ var OverlayEngine = class {
|
|
|
3781
3978
|
this.destroyed = true;
|
|
3782
3979
|
this.cycleNonce++;
|
|
3783
3980
|
this.bus.clear();
|
|
3981
|
+
this.setWillChange(false);
|
|
3784
3982
|
this.releaseInteractiveListeners();
|
|
3785
3983
|
this.releaseStackEntry?.();
|
|
3786
3984
|
this.releaseStackEntry = null;
|
|
@@ -4006,7 +4204,6 @@ var OverlayEngine = class {
|
|
|
4006
4204
|
this.originalNextSibling = null;
|
|
4007
4205
|
}
|
|
4008
4206
|
applyClosedStyles() {
|
|
4009
|
-
this.element.style.willChange = "transform, opacity";
|
|
4010
4207
|
this.element.style.transform = closedTransformFor(
|
|
4011
4208
|
this.edge,
|
|
4012
4209
|
this.enterAnimation,
|
|
@@ -4020,7 +4217,12 @@ var OverlayEngine = class {
|
|
|
4020
4217
|
if (this.backdrop) {
|
|
4021
4218
|
this.backdrop.style.opacity = "0";
|
|
4022
4219
|
this.backdrop.style.pointerEvents = "none";
|
|
4023
|
-
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
setWillChange(on) {
|
|
4223
|
+
this.element.style.willChange = on ? "transform, opacity" : "";
|
|
4224
|
+
if (this.backdrop) {
|
|
4225
|
+
this.backdrop.style.willChange = on ? "opacity" : "";
|
|
4024
4226
|
}
|
|
4025
4227
|
}
|
|
4026
4228
|
awaitTransition(cycle, property = "transform") {
|
|
@@ -4106,73 +4308,15 @@ var OverlayEngine = class {
|
|
|
4106
4308
|
this.lifecycle.release();
|
|
4107
4309
|
}
|
|
4108
4310
|
installSwipeToClose() {
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
let dragging = false;
|
|
4119
|
-
let pointerId = null;
|
|
4120
|
-
const previousTouchAction = el.style.touchAction;
|
|
4121
|
-
el.style.touchAction = isVertical ? "pan-x" : "pan-y";
|
|
4122
|
-
const onDown = (e) => {
|
|
4123
|
-
if (e.button !== void 0 && e.button !== 0) return;
|
|
4124
|
-
pointerId = e.pointerId;
|
|
4125
|
-
startX = e.clientX;
|
|
4126
|
-
startY = e.clientY;
|
|
4127
|
-
startT = performance.now();
|
|
4128
|
-
tracking = true;
|
|
4129
|
-
dragging = false;
|
|
4130
|
-
};
|
|
4131
|
-
const onMove = (e) => {
|
|
4132
|
-
if (!tracking || e.pointerId !== pointerId) return;
|
|
4133
|
-
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
4134
|
-
if (!dragging) {
|
|
4135
|
-
if (Math.abs(delta) < SLOP) return;
|
|
4136
|
-
dragging = true;
|
|
4137
|
-
el.style.transition = "none";
|
|
4138
|
-
try {
|
|
4139
|
-
el.setPointerCapture(e.pointerId);
|
|
4140
|
-
} catch {
|
|
4141
|
-
}
|
|
4142
|
-
}
|
|
4143
|
-
const offset = Math.max(0, sign * delta);
|
|
4144
|
-
el.style.transform = isVertical ? `translate3d(0, ${sign * offset}px, 0)` : `translate3d(${sign * offset}px, 0, 0)`;
|
|
4145
|
-
};
|
|
4146
|
-
const finish = (e) => {
|
|
4147
|
-
if (!tracking || e.pointerId !== pointerId) return;
|
|
4148
|
-
tracking = false;
|
|
4149
|
-
pointerId = null;
|
|
4150
|
-
if (!dragging) return;
|
|
4151
|
-
dragging = false;
|
|
4152
|
-
const dt = performance.now() - startT || 1;
|
|
4153
|
-
const delta = isVertical ? e.clientY - startY : e.clientX - startX;
|
|
4154
|
-
const offset = Math.max(0, sign * delta);
|
|
4155
|
-
const velocity = sign * delta / dt;
|
|
4156
|
-
const size = isVertical ? el.offsetHeight : el.offsetWidth;
|
|
4157
|
-
const past = offset > size * this.swipeThreshold || velocity > this.swipeVelocityThreshold;
|
|
4158
|
-
el.style.transition = `transform ${this.effectiveDuration()}ms ${this.exitEasing}`;
|
|
4159
|
-
if (past) {
|
|
4160
|
-
void this.close("swipe");
|
|
4161
|
-
} else {
|
|
4162
|
-
el.style.transform = openTransformFor(this.enterAnimation);
|
|
4163
|
-
}
|
|
4164
|
-
};
|
|
4165
|
-
el.addEventListener("pointerdown", onDown);
|
|
4166
|
-
el.addEventListener("pointermove", onMove);
|
|
4167
|
-
el.addEventListener("pointerup", finish);
|
|
4168
|
-
el.addEventListener("pointercancel", finish);
|
|
4169
|
-
return () => {
|
|
4170
|
-
el.style.touchAction = previousTouchAction;
|
|
4171
|
-
el.removeEventListener("pointerdown", onDown);
|
|
4172
|
-
el.removeEventListener("pointermove", onMove);
|
|
4173
|
-
el.removeEventListener("pointerup", finish);
|
|
4174
|
-
el.removeEventListener("pointercancel", finish);
|
|
4175
|
-
};
|
|
4311
|
+
return installOverlaySwipe({
|
|
4312
|
+
element: this.element,
|
|
4313
|
+
edge: this.edge,
|
|
4314
|
+
getThreshold: () => this.swipeThreshold,
|
|
4315
|
+
getVelocityThreshold: () => this.swipeVelocityThreshold,
|
|
4316
|
+
getExitTransition: () => `transform ${this.effectiveDuration()}ms ${this.exitEasing}`,
|
|
4317
|
+
getOpenTransform: () => openTransformFor(this.enterAnimation),
|
|
4318
|
+
close: () => void this.close("swipe")
|
|
4319
|
+
});
|
|
4176
4320
|
}
|
|
4177
4321
|
registerInStack() {
|
|
4178
4322
|
this.releaseStackEntry = sheetStack.push({
|