mirror of
https://github.com/reonokiy/blog.nokiy.net.git
synced 2025-06-17 03:56:19 +02:00
77 lines
2.1 KiB
Text
77 lines
2.1 KiB
Text
<script>
|
|
const copyIcons = {
|
|
copy:
|
|
`<svg
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
>
|
|
<path d="M6.9.8v18h14.5V.8zm12.8 16h-11v-14h11z"/>
|
|
<path d="M4.3 21.2V5.6l-1.7.5v17.1h14.3l.6-2z"/>
|
|
</svg>`,
|
|
success:
|
|
`<svg
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
>
|
|
<path d="m23.1 6.4-1.3-1.3L9.4 16.6l-6.3-5.4-1.2 1.2L9.4 20z"/>
|
|
</svg>`,
|
|
}
|
|
|
|
// Track timeout references for each button to manage icon state transitions
|
|
const activeTimeouts = new WeakMap<HTMLButtonElement, ReturnType<typeof setTimeout>>()
|
|
|
|
async function handleCopy(button: HTMLButtonElement) {
|
|
const codeElement = button.parentElement?.querySelector('pre code')
|
|
const code = codeElement?.textContent || ''
|
|
|
|
try {
|
|
await navigator.clipboard.writeText(code)
|
|
|
|
// Clear existing timeout to prevent icon state conflicts on multiple clicks
|
|
const existingTimeout = activeTimeouts.get(button)
|
|
if (existingTimeout) {
|
|
clearTimeout(existingTimeout)
|
|
}
|
|
|
|
button.innerHTML = copyIcons.success
|
|
button.classList.add('copy-success')
|
|
|
|
// Set timeout to revert to copy icon after 1.5s
|
|
const timeoutId = setTimeout(() => {
|
|
button.innerHTML = copyIcons.copy
|
|
button.classList.remove('copy-success')
|
|
activeTimeouts.delete(button)
|
|
}, 1500)
|
|
|
|
activeTimeouts.set(button, timeoutId)
|
|
}
|
|
catch {
|
|
|
|
}
|
|
}
|
|
|
|
// Initialize copy buttons with icons and mark them to prevent duplicate initialization
|
|
function setupCodeCopyButtons() {
|
|
document
|
|
.querySelectorAll<HTMLButtonElement>('.code-copy-button:not([data-initialized])')
|
|
.forEach((button) => {
|
|
button.innerHTML = copyIcons.copy
|
|
button.setAttribute('data-initialized', 'true')
|
|
})
|
|
}
|
|
|
|
// Use event delegation for better performance
|
|
document.addEventListener('click', (e) => {
|
|
if (!(e.target instanceof HTMLElement))
|
|
return
|
|
|
|
// Find closest button element if clicked on button or child element
|
|
const button = e.target.closest('.code-copy-button') as HTMLButtonElement | null
|
|
if (button) {
|
|
handleCopy(button)
|
|
}
|
|
}, { passive: true })
|
|
|
|
setupCodeCopyButtons()
|
|
document.addEventListener('astro:page-load', setupCodeCopyButtons)
|
|
</script>
|