index.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { isRef, onScopeDispose, watch } from 'vue'
  2. import { computed } from '@vue/reactivity'
  3. import { isClient } from '@vueuse/core'
  4. import {
  5. addClass,
  6. getScrollBarWidth,
  7. getStyle,
  8. hasClass,
  9. removeClass,
  10. throwError,
  11. } from '@kankan-components/utils'
  12. import { useNamespace } from '../use-namespace'
  13. import type { Ref } from 'vue'
  14. /**
  15. * Hook that monitoring the ref value to lock or unlock the screen.
  16. * When the trigger became true, it assumes modal is now opened and vice versa.
  17. * @param trigger {Ref<boolean>}
  18. */
  19. export const useLockscreen = (trigger: Ref<boolean>) => {
  20. if (!isRef(trigger)) {
  21. throwError(
  22. '[useLockscreen]',
  23. 'You need to pass a ref param to this function'
  24. )
  25. }
  26. const ns = useNamespace('popup')
  27. const hiddenCls = computed(() => ns.bm('parent', 'hidden'))
  28. if (!isClient || hasClass(document.body, hiddenCls.value)) {
  29. return
  30. }
  31. let scrollBarWidth = 0
  32. let withoutHiddenClass = false
  33. let bodyWidth = '0'
  34. const cleanup = () => {
  35. setTimeout(() => {
  36. removeClass(document.body, hiddenCls.value)
  37. if (withoutHiddenClass) {
  38. document.body.style.width = bodyWidth
  39. }
  40. }, 200)
  41. }
  42. watch(trigger, (val) => {
  43. if (!val) {
  44. cleanup()
  45. return
  46. }
  47. withoutHiddenClass = !hasClass(document.body, hiddenCls.value)
  48. if (withoutHiddenClass) {
  49. bodyWidth = document.body.style.width
  50. }
  51. scrollBarWidth = getScrollBarWidth(ns.namespace.value)
  52. const bodyHasOverflow =
  53. document.documentElement.clientHeight < document.body.scrollHeight
  54. const bodyOverflowY = getStyle(document.body, 'overflowY')
  55. if (
  56. scrollBarWidth > 0 &&
  57. (bodyHasOverflow || bodyOverflowY === 'scroll') &&
  58. withoutHiddenClass
  59. ) {
  60. document.body.style.width = `calc(100% - ${scrollBarWidth}px)`
  61. }
  62. addClass(document.body, hiddenCls.value)
  63. })
  64. onScopeDispose(() => cleanup())
  65. }