@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/solid.js CHANGED
@@ -439,46 +439,202 @@ function notifyLinkedSheets(sheets, self) {
439
439
  }
440
440
  }
441
441
 
442
- // src/core/features/route.ts
443
- var closers = [];
444
- var handlerInstalled = false;
442
+ // src/core/features/history-coordinator.ts
443
+ var entries = [];
444
+ var subscribers = /* @__PURE__ */ new Set();
445
445
  var suppress = 0;
446
- var ensureHandler = () => {
447
- if (handlerInstalled || typeof window === "undefined") return;
448
- handlerInstalled = true;
449
- window.addEventListener("popstate", () => {
450
- if (suppress > 0) {
451
- suppress -= 1;
452
- return;
446
+ var internalDepth = 0;
447
+ var pendingRebrand = null;
448
+ var listenerInstalled = false;
449
+ var patchInstalled = false;
450
+ var origPushState = null;
451
+ var origReplaceState = null;
452
+ var patchedPushState = null;
453
+ var patchedReplaceState = null;
454
+ var hasWindow = () => typeof window !== "undefined";
455
+ var hasHistory = () => typeof history !== "undefined";
456
+ var brandMarker = (surface) => ({
457
+ ...surface.markerState(),
458
+ __bs: true
459
+ });
460
+ var runInternal = (fn) => {
461
+ internalDepth += 1;
462
+ try {
463
+ fn();
464
+ } finally {
465
+ internalDepth -= 1;
466
+ }
467
+ };
468
+ var notifyRouteChange = () => {
469
+ const snapshot = Array.from(subscribers);
470
+ for (const fn of snapshot) fn();
471
+ };
472
+ var ensureListener = () => {
473
+ if (listenerInstalled || !hasWindow()) return;
474
+ window.addEventListener("popstate", onPopState);
475
+ listenerInstalled = true;
476
+ };
477
+ var maybeTeardownListener = () => {
478
+ if (!listenerInstalled) return;
479
+ if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
480
+ if (hasWindow()) window.removeEventListener("popstate", onPopState);
481
+ listenerInstalled = false;
482
+ };
483
+ var installPatch = () => {
484
+ if (patchInstalled || !hasHistory()) return;
485
+ origPushState = history.pushState;
486
+ origReplaceState = history.replaceState;
487
+ patchedPushState = function(...args) {
488
+ origPushState.apply(this, args);
489
+ if (internalDepth === 0) notifyRouteChange();
490
+ };
491
+ patchedReplaceState = function(...args) {
492
+ origReplaceState.apply(this, args);
493
+ if (internalDepth === 0) notifyRouteChange();
494
+ };
495
+ history.pushState = patchedPushState;
496
+ history.replaceState = patchedReplaceState;
497
+ patchInstalled = true;
498
+ };
499
+ var removePatch = () => {
500
+ if (!patchInstalled) return;
501
+ if (history.pushState === patchedPushState && origPushState) {
502
+ history.pushState = origPushState;
503
+ }
504
+ if (history.replaceState === patchedReplaceState && origReplaceState) {
505
+ history.replaceState = origReplaceState;
506
+ }
507
+ origPushState = null;
508
+ origReplaceState = null;
509
+ patchedPushState = null;
510
+ patchedReplaceState = null;
511
+ patchInstalled = false;
512
+ };
513
+ function onPopState() {
514
+ if (suppress > 0) {
515
+ suppress -= 1;
516
+ const rebrand = pendingRebrand;
517
+ pendingRebrand = null;
518
+ if (rebrand) rebrand();
519
+ maybeTeardownListener();
520
+ return;
521
+ }
522
+ if (entries.length === 0) {
523
+ notifyRouteChange();
524
+ maybeTeardownListener();
525
+ return;
526
+ }
527
+ let target = null;
528
+ let targetIdx = -1;
529
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
530
+ const entry = entries[i];
531
+ if (!entry.surface.isOpen()) continue;
532
+ if (!target) {
533
+ target = entry;
534
+ targetIdx = i;
453
535
  }
454
- let target = null;
455
- for (let i = closers.length - 1; i >= 0; i -= 1) {
456
- const c = closers[i];
457
- if (!c.isOpen()) continue;
458
- if (!target) target = c;
459
- if (c.isTop()) {
460
- target = c;
461
- break;
462
- }
536
+ if (entry.surface.isTop()) {
537
+ target = entry;
538
+ targetIdx = i;
539
+ break;
463
540
  }
464
- if (!target) return;
465
- target.consumed = true;
466
- const idx = closers.indexOf(target);
467
- if (idx !== -1) closers.splice(idx, 1);
468
- const settled = target;
469
- void Promise.resolve(settled.close()).then(() => {
470
- if (settled.isOpen()) settled.restore();
471
- });
541
+ }
542
+ if (!target) {
543
+ const removed = entries.pop();
544
+ if (removed) removed.live = false;
545
+ maybeTeardownListener();
546
+ return;
547
+ }
548
+ target.live = false;
549
+ entries.splice(targetIdx, 1);
550
+ const settled = target;
551
+ void Promise.resolve(settled.surface.close()).then(() => {
552
+ if (settled.surface.isOpen()) restore(settled);
472
553
  });
473
- };
474
- var programmaticBack = () => {
475
- suppress += 1;
476
- try {
477
- history.back();
478
- } catch {
479
- suppress = Math.max(0, suppress - 1);
554
+ maybeTeardownListener();
555
+ }
556
+ function restore(entry) {
557
+ if (!hasWindow() || !hasHistory()) return;
558
+ entry.live = true;
559
+ runInternal(() => {
560
+ try {
561
+ history.pushState(brandMarker(entry.surface), "", entry.surface.url);
562
+ } catch {
563
+ entry.live = false;
564
+ }
565
+ });
566
+ if (entry.live) {
567
+ entries.push(entry);
568
+ ensureListener();
480
569
  }
481
- };
570
+ }
571
+ function pushBackMarker(surface) {
572
+ const entry = { surface, priorUrl: void 0, live: false };
573
+ if (!hasWindow() || !hasHistory()) {
574
+ return entry;
575
+ }
576
+ entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
577
+ runInternal(() => {
578
+ try {
579
+ history.pushState(brandMarker(surface), "", surface.url);
580
+ entry.live = true;
581
+ } catch {
582
+ entry.live = false;
583
+ }
584
+ });
585
+ if (entry.live) {
586
+ entries.push(entry);
587
+ ensureListener();
588
+ }
589
+ return entry;
590
+ }
591
+ function popBackMarker(handle) {
592
+ if (!hasWindow() || !hasHistory()) return;
593
+ const entry = handle;
594
+ const idx = entries.indexOf(entry);
595
+ if (idx === -1 || !entry.live) return;
596
+ const last = entries.length - 1;
597
+ entry.live = false;
598
+ entries.splice(idx, 1);
599
+ if (idx !== last) {
600
+ const rebrandSurface = entries[entries.length - 1].surface;
601
+ const rebrandUrl = entry.priorUrl;
602
+ pendingRebrand = () => {
603
+ runInternal(() => {
604
+ history.replaceState(
605
+ brandMarker(rebrandSurface),
606
+ "",
607
+ rebrandUrl !== void 0 ? rebrandUrl : location.href
608
+ );
609
+ });
610
+ };
611
+ }
612
+ suppress += 1;
613
+ runInternal(() => {
614
+ try {
615
+ history.back();
616
+ } catch {
617
+ suppress = Math.max(0, suppress - 1);
618
+ pendingRebrand = null;
619
+ }
620
+ });
621
+ maybeTeardownListener();
622
+ }
623
+ function subscribeRouteChange(fn) {
624
+ if (!hasWindow() || !hasHistory()) return () => {
625
+ };
626
+ subscribers.add(fn);
627
+ if (subscribers.size === 1) installPatch();
628
+ ensureListener();
629
+ return () => {
630
+ if (!subscribers.has(fn)) return;
631
+ subscribers.delete(fn);
632
+ if (subscribers.size === 0) removePatch();
633
+ maybeTeardownListener();
634
+ };
635
+ }
636
+
637
+ // src/core/features/route.ts
482
638
  function installRoute(deps) {
483
639
  if (typeof window === "undefined") {
484
640
  return () => {
@@ -488,92 +644,39 @@ function installRoute(deps) {
488
644
  return () => {
489
645
  };
490
646
  }
491
- let pushed = false;
492
- let closer = null;
493
- const teardownEntry = () => {
494
- if (closer) {
495
- const idx = closers.indexOf(closer);
496
- if (idx !== -1) closers.splice(idx, 1);
497
- }
498
- const wasConsumed = closer?.consumed ?? false;
499
- closer = null;
500
- if (pushed && !wasConsumed) {
501
- pushed = false;
502
- programmaticBack();
503
- } else {
504
- pushed = false;
505
- }
506
- };
507
- const pushEntry = () => {
508
- try {
509
- if (deps.routedTo !== void 0) {
510
- history.pushState({ __bsRouted: deps.sheetId }, "", deps.routedTo);
511
- } else {
512
- history.pushState({ __bsSheet: deps.sheetId }, "");
513
- }
514
- pushed = true;
515
- } catch {
516
- pushed = false;
517
- }
518
- };
647
+ let handle = null;
519
648
  const onOpen = () => {
520
- if (closer) return;
521
- const self = {
649
+ if (handle) return;
650
+ handle = pushBackMarker({
522
651
  isOpen: () => !deps.isDestroyed() && deps.getSize() > 0,
523
- isTop: () => deps.isTopSheet(),
524
- close: () => deps.close(),
525
- restore: () => {
526
- if (deps.isDestroyed() || closer !== self) return;
527
- self.consumed = false;
528
- if (!closers.includes(self)) closers.push(self);
529
- pushEntry();
530
- },
531
- consumed: false
532
- };
533
- closer = self;
534
- ensureHandler();
535
- closers.push(self);
536
- pushEntry();
652
+ isTop: deps.isTopSheet,
653
+ close: deps.close,
654
+ markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
655
+ url: deps.routedTo
656
+ });
657
+ };
658
+ const onClose = () => {
659
+ if (!handle) return;
660
+ popBackMarker(handle);
661
+ handle = null;
537
662
  };
538
663
  const unsubscribeOpen = deps.on("open", onOpen);
539
- const unsubscribeClose = deps.on("close", teardownEntry);
664
+ const unsubscribeClose = deps.on("close", onClose);
540
665
  if (deps.getSize() > 0) onOpen();
541
666
  return () => {
542
667
  unsubscribeOpen();
543
668
  unsubscribeClose();
544
- teardownEntry();
669
+ if (handle) {
670
+ popBackMarker(handle);
671
+ handle = null;
672
+ }
545
673
  };
546
674
  }
547
675
  function installRouteChange(deps) {
548
- if (typeof window === "undefined" || typeof history === "undefined") {
549
- return () => {
550
- };
551
- }
552
- const onChange = () => {
676
+ return subscribeRouteChange(() => {
553
677
  if (deps.isDestroyed() || deps.getSize() <= 0) return;
554
678
  void deps.close();
555
- };
556
- const wrap = (key) => {
557
- const original = history[key];
558
- const patched = function(...args) {
559
- original.apply(this, args);
560
- onChange();
561
- };
562
- history[key] = patched;
563
- return () => {
564
- if (history[key] === patched) {
565
- history[key] = original;
566
- }
567
- };
568
- };
569
- window.addEventListener("popstate", onChange);
570
- const restorePush = wrap("pushState");
571
- const restoreReplace = wrap("replaceState");
572
- return () => {
573
- window.removeEventListener("popstate", onChange);
574
- restorePush();
575
- restoreReplace();
576
- };
679
+ });
577
680
  }
578
681
 
579
682
  // src/core/features/content-swipe.ts
@@ -843,11 +946,15 @@ function createMaxHeightController(deps) {
843
946
 
844
947
  // src/core/features/fit-measurement.ts
845
948
  var measureSheetNatural = (element, content, vertical) => {
846
- if (!content) {
847
- return vertical ? element.offsetHeight : element.offsetWidth;
848
- }
849
949
  const axis = vertical ? "height" : "width";
850
950
  const sheetStyle = element.style;
951
+ if (!content) {
952
+ const prev = sheetStyle[axis];
953
+ sheetStyle[axis] = "auto";
954
+ const poked2 = vertical ? element.offsetHeight : element.offsetWidth;
955
+ sheetStyle[axis] = prev;
956
+ return poked2;
957
+ }
851
958
  const cs = content.style;
852
959
  const prevSheet = sheetStyle[axis];
853
960
  const prevFlex = cs.flex;
@@ -2426,7 +2533,7 @@ var matchesRange = (def, progress) => {
2426
2533
  };
2427
2534
  function installScrimStages(deps, opts) {
2428
2535
  const doc = deps.host.ownerDocument;
2429
- const entries = opts.stages.map((def) => {
2536
+ const entries2 = opts.stages.map((def) => {
2430
2537
  const wrapper = doc.createElement("div");
2431
2538
  wrapper.className = "bs-scrim-stage";
2432
2539
  const ws = wrapper.style;
@@ -2447,9 +2554,9 @@ function installScrimStages(deps, opts) {
2447
2554
  const resolveActive = () => {
2448
2555
  const state = deps.getState();
2449
2556
  if (state.size === 0) {
2450
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
2557
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? null;
2451
2558
  }
2452
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
2559
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? entries2.find((e) => matchesRange(e.def, state.progress)) ?? null;
2453
2560
  };
2454
2561
  const hide = (entry, animate) => {
2455
2562
  entry.inFlight?.cancel();
@@ -2498,13 +2605,13 @@ function installScrimStages(deps, opts) {
2498
2605
  deps.on("open", () => update(true)),
2499
2606
  deps.on("close", () => update(true))
2500
2607
  ];
2501
- if (entries.some((e) => e.def.forRange)) {
2608
+ if (entries2.some((e) => e.def.forRange)) {
2502
2609
  offs.push(deps.on("progress", () => update(true)));
2503
2610
  }
2504
2611
  update(false);
2505
2612
  return () => {
2506
2613
  offs.forEach((off) => off());
2507
- for (const entry of entries) {
2614
+ for (const entry of entries2) {
2508
2615
  entry.inFlight?.cancel();
2509
2616
  entry.inFlight = null;
2510
2617
  if (entry.wrapper.parentNode) {
@@ -2763,17 +2870,12 @@ var BottomSheetEngine = class {
2763
2870
  this.attach();
2764
2871
  this.registerInStack();
2765
2872
  if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
2766
- const io = new IntersectionObserver((entries) => {
2767
- for (const entry of entries) {
2873
+ const io = new IntersectionObserver((entries2) => {
2874
+ for (const entry of entries2) {
2768
2875
  if (!entry.isIntersecting) continue;
2769
2876
  if (this.destroyed) return;
2770
2877
  this.snaps.recompute();
2771
- const current = this.snaps.findById(this.activeId);
2772
- if (current) {
2773
- this.size = current.size;
2774
- this.applySize(this.size);
2775
- this.updateAriaSlider();
2776
- }
2878
+ this.healActiveSnap();
2777
2879
  io.disconnect();
2778
2880
  return;
2779
2881
  }
@@ -2937,6 +3039,8 @@ var BottomSheetEngine = class {
2937
3039
  const vt = document.startViewTransition(() => {
2938
3040
  this.applySize(target.size);
2939
3041
  });
3042
+ vt.ready?.catch(() => {
3043
+ });
2940
3044
  this.currentViewTransition = vt;
2941
3045
  try {
2942
3046
  await vt.finished;
@@ -3188,11 +3292,16 @@ var BottomSheetEngine = class {
3188
3292
  this.maxHeight.clampTo();
3189
3293
  this.scrim.invalidateOpacityCache();
3190
3294
  if (this.gesture?.isDragging) return;
3295
+ this.healActiveSnap();
3296
+ }
3297
+ healActiveSnap() {
3191
3298
  const current = this.snaps.findById(this.activeId);
3192
- if (current) {
3193
- this.size = current.size;
3194
- this.applySize(this.size);
3195
- this.updateAriaSlider();
3299
+ if (!current) return;
3300
+ this.size = current.size;
3301
+ this.applySize(this.size);
3302
+ this.updateAriaSlider();
3303
+ if (this.size > 0 && !this.lifecycle.isInstalled && !this.opening && !this.animation.isAnimating) {
3304
+ this.emitOpenSequence(this.activeId);
3196
3305
  }
3197
3306
  }
3198
3307
  destroy() {
@@ -3481,9 +3590,9 @@ var BottomSheetEngine = class {
3481
3590
  return;
3482
3591
  }
3483
3592
  if (this.emitBeforeSnap(target, previousId)) {
3484
- const restore = this.snaps.findById(previousId);
3485
- if (restore) {
3486
- void this.animation.animateTo(restore.size, 0);
3593
+ const restore2 = this.snaps.findById(previousId);
3594
+ if (restore2) {
3595
+ void this.animation.animateTo(restore2.size, 0);
3487
3596
  }
3488
3597
  return;
3489
3598
  }