react-modal-sheet 2.0.0 → 2.2.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.
@@ -4,35 +4,29 @@ import { useMotionValue, useReducedMotion, useTransform, animate, motion, Animat
4
4
  import { useLayoutEffect as useLayoutEffect$1, isIOS, chain, getScrollParent } from '@react-aria/utils';
5
5
 
6
6
  function _extends() {
7
- _extends = Object.assign || function (target) {
7
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
8
8
  for (var i = 1; i < arguments.length; i++) {
9
9
  var source = arguments[i];
10
-
11
10
  for (var key in source) {
12
11
  if (Object.prototype.hasOwnProperty.call(source, key)) {
13
12
  target[key] = source[key];
14
13
  }
15
14
  }
16
15
  }
17
-
18
16
  return target;
19
17
  };
20
-
21
18
  return _extends.apply(this, arguments);
22
19
  }
23
-
24
20
  function _objectWithoutPropertiesLoose(source, excluded) {
25
21
  if (source == null) return {};
26
22
  var target = {};
27
23
  var sourceKeys = Object.keys(source);
28
24
  var key, i;
29
-
30
25
  for (i = 0; i < sourceKeys.length; i++) {
31
26
  key = sourceKeys[i];
32
27
  if (excluded.indexOf(key) >= 0) continue;
33
28
  target[key] = source[key];
34
29
  }
35
-
36
30
  return target;
37
31
  }
38
32
 
@@ -52,22 +46,18 @@ var DRAG_VELOCITY_THRESHOLD = 500;
52
46
  function getClosest(nums, goal) {
53
47
  var closest = nums[0];
54
48
  var minDifference = Math.abs(nums[0] - goal);
55
-
56
49
  for (var i = 1; i < nums.length; i++) {
57
50
  var difference = Math.abs(nums[i] - goal);
58
-
59
51
  if (difference < minDifference) {
60
52
  closest = nums[i];
61
53
  minDifference = difference;
62
54
  }
63
55
  }
64
-
65
56
  return closest;
66
57
  }
67
58
  function applyRootStyles(rootId) {
68
59
  var body = document.querySelector('body');
69
60
  var root = document.querySelector("#" + rootId);
70
-
71
61
  if (root) {
72
62
  var p = 24;
73
63
  var h = window.innerHeight;
@@ -77,7 +67,6 @@ function applyRootStyles(rootId) {
77
67
  root.style.willChange = 'transform';
78
68
  root.style.transition = 'transform 200ms ease-in-out, border-radius 200ms linear';
79
69
  root.style.transform = "translateY(calc(env(safe-area-inset-top) + " + p / 2 + "px)) scale(" + s + ")"; // prettier-ignore
80
-
81
70
  root.style.borderTopRightRadius = '10px';
82
71
  root.style.borderTopLeftRadius = '10px';
83
72
  }
@@ -85,7 +74,6 @@ function applyRootStyles(rootId) {
85
74
  function cleanupRootStyles(rootId) {
86
75
  var body = document.querySelector('body');
87
76
  var root = document.getElementById(rootId);
88
-
89
77
  function onTransitionEnd() {
90
78
  root.style.removeProperty('overflow');
91
79
  root.style.removeProperty('will-change');
@@ -93,13 +81,12 @@ function cleanupRootStyles(rootId) {
93
81
  body.style.removeProperty('background-color');
94
82
  root.removeEventListener('transitionend', onTransitionEnd);
95
83
  }
96
-
97
84
  if (root) {
98
85
  // Start animating back
99
86
  root.style.removeProperty('border-top-right-radius');
100
87
  root.style.removeProperty('border-top-left-radius');
101
- root.style.removeProperty('transform'); // Remove temp properties after animation is finished
102
-
88
+ root.style.removeProperty('transform');
89
+ // Remove temp properties after animation is finished
103
90
  root.addEventListener('transitionend', onTransitionEnd);
104
91
  }
105
92
  }
@@ -107,17 +94,14 @@ function inDescendingOrder(arr) {
107
94
  for (var i = 0; i < arr.length; i++) {
108
95
  if (arr[i + 1] > arr[i]) return false;
109
96
  }
110
-
111
97
  return true;
112
98
  }
113
99
  function validateSnapTo(_ref) {
114
100
  var snapTo = _ref.snapTo,
115
- sheetHeight = _ref.sheetHeight;
116
-
101
+ sheetHeight = _ref.sheetHeight;
117
102
  if (snapTo < 0) {
118
103
  console.warn("Snap point is out of bounds. Sheet height is " + sheetHeight + " but snap point is " + (sheetHeight + Math.abs(snapTo)) + ".");
119
104
  }
120
-
121
105
  return Math.max(Math.round(snapTo), 0);
122
106
  }
123
107
  function mergeRefs(refs) {
@@ -138,8 +122,8 @@ function isTouchDevice() {
138
122
 
139
123
  var useIsomorphicLayoutEffect = IS_SSR ? useEffect : useLayoutEffect;
140
124
  function useModalEffect(isOpen, rootId) {
141
- var prevOpen = usePrevious(isOpen); // Automatically apply the iOS modal effect to the body when sheet opens/closes
142
-
125
+ var prevOpen = usePrevious(isOpen);
126
+ // Automatically apply the iOS modal effect to the body when sheet opens/closes
143
127
  useEffect(function () {
144
128
  if (rootId && !prevOpen && isOpen) {
145
129
  applyRootStyles(rootId);
@@ -148,51 +132,47 @@ function useModalEffect(isOpen, rootId) {
148
132
  }
149
133
  }, [isOpen, prevOpen]); // eslint-disable-line
150
134
  // Make sure to cleanup modal styles on unmount
151
-
152
135
  useEffect(function () {
153
136
  return function () {
154
137
  if (rootId && isOpen) cleanupRootStyles(rootId);
155
138
  };
156
139
  }, [isOpen]); // eslint-disable-line
157
140
  }
141
+
158
142
  function useEventCallbacks(isOpen, callbacks) {
159
143
  var prevOpen = usePrevious(isOpen);
160
- var didOpen = useRef(false); // Because of AnimatePrecence we don't have access to latest isOpen value
144
+ var didOpen = useRef(false);
145
+ // Because of AnimatePrecence we don't have access to latest isOpen value
161
146
  // so we need to read and write to a ref to determine if we are
162
147
  // opening or closing the sheet
163
-
164
148
  var handleAnimationComplete = useCallback(function () {
165
149
  if (!didOpen.current) {
166
- callbacks.current.onOpenEnd == null ? void 0 : callbacks.current.onOpenEnd();
150
+ callbacks.current.onOpenEnd == null || callbacks.current.onOpenEnd();
167
151
  didOpen.current = true;
168
152
  } else {
169
- callbacks.current.onCloseEnd == null ? void 0 : callbacks.current.onCloseEnd();
153
+ callbacks.current.onCloseEnd == null || callbacks.current.onCloseEnd();
170
154
  didOpen.current = false;
171
155
  }
172
156
  }, [isOpen, prevOpen]); // eslint-disable-line
173
-
174
157
  useEffect(function () {
175
158
  if (!prevOpen && isOpen) {
176
- callbacks.current.onOpenStart == null ? void 0 : callbacks.current.onOpenStart();
159
+ callbacks.current.onOpenStart == null || callbacks.current.onOpenStart();
177
160
  } else if (!isOpen && prevOpen) {
178
- callbacks.current.onCloseStart == null ? void 0 : callbacks.current.onCloseStart();
161
+ callbacks.current.onCloseStart == null || callbacks.current.onCloseStart();
179
162
  }
180
163
  }, [isOpen, prevOpen]); // eslint-disable-line
181
-
182
164
  return {
183
165
  handleAnimationComplete: handleAnimationComplete
184
166
  };
185
167
  }
186
168
  function useWindowHeight() {
187
169
  var _React$useState = useState(0),
188
- windowHeight = _React$useState[0],
189
- setWindowHeight = _React$useState[1];
190
-
170
+ windowHeight = _React$useState[0],
171
+ setWindowHeight = _React$useState[1];
191
172
  useIsomorphicLayoutEffect(function () {
192
173
  var updateHeight = function updateHeight() {
193
174
  return setWindowHeight(window.innerHeight);
194
175
  };
195
-
196
176
  window.addEventListener('resize', updateHeight);
197
177
  updateHeight();
198
178
  return function () {
@@ -207,9 +187,9 @@ function usePrevious(state) {
207
187
  ref.current = state;
208
188
  });
209
189
  return ref.current;
210
- } // Userland version of the `useEvent` React hook:
190
+ }
191
+ // Userland version of the `useEvent` React hook:
211
192
  // RFC: https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md
212
-
213
193
  function useEvent(handler) {
214
194
  var handlerRef = useRef();
215
195
  useIsomorphicLayoutEffect(function () {
@@ -217,14 +197,31 @@ function useEvent(handler) {
217
197
  });
218
198
  return useCallback(function () {
219
199
  var fn = handlerRef.current;
220
-
221
200
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
222
201
  args[_key] = arguments[_key];
223
202
  }
224
-
225
203
  return fn == null ? void 0 : fn.apply(void 0, args);
226
204
  }, []);
227
205
  }
206
+ // This is a hacky way to fix a bug in framer-motion where the drag
207
+ // constraints are not updated when window is resized.
208
+ // https://github.com/framer/motion/issues/1659
209
+ var constraints = {
210
+ bottom: 0,
211
+ top: 0,
212
+ left: 0,
213
+ right: 0
214
+ };
215
+ function useDragConstraints() {
216
+ var constraintsRef = useRef(null);
217
+ var onMeasureDragConstraints = useCallback(function () {
218
+ return constraints;
219
+ }, []);
220
+ return {
221
+ constraintsRef: constraintsRef,
222
+ onMeasureDragConstraints: onMeasureDragConstraints
223
+ };
224
+ }
228
225
 
229
226
  var SheetContext = /*#__PURE__*/createContext(undefined);
230
227
  var useSheetContext = function useSheetContext() {
@@ -236,19 +233,15 @@ var SheetScrollerContext = /*#__PURE__*/createContext(undefined);
236
233
  function SheetScrollerContextProvider(_ref) {
237
234
  var children = _ref.children;
238
235
  var sheetContext = useSheetContext();
239
-
240
236
  var _React$useState = useState(!!sheetContext.disableDrag),
241
- disableDrag = _React$useState[0],
242
- setDisableDrag = _React$useState[1];
243
-
237
+ disableDrag = _React$useState[0],
238
+ setDisableDrag = _React$useState[1];
244
239
  function setDragEnabled() {
245
240
  if (!sheetContext.disableDrag) setDisableDrag(false);
246
241
  }
247
-
248
242
  function setDragDisabled() {
249
243
  if (!disableDrag) setDisableDrag(true);
250
244
  }
251
-
252
245
  return createElement(SheetScrollerContext.Provider, {
253
246
  value: {
254
247
  disableDrag: disableDrag,
@@ -264,11 +257,11 @@ var useSheetScrollerContext = function useSheetScrollerContext() {
264
257
  };
265
258
 
266
259
  // Source: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/overlays/src/usePreventScroll.ts
267
-
268
- var visualViewport = typeof window !== 'undefined' && window.visualViewport; // HTML input types that do not cause the software keyboard to appear.
269
-
270
- var nonTextInputTypes = /*#__PURE__*/new Set(['checkbox', 'radio', 'range', 'color', 'file', 'image', 'button', 'submit', 'reset']); // The number of active usePreventScroll calls. Used to determine whether to revert back to the original page style/scroll position
271
-
260
+ // @ts-ignore
261
+ var visualViewport = typeof window !== 'undefined' && window.visualViewport;
262
+ // HTML input types that do not cause the software keyboard to appear.
263
+ var nonTextInputTypes = /*#__PURE__*/new Set(['checkbox', 'radio', 'range', 'color', 'file', 'image', 'button', 'submit', 'reset']);
264
+ // The number of active usePreventScroll calls. Used to determine whether to revert back to the original page style/scroll position
272
265
  var preventScrollCount = 0;
273
266
  var restore;
274
267
  /**
@@ -276,21 +269,17 @@ var restore;
276
269
  * restores it on unmount. Also ensures that content does not
277
270
  * shift due to the scrollbars disappearing.
278
271
  */
279
-
280
272
  function usePreventScroll(options) {
281
273
  if (options === void 0) {
282
274
  options = {};
283
275
  }
284
-
285
276
  var _options = options,
286
- isDisabled = _options.isDisabled;
277
+ isDisabled = _options.isDisabled;
287
278
  useLayoutEffect$1(function () {
288
279
  if (isDisabled) {
289
280
  return;
290
281
  }
291
-
292
282
  preventScrollCount++;
293
-
294
283
  if (preventScrollCount === 1) {
295
284
  if (isIOS()) {
296
285
  restore = preventScrollMobileSafari();
@@ -298,21 +287,20 @@ function usePreventScroll(options) {
298
287
  restore = preventScrollStandard();
299
288
  }
300
289
  }
301
-
302
290
  return function () {
303
291
  preventScrollCount--;
304
-
305
292
  if (preventScrollCount === 0) {
306
293
  restore();
307
294
  }
308
295
  };
309
296
  }, [isDisabled]);
310
- } // For most browsers, all we need to do is set `overflow: hidden` on the root element, and
297
+ }
298
+ // For most browsers, all we need to do is set `overflow: hidden` on the root element, and
311
299
  // add some padding to prevent the page from shifting when the scrollbar is hidden.
312
-
313
300
  function preventScrollStandard() {
314
301
  return chain(setStyle(document.documentElement, 'paddingRight', window.innerWidth - document.documentElement.clientWidth + "px"), setStyle(document.documentElement, 'overflow', 'hidden'));
315
- } // Mobile Safari is a whole different beast. Even with overflow: hidden,
302
+ }
303
+ // Mobile Safari is a whole different beast. Even with overflow: hidden,
316
304
  // it still scrolls the page in many situations:
317
305
  //
318
306
  // 1. When the bottom toolbar and address bar are collapsed, page scrolling is always allowed.
@@ -338,57 +326,47 @@ function preventScrollStandard() {
338
326
  // above work or Safari will still try to scroll the page when focusing an input.
339
327
  // 6. As a last resort, handle window scroll events, and scroll back to the top. This can happen when attempting
340
328
  // to navigate to an input with the next/previous buttons that's outside a modal.
341
-
342
-
343
329
  function preventScrollMobileSafari() {
344
330
  var scrollable;
345
331
  var lastY = 0;
346
-
347
332
  var onTouchStart = function onTouchStart(e) {
348
333
  // Store the nearest scrollable parent element from the element that the user touched.
349
334
  scrollable = getScrollParent(e.target);
350
-
351
335
  if (scrollable === document.documentElement && scrollable === document.body) {
352
336
  return;
353
337
  }
354
-
355
338
  lastY = e.changedTouches[0].pageY;
356
339
  };
357
-
358
340
  var onTouchMove = function onTouchMove(e) {
359
341
  // Prevent scrolling the window.
360
342
  if (scrollable === document.documentElement || scrollable === document.body) {
361
343
  e.preventDefault();
362
344
  return;
363
- } // Prevent scrolling up when at the top and scrolling down when at the bottom
345
+ }
346
+ // Prevent scrolling up when at the top and scrolling down when at the bottom
364
347
  // of a nested scrollable area, otherwise mobile Safari will start scrolling
365
348
  // the window instead. Unfortunately, this disables bounce scrolling when at
366
349
  // the top but it's the best we can do.
367
-
368
-
369
350
  var y = e.changedTouches[0].pageY;
370
351
  var scrollTop = scrollable.scrollTop;
371
- var bottom = scrollable.scrollHeight - scrollable.clientHeight; // Fix for: https://github.com/adobe/react-spectrum/pull/3780/files
372
-
352
+ var bottom = scrollable.scrollHeight - scrollable.clientHeight;
353
+ // Fix for: https://github.com/adobe/react-spectrum/pull/3780/files
373
354
  if (bottom === 0) {
374
355
  return;
375
356
  }
376
-
377
357
  if (scrollTop <= 0 && y > lastY || scrollTop >= bottom && y < lastY) {
378
358
  e.preventDefault();
379
359
  }
380
-
381
360
  lastY = y;
382
361
  };
383
-
384
362
  var onTouchEnd = function onTouchEnd(e) {
385
- var target = e.target; // Apply this change if we're not already focused on the target element
386
-
363
+ var target = e.target;
364
+ // Apply this change if we're not already focused on the target element
387
365
  if (willOpenKeyboard(target) && target !== document.activeElement) {
388
- e.preventDefault(); // Apply a transform to trick Safari into thinking the input is at the top of the page
366
+ e.preventDefault();
367
+ // Apply a transform to trick Safari into thinking the input is at the top of the page
389
368
  // so it doesn't try to scroll it into view. When tapping on an input, this needs to
390
369
  // be done before the "focus" event, so we have to focus the element ourselves.
391
-
392
370
  target.style.transform = 'translateY(-2000px)';
393
371
  target.focus();
394
372
  requestAnimationFrame(function () {
@@ -396,10 +374,8 @@ function preventScrollMobileSafari() {
396
374
  });
397
375
  }
398
376
  };
399
-
400
377
  var onFocus = function onFocus(e) {
401
378
  var target = e.target;
402
-
403
379
  if (willOpenKeyboard(target)) {
404
380
  // Transform also needs to be applied in the focus event in cases where focus moves
405
381
  // other than tapping on an input directly, e.g. the next/previous buttons in the
@@ -407,9 +383,9 @@ function preventScrollMobileSafari() {
407
383
  // is good enough, whereas when tapping an input, it must be done before the focus event. 🤷‍♂️
408
384
  target.style.transform = 'translateY(-2000px)';
409
385
  requestAnimationFrame(function () {
410
- target.style.transform = ''; // This will have prevented the browser from scrolling the focused element into view,
386
+ target.style.transform = '';
387
+ // This will have prevented the browser from scrolling the focused element into view,
411
388
  // so we need to do this ourselves in a way that doesn't cause the whole page to scroll.
412
-
413
389
  if (visualViewport) {
414
390
  if (visualViewport.height < window.innerHeight) {
415
391
  // If the keyboard is already visible, do this after one additional frame
@@ -430,20 +406,18 @@ function preventScrollMobileSafari() {
430
406
  });
431
407
  }
432
408
  };
433
-
434
409
  var onWindowScroll = function onWindowScroll() {
435
410
  // Last resort. If the window scrolled, scroll it back to the top.
436
411
  // It should always be at the top because the body will have a negative margin (see below).
437
412
  window.scrollTo(0, 0);
438
- }; // Record the original scroll position so we can restore it.
413
+ };
414
+ // Record the original scroll position so we can restore it.
439
415
  // Then apply a negative margin to the body to offset it by the scroll position. This will
440
416
  // enable us to scroll the window to the top, which is required for the rest of this to work.
441
-
442
-
443
417
  var scrollX = window.pageXOffset;
444
418
  var scrollY = window.pageYOffset;
445
- var restoreStyles = chain(setStyle(document.documentElement, 'paddingRight', window.innerWidth - document.documentElement.clientWidth + "px"), setStyle(document.documentElement, 'overflow', 'hidden'), setStyle(document.body, 'marginTop', "-" + scrollY + "px")); // Scroll to the top. The negative margin on the body will make this appear the same.
446
-
419
+ var restoreStyles = chain(setStyle(document.documentElement, 'paddingRight', window.innerWidth - document.documentElement.clientWidth + "px"), setStyle(document.documentElement, 'overflow', 'hidden'), setStyle(document.body, 'marginTop', "-" + scrollY + "px"));
420
+ // Scroll to the top. The negative margin on the body will make this appear the same.
447
421
  window.scrollTo(0, 0);
448
422
  var removeEvents = chain(addEvent(document, 'touchstart', onTouchStart, {
449
423
  passive: false,
@@ -461,45 +435,37 @@ function preventScrollMobileSafari() {
461
435
  removeEvents();
462
436
  window.scrollTo(scrollX, scrollY);
463
437
  };
464
- } // Sets a CSS property on an element, and returns a function to revert it to the previous value.
465
-
466
-
438
+ }
439
+ // Sets a CSS property on an element, and returns a function to revert it to the previous value.
467
440
  function setStyle(element, style, value) {
468
441
  var cur = element.style[style];
469
442
  element.style[style] = value;
470
443
  return function () {
471
444
  element.style[style] = cur;
472
445
  };
473
- } // Adds an event listener to an element, and returns a function to remove it.
474
-
475
-
446
+ }
447
+ // Adds an event listener to an element, and returns a function to remove it.
476
448
  function addEvent(target, event, handler, options) {
477
449
  target.addEventListener(event, handler, options);
478
450
  return function () {
479
451
  target.removeEventListener(event, handler, options);
480
452
  };
481
453
  }
482
-
483
454
  function scrollIntoView(target) {
484
455
  var root = document.scrollingElement || document.documentElement;
485
-
486
456
  while (target && target !== root) {
487
457
  // Find the parent scrollable element and adjust the scroll position if the target is not already in view.
488
458
  var scrollable = getScrollParent(target);
489
-
490
459
  if (scrollable !== document.documentElement && scrollable !== document.body && scrollable !== target) {
491
460
  var scrollableTop = scrollable.getBoundingClientRect().top;
492
461
  var targetTop = target.getBoundingClientRect().top;
493
-
494
462
  if (targetTop > scrollableTop + target.clientHeight) {
495
463
  scrollable.scrollTop += targetTop - scrollableTop;
496
464
  }
497
465
  }
498
-
499
466
  target = scrollable.parentElement;
500
467
  }
501
468
  }
502
-
503
469
  function willOpenKeyboard(target) {
504
470
  return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
505
471
  }
@@ -569,53 +535,53 @@ var styles = {
569
535
  }
570
536
  };
571
537
 
538
+ var _excluded = ["onOpenStart", "onOpenEnd", "onClose", "onCloseStart", "onCloseEnd", "onSnap", "children", "disableScrollLocking", "isOpen", "snapPoints", "rootId", "mountPoint", "style", "detent", "initialSnap", "disableDrag", "prefersReducedMotion", "tweenConfig"];
572
539
  var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
573
540
  var onOpenStart = _ref.onOpenStart,
574
- onOpenEnd = _ref.onOpenEnd,
575
- onClose = _ref.onClose,
576
- onCloseStart = _ref.onCloseStart,
577
- onCloseEnd = _ref.onCloseEnd,
578
- onSnap = _ref.onSnap,
579
- children = _ref.children,
580
- isOpen = _ref.isOpen,
581
- snapPoints = _ref.snapPoints,
582
- rootId = _ref.rootId,
583
- mountPoint = _ref.mountPoint,
584
- style = _ref.style,
585
- _ref$detent = _ref.detent,
586
- detent = _ref$detent === void 0 ? 'full-height' : _ref$detent,
587
- _ref$initialSnap = _ref.initialSnap,
588
- initialSnap = _ref$initialSnap === void 0 ? 0 : _ref$initialSnap,
589
- _ref$disableDrag = _ref.disableDrag,
590
- disableDrag = _ref$disableDrag === void 0 ? false : _ref$disableDrag,
591
- _ref$prefersReducedMo = _ref.prefersReducedMotion,
592
- prefersReducedMotion = _ref$prefersReducedMo === void 0 ? false : _ref$prefersReducedMo,
593
- _ref$tweenConfig = _ref.tweenConfig,
594
- tweenConfig = _ref$tweenConfig === void 0 ? DEFAULT_TWEEN_CONFIG : _ref$tweenConfig,
595
- rest = _objectWithoutPropertiesLoose(_ref, ["onOpenStart", "onOpenEnd", "onClose", "onCloseStart", "onCloseEnd", "onSnap", "children", "isOpen", "snapPoints", "rootId", "mountPoint", "style", "detent", "initialSnap", "disableDrag", "prefersReducedMotion", "tweenConfig"]);
596
-
541
+ onOpenEnd = _ref.onOpenEnd,
542
+ onClose = _ref.onClose,
543
+ onCloseStart = _ref.onCloseStart,
544
+ onCloseEnd = _ref.onCloseEnd,
545
+ onSnap = _ref.onSnap,
546
+ children = _ref.children,
547
+ _ref$disableScrollLoc = _ref.disableScrollLocking,
548
+ disableScrollLocking = _ref$disableScrollLoc === void 0 ? false : _ref$disableScrollLoc,
549
+ isOpen = _ref.isOpen,
550
+ snapPoints = _ref.snapPoints,
551
+ rootId = _ref.rootId,
552
+ mountPoint = _ref.mountPoint,
553
+ style = _ref.style,
554
+ _ref$detent = _ref.detent,
555
+ detent = _ref$detent === void 0 ? 'full-height' : _ref$detent,
556
+ _ref$initialSnap = _ref.initialSnap,
557
+ initialSnap = _ref$initialSnap === void 0 ? 0 : _ref$initialSnap,
558
+ _ref$disableDrag = _ref.disableDrag,
559
+ disableDrag = _ref$disableDrag === void 0 ? false : _ref$disableDrag,
560
+ _ref$prefersReducedMo = _ref.prefersReducedMotion,
561
+ prefersReducedMotion = _ref$prefersReducedMo === void 0 ? false : _ref$prefersReducedMo,
562
+ _ref$tweenConfig = _ref.tweenConfig,
563
+ tweenConfig = _ref$tweenConfig === void 0 ? DEFAULT_TWEEN_CONFIG : _ref$tweenConfig,
564
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded);
597
565
  var sheetRef = useRef(null);
598
566
  var indicatorRotation = useMotionValue(0);
599
567
  var windowHeight = useWindowHeight();
600
568
  var shouldReduceMotion = useReducedMotion();
601
569
  var reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
602
-
603
570
  var animationOptions = _extends({
604
571
  type: 'tween'
605
- }, reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig); // NOTE: the inital value for `y` doesn't matter since it is overwritten by
572
+ }, reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig);
573
+ // NOTE: the inital value for `y` doesn't matter since it is overwritten by
606
574
  // the value driven by the `AnimatePresence` component when the sheet is opened
607
575
  // and after that it is driven by the gestures and/or snapping
608
-
609
-
610
576
  var y = useMotionValue(0);
611
577
  var zIndex = useTransform(y, function (value) {
612
578
  return value >= windowHeight ? -1 : 9999999;
613
579
  });
614
580
  var visibility = useTransform(y, function (value) {
615
581
  return value >= windowHeight ? 'hidden' : 'visible';
616
- }); // Keep the callback fns up-to-date so that they can be accessed inside
582
+ });
583
+ // Keep the callback fns up-to-date so that they can be accessed inside
617
584
  // the effect without including them to the dependencies array
618
-
619
585
  var callbacks = useRef({
620
586
  onOpenStart: onOpenStart,
621
587
  onOpenEnd: onOpenEnd,
@@ -630,7 +596,6 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
630
596
  onCloseEnd: onCloseEnd
631
597
  };
632
598
  });
633
-
634
599
  if (snapPoints) {
635
600
  // Convert negative / percentage snap points to absolute values
636
601
  snapPoints = snapPoints.map(function (point) {
@@ -638,21 +603,20 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
638
603
  if (point > 0 && point <= 1) return Math.round(point * windowHeight);
639
604
  return point < 0 ? windowHeight + point : point; // negative values
640
605
  });
606
+
641
607
  console.assert(inDescendingOrder(snapPoints) || windowHeight === 0, "Snap points need to be in descending order got: [" + snapPoints + "]");
642
608
  }
643
-
644
609
  var onDrag = useEvent(function (_, _ref2) {
645
610
  var delta = _ref2.delta;
646
611
  // Update drag indicator rotation based on drag velocity
647
612
  var velocity = y.getVelocity();
648
613
  if (velocity > 0) indicatorRotation.set(10);
649
- if (velocity < 0) indicatorRotation.set(-10); // Make sure user cannot drag beyond the top of the sheet
650
-
614
+ if (velocity < 0) indicatorRotation.set(-10);
615
+ // Make sure user cannot drag beyond the top of the sheet
651
616
  y.set(Math.max(y.get() + delta.y, 0));
652
617
  });
653
618
  var onDragEnd = useEvent(function (_, _ref3) {
654
619
  var velocity = _ref3.velocity;
655
-
656
620
  if (velocity.y > DRAG_VELOCITY_THRESHOLD) {
657
621
  // User flicked the sheet down
658
622
  onClose();
@@ -661,58 +625,49 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
661
625
  var sheetHeight = sheetEl.getBoundingClientRect().height;
662
626
  var currentY = y.get();
663
627
  var snapTo = 0;
664
-
665
628
  if (snapPoints) {
666
629
  var snapToValues = snapPoints.map(function (p) {
667
630
  return sheetHeight - Math.min(p, sheetHeight);
668
- }); // Allow snapping to the top of the sheet if detent is set to `content-height`
669
-
631
+ });
632
+ // Allow snapping to the top of the sheet if detent is set to `content-height`
670
633
  if (detent === 'content-height' && !snapToValues.includes(0)) {
671
634
  snapToValues.unshift(0);
672
- } // Get the closest snap point
673
-
674
-
635
+ }
636
+ // Get the closest snap point
675
637
  snapTo = getClosest(snapToValues, currentY);
676
638
  } else if (currentY / sheetHeight > DRAG_CLOSE_THRESHOLD) {
677
639
  // Close if dragged over enough far
678
640
  snapTo = sheetHeight;
679
641
  }
680
-
681
642
  snapTo = validateSnapTo({
682
643
  snapTo: snapTo,
683
644
  sheetHeight: sheetHeight
684
- }); // Update the spring value so that the sheet is animated to the snap point
685
-
645
+ });
646
+ // Update the spring value so that the sheet is animated to the snap point
686
647
  animate(y, snapTo, animationOptions);
687
-
688
648
  if (snapPoints && onSnap) {
689
649
  var snapValue = Math.abs(Math.round(snapPoints[0] - snapTo));
690
650
  var snapIndex = snapPoints.indexOf(getClosest(snapPoints, snapValue)); // prettier-ignore
691
-
692
651
  onSnap(snapIndex);
693
652
  }
694
-
695
653
  var roundedSheetHeight = Math.round(sheetHeight);
696
654
  var shouldClose = snapTo >= roundedSheetHeight;
697
655
  if (shouldClose) onClose();
698
- } // Reset indicator rotation after dragging
699
-
700
-
656
+ }
657
+ // Reset indicator rotation after dragging
701
658
  indicatorRotation.set(0);
702
- }); // Trigger onSnap callback when sheet is opened or closed
703
-
659
+ });
660
+ // Trigger onSnap callback when sheet is opened or closed
704
661
  useEffect(function () {
705
662
  if (!snapPoints || !onSnap) return;
706
663
  var snapIndex = isOpen ? initialSnap : snapPoints.length - 1;
707
664
  onSnap(snapIndex);
708
665
  }, [isOpen]); // eslint-disable-line
709
-
710
666
  useImperativeHandle(ref, function () {
711
667
  return {
712
668
  y: y,
713
669
  snapTo: function snapTo(snapIndex) {
714
670
  var sheetEl = sheetRef.current;
715
-
716
671
  if (snapPoints && snapPoints[snapIndex] !== undefined && sheetEl !== null) {
717
672
  var sheetHeight = sheetEl.getBoundingClientRect().height;
718
673
  var snapPoint = snapPoints[snapIndex];
@@ -727,20 +682,16 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
727
682
  }
728
683
  };
729
684
  });
730
- useModalEffect(isOpen, rootId); // Framer Motion should handle body scroll locking but it's not working
685
+ useModalEffect(isOpen, rootId);
686
+ // Framer Motion should handle body scroll locking but it's not working
731
687
  // properly on iOS. Scroll locking from React Aria seems to work much better.
732
-
733
688
  usePreventScroll({
734
- isDisabled: !isOpen
689
+ isDisabled: disableScrollLocking === true || !isOpen
735
690
  });
736
691
  var dragProps = useMemo(function () {
737
692
  var dragProps = {
738
693
  drag: 'y',
739
694
  dragElastic: 0,
740
- dragConstraints: {
741
- top: 0,
742
- bottom: 0
743
- },
744
695
  dragMomentum: false,
745
696
  dragPropagation: false,
746
697
  onDrag: onDrag,
@@ -748,7 +699,6 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
748
699
  };
749
700
  return disableDrag ? undefined : dragProps;
750
701
  }, [disableDrag]); // eslint-disable-line
751
-
752
702
  var context = {
753
703
  y: y,
754
704
  sheetRef: sheetRef,
@@ -781,30 +731,28 @@ var Sheet = /*#__PURE__*/forwardRef(function (_ref, ref) {
781
731
  return createPortal(sheet, mountPoint != null ? mountPoint : document.body);
782
732
  });
783
733
 
734
+ var _excluded$1 = ["children", "style", "className"];
784
735
  var SheetContainer = /*#__PURE__*/forwardRef(function (_ref, ref) {
785
736
  var children = _ref.children,
786
- _ref$style = _ref.style,
787
- style = _ref$style === void 0 ? {} : _ref$style,
788
- _ref$className = _ref.className,
789
- className = _ref$className === void 0 ? '' : _ref$className,
790
- rest = _objectWithoutPropertiesLoose(_ref, ["children", "style", "className"]);
791
-
737
+ _ref$style = _ref.style,
738
+ style = _ref$style === void 0 ? {} : _ref$style,
739
+ _ref$className = _ref.className,
740
+ className = _ref$className === void 0 ? '' : _ref$className,
741
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
792
742
  var _useSheetContext = useSheetContext(),
793
- y = _useSheetContext.y,
794
- isOpen = _useSheetContext.isOpen,
795
- callbacks = _useSheetContext.callbacks,
796
- snapPoints = _useSheetContext.snapPoints,
797
- _useSheetContext$init = _useSheetContext.initialSnap,
798
- initialSnap = _useSheetContext$init === void 0 ? 0 : _useSheetContext$init,
799
- sheetRef = _useSheetContext.sheetRef,
800
- windowHeight = _useSheetContext.windowHeight,
801
- detent = _useSheetContext.detent,
802
- animationOptions = _useSheetContext.animationOptions,
803
- reduceMotion = _useSheetContext.reduceMotion;
804
-
743
+ y = _useSheetContext.y,
744
+ isOpen = _useSheetContext.isOpen,
745
+ callbacks = _useSheetContext.callbacks,
746
+ snapPoints = _useSheetContext.snapPoints,
747
+ _useSheetContext$init = _useSheetContext.initialSnap,
748
+ initialSnap = _useSheetContext$init === void 0 ? 0 : _useSheetContext$init,
749
+ sheetRef = _useSheetContext.sheetRef,
750
+ windowHeight = _useSheetContext.windowHeight,
751
+ detent = _useSheetContext.detent,
752
+ animationOptions = _useSheetContext.animationOptions,
753
+ reduceMotion = _useSheetContext.reduceMotion;
805
754
  var _useEventCallbacks = useEventCallbacks(isOpen, callbacks),
806
- handleAnimationComplete = _useEventCallbacks.handleAnimationComplete;
807
-
755
+ handleAnimationComplete = _useEventCallbacks.handleAnimationComplete;
808
756
  var initialY = snapPoints ? snapPoints[0] - snapPoints[initialSnap] : 0;
809
757
  var maxSnapHeight = snapPoints ? snapPoints[0] : null;
810
758
  var height = maxSnapHeight !== null ? "min(" + maxSnapHeight + "px, " + MAX_HEIGHT + ")" : MAX_HEIGHT;
@@ -833,36 +781,43 @@ var SheetContainer = /*#__PURE__*/forwardRef(function (_ref, ref) {
833
781
  }), children);
834
782
  });
835
783
 
784
+ var _excluded$2 = ["children", "style", "disableDrag", "className"];
836
785
  var SheetContent = /*#__PURE__*/forwardRef(function (_ref, ref) {
837
786
  var children = _ref.children,
838
- style = _ref.style,
839
- disableDrag = _ref.disableDrag,
840
- _ref$className = _ref.className,
841
- className = _ref$className === void 0 ? '' : _ref$className,
842
- rest = _objectWithoutPropertiesLoose(_ref, ["children", "style", "disableDrag", "className"]);
843
-
787
+ style = _ref.style,
788
+ disableDrag = _ref.disableDrag,
789
+ _ref$className = _ref.className,
790
+ className = _ref$className === void 0 ? '' : _ref$className,
791
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
844
792
  var sheetContext = useSheetContext();
845
793
  var sheetScrollerContext = useSheetScrollerContext();
794
+ var _useDragConstraints = useDragConstraints(),
795
+ constraintsRef = _useDragConstraints.constraintsRef,
796
+ onMeasureDragConstraints = _useDragConstraints.onMeasureDragConstraints;
846
797
  var dragProps = disableDrag || sheetScrollerContext.disableDrag ? undefined : sheetContext.dragProps;
847
798
  return createElement(motion.div, Object.assign({}, rest, {
848
- ref: ref,
799
+ ref: mergeRefs([ref, constraintsRef]),
849
800
  className: "react-modal-sheet-content " + className,
850
801
  style: _extends({}, styles.content, style)
851
- }, dragProps), children);
802
+ }, dragProps, {
803
+ dragConstraints: constraintsRef,
804
+ onMeasureDragConstraints: onMeasureDragConstraints
805
+ }), children);
852
806
  });
853
807
 
808
+ var _excluded$3 = ["children", "style", "disableDrag"];
854
809
  var SheetHeader = /*#__PURE__*/forwardRef(function (_ref, ref) {
855
810
  var children = _ref.children,
856
- style = _ref.style,
857
- disableDrag = _ref.disableDrag,
858
- rest = _objectWithoutPropertiesLoose(_ref, ["children", "style", "disableDrag"]);
859
-
811
+ style = _ref.style,
812
+ disableDrag = _ref.disableDrag,
813
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$3);
860
814
  var _useSheetContext = useSheetContext(),
861
- indicatorRotation = _useSheetContext.indicatorRotation,
862
- dragProps = _useSheetContext.dragProps;
863
-
815
+ indicatorRotation = _useSheetContext.indicatorRotation,
816
+ dragProps = _useSheetContext.dragProps;
817
+ var _useDragConstraints = useDragConstraints(),
818
+ constraintsRef = _useDragConstraints.constraintsRef,
819
+ onMeasureDragConstraints = _useDragConstraints.onMeasureDragConstraints;
864
820
  var _dragProps = disableDrag ? undefined : dragProps;
865
-
866
821
  var indicator1Transform = useTransform(indicatorRotation, function (r) {
867
822
  return "translateX(2px) rotate(" + r + "deg)";
868
823
  });
@@ -870,9 +825,12 @@ var SheetHeader = /*#__PURE__*/forwardRef(function (_ref, ref) {
870
825
  return "translateX(-2px) rotate(" + -1 * r + "deg)";
871
826
  });
872
827
  return createElement(motion.div, Object.assign({}, rest, {
873
- ref: ref,
828
+ ref: mergeRefs([ref, constraintsRef]),
874
829
  style: _extends({}, styles.headerWrapper, style)
875
- }, _dragProps), children || createElement("div", {
830
+ }, _dragProps, {
831
+ dragConstraints: constraintsRef,
832
+ onMeasureDragConstraints: onMeasureDragConstraints
833
+ }), children || createElement("div", {
876
834
  className: "react-modal-sheet-header",
877
835
  style: styles.header
878
836
  }, createElement(motion.span, {
@@ -888,17 +846,16 @@ var SheetHeader = /*#__PURE__*/forwardRef(function (_ref, ref) {
888
846
  })));
889
847
  });
890
848
 
849
+ var _excluded$4 = ["style", "className"];
891
850
  var isClickable = function isClickable(props) {
892
851
  return !!props.onClick || !!props.onTap;
893
852
  };
894
-
895
853
  var SheetBackdrop = /*#__PURE__*/forwardRef(function (_ref, ref) {
896
854
  var _ref$style = _ref.style,
897
- style = _ref$style === void 0 ? {} : _ref$style,
898
- _ref$className = _ref.className,
899
- className = _ref$className === void 0 ? '' : _ref$className,
900
- rest = _objectWithoutPropertiesLoose(_ref, ["style", "className"]);
901
-
855
+ style = _ref$style === void 0 ? {} : _ref$style,
856
+ _ref$className = _ref.className,
857
+ className = _ref$className === void 0 ? '' : _ref$className,
858
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$4);
902
859
  var Comp = isClickable(rest) ? motion.button : motion.div;
903
860
  var pointerEvents = isClickable(rest) ? 'auto' : 'none';
904
861
  return createElement(Comp, Object.assign({}, rest, {
@@ -919,42 +876,37 @@ var SheetBackdrop = /*#__PURE__*/forwardRef(function (_ref, ref) {
919
876
  }));
920
877
  });
921
878
 
879
+ var _excluded$5 = ["draggableAt", "children", "style", "className"];
922
880
  var SheetScroller = /*#__PURE__*/forwardRef(function (_ref, ref) {
923
881
  var _ref$draggableAt = _ref.draggableAt,
924
- draggableAt = _ref$draggableAt === void 0 ? 'top' : _ref$draggableAt,
925
- children = _ref.children,
926
- style = _ref.style,
927
- _ref$className = _ref.className,
928
- className = _ref$className === void 0 ? '' : _ref$className,
929
- rest = _objectWithoutPropertiesLoose(_ref, ["draggableAt", "children", "style", "className"]);
930
-
882
+ draggableAt = _ref$draggableAt === void 0 ? 'top' : _ref$draggableAt,
883
+ children = _ref.children,
884
+ style = _ref.style,
885
+ _ref$className = _ref.className,
886
+ className = _ref$className === void 0 ? '' : _ref$className,
887
+ rest = _objectWithoutPropertiesLoose(_ref, _excluded$5);
931
888
  var sheetScrollerContext = useSheetScrollerContext();
932
-
933
889
  function determineDragState(element) {
934
890
  var scrollTop = element.scrollTop,
935
- scrollHeight = element.scrollHeight,
936
- clientHeight = element.clientHeight;
891
+ scrollHeight = element.scrollHeight,
892
+ clientHeight = element.clientHeight;
937
893
  var isScrollable = scrollHeight > clientHeight;
938
894
  if (!isScrollable) return;
939
895
  var isAtTop = scrollTop <= 0;
940
896
  var isAtBottom = scrollHeight - scrollTop === clientHeight;
941
897
  var shouldEnable = draggableAt === 'top' && isAtTop || draggableAt === 'bottom' && isAtBottom || draggableAt === 'both' && (isAtTop || isAtBottom);
942
-
943
898
  if (shouldEnable) {
944
899
  sheetScrollerContext.setDragEnabled();
945
900
  } else {
946
901
  sheetScrollerContext.setDragDisabled();
947
902
  }
948
903
  }
949
-
950
904
  function onScroll(e) {
951
905
  determineDragState(e.currentTarget);
952
906
  }
953
-
954
907
  function onTouchStart(e) {
955
908
  determineDragState(e.currentTarget);
956
909
  }
957
-
958
910
  var scrollProps = isTouchDevice() ? {
959
911
  onScroll: onScroll,
960
912
  onTouchStart: onTouchStart
@@ -966,6 +918,7 @@ var SheetScroller = /*#__PURE__*/forwardRef(function (_ref, ref) {
966
918
  }, scrollProps), children);
967
919
  });
968
920
 
921
+ // HACK: this is needed to get the typing to work properly...
969
922
  var _SheetCompound = Sheet;
970
923
  _SheetCompound.Container = SheetContainer;
971
924
  _SheetCompound.Header = SheetHeader;