@surdeddd/bottom-sheet 0.10.0 → 0.11.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/qwik.js CHANGED
@@ -439,46 +439,198 @@ 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 runInternal = (fn) => {
457
+ internalDepth += 1;
458
+ try {
459
+ fn();
460
+ } finally {
461
+ internalDepth -= 1;
462
+ }
463
+ };
464
+ var notifyRouteChange = () => {
465
+ const snapshot = Array.from(subscribers);
466
+ for (const fn of snapshot) fn();
467
+ };
468
+ var ensureListener = () => {
469
+ if (listenerInstalled || !hasWindow()) return;
470
+ window.addEventListener("popstate", onPopState);
471
+ listenerInstalled = true;
472
+ };
473
+ var maybeTeardownListener = () => {
474
+ if (!listenerInstalled) return;
475
+ if (entries.length > 0 || subscribers.size > 0 || suppress > 0) return;
476
+ if (hasWindow()) window.removeEventListener("popstate", onPopState);
477
+ listenerInstalled = false;
478
+ };
479
+ var installPatch = () => {
480
+ if (patchInstalled || !hasHistory()) return;
481
+ origPushState = history.pushState;
482
+ origReplaceState = history.replaceState;
483
+ patchedPushState = function(...args) {
484
+ origPushState.apply(this, args);
485
+ if (internalDepth === 0) notifyRouteChange();
486
+ };
487
+ patchedReplaceState = function(...args) {
488
+ origReplaceState.apply(this, args);
489
+ if (internalDepth === 0) notifyRouteChange();
490
+ };
491
+ history.pushState = patchedPushState;
492
+ history.replaceState = patchedReplaceState;
493
+ patchInstalled = true;
494
+ };
495
+ var removePatch = () => {
496
+ if (!patchInstalled) return;
497
+ if (history.pushState === patchedPushState && origPushState) {
498
+ history.pushState = origPushState;
499
+ }
500
+ if (history.replaceState === patchedReplaceState && origReplaceState) {
501
+ history.replaceState = origReplaceState;
502
+ }
503
+ origPushState = null;
504
+ origReplaceState = null;
505
+ patchedPushState = null;
506
+ patchedReplaceState = null;
507
+ patchInstalled = false;
508
+ };
509
+ function onPopState() {
510
+ if (suppress > 0) {
511
+ suppress -= 1;
512
+ const rebrand = pendingRebrand;
513
+ pendingRebrand = null;
514
+ if (rebrand) rebrand();
515
+ maybeTeardownListener();
516
+ return;
517
+ }
518
+ if (entries.length === 0) {
519
+ notifyRouteChange();
520
+ maybeTeardownListener();
521
+ return;
522
+ }
523
+ let target = null;
524
+ let targetIdx = -1;
525
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
526
+ const entry = entries[i];
527
+ if (!entry.surface.isOpen()) continue;
528
+ if (!target) {
529
+ target = entry;
530
+ targetIdx = i;
453
531
  }
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
- }
532
+ if (entry.surface.isTop()) {
533
+ target = entry;
534
+ targetIdx = i;
535
+ break;
463
536
  }
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
- });
537
+ }
538
+ if (!target) {
539
+ const removed = entries.pop();
540
+ if (removed) removed.live = false;
541
+ maybeTeardownListener();
542
+ return;
543
+ }
544
+ target.live = false;
545
+ entries.splice(targetIdx, 1);
546
+ const settled = target;
547
+ void Promise.resolve(settled.surface.close()).then(() => {
548
+ if (settled.surface.isOpen()) restore(settled);
472
549
  });
