UNPKG

@substrate-system/scroll-lock

Version:
8 lines (7 loc) 4.63 kB
{ "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": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uBAAAE,EAAA,wBAAAC,IAAA,eAAAC,EAAAJ,GAMA,MAAMK,EAAQ,IAAI,IAKlB,SAASC,GAAqB,CAC1B,MAAMC,EAAgB,SAAS,gBAAgB,YAC/C,OAAO,KAAK,IAAI,OAAO,WAAaA,CAAa,CACrD,CAHSC,EAAAF,EAAA,qBAST,SAASG,GAA0B,CAC/B,MAAMC,EAAU,OAAO,iBAAiB,SAAS,IAAI,EAChD,aAAa,QAAQ,KAAM,EAAE,CAClC,EAEA,OAAI,MAAMA,CAAO,GAAK,CAACA,EACZ,EAGJA,CACX,CAVSF,EAAAC,EAAA,0BAmBF,SAASE,EAAmBC,EAA4B,CAO3D,GANAP,EAAM,IAAIO,CAAS,EAMf,CAAC,SAAS,gBAAgB,UAAU,SAAS,aAAa,EAAG,CAM7D,MAAMC,EAAiBP,EAAkB,EAAIG,EAAuB,EAEpE,IAAIK,EAA2B,iBAAiB,SAAS,eAAe,EACnE,iBAGD,CAACA,GAA2BA,IAA4B,UACxDA,EAA0B,UAK1BD,EAAiB,IAMjBC,EAA0B,IAG9B,SAAS,gBAAgB,MAAM,YAC3B,uBACAA,CACJ,EACA,SAAS,gBAAgB,UAAU,IAAI,aAAa,EACpD,SAAS,gBAAgB,MAAM,YAC3B,qBACA,GAAGD,CAAc,IACrB,CACJ,CACJ,CA5CgBL,EAAAG,EAAA,qBAkDT,SAASI,EAAqBH,EAA4B,CAC7DP,EAAM,OAAOO,CAAS,EAElBP,EAAM,OAAS,IACf,SAAS,gBAAgB,UAAU,OAAO,aAAa,EACvD,SAAS,gBAAgB,MAAM,eAAe,oBAAoB,EAE1E,CAPgBG,EAAAO,EAAA", "names": ["index_exports", "__export", "lockBodyScrolling", "unlockBodyScrolling", "__toCommonJS", "locks", "getScrollbarWidth", "documentWidth", "__name", "getExistingBodyPadding", "padding", "lockBodyScrolling", "lockingEl", "scrollbarWidth", "scrollbarGutterProperty", "unlockBodyScrolling"] }