@surdeddd/bottom-sheet 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +52 -35
  2. package/dist/{BottomSheetEngine-DzsIwD28.d.cts → BottomSheetEngine-D6oiEfZ4.d.cts} +1 -0
  3. package/dist/{BottomSheetEngine-DRjCU73e.d.ts → BottomSheetEngine-Dhy0X_e9.d.ts} +1 -0
  4. package/dist/element.cjs +250 -136
  5. package/dist/element.d.cts +1 -1
  6. package/dist/element.d.ts +1 -1
  7. package/dist/element.iife.global.js +2 -2
  8. package/dist/element.js +250 -136
  9. package/dist/index.cjs +257 -164
  10. package/dist/index.d.cts +2 -2
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +257 -164
  13. package/dist/integrations/formik.d.cts +1 -1
  14. package/dist/integrations/formik.d.ts +1 -1
  15. package/dist/integrations/react-hook-form.d.cts +1 -1
  16. package/dist/integrations/react-hook-form.d.ts +1 -1
  17. package/dist/overlay.cjs +161 -33
  18. package/dist/overlay.d.cts +1 -3
  19. package/dist/overlay.d.ts +1 -3
  20. package/dist/overlay.js +161 -33
  21. package/dist/preact.d.cts +1 -1
  22. package/dist/preact.d.ts +1 -1
  23. package/dist/qwik.cjs +240 -131
  24. package/dist/qwik.d.cts +2 -2
  25. package/dist/qwik.d.ts +2 -2
  26. package/dist/qwik.js +240 -131
  27. package/dist/react.cjs +257 -164
  28. package/dist/react.d.cts +2 -2
  29. package/dist/react.d.ts +2 -2
  30. package/dist/react.js +257 -164
  31. package/dist/solid.cjs +240 -131
  32. package/dist/solid.d.cts +1 -0
  33. package/dist/solid.d.ts +1 -0
  34. package/dist/solid.js +240 -131
  35. package/dist/solid.source.jsx +240 -131
  36. package/dist/svelte-core.cjs +240 -131
  37. package/dist/svelte-core.js +240 -131
  38. package/dist/svelte.cjs +252 -143
  39. package/dist/svelte.js +252 -143
  40. package/dist/vue.cjs +240 -131
  41. package/dist/vue.js +240 -131
  42. package/package.json +10 -8
package/dist/element.js CHANGED
@@ -502,6 +502,206 @@ var init_linked_sheets = __esm({
502
502
  }
503
503
  });
504
504
 