473
- };
474
- var programmaticBack = () => {
475
- suppress += 1;
476
- try {
477
- history.back();
478
- } catch {
479
- suppress = Math.max(0, suppress - 1);
550
+ maybeTeardownListener();
551
+ }
552
+ function restore(entry) {
553
+ if (!hasWindow() || !hasHistory()) return;
554
+ entry.live = true;
555
+ runInternal(() => {
556
+ try {
557
+ history.pushState(entry.surface.markerState(), "", entry.surface.url);
558
+ } catch {
559
+ entry.live = false;
560
+ }
561
+ });
562
+ if (entry.live) {
563
+ entries.push(entry);
564
+ ensureListener();
480
565
  }
481
- };
566
+ }
567
+ function pushBackMarker(surface) {
568
+ const entry = { surface, priorUrl: void 0, live: false };
569
+ if (!hasWindow() || !hasHistory()) {
570
+ return entry;
571
+ }
572
+ entry.priorUrl = surface.url !== void 0 ? location.href : void 0;
573
+ runInternal(() => {
574
+ try {
575
+ history.pushState(surface.markerState(), "", surface.url);
576
+ entry.live = true;
577
+ } catch {
578
+ entry.live = false;
579
+ }
580
+ });
581
+ if (entry.live) {
582
+ entries.push(entry);
583
+ ensureListener();
584
+ }
585
+ return entry;
586
+ }
587
+ function popBackMarker(handle) {
588
+ if (!hasWindow() || !hasHistory()) return;
589
+ const entry = handle;
590
+ const idx = entries.indexOf(entry);
591
+ if (idx === -1 || !entry.live) return;
592
+ const last = entries.length - 1;
593
+ entry.live = false;
594
+ entries.splice(idx, 1);
595
+ if (idx !== last) {
596
+ const rebrandSurface = entries[entries.length - 1].surface;
597
+ const rebrandUrl = entry.priorUrl;
598
+ pendingRebrand = () => {
599
+ runInternal(() => {
600
+ history.replaceState(
601
+ rebrandSurface.markerState(),
602
+ "",
603
+ rebrandUrl !== void 0 ? rebrandUrl : location.href
604
+ );
605
+ });
606
+ };
607
+ }
608
+ suppress += 1;
609
+ runInternal(() => {
610
+ try {
611
+ history.back();
612
+ } catch {
613
+ suppress = Math.max(0, suppress - 1);
614
+ pendingRebrand = null;
615
+ }
616
+ });
617
+ maybeTeardownListener();
618
+ }
619
+ function subscribeRouteChange(fn) {
620
+ if (!hasWindow() || !hasHistory()) return () => {
621
+ };
622
+ subscribers.add(fn);
623
+ if (subscribers.size === 1) installPatch();
624
+ ensureListener();
625
+ return () => {
626
+ if (!subscribers.has(fn)) return;
627
+ subscribers.delete(fn);
628
+ if (subscribers.size === 0) removePatch();
629
+ maybeTeardownListener();
630
+ };
631
+ }
632
+
633
+ // src/core/features/route.ts
482
634
  function installRoute(deps) {
483
635
  if (typeof window === "undefined") {
484
636
  return () => {
@@ -488,92 +640,39 @@ function installRoute(deps) {
488
640
  return () => {
489
641
  };
490
642
  }
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
- };
643
+ let handle = null;
519
644
  const onOpen = () => {
520
- if (closer) return;
521
- const self = {
645
+ if (handle) return;
646
+ handle = pushBackMarker({
522
647
  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();
648
+ isTop: deps.isTopSheet,
649
+ close: deps.close,
650
+ markerState: () => deps.routedTo !== void 0 ? { __bsRouted: deps.sheetId } : { __bsSheet: deps.sheetId },
651
+ url: deps.routedTo
652
+ });
653
+ };
654
+ const onClose = () => {
655
+ if (!handle) return;
656
+ popBackMarker(handle);
657
+ handle = null;
537
658
  };
538
659
  const unsubscribeOpen = deps.on("open", onOpen);
539
- const unsubscribeClose = deps.on("close", teardownEntry);
660
+ const unsubscribeClose = deps.on("close", onClose);
540
661
  if (deps.getSize() > 0) onOpen();
541
662
  return () => {
542
663
  unsubscribeOpen();
543
664
  unsubscribeClose();
544
- teardownEntry();
665
+ if (handle) {
666
+ popBackMarker(handle);
667
+ handle = null;
668
+ }
545
669
  };
546
670
  }
547
671
  function installRouteChange(deps) {
548
- if (typeof window === "undefined" || typeof history === "undefined") {
549
- return () => {
550
- };
551
- }
552
- const onChange = () => {
672
+ return subscribeRouteChange(() => {
553
673
  if (deps.isDestroyed() || deps.getSize() <= 0) return;
554
674
  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
- };
675
+ });
577
676
  }
578
677
 
579
678
  // src/core/features/content-swipe.ts
@@ -2426,7 +2525,7 @@ var matchesRange = (def, progress) => {
2426
2525
  };
2427
2526
  function installScrimStages(deps, opts) {
2428
2527
  const doc = deps.host.ownerDocument;
2429
- const entries = opts.stages.map((def) => {
2528
+ const entries2 = opts.stages.map((def) => {
2430
2529
  const wrapper = doc.createElement("div");
2431
2530
  wrapper.className = "bs-scrim-stage";
2432
2531
  const ws = wrapper.style;
@@ -2447,9 +2546,9 @@ function installScrimStages(deps, opts) {
2447
2546
  const resolveActive = () => {
2448
2547
  const state = deps.getState();
2449
2548
  if (state.size === 0) {
2450
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? null;
2549
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? null;
2451
2550
  }
2452
- return entries.find((e) => matchesId(e.def, state.activeId)) ?? entries.find((e) => matchesRange(e.def, state.progress)) ?? null;
2551
+ return entries2.find((e) => matchesId(e.def, state.activeId)) ?? entries2.find((e) => matchesRange(e.def, state.progress)) ?? null;
2453
2552
  };
2454
2553
  const hide = (entry, animate) => {
2455
2554
  entry.inFlight?.cancel();
@@ -2498,13 +2597,13 @@ function installScrimStages(deps, opts) {
2498
2597
  deps.on("open", () => update(true)),
2499
2598
  deps.on("close", () => update(true))
2500
2599
  ];
2501
- if (entries.some((e) => e.def.forRange)) {
2600
+ if (entries2.some((e) => e.def.forRange)) {
2502
2601
  offs.push(deps.on("progress", () => update(true)));
2503
2602
  }
2504
2603
  update(false);
2505
2604
  return () => {
2506
2605
  offs.forEach((off) => off());
2507
- for (const entry of entries) {
2606
+ for (const entry of entries2) {
2508
2607
  entry.inFlight?.cancel();
2509
2608
  entry.inFlight = null;
2510
2609
  if (entry.wrapper.parentNode) {
@@ -2763,8 +2862,8 @@ var BottomSheetEngine = class {
2763
2862
  this.attach();
2764
2863
  this.registerInStack();
2765
2864
  if (this.snaps.getMaxAxisSize() === 0 && typeof IntersectionObserver !== "undefined" && typeof document !== "undefined") {
2766
- const io = new IntersectionObserver((entries) => {
2767
- for (const entry of entries) {
2865
+ const io = new IntersectionObserver((entries2) => {
2866
+ for (const entry of entries2) {
2768
2867
  if (!entry.isIntersecting) continue;
2769
2868
  if (this.destroyed) return;
2770
2869
  this.snaps.recompute();
@@ -3481,9 +3580,9 @@ var BottomSheetEngine = class {
3481
3580
  return;
3482
3581
  }
3483
3582
  if (this.emitBeforeSnap(target, previousId)) {
3484
- const restore = this.snaps.findById(previousId);
3485
- if (restore) {
3486
- void this.animation.animateTo(restore.size, 0);
3583
+ const restore2 = this.snaps.findById(previousId);
3584
+ if (restore2) {
3585
+ void this.animation.animateTo(restore2.size, 0);
3487
3586
  }
3488
3587
  return;
3489
3588
  }