var $59kHH$reactariautils = require("@react-aria/utils"); function $parcel$export(e, n, v, s) { Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); } $parcel$export(module.exports, "usePreventScroll", () => $5c2f5cd01815d369$export$ee0f7cc6afcd1c18); /* * Copyright 2020 Adobe. All rights reserved. * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ const $5c2f5cd01815d369$var$visualViewport = typeof document !== 'undefined' && window.visualViewport; // The number of active usePreventScroll calls. Used to determine whether to revert back to the original page style/scroll position let $5c2f5cd01815d369$var$preventScrollCount = 0; let $5c2f5cd01815d369$var$restore; function $5c2f5cd01815d369$export$ee0f7cc6afcd1c18(options = {}) { let { isDisabled: isDisabled } = options; (0, $59kHH$reactariautils.useLayoutEffect)(()=>{ if (isDisabled) return; $5c2f5cd01815d369$var$preventScrollCount++; if ($5c2f5cd01815d369$var$preventScrollCount === 1) { if ((0, $59kHH$reactariautils.isIOS)()) $5c2f5cd01815d369$var$restore = $5c2f5cd01815d369$var$preventScrollMobileSafari(); else $5c2f5cd01815d369$var$restore = $5c2f5cd01815d369$var$preventScrollStandard(); } return ()=>{ $5c2f5cd01815d369$var$preventScrollCount--; if ($5c2f5cd01815d369$var$preventScrollCount === 0) $5c2f5cd01815d369$var$restore(); }; }, [ isDisabled ]); } // For most browsers, all we need to do is set `overflow: hidden` on the root element, and // add some padding to prevent the page from shifting when the scrollbar is hidden. function $5c2f5cd01815d369$var$preventScrollStandard() { let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; return (0, $59kHH$reactariautils.chain)(scrollbarWidth > 0 && // Use scrollbar-gutter when supported because it also works for fixed positioned elements. ('scrollbarGutter' in document.documentElement.style ? $5c2f5cd01815d369$var$setStyle(document.documentElement, 'scrollbarGutter', 'stable') : $5c2f5cd01815d369$var$setStyle(document.documentElement, 'paddingRight', `${scrollbarWidth}px`)), $5c2f5cd01815d369$var$setStyle(document.documentElement, 'overflow', 'hidden')); } // Mobile Safari is a whole different beast. Even with overflow: hidden, // it still scrolls the page in many situations: // // 1. When the bottom toolbar and address bar are collapsed, page scrolling is always allowed. // 2. When the keyboard is visible, the viewport does not resize. Instead, the keyboard covers part of // it, so it becomes scrollable. // 3. When tapping on an input, the page always scrolls so that the input is centered in the visual viewport. // This may cause even fixed position elements to scroll off the screen. // 4. When using the next/previous buttons in the keyboard to navigate between inputs, the whole page always // scrolls, even if the input is inside a nested scrollable element that could be scrolled instead. // // In order to work around these cases, and prevent scrolling without jankiness, we do a few things: // // 1. Prevent default on `touchmove` events that are not in a scrollable element. This prevents touch scrolling // on the window. // 2. Set `overscroll-behavior: contain` on nested scrollable regions so they do not scroll the page when at // the top or bottom. Work around a bug where this does not work when the element does not actually overflow // by preventing default in a `touchmove` event. This is best effort: we can't prevent default when pinch // zooming or when an element contains text selection, which may allow scrolling in some cases. // 3. Prevent default on `touchend` events on input elements and handle focusing the element ourselves. // 4. When focus moves to an input, create an off screen input and focus that temporarily. This prevents // Safari from scrolling the page. After a small delay, focus the real input and scroll it into view // ourselves, without scrolling the whole page. function $5c2f5cd01815d369$var$preventScrollMobileSafari() { let scrollable; let allowTouchMove = false; let onTouchStart = (e)=>{ // Store the nearest scrollable parent element from the element that the user touched. let target = e.target; scrollable = (0, $59kHH$reactariautils.isScrollable)(target) ? target : (0, $59kHH$reactariautils.getScrollParent)(target, true); allowTouchMove = false; // If the target is selected, don't preventDefault in touchmove to allow user to adjust selection. let selection = target.ownerDocument.defaultView.getSelection(); if (selection && !selection.isCollapsed && selection.containsNode(target, true)) allowTouchMove = true; // If this is a focused input element with a selected range, allow user to drag the selection handles. if ('selectionStart' in target && 'selectionEnd' in target && target.selectionStart < target.selectionEnd && target.ownerDocument.activeElement === target) allowTouchMove = true; }; // Prevent scrolling up when at the top and scrolling down when at the bottom // of a nested scrollable area, otherwise mobile Safari will start scrolling // the window instead. // This must be applied before the touchstart event as of iOS 26, so inject it as a