505
+ // src/core/features/history-coordinator.ts
506
+ function onPopState() {
507
+ if (suppress > 0) {
508
+ suppress -= 1;
509
+ const rebrand = pendingRebrand;
510
+ pendingRebrand = null;
511
+ if (rebrand) rebrand();
512
+ maybeTeardownListener();
513
+ return;
514
+ }
515
+ if (entries.length === 0) {
516
+ notifyRouteChange();
517
+ maybeTeardownListener();
518
+ return;
519
+ }
520
+ let target = null;
521
+ let targetIdx = -1;
522
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
523
+ const entry = entries[i];
524
+ if (!entry.surface.isOpen()) continue;
525
+ if (!target) {
526
+ target = entry;
527
+ targetIdx = i;
528
+ }
529
+ if (entry.surface.isTop()) {
530
+ target = entry;
531
+ targetIdx = i;
532
+ break;
533
+ }
534
+ }
535
+ if (!target) {
536
+ const removed = entries.pop();
537
+ if (removed) removed.live = false;
538
+ maybeTeardownListener();
539
+ return;
540
+ }
541
+ target.live = false;
542
+ entries.splice(targetIdx, 1);
543
+ const settled = target;
544
+ void Promise.resolve(settled.surface.close()).then(() => {
545
+ if (settled.surface.isOpen()) restore(settled);
546
+ });
547
+ maybeTeardownListener();
548
+ }
549
+ function restore(entry) {
550
+ if (!hasWindow() || !hasHistory()) return;
551
+ entry.live = true;
552
+ runInternal(() => {
553
+ try {
554
+ history.pushState(brandMarker(entry.surface), "", entry.surface.url);
555
+ } catch {
556
+ entry.live = false;
557
+ }
558
+ });
559
+ if (entry.live) {
560
+ entries.push(entry);
561
+ ensureListener();
562
+ }
563
+ }
564
+ function pushBackMarker(surface) {
565
+ const entry = { surface, priorUrl: void 0, live: false };
566
+ if (!hasWindow() || !hasHistory()) {
567
+ return entry;
568
+ }
569
+ entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
570
+ runInternal(() => {
571
+ try {
572
+ history.pushState(brandMarker(surface), "", surface.url);
573
+ entry.live = true;
574
+ } catch {
575
+ entry.live = false;
576
+ }
577
+ });
578
+ if (entry.live) {
579
+ entries.push(entry);
580
+ ensureListener();
581
+ }
582
+ return entry;
583
+ }
584
+ function popBackMarker(handle) {
585
+ if (!hasWindow() || !hasHistory()) return;
586
+ const entry = handle;
587
+ const idx = entries.indexOf(entry);
588
+ if (idx === -1 || !entry.live) return;
589
+ const last = entries.length - 1;
590
+ entry.live = false;
591
+ entries.splice(idx, 1);
592
+ if (idx !== last) {
593
+ const rebrandSurface = entries[entries.length - 1].surface;
594
+ const rebrandUrl = entry.priorUrl;
595
+ pendingRebrand = () => {
596
+ runInternal(() => {
597
+ history.replaceState(
598
+ brandMarker(rebrandSurface),
599
+ "",
600
+ rebrandUrl !== void 0 ? rebrandUrl : location.href
601
+ );
602
+ });
603
+ };
604
+ }
605
+ suppress += 1;
606
+ runInternal(() => {
607
+ try {
608
+ history.back();
609
+ } catch {
610
+ suppress = Math.max(0, suppress - 1);
611
+ pendingRebrand = null;
612
+ }
613
+ });
614
+ maybeTeardownListener();
615
+ }
616
+ function subscribeRouteChange(fn) {
617
+ if (!hasWindow() || !hasHistory()) return () => {
618
+ };
619
+ subscribers.add(fn);
620
+ if (subscribers.size === 1) installPatch();
621
+ ensureListener();
622
+ return () => {
623
+ if (!subscribers.has(fn)) return;
624
+ subscribers.delete(fn);
625
+ if (subscribers.size === 0) removePatch();
626
+ maybeTeardownListener();
627
+ };
628
+ }
629
+ var entries, subscribers, suppress, internalDepth, pendingRebrand, listenerInstalled, patchInstalled, origPushState, origReplaceState, patchedPushState, patchedReplaceState, hasWindow, hasHistory, brandMarker, runInternal, notifyRouteChange, ensureListener, maybeTeardownListener, installPatch, removePatch;
630
+ var init_history_coordinator = __esm({
631
+ "src/core/features/history-coordinator.ts"() {
632
+ entries = [];
633
+ subscribers = /* @__PURE__ */ new Set();
634
+ suppress = 0;
635
+ internalDepth = 0;
636
+ pendingRebrand = null;
637
+ listenerInstalled = false;
638
+ patchInstalled = false;
639
+ origPushState = null;
640
+ origReplaceState = null;
641
+ patchedPushState = null;
642
+ patchedReplaceState = null;
643
+ hasWindow = () => typeof window !== "undefined";
644
+ hasHistory = () => typeof history !== "undefined";
645
+ brandMarker = (surface) => ({
646
+ ...surface.markerState(),
647
+ __bs: true
648
+ });
649
+ runInternal = (fn) => {
650
+ internalDepth += 1;
651
+ try {
652
+ fn();
653
+ } finally {
654
+ internalDepth -= 1;
655
+ }
656
+ };
657
+ notifyRouteChange = () => {
658
+ const snapshot = Array.from(subscribers);
659
+ for (const fn of snapshot) fn();
660
+ };
661
+ ensureListener = () => {
662
+ if (listenerInstalled || !hasWindow()) return;
663
+ window.addEventListener("popstate", onPopState);
664
+ listenerInstalled = true;
665
+ };
666
+ maybeTeardownListener = () => {
667
+ if (!listenerInstalled) return;
668
+ if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
669
+ if (hasWindow()) window.removeEventListener("popstate", onPopState);
670
+ listenerInstalled = false;
671
+ };
672
+ installPatch = () => {
673
+ if (patchInstalled || !hasHistory()) return;
674
+ origPushState = history.pushState;
675
+ origReplaceState = history.replaceState;
676
+ patchedPushState = function(...args) {
677
+ origPushState.apply(this, args);
678
+ if (internalDepth === 0) notifyRouteChange();
679
+ };
680
+ patchedReplaceState = function(...args) {
681
+ origReplaceState.apply(this, args);
682
+ if (internalDepth === 0) notifyRouteChange();
683
+ };
684
+ history.pushState = patchedPushState;
685
+ history.replaceState = patchedReplaceState;
686
+ patchInstalled = true;
687
+ };
688
+ removePatch = () => {
689
+ if (!patchInstalled) return;
690
+ if (history.pushState === patchedPushState && origPushState) {
691
+ history.pushState = origPushState;
692
+ }
693
+ if (history.replaceState === patchedReplaceState && origReplaceState) {
694
+ history.replaceState = origReplaceState;
695
+ }
696
+ origPushState = null;
697
+ origReplaceState = null;
698
+ patchedPushState = null;
699
+ patchedReplaceState = null;
700
+ patchInstalled = false;
701
+ };
702
+ }
703
+ });
704
+
505
705
  // src/core/features/route.ts
