@samline/drawer 2.0.4 → 2.0.5

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/index.js CHANGED
@@ -1105,7 +1105,7 @@ var require_react_development = __commonJS({
1105
1105
  var dispatcher = resolveDispatcher();
1106
1106
  return dispatcher.useReducer(reducer, initialArg, init);
1107
1107
  }
1108
- function useRef10(initialValue) {
1108
+ function useRef11(initialValue) {
1109
1109
  var dispatcher = resolveDispatcher();
1110
1110
  return dispatcher.useRef(initialValue);
1111
1111
  }
@@ -1899,7 +1899,7 @@ var require_react_development = __commonJS({
1899
1899
  exports.useLayoutEffect = useLayoutEffect5;
1900
1900
  exports.useMemo = useMemo6;
1901
1901
  exports.useReducer = useReducer3;
1902
- exports.useRef = useRef10;
1902
+ exports.useRef = useRef11;
1903
1903
  exports.useState = useState10;
1904
1904
  exports.useSyncExternalStore = useSyncExternalStore;
1905
1905
  exports.useTransition = useTransition;
@@ -26987,25 +26987,34 @@ var nonTextInputTypes = /* @__PURE__ */ new Set([
26987
26987
  "submit",
26988
26988
  "reset"
26989
26989
  ]);
26990
- var preventScrollCount = 0;
26991
- var restore;
26990
+ var activePreventScrollLocks = /* @__PURE__ */ new Set();
26991
+ var activePreventScrollRestore = null;
26992
+ function acquirePreventScrollLock(lockId) {
26993
+ activePreventScrollLocks.add(lockId);
26994
+ if (activePreventScrollLocks.size === 1 && isIOS()) {
26995
+ activePreventScrollRestore = preventScrollMobileSafari();
26996
+ }
26997
+ }
26998
+ function releasePreventScrollLock(lockId) {
26999
+ activePreventScrollLocks.delete(lockId);
27000
+ if (activePreventScrollLocks.size === 0) {
27001
+ activePreventScrollRestore?.();
27002
+ activePreventScrollRestore = null;
27003
+ }
27004
+ }
26992
27005
  function usePreventScroll(options = {}) {
26993
27006
  let { isDisabled } = options;
27007
+ const lockIdRef = (0, import_react3.useRef)();
27008
+ if (!lockIdRef.current) {
27009
+ lockIdRef.current = /* @__PURE__ */ Symbol("drawer-prevent-scroll-lock");
27010
+ }
26994
27011
  useIsomorphicLayoutEffect2(() => {
26995
27012
  if (isDisabled) {
26996
27013
  return;
26997
27014
  }
26998
- preventScrollCount++;
26999
- if (preventScrollCount === 1) {
27000
- if (isIOS()) {
27001
- restore = preventScrollMobileSafari();
27002
- }
27003
- }
27015
+ acquirePreventScrollLock(lockIdRef.current);
27004
27016
  return () => {
27005
- preventScrollCount--;
27006
- if (preventScrollCount === 0) {
27007
- restore?.();
27008
- }
27017
+ releasePreventScrollLock(lockIdRef.current);
27009
27018
  };
27010
27019
  }, [isDisabled]);
27011
27020
  }
@@ -27579,12 +27588,23 @@ function useScaleBackground() {
27579
27588
  const { direction, isOpen, shouldScaleBackground, setBackgroundColorOnScale, noBodyStyles } = useDrawerContext();
27580
27589
  const timeoutIdRef = import_react6.default.useRef(null);
27581
27590
  const initialBackgroundColor = (0, import_react6.useMemo)(() => document.body.style.backgroundColor, []);
27591
+ import_react6.default.useEffect(() => {
27592
+ return () => {
27593
+ if (timeoutIdRef.current !== null) {
27594
+ window.clearTimeout(timeoutIdRef.current);
27595
+ timeoutIdRef.current = null;
27596
+ }
27597
+ };
27598
+ }, []);
27582
27599
  function getScale() {
27583
27600
  return (window.innerWidth - WINDOW_TOP_OFFSET) / window.innerWidth;
27584
27601
  }
27585
27602
  import_react6.default.useEffect(() => {
27586
27603
  if (isOpen && shouldScaleBackground) {
27587
- if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current);
27604
+ if (timeoutIdRef.current !== null) {
27605
+ clearTimeout(timeoutIdRef.current);
27606
+ timeoutIdRef.current = null;
27607
+ }
27588
27608
  const wrapper = document.querySelector("[data-drawer-wrapper]");
27589
27609
  if (!wrapper) return;
27590
27610
  chain(
@@ -27613,6 +27633,7 @@ function useScaleBackground() {
27613
27633
  } else {
27614
27634
  document.body.style.removeProperty("background");
27615
27635
  }
27636
+ timeoutIdRef.current = null;
27616
27637
  }, TRANSITIONS.DURATION * 1e3);
27617
27638
  };
27618
27639
  }
@@ -27622,6 +27643,14 @@ function useScaleBackground() {
27622
27643
  // src/use-position-fixed.ts
27623
27644
  var import_react7 = __toESM(require_react());
27624
27645
  var previousBodyPosition = null;
27646
+ var activeBodyPositionLocks = /* @__PURE__ */ new Set();
27647
+ var bodyPositionTimeoutId = null;
27648
+ function clearBodyPositionTimeout() {
27649
+ if (bodyPositionTimeoutId !== null) {
27650
+ window.clearTimeout(bodyPositionTimeoutId);
27651
+ bodyPositionTimeoutId = null;
27652
+ }
27653
+ }
27625
27654
  function usePositionFixed({
27626
27655
  isOpen,
27627
27656
  modal,
@@ -27632,8 +27661,17 @@ function usePositionFixed({
27632
27661
  }) {
27633
27662
  const [activeUrl, setActiveUrl] = import_react7.default.useState(() => typeof window !== "undefined" ? window.location.href : "");
27634
27663
  const scrollPos = import_react7.default.useRef(0);
27664
+ const lockIdRef = import_react7.default.useRef();
27665
+ if (!lockIdRef.current) {
27666
+ lockIdRef.current = /* @__PURE__ */ Symbol("drawer-body-position-lock");
27667
+ }
27635
27668
  const setPositionFixed = import_react7.default.useCallback(() => {
27636
27669
  if (!isSafari()) return;
27670
+ const lockId = lockIdRef.current;
27671
+ if (activeBodyPositionLocks.has(lockId)) {
27672
+ return;
27673
+ }
27674
+ activeBodyPositionLocks.add(lockId);
27637
27675
  if (previousBodyPosition === null && isOpen && !noBodyStyles) {
27638
27676
  previousBodyPosition = {
27639
27677
  position: document.body.style.position,
@@ -27650,7 +27688,8 @@ function usePositionFixed({
27650
27688
  right: "0px",
27651
27689
  height: "auto"
27652
27690
  });
27653
- window.setTimeout(
27691
+ clearBodyPositionTimeout();
27692
+ bodyPositionTimeoutId = window.setTimeout(
27654
27693
  () => window.requestAnimationFrame(() => {
27655
27694
  const bottomBarHeight = innerHeight - window.innerHeight;
27656
27695
  if (bottomBarHeight && scrollPos.current >= innerHeight) {
@@ -27660,10 +27699,16 @@ function usePositionFixed({
27660
27699
  300
27661
27700
  );
27662
27701
  }
27663
- }, [isOpen]);
27702
+ }, [isOpen, noBodyStyles]);
27664
27703
  const restorePositionSetting = import_react7.default.useCallback(() => {
27665
27704
  if (!isSafari()) return;
27705
+ const lockId = lockIdRef.current;
27706
+ activeBodyPositionLocks.delete(lockId);
27707
+ if (activeBodyPositionLocks.size > 0) {
27708
+ return;
27709
+ }
27666
27710
  if (previousBodyPosition !== null && !noBodyStyles) {
27711
+ clearBodyPositionTimeout();
27667
27712
  const y = -parseInt(document.body.style.top, 10);
27668
27713
  const x = -parseInt(document.body.style.left, 10);
27669
27714
  Object.assign(document.body.style, previousBodyPosition);
@@ -27676,7 +27721,7 @@ function usePositionFixed({
27676
27721
  });
27677
27722
  previousBodyPosition = null;
27678
27723
  }
27679
- }, [activeUrl]);
27724
+ }, [activeUrl, noBodyStyles, setActiveUrl]);
27680
27725
  import_react7.default.useEffect(() => {
27681
27726
  function onScroll() {
27682
27727
  scrollPos.current = window.scrollY;
@@ -27974,6 +28019,12 @@ function Root2({
27974
28019
  container,
27975
28020
  autoFocus = false
27976
28021
  }) {
28022
+ const animationEndTimeoutRef = import_react9.default.useRef(null);
28023
+ const nonModalPointerEventsRafRef = import_react9.default.useRef(null);
28024
+ const shouldAnimateRafRef = import_react9.default.useRef(null);
28025
+ const snapPointsResetTimeoutRef = import_react9.default.useRef(null);
28026
+ const justReleasedTimeoutRef = import_react9.default.useRef(null);
28027
+ const touchEndHandlerRef = import_react9.default.useRef(null);
27977
28028
  const [isOpen = false, setIsOpen] = useControllableState2({
27978
28029
  defaultProp: defaultOpen,
27979
28030
  prop: openProp,
@@ -27982,13 +28033,20 @@ function Root2({
27982
28033
  if (!o && !nested) {
27983
28034
  restorePositionSetting();
27984
28035
  }
27985
- setTimeout(() => {
28036
+ if (animationEndTimeoutRef.current !== null) {
28037
+ window.clearTimeout(animationEndTimeoutRef.current);
28038
+ }
28039
+ animationEndTimeoutRef.current = window.setTimeout(() => {
27986
28040
  onAnimationEnd?.(o);
27987
28041
  }, TRANSITIONS.DURATION * 1e3);
27988
28042
  if (o && !modal) {
27989
28043
  if (typeof window !== "undefined") {
27990
- window.requestAnimationFrame(() => {
28044
+ if (nonModalPointerEventsRafRef.current !== null) {
28045
+ window.cancelAnimationFrame(nonModalPointerEventsRafRef.current);
28046
+ }
28047
+ nonModalPointerEventsRafRef.current = window.requestAnimationFrame(() => {
27991
28048
  document.body.style.pointerEvents = "auto";
28049
+ nonModalPointerEventsRafRef.current = null;
27992
28050
  });
27993
28051
  }
27994
28052
  }
@@ -28097,7 +28155,15 @@ function Root2({
28097
28155
  setIsDragging(true);
28098
28156
  dragStartTime.current = /* @__PURE__ */ new Date();
28099
28157
  if (isIOS()) {
28100
- window.addEventListener("touchend", () => isAllowedToDrag.current = false, { once: true });
28158
+ if (touchEndHandlerRef.current) {
28159
+ window.removeEventListener("touchend", touchEndHandlerRef.current);
28160
+ }
28161
+ const handleTouchEnd = () => {
28162
+ isAllowedToDrag.current = false;
28163
+ touchEndHandlerRef.current = null;
28164
+ };
28165
+ touchEndHandlerRef.current = handleTouchEnd;
28166
+ window.addEventListener("touchend", handleTouchEnd, { once: true });
28101
28167
  }
28102
28168
  event.target.setPointerCapture(event.pointerId);
28103
28169
  pointerStart.current = isVertical(direction) ? event.pageY : event.pageX;
@@ -28204,9 +28270,15 @@ function Root2({
28204
28270
  }
28205
28271
  }
28206
28272
  import_react9.default.useEffect(() => {
28207
- window.requestAnimationFrame(() => {
28273
+ shouldAnimateRafRef.current = window.requestAnimationFrame(() => {
28208
28274
  shouldAnimate.current = true;
28209
28275
  });
28276
+ return () => {
28277
+ if (shouldAnimateRafRef.current !== null) {
28278
+ window.cancelAnimationFrame(shouldAnimateRafRef.current);
28279
+ shouldAnimateRafRef.current = null;
28280
+ }
28281
+ };
28210
28282
  }, []);
28211
28283
  import_react9.default.useEffect(() => {
28212
28284
  function onVisualViewportChange() {
@@ -28247,10 +28319,14 @@ function Root2({
28247
28319
  if (!fromWithin) {
28248
28320
  setIsOpen(false);
28249
28321
  }
28250
- setTimeout(() => {
28322
+ if (snapPointsResetTimeoutRef.current !== null) {
28323
+ window.clearTimeout(snapPointsResetTimeoutRef.current);
28324
+ }
28325
+ snapPointsResetTimeoutRef.current = window.setTimeout(() => {
28251
28326
  if (snapPoints) {
28252
28327
  setActiveSnapPoint(snapPoints[0]);
28253
28328
  }
28329
+ snapPointsResetTimeoutRef.current = null;
28254
28330
  }, TRANSITIONS.DURATION * 1e3);
28255
28331
  }
28256
28332
  function resetDrawer() {
@@ -28325,8 +28401,12 @@ function Root2({
28325
28401
  });
28326
28402
  if (releaseResult.shouldPreventFocus) {
28327
28403
  setJustReleased(true);
28328
- setTimeout(() => {
28404
+ if (justReleasedTimeoutRef.current !== null) {
28405
+ window.clearTimeout(justReleasedTimeoutRef.current);
28406
+ }
28407
+ justReleasedTimeoutRef.current = window.setTimeout(() => {
28329
28408
  setJustReleased(false);
28409
+ justReleasedTimeoutRef.current = null;
28330
28410
  }, 200);
28331
28411
  }
28332
28412
  if (releaseResult.action === "close") {
@@ -28400,11 +28480,44 @@ function Root2({
28400
28480
  });
28401
28481
  }
28402
28482
  }
28483
+ import_react9.default.useEffect(() => {
28484
+ return () => {
28485
+ if (animationEndTimeoutRef.current !== null) {
28486
+ window.clearTimeout(animationEndTimeoutRef.current);
28487
+ }
28488
+ if (nonModalPointerEventsRafRef.current !== null) {
28489
+ window.cancelAnimationFrame(nonModalPointerEventsRafRef.current);
28490
+ }
28491
+ if (snapPointsResetTimeoutRef.current !== null) {
28492
+ window.clearTimeout(snapPointsResetTimeoutRef.current);
28493
+ }
28494
+ if (justReleasedTimeoutRef.current !== null) {
28495
+ window.clearTimeout(justReleasedTimeoutRef.current);
28496
+ }
28497
+ if (nestedOpenChangeTimer.current) {
28498
+ window.clearTimeout(nestedOpenChangeTimer.current);
28499
+ }
28500
+ if (touchEndHandlerRef.current) {
28501
+ window.removeEventListener("touchend", touchEndHandlerRef.current);
28502
+ touchEndHandlerRef.current = null;
28503
+ }
28504
+ };
28505
+ }, []);
28403
28506
  import_react9.default.useEffect(() => {
28404
28507
  if (!modal) {
28405
- window.requestAnimationFrame(() => {
28508
+ if (nonModalPointerEventsRafRef.current !== null) {
28509
+ window.cancelAnimationFrame(nonModalPointerEventsRafRef.current);
28510
+ }
28511
+ nonModalPointerEventsRafRef.current = window.requestAnimationFrame(() => {
28406
28512
  document.body.style.pointerEvents = "auto";
28513
+ nonModalPointerEventsRafRef.current = null;
28407
28514
  });
28515
+ return () => {
28516
+ if (nonModalPointerEventsRafRef.current !== null) {
28517
+ window.cancelAnimationFrame(nonModalPointerEventsRafRef.current);
28518
+ nonModalPointerEventsRafRef.current = null;
28519
+ }
28520
+ };
28408
28521
  }
28409
28522
  }, [modal]);
28410
28523
  return /* @__PURE__ */ import_react9.default.createElement(
@@ -28511,15 +28624,23 @@ var Content2 = import_react9.default.forwardRef(function({ onPointerDownOutside,
28511
28624
  const pointerStartRef = import_react9.default.useRef(null);
28512
28625
  const lastKnownPointerEventRef = import_react9.default.useRef(null);
28513
28626
  const wasBeyondThePointRef = import_react9.default.useRef(false);
28627
+ const delayedSnapPointsRafRef = import_react9.default.useRef(null);
28514
28628
  const hasSnapPoints = snapPoints && snapPoints.length > 0;
28515
28629
  useScaleBackground();
28516
28630
  import_react9.default.useEffect(() => {
28517
28631
  if (hasSnapPoints) {
28518
- window.requestAnimationFrame(() => {
28632
+ delayedSnapPointsRafRef.current = window.requestAnimationFrame(() => {
28519
28633
  setDelayedSnapPoints(true);
28634
+ delayedSnapPointsRafRef.current = null;
28520
28635
  });
28521
28636
  }
28522
- }, []);
28637
+ return () => {
28638
+ if (delayedSnapPointsRafRef.current !== null) {
28639
+ window.cancelAnimationFrame(delayedSnapPointsRafRef.current);
28640
+ delayedSnapPointsRafRef.current = null;
28641
+ }
28642
+ };
28643
+ }, [hasSnapPoints]);
28523
28644
  function handleOnPointerUp(event) {
28524
28645
  pointerStartRef.current = null;
28525
28646
  wasBeyondThePointRef.current = false;
@@ -28628,13 +28749,14 @@ var Handle = import_react9.default.forwardRef(function({ preventCycle = false, c
28628
28749
  onDrag
28629
28750
  } = useDrawerContext();
28630
28751
  const closeTimeoutIdRef = import_react9.default.useRef(null);
28752
+ const cycleTimeoutIdRef = import_react9.default.useRef(null);
28631
28753
  const shouldCancelInteractionRef = import_react9.default.useRef(false);
28632
28754
  function handleStartCycle() {
28633
28755
  if (shouldCancelInteractionRef.current) {
28634
28756
  handleCancelInteraction();
28635
28757
  return;
28636
28758
  }
28637
- window.setTimeout(() => {
28759
+ cycleTimeoutIdRef.current = window.setTimeout(() => {
28638
28760
  handleCycleSnapPoints();
28639
28761
  }, DOUBLE_TAP_TIMEOUT);
28640
28762
  }
@@ -28665,9 +28787,19 @@ var Handle = import_react9.default.forwardRef(function({ preventCycle = false, c
28665
28787
  function handleCancelInteraction() {
28666
28788
  if (closeTimeoutIdRef.current) {
28667
28789
  window.clearTimeout(closeTimeoutIdRef.current);
28790
+ closeTimeoutIdRef.current = null;
28791
+ }
28792
+ if (cycleTimeoutIdRef.current) {
28793
+ window.clearTimeout(cycleTimeoutIdRef.current);
28794
+ cycleTimeoutIdRef.current = null;
28668
28795
  }
28669
28796
  shouldCancelInteractionRef.current = false;
28670
28797
  }
28798
+ import_react9.default.useEffect(() => {
28799
+ return () => {
28800
+ handleCancelInteraction();
28801
+ };
28802
+ }, []);
28671
28803
  return /* @__PURE__ */ import_react9.default.createElement(
28672
28804
  "div",
28673
28805
  {