@substrate-system/scroll-lock
Version:
Prevent scrolling
8 lines (7 loc) • 4.4 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../src/index.ts"],
"sourcesContent": ["/**\n * Originally seen in [shoelace](https://github.com/shoelace-style/shoelace/blob/next/src/internal/scroll.ts)\n *\n * Useful for modal windows.\n */\n\nconst locks = new Set()\n\n/**\n * @returns The width of the document's scrollbar\n */\nfunction getScrollbarWidth () {\n const documentWidth = document.documentElement.clientWidth\n return Math.abs(window.innerWidth - documentWidth)\n}\n\n/**\n * Used in conjunction with `scrollbarWidth` to set proper body padding in case\n * the user has padding already on the `<body>` element.\n */\nfunction getExistingBodyPadding () {\n const padding = Number(getComputedStyle(document.body)\n .paddingRight.replace(/px/, '')\n )\n\n if (isNaN(padding) || !padding) {\n return 0\n }\n\n return padding\n}\n\n/**\n * Prevents body scrolling. Keeps track of which elements requested a lock so\n * multiple levels of locking are possible\n * without premature unlocking.\n *\n * Useful for modal windows.\n */\nexport function lockBodyScrolling (lockingEl:HTMLElement):void {\n locks.add(lockingEl)\n\n // When the first lock is created, set the scroll lock size to match the\n // scrollbar's width to prevent content from\n // shifting. We only do this on the first lock because the scrollbar width\n // will measure zero after overflow is hidden.\n if (!document.documentElement.classList.contains('scroll-lock')) {\n /**\n * Scrollbar width + body padding calculation can go away once Safari\n * has scrollbar-gutter support.\n * */\n // must be measured before the `scroll-lock` class is applied\n const scrollbarWidth = getScrollbarWidth() + getExistingBodyPadding()\n\n let scrollbarGutterProperty = (getComputedStyle(document.documentElement)\n .scrollbarGutter)\n\n // default is auto, unsupported browsers is \"undefined\"\n if (!scrollbarGutterProperty || scrollbarGutterProperty === 'auto') {\n scrollbarGutterProperty = 'stable'\n }\n\n /** Sometimes the scrollbar width is 1px, even then, we assume nothing\n * is overflowing. */\n if (scrollbarWidth < 2) {\n // if there's no scrollbar, just set it to an empty string so\n // whatever the user has set gets used. This is useful if the page\n // is not overflowing and showing a scrollbar, or if the user has\n // overflow: hidden, or any other reason a scrollbar may not\n // be showing.\n scrollbarGutterProperty = ''\n }\n\n document.documentElement.style.setProperty(\n '--scroll-lock-gutter',\n scrollbarGutterProperty\n )\n document.documentElement.classList.add('scroll-lock')\n document.documentElement.style.setProperty(\n '--scroll-lock-size',\n `${scrollbarWidth}px`\n )\n }\n}\n\n/**\n * Unlocks body scrolling. Scrolling will only be unlocked once all elements\n * that requested a lock call this method.\n */\nexport function unlockBodyScrolling (lockingEl:HTMLElement):void {\n locks.delete(lockingEl)\n\n if (locks.size === 0) {\n document.documentElement.classList.remove('scroll-lock')\n document.documentElement.style.removeProperty('--scroll-lock-size')\n }\n}\n"],
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,QAAQ,oBAAI,IAAI;AAKtB,SAAS,oBAAqB;AAC1B,QAAM,gBAAgB,SAAS,gBAAgB;AAC/C,SAAO,KAAK,IAAI,OAAO,aAAa,aAAa;AACrD;AAHS;AAST,SAAS,yBAA0B;AAC/B,QAAM,UAAU;AAAA,IAAO,iBAAiB,SAAS,IAAI,EAChD,aAAa,QAAQ,MAAM,EAAE;AAAA,EAClC;AAEA,MAAI,MAAM,OAAO,KAAK,CAAC,SAAS;AAC5B,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAVS;AAmBF,SAAS,kBAAmB,WAA4B;AAC3D,QAAM,IAAI,SAAS;AAMnB,MAAI,CAAC,SAAS,gBAAgB,UAAU,SAAS,aAAa,GAAG;AAM7D,UAAM,iBAAiB,kBAAkB,IAAI,uBAAuB;AAEpE,QAAI,0BAA2B,iBAAiB,SAAS,eAAe,EACnE;AAGL,QAAI,CAAC,2BAA2B,4BAA4B,QAAQ;AAChE,gCAA0B;AAAA,IAC9B;AAIA,QAAI,iBAAiB,GAAG;AAMpB,gCAA0B;AAAA,IAC9B;AAEA,aAAS,gBAAgB,MAAM;AAAA,MAC3B;AAAA,MACA;AAAA,IACJ;AACA,aAAS,gBAAgB,UAAU,IAAI,aAAa;AACpD,aAAS,gBAAgB,MAAM;AAAA,MAC3B;AAAA,MACA,GAAG,cAAc;AAAA,IACrB;AAAA,EACJ;AACJ;AA5CgB;AAkDT,SAAS,oBAAqB,WAA4B;AAC7D,QAAM,OAAO,SAAS;AAEtB,MAAI,MAAM,SAAS,GAAG;AAClB,aAAS,gBAAgB,UAAU,OAAO,aAAa;AACvD,aAAS,gBAAgB,MAAM,eAAe,oBAAoB;AAAA,EACtE;AACJ;AAPgB;",
"names": []
}