506
706
  function installRoute(deps) {
507
707
  if (typeof window === "undefined") {
@@ -512,135 +712,43 @@ function installRoute(deps) {
512
712
  return () => {
513
713
  };
514
714
  }
515
- let pushed = false;
516
- let closer = null;
517
- const teardownEntry = () => {
518
- if (closer) {
519
- const idx = closers.indexOf(closer);
520
- if (idx !== -1) closers.splice(idx, 1);
521
- }
522
- const wasConsumed = closer?.consumed ?? false;
523
- closer = null;
524
- if (pushed && !wasConsumed) {
525
- pushed = false;
526
- programmaticBack();
527
- } else {
528
- pushed = false;
529
- }
530
- };
531
- const pushEntry = () => {
532
- try {
533
- if (deps.routedTo !== void 0) {
534
- history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
535
- } else {
536
- history.pushState({ __bsSheet: deps.sheetId }, "");
537
- }
538
- pushed = true;
539
- } catch {
540
- pushed = false;
541
- }
542
- };
715
+ let handle = null;
543
716
  const onOpen = () => {
544
- if (closer) return;
545
- const self = {
717
+ if (handle) return;
718
+ handle = pushBackMarker({
546
719
  isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
547
- isTop: () => deps.isTopSheet(),
548
- close: () => deps.close(),
549
- restore: () => {
550
- if (deps.isDestroyed() || closer !== self) return;
551
- self.consumed = false;
552
- if (!closers.includes(self)) closers.push(self);
553
- pushEntry();
554
- },
555
- consumed: false
556
- };
557
- closer = self;
558
- ensureHandler();
559
- closers.push(self);
560
- pushEntry();
720
+ isTop: deps.isTopSheet,
721
+ close: deps.close,
722
+ markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
723
+ url: deps.routedTo
724
+ });
725
+ };
726
+ const onClose = () => {
727
+ if (!handle) return;
728
+ popBackMarker(handle);
729
+ handle = null;
561
730
  };
562
731
  const unsubscribeOpen = deps.on("open", onOpen);
563
- const unsubscribeClose = deps.on("close", teardownEntry);
732
+ const unsubscribeClose = deps.on("close", onClose);
564
733
  if (deps.getSize() > 0) onOpen();
565
734
  return () => {
566
735
  unsubscribeOpen();
567
736
  unsubscribeClose();
568
- teardownEntry();
737
+ if (handle) {
738
+ popBackMarker(handle);
739
+ handle = null;
740
+ }
569
741
  };
570
742
  }
571
743
  function installRouteChange(deps) {
572
- if (typeof window === "undefined" || typeof history === "undefined") {
573
- return () => {
574
- };
575
- }
576
- const onChange = () => {
744
+ return subscribeRouteChange(() => {
577
745
  if (deps.isDestroyed() || deps.getSize() <= 0) return;
578
746
  void deps.close();
579
- };
580
- const wrap = (key) => {
581
- const original = history[key];
582
- const patched = function(...args) {
583
- original.apply(this, args);
584
- onChange();
585
- };
586
- history[key] = patched;
587
- return () => {
588
- if (history[key] === patched) {
589
- history[key] = original;
590
- }
591
- };
592
- };
593
- window.addEventListener("popstate", onChange);
594
- const restorePush = wrap("pushState");
595
- const restoreReplace = wrap("replaceState");
596
- return () => {
597
- window.removeEventListener("popstate", onChange);
598
- restorePush();
599
- restoreReplace();
600
- };
747
+ });
601
748
  }
602
- var closers, handlerInstalled, suppress, ensureHandler, programmaticBack;
603
749
  var init_route = __esm({
604
750
  "src/core/features/route.ts"() {
605
- closers = [];
606
- handlerInstalled = false;
607
- suppress = 0;
608
- ensureHandler = () => {
609
- if (handlerInstalled || typeof window === "undefined") return;
610
- handlerInstalled = true;
611
- window.addEventListener("popstate", () => {
612
- if (suppress > 0) {
613
- suppress -= 1;
614
- return;
615
- }
616
- let target = null;
617
- for (let i = closers.length - 1; i >= 0; i -= 1) {
618
- const c = closers[i];
619
- if (!c.isOpen()) continue;
620
- if (!target) target = c;
621
- if (c.isTop()) {
622
- target = c;
623
- break;
624
- }
625
- }
626
- if (!target) return;
627
- target.consumed = true;
628
- const idx = closers.indexOf(target);
629
- if (idx !== -1) closers.splice(idx, 1);
630
- const settled = target;
631
- void Promise.resolve(settled.close()).then(() => {
632
- if (settled.isOpen()) settled.restore();
633
- });
634
- });
635
- };
636
- programmaticBack = () => {
637
- suppress += 1;
638
- try {
639
- history.back();
640
- } catch {
641
- suppress = Math.max(0, suppress - 1);
642
- }
643
- };
751
+ init_history_coordinator();
644
752
  }
645
753
  });
646
754
 
@@ -940,11 +1048,15 @@ var init_fit_measurement = __esm({
940
1048
  "src/core/features/fit-measurement.ts"() {
941
1049
  init_transform();
942
1050
  measureSheetNatural = (element, content, vertical) => {
943
- if (!content) {
944
- return vertical ? element.offsetHeight : element.offsetWidth;
945
- }
946
1051
  const axis = vertical ? "height" : "width";
947
1052
  const sheetStyle = element.style;
1053
+ if (!content) {
1054
+ const prev = sheetStyle[axis];
1055
+ sheetStyle[axis] = "auto";
1056
+ const poked2 = vertical ? element.offsetHeight : element.offsetWidth;
1057
+ sheetStyle[axis] = prev;
1058
+ return poked2;
1059
+ }
948
1060
  const cs = content.style;
949
1061
  const prevSheet = sheetStyle[axis];
950
1062
  const prevFlex = cs.flex;
@@ -2638,7 +2750,7 @@ var init_sheet_anchors = __esm({
2638
2750
  // src/core/features/scrim-stages.ts
2639
2751
  function installScrimStages(deps, opts) {
2640
2752
  const doc = deps.host.ownerDocument;
2641
- const entries = opts.stages.map((def) => {
2753
+ const entries2 = opts.stages.map((def) => {
2642
2754
  const wrapper = doc.createElement("div");
2643
2755
  wrapper.className = "bs-scrim-stage";
2644
2756
  const ws = wrapper.style;
@@ -2659,9 +2771,9 @@ function installScrimStages(deps, opts) {
2659
2771
  const resolveActive = () => {
2660
2772
  const state = deps.getState();
2661
2773
  if (state.size === 0) {
2662
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
2774
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? null;
2663
2775
  }
2664
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
2776
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? entries2.find((e) => matchesRange(e.def, state.progress)) ?? null;
2665
2777
  };
2666
2778
  const hide = (entry, animate) => {
2667
2779
  entry.inFlight?.cancel();
@@ -2710,13 +2822,13 @@ function installScrimStages(deps, opts) {
2710
2822
  deps.on("open", () => update(true)),
2711
2823
  deps.on("close", () => update(true))
2712
2824
  ];
2713
- if (entries.some((e) => e.def.forRange)) {
2825
+ if (entries2.some((e) => e.def.forRange)) {
2714
2826
  offs.push(deps.on("progress", () => update(true)));
2715
2827
  }
2716
2828
  update(false);
2717
2829
  return () => {
2718
2830
  offs.forEach((off) => off());
2719
- for (const entry of entries) {
2831
+ for (const entry of entries2) {
2720
2832
  entry.inFlight?.cancel();
2721
2833
  entry.inFlight = null;
2722
2834
  if (entry.wrapper.parentNode) {
@@ -3036,17 +3148,12 @@ var init_BottomSheetEngine = __esm({
3036
3148
  this.attach();
3037
3149
  this.registerInStack();
3038
3150
  if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
3039
- const io = new IntersectionObserver((entries) => {
3040
- for (const entry of entries) {
3151
+ const io = new IntersectionObserver((entries2) => {
3152
+ for (const entry of entries2) {
3041
3153
  if (!entry.isIntersecting) continue;
3042
3154
  if (this.destroyed) return;
3043
3155
  this.snaps.recompute();
3044
- const current = this.snaps.findById(this.activeId);
3045
- if (current) {
3046
- this.size = current.size;
3047
- this.applySize(this.size);
3048
- this.updateAriaSlider();
3049
- }
3156
+ this.healActiveSnap();
3050
3157
  io.disconnect();
3051
3158
  return;
3052
3159
  }
@@ -3210,6 +3317,8 @@ var init_BottomSheetEngine = __esm({
3210
3317
  const vt = document.startViewTransition(() => {
3211
3318
  this.applySize(target.size);
3212
3319
  });
3320
+ vt.ready?.catch(() => {
3321
+ });
3213
3322
  this.currentViewTransition = vt;
3214
3323
  try {
3215
3324
  await vt.finished;
@@ -3461,11 +3570,16 @@ var init_BottomSheetEngine = __esm({
3461
3570
  this.maxHeight.clampTo();
3462
3571
  this.scrim.invalidateOpacityCache();
3463
3572
  if (this.gesture?.isDragging) return;
3573
+ this.healActiveSnap();
3574
+ }
3575
+ healActiveSnap() {
3464
3576
  const current = this.snaps.findById(this.activeId);
3465
- if (current) {
3466
- this.size = current.size;
3467
- this.applySize(this.size);
3468
- this.updateAriaSlider();
3577
+ if (!current) return;
3578
+ this.size = current.size;
3579
+ this.applySize(this.size);
3580
+ this.updateAriaSlider();
3581
+ if (this.size > 0 && !this.lifecycle.isInstalled && !this.opening && !this.animation.isAnimating) {
3582
+ this.emitOpenSequence(this.activeId);
3469
3583
  }
3470
3584
  }
3471
3585
  destroy() {
@@ -3754,9 +3868,9 @@ var init_BottomSheetEngine = __esm({
3754
3868
  return;
3755
3869
  }
3756
3870
  if (this.emitBeforeSnap(target, previousId)) {
3757
- const restore = this.snaps.findById(previousId);
3758
- if (restore) {
3759
- void this.animation.animateTo(restore.size, 0);
3871
+ const restore2 = this.snaps.findById(previousId);
3872
+ if (restore2) {
3873
+ void this.animation.animateTo(restore2.size, 0);
3760
3874
  }
3761
3875
  return;
3762
3876
  }