kliping.pro
  • Docs
  • Explore
  • Builder
  • Directory
  • Colors
  • Typeset
Saved
Hooks
  • Getting Started2
  • 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
  1. Hooks
  2. Browser
  3. useClipboard

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 kliping@latest add use-clipboard

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 {
    /** Whether copying can work here (Clipboard API, or `legacy`). Reactive. */
    isSupported: readonly(isSupported),
    /** The last copied text, or the clipboard contents when `read` is on. Reactive. */
    text,
    /** `true` for `copiedDuring` ms after a copy. Reactive. */
    copied: readonly(copied),
    /** Copies `value`, or `source` when omitted. */
    copy,
  }
}

Requirements ​

RequirementValue
ProjectVue 3.5+, alias @ — disiapkan kliping init
Kliping itemsis-browser, use-event-listener
Filescomposables/use-clipboard.ts

API Reference ​

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 = {})

Parameters ​

ParameterTypeDefaultDescription
options?UseClipboardOptions{}Read tracking, default source, copied-flag duration, and legacy fallback.
options.read?boolean—Track clipboard contents when the user copies elsewhere. Default: false.
options.source?MaybeRefOrGetter<string | undefined>—Default text to copy when copy() is called without an argument.
options.copiedDuring?number—How long copied stays true, in milliseconds. Default: 1500.
options.legacy?boolean—Fall back to execCommand when the Clipboard API is unavailable. Default: false.

Returns ​

PropertyTypeDescription
isSupportedReadonly<Ref<boolean, boolean>>Whether copying can work here (Clipboard API, or legacy). Reactive.
textRef<string, string>The last copied text, or the clipboard contents when read is on. Reactive.
copiedReadonly<Ref<boolean, boolean>>true for copiedDuring ms after a copy. Reactive.
copy(value?: string) => Promise<void>Copies value, or source when omitted.

Credits ​

Berasal dari shadcn-hooks (MIT, Copyright (c) 2025 Brendan Dash). Rantai lengkapnya di Credits.

PrevioususeClickAwayNext useDocumentVisibility

On This Page

InstallationRequirementsAPI ReferenceParametersReturnsCredits

© 2026 Kliping. Free components are open source under the MIT License.

LicenseCreditsRoadmap