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

useClipboard

PreviousNext

Menyalin ke papan klip, dengan penanda tersalin yang padam sendiri.

Menyalin ke papan klip, dengan penanda "tersalin" yang padam sendiri.

Jalur lamanya — document.execCommand('copy') lewat <textarea> tersembunyi — sengaja dipertahankan di balik opsi legacy, dan bukan karena peramban tua. navigator.clipboard hanya ada di konteks aman: HTTPS atau localhost. Tombol salin yang bekerja sempurna di mesin sendiri dan diam saja di jaringan kantor lewat HTTP adalah cacat yang membingungkan justru karena tidak melempar apa-apa.

copied padam sendiri setelah copiedDuring, dan timernya dibatalkan bersama scope.

Installation ​

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

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

Ikut terpasang sendiri: is-browser, use-event-listener.

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

ts
import { getCurrentScope, onScopeDispose, readonly, ref, toValue } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
import { isBrowser } from '@/lib/is-browser'
import { useEventListener } from '@/composables/use-event-listener'

export interface UseClipboardOptions {
  /** Track clipboard contents when the user copies elsewhere. Default: false. */
  read?: boolean
  /** Default text to copy when `copy()` is called without an argument. */
  source?: MaybeRefOrGetter<string | undefined>
  /** How long `copied` stays true, in milliseconds. Default: 1500. */
  copiedDuring?: number
  /** Fall back to `execCommand` when the Clipboard API is unavailable. Default: false. */
  legacy?: boolean
}

function copyLegacy(value: string) {
  const textarea = document.createElement('textarea')
  textarea.value = value
  textarea.style.position = 'absolute'
  textarea.style.opacity = '0'
  textarea.setAttribute('readonly', '')
  document.body.appendChild(textarea)
  textarea.select()
  document.execCommand('copy')
  textarea.remove()
}

export function useClipboard(options: UseClipboardOptions = {}) {
  const { read = false, source, copiedDuring = 1500, legacy = false } = options

  const hasApi = isBrowser && 'clipboard' in navigator
  const isSupported = ref(hasApi || legacy)

  const text = ref('')
  const copied = ref(false)

  let timer: ReturnType<typeof setTimeout> | undefined

  const readClipboard = async () => {
    if (hasApi) {
      try {
        text.value = await navigator.clipboard.readText()
        return
      } catch {}
    }
    text.value = document?.getSelection?.()?.toString() ?? ''
  }

  useEventListener(['copy', 'cut'], readClipboard, {
    target: isBrowser ? document : undefined,
    passive: true,
    enable: () => isSupported.value && read,
  })

  const copy = async (value?: string) => {
    const content = value ?? toValue(source)
    if (!isSupported.value || content == null) return

    let fallBack = !hasApi
    if (!fallBack) {
      try {
        await navigator.clipboard.writeText(content)
      } catch {
        fallBack = true
      }
    }
    if (fallBack && legacy) copyLegacy(content)

    text.value = content
    copied.value = true

    if (timer !== undefined) clearTimeout(timer)

    timer = setTimeout(() => {
      copied.value = false
      timer = undefined
    }, copiedDuring)
  }

  if (getCurrentScope()) {
    onScopeDispose(() => {
      if (timer !== undefined) clearTimeout(timer)
    })
  }

  return { isSupported: readonly(isSupported), text, copied: readonly(copied), copy }
}

API ​

ts
export interface UseClipboardOptions {
  /** Track clipboard contents when the user copies elsewhere. Default: false. */
  read?: boolean
  /** Default text to copy when `copy()` is called without an argument. */
  source?: MaybeRefOrGetter<string | undefined>
  /** How long `copied` stays true, in milliseconds. Default: 1500. */
  copiedDuring?: number
  /** Fall back to `execCommand` when the Clipboard API is unavailable. Default: false. */
  legacy?: boolean
}

export function useClipboard(options: UseClipboardOptions = {})
PrevioususeClickAwayNext useDocumentVisibility

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