LouisMazel/maz-ui

View on GitHub
packages/lib/modules/composables/use-window-size.ts

Summary

Maintainability
A
1 hr
Test Coverage
F
47%
import { onMounted, onUnmounted, ref } from 'vue'
import { isClient } from './../helpers/is-client'

export interface UseWindowSizeOptions {
  /**
   * The window object to use
   * @default window - in browser, undefined in SSR
   */
  internalWindow?: Window | undefined
  /**
   * Initial width of the window (useful in SSR)
   * @default Number.POSITIVE_INFINITY
   */
  initialWidth?: number
  /**
   * Initial height of the window (useful in SSR)
   * @default Number.POSITIVE_INFINITY
   */
  initialHeight?: number
  /**
   * Listen to window `orientationchange` event
   *
   * @default true
   */
  listenOrientation?: boolean

  /**
   * Whether the scrollbar should be included in the width and height
   * @default true
   */
  includeScrollbar?: boolean
}

export function useWindowSize(options: UseWindowSizeOptions = {}) {
  const {
    internalWindow = isClient() ? window : undefined,
    initialWidth = Number.POSITIVE_INFINITY,
    initialHeight = Number.POSITIVE_INFINITY,
    includeScrollbar = true,
  } = options

  const width = ref(initialWidth)
  const height = ref(initialHeight)

  function update() {
    if (internalWindow) {
      if (includeScrollbar) {
        width.value = internalWindow.innerWidth
        height.value = internalWindow.innerHeight
      } else {
        width.value = internalWindow.document.documentElement.clientWidth
        height.value = internalWindow.document.documentElement.clientHeight
      }
    }
  }

  update()

  onMounted(() => {
    if (internalWindow) {
      window.addEventListener('resize', update, { passive: true })
    }
  })

  onUnmounted(() => {
    if (internalWindow) {
      window.removeEventListener('resize', update)
    }
  })

  return { width, height }
}