|
@@ -0,0 +1,48 @@
|
|
|
+import { getScrollbarWidth } from '@vben-core/shared/utils';
|
|
|
+
|
|
|
+import {
|
|
|
+ useScrollLock as _useScrollLock,
|
|
|
+ tryOnBeforeMount,
|
|
|
+ tryOnBeforeUnmount,
|
|
|
+} from '@vueuse/core';
|
|
|
+
|
|
|
+export const SCROLL_FIXED_CLASS = `_scroll__fixed_`;
|
|
|
+
|
|
|
+export function useScrollLock() {
|
|
|
+ const isLocked = _useScrollLock(document.body);
|
|
|
+ const scrollbarWidth = getScrollbarWidth();
|
|
|
+
|
|
|
+ tryOnBeforeMount(() => {
|
|
|
+ document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
|
+
|
|
|
+ const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
|
|
|
+ `.${SCROLL_FIXED_CLASS}`,
|
|
|
+ );
|
|
|
+ const nodes = [...layoutFixedNodes];
|
|
|
+ if (nodes.length > 0) {
|
|
|
+ nodes.forEach((node) => {
|
|
|
+ node.dataset.transition = node.style.transition;
|
|
|
+ node.style.transition = 'none';
|
|
|
+ node.style.paddingRight = `${scrollbarWidth}px`;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ isLocked.value = true;
|
|
|
+ });
|
|
|
+
|
|
|
+ tryOnBeforeUnmount(() => {
|
|
|
+ isLocked.value = false;
|
|
|
+ const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
|
|
|
+ `.${SCROLL_FIXED_CLASS}`,
|
|
|
+ );
|
|
|
+ const nodes = [...layoutFixedNodes];
|
|
|
+ if (nodes.length > 0) {
|
|
|
+ nodes.forEach((node) => {
|
|
|
+ node.style.paddingRight = '';
|
|
|
+ requestAnimationFrame(() => {
|
|
|
+ node.style.transition = node.dataset.transition || '';
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ document.body.style.paddingRight = '';
|
|
|
+ });
|
|
|
+}
|