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