kliping.pro
  • Docs
  • Directory
  • Colors
  • Typeset
Hooks
  • State7
  • Advanced6
  • Lifecycle16
  • Browser21
    • useActiveElement
    • useBattery
    • useClickAnyWhere
    • useClickAway
    • useClipboard
    • useDocumentVisibility
    • useElementSize
    • useEventListener
    • useFps
    • useFullscreen
    • useHash
    • useHover
    • useInViewport
    • useIsMatchMedia
    • useIsOnline
    • useMouse
    • useNetwork
    • useOs
    • useScrollLock
    • useTextSelection
    • useTitle
  • Development1
  • Third-Party4
  • Libraries4

useFullscreen

PreviousNext

Layar penuh, dengan seluruh awalan vendor yang masih dibutuhkan.

Ini composable terpanjang di registry, dan panjangnya bukan hiasan. Fullscreen API punya empat nama berbeda untuk hal yang sama, dan Safari di iOS memakai jalur yang sama sekali lain: metodenya ada di elemen <video>, bukan di document. Setiap nama yang didaftar di bawah pernah jadi satu-satunya yang bekerja di suatu peramban.

Keadaannya dibaca dari peramban lewat peristiwa, bukan disimpan sendiri saat enter() dipanggil. Itu wajib: orang bisa keluar dari layar penuh dengan menekan Escape, dan tidak ada satu pun kode kita yang tahu itu terjadi kecuali melalui fullscreenchange.

Installation ​

pnpm dlx shadcn-vue@latest add @kliping/use-fullscreen

Perlu @kliping terdaftar di components.json project Anda. Lihat cara menyiapkannya.

Ikut terpasang sendiri: is-browser, target, try-on-mounted, use-event-listener.

Salin dulu is-browser, target, try-on-mounted, use-event-listener — masing-masing memuat sumbernya di halamannya sendiri — lalu tempel berkas ini.

ts
import { getCurrentScope, onScopeDispose, readonly, ref } from 'vue'
import { isBrowser } from '@/lib/is-browser'
import { tryOnMounted } from '@/lib/try-on-mounted'
import { getTargetElement } from '@/lib/target'
import { useEventListener } from '@/composables/use-event-listener'
import type { BasicTarget } from '@/lib/target'

const EVENTS = [
  'fullscreenchange',
  'webkitfullscreenchange',
  'webkitendfullscreen',
  'mozfullscreenchange',
  'MSFullscreenChange',
]

const ENTER_METHODS = [
  'requestFullscreen',
  'webkitRequestFullscreen',
  'webkitEnterFullscreen',
  'webkitEnterFullScreen',
  'webkitRequestFullScreen',
  'mozRequestFullScreen',
  'msRequestFullscreen',
]

const EXIT_METHODS = [
  'exitFullscreen',
  'webkitExitFullscreen',
  'webkitExitFullScreen',
  'webkitCancelFullScreen',
  'mozCancelFullScreen',
  'msExitFullscreen',
]

const ACTIVE_PROPS = [
  'fullScreen',
  'webkitIsFullScreen',
  'webkitDisplayingFullscreen',
  'mozFullScreen',
  'msFullscreenElement',
]

const ELEMENT_PROPS = [
  'fullscreenElement',
  'webkitFullscreenElement',
  'mozFullScreenElement',
  'msFullscreenElement',
]

export interface UseFullscreenOptions {
  /** Exit fullscreen when the scope is disposed. Default: false. */
  autoExit?: boolean
}

export function useFullscreen(target?: BasicTarget, options: UseFullscreenOptions = {}) {
  const { autoExit = false } = options

  const isSupported = ref(false)
  const isFullscreen = ref(false)

  let enterMethod: string | undefined
  let exitMethod: string | undefined
  let activeProp: string | undefined
  let elementProp: string | undefined

  const element = (): any =>
    getTargetElement(target) ?? (isBrowser ? document.documentElement : undefined)

  const find = (candidates: string[]) => {
    const el = element()
    return candidates.find((name) => (el && name in el) || (isBrowser && name in document))
  }

  const detectSupport = () => {
    if (!isBrowser) return
    enterMethod = find(ENTER_METHODS)
    exitMethod = find(EXIT_METHODS)
    activeProp = find(ACTIVE_PROPS)
    elementProp = find(ELEMENT_PROPS)
    isSupported.value = Boolean(element() && enterMethod && exitMethod && activeProp)
  }

  const anyFullscreen = (): boolean => {
    if (!activeProp || !isBrowser) return false

    const doc = document as any
    if (doc[activeProp] != null) return Boolean(doc[activeProp])

    const el = element()
    if (el && el[activeProp] != null) return Boolean(el[activeProp])

    return false
  }

  const ownElementFullscreen = (): boolean => {
    if (!elementProp || !isBrowser) return false
    return (document as any)[elementProp] === element()
  }

  const exit = async () => {
    if (!isSupported.value || !isFullscreen.value || !exitMethod) return

    const doc = document as any
    const el = element()

    if (doc[exitMethod] != null) await doc[exitMethod]()
    else if (el?.[exitMethod] != null) await el[exitMethod]()

    isFullscreen.value = false
  }

  const enter = async () => {
    if (!isSupported.value || isFullscreen.value) return

    if (anyFullscreen()) await exit()

    const el = element()
    if (enterMethod && el?.[enterMethod] != null) {
      await el[enterMethod]()
      isFullscreen.value = true
    }
  }

  const toggle = async () => {
    await (isFullscreen.value ? exit() : enter())
  }

  const onChange = () => {
    const full = anyFullscreen()
    if (!full || ownElementFullscreen()) isFullscreen.value = full
  }

  useEventListener(EVENTS, onChange, {
    target: () => (isBrowser ? document : undefined),
    passive: true,
  })
  useEventListener(EVENTS, onChange, {
    target: () => element(),
    passive: true,
  })

  tryOnMounted(() => {
    detectSupport()
    onChange()
  })

  if (getCurrentScope()) {
    onScopeDispose(() => {
      if (autoExit) void exit()
    })
  }

  return {
    isSupported: readonly(isSupported),
    isFullscreen: readonly(isFullscreen),
    enter,
    exit,
    toggle,
  }
}

API ​

ts
export interface UseFullscreenOptions {
  /** Exit fullscreen when the scope is disposed. Default: false. */
  autoExit?: boolean
}

export function useFullscreen(
  target?: BasicTarget,
  options: UseFullscreenOptions = {},
)
PrevioususeFpsNext useHash

On This Page

InstallationAPI
Dirilis di bawah lisensi MIT. Ditulis ulang untuk Vue dari shadcn-vue, shadcn-ui-blocks, dan shadcn-hooks. Hak cipta © 2026 Kliping