document.addEventListener('DOMContentLoaded', () => { // --- DIALOG / MODAL --- window.openModal = function(modalId) { const modal = document.getElementById(modalId); if (!modal) return; modal.classList.remove('hidden'); modal.classList.add('flex'); setTimeout(() => { const content = modal.querySelector('.modal-content'); if (content) { content.classList.remove('scale-95', 'opacity-0'); content.classList.add('scale-100', 'opacity-100'); } }, 10); }; window.closeModal = function(modal) { if (typeof modal === 'string') modal = document.getElementById(modal); if (!modal) return; const content = modal.querySelector('.modal-content'); if (content) { content.classList.remove('scale-100', 'opacity-100'); content.classList.add('scale-95', 'opacity-0'); } setTimeout(() => { modal.classList.add('hidden'); modal.classList.remove('flex'); }, 300); // Wait for transition animation }; document.addEventListener('click', (event) => { // Modal Trigger Buttons const trigger = event.target.closest('[data-modal-target]'); if (trigger) { const targetId = trigger.getAttribute('data-modal-target'); window.openModal(targetId); } // Modal Close Buttons if (event.target.closest('.modal-close') || event.target.closest('.modal-backdrop')) { const modal = event.target.closest('.modal-dialog'); window.closeModal(modal); } }); // --- DROPDOWNS --- document.addEventListener('click', (event) => { const trigger = event.target.closest('.dropdown-trigger'); // Close all other dropdowns document.querySelectorAll('.dropdown-menu').forEach(menu => { const content = menu.querySelector('.dropdown-content'); if (content && (!trigger || menu !== trigger.closest('.dropdown-menu'))) { content.classList.add('hidden'); } }); // Toggle selected dropdown if (trigger) { const menu = trigger.closest('.dropdown-menu'); const content = menu.querySelector('.dropdown-content'); if (content) content.classList.toggle('hidden'); } }); // --- TOAST NOTIFICATIONS --- window.showToast = function(message, type = 'success') { const container = document.getElementById('toast-container'); if (!container) return; const toast = document.createElement('div'); toast.className = `toast-item flex items-center gap-3 w-80 p-4 rounded-lg border border-border bg-card shadow-lg transform transition-all duration-300 translate-y-10 opacity-0`; toast.innerHTML = `
${message}
`; container.appendChild(toast); // Slide in setTimeout(() => { toast.classList.remove('translate-y-10', 'opacity-0'); }, 10); // Auto-dismiss after 4 seconds const dismissTimeout = setTimeout(() => dismissToast(toast), 4000); // Manual dismiss listener toast.querySelector('.toast-close').addEventListener('click', () => { clearTimeout(dismissTimeout); dismissToast(toast); }); }; function dismissToast(toast) { toast.classList.add('translate-y-10', 'opacity-0'); setTimeout(() => { toast.remove(); }, 300); } // --- CUSTOM DATE PICKER LOGIC --- function formatDateLabel(dateStr) { if (!dateStr) return 'Pick a date'; const parts = dateStr.split('-'); if (parts.length !== 3) return dateStr; const d = new Date(parts[0], parts[1] - 1, parts[2]); const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; return `${monthNames[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`; } function renderCalendar(picker) { const valueInput = picker.querySelector('.datepicker-value'); const monthYearLabel = picker.querySelector('.datepicker-month-year'); const daysContainer = picker.querySelector('.datepicker-days'); const weekdaysRow = picker.querySelector('.datepicker-weekdays'); if (!valueInput || !daysContainer) return; let currentYear = parseInt(picker.dataset.year); let currentMonth = parseInt(picker.dataset.month); // 0-indexed let view = picker.dataset.view || 'days'; picker.dataset.view = view; if (isNaN(currentYear) || isNaN(currentMonth)) { const val = valueInput.value; const d = val ? new Date(val) : new Date(); currentYear = d.getFullYear(); currentMonth = d.getMonth(); picker.dataset.year = currentYear; picker.dataset.month = currentMonth; } const selectedDateVal = valueInput.value; const today = new Date(); const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; // Update header label if (monthYearLabel) { if (view === 'days') { monthYearLabel.textContent = `${monthNames[currentMonth]} ${currentYear}`; } else if (view === 'months') { monthYearLabel.textContent = `${currentYear}`; } else if (view === 'years') { const startYear = currentYear - (currentYear % 12); monthYearLabel.textContent = `${startYear} - ${startYear + 11}`; } } // Toggle weekdays row visibility if (weekdaysRow) { if (view === 'days') { weekdaysRow.classList.remove('hidden'); } else { weekdaysRow.classList.add('hidden'); } } // Reset grid columns class based on active view mode if (view === 'days') { daysContainer.classList.remove('grid-cols-3'); daysContainer.classList.add('grid-cols-7'); } else { daysContainer.classList.remove('grid-cols-7'); daysContainer.classList.add('grid-cols-3'); } daysContainer.innerHTML = ''; if (view === 'days') { const firstDayIndex = new Date(currentYear, currentMonth, 1).getDay(); const totalDays = new Date(currentYear, currentMonth + 1, 0).getDate(); const prevTotalDays = new Date(currentYear, currentMonth, 0).getDate(); // Prev month padding for (let i = firstDayIndex - 1; i >= 0; i--) { const dayNum = prevTotalDays - i; const btn = document.createElement('button'); btn.type = 'button'; btn.disabled = true; btn.className = 'py-1 text-center text-xs text-slate-700 cursor-not-allowed font-medium'; btn.textContent = dayNum; daysContainer.appendChild(btn); } // Current month days for (let day = 1; day <= totalDays; day++) { const btn = document.createElement('button'); btn.type = 'button'; const yearStr = currentYear; const monthStr = String(currentMonth + 1).padStart(2, '0'); const dayStr = String(day).padStart(2, '0'); const dateStr = `${yearStr}-${monthStr}-${dayStr}`; const isSelected = selectedDateVal === dateStr; const isToday = today.getFullYear() === currentYear && today.getMonth() === currentMonth && today.getDate() === day; btn.className = `py-1 text-xs rounded-lg font-semibold hover:bg-accent hover:text-accent-foreground transition flex items-center justify-center h-7 w-7 mx-auto ${ isSelected ? 'bg-indigo-600 text-white hover:bg-indigo-650' : isToday ? 'border border-sky-500/50 text-sky-400' : 'text-slate-350' }`; btn.dataset.date = dateStr; btn.textContent = day; daysContainer.appendChild(btn); } // Next month padding const totalGrids = 42; const currentGrids = firstDayIndex + totalDays; for (let i = 1; i <= (totalGrids - currentGrids); i++) { const btn = document.createElement('button'); btn.type = 'button'; btn.disabled = true; btn.className = 'py-1 text-center text-xs text-slate-700 cursor-not-allowed font-medium'; btn.textContent = i; daysContainer.appendChild(btn); } } else if (view === 'months') { const shortMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; for (let m = 0; m < 12; m++) { const btn = document.createElement('button'); btn.type = 'button'; btn.className = `py-3.5 text-xs rounded-xl font-semibold transition text-center hover:bg-accent hover:text-accent-foreground ${ m === currentMonth ? 'bg-indigo-600 text-white font-bold' : 'text-slate-350' }`; btn.dataset.monthVal = m; btn.textContent = shortMonthNames[m]; daysContainer.appendChild(btn); } } else if (view === 'years') { const startYear = currentYear - (currentYear % 12); for (let y = 0; y < 12; y++) { const yearNum = startYear + y; const btn = document.createElement('button'); btn.type = 'button'; btn.className = `py-3.5 text-xs rounded-xl font-semibold transition text-center hover:bg-accent hover:text-accent-foreground ${ yearNum === currentYear ? 'bg-indigo-600 text-white font-bold' : 'text-slate-350' }`; btn.dataset.yearVal = yearNum; btn.textContent = yearNum; daysContainer.appendChild(btn); } } } // Initialize custom date pickers document.querySelectorAll('.custom-datepicker').forEach(picker => { renderCalendar(picker); const val = picker.querySelector('.datepicker-value').value; const text = picker.querySelector('.datepicker-text'); if (text && val) text.textContent = formatDateLabel(val); }); // Custom Date Picker events document.addEventListener('click', (event) => { // Trigger Click const trigger = event.target.closest('.datepicker-trigger'); if (trigger) { const picker = trigger.closest('.custom-datepicker'); const popover = picker.querySelector('.datepicker-popover'); // Close other pickers document.querySelectorAll('.datepicker-popover, .timepicker-popover').forEach(pop => { if (pop !== popover) pop.classList.add('hidden'); }); const isHidden = popover.classList.toggle('hidden'); if (!isHidden) { picker.dataset.view = 'days'; renderCalendar(picker); } return; } // Prev Month / Year / Decade const prevBtn = event.target.closest('.datepicker-prev'); if (prevBtn) { const picker = prevBtn.closest('.custom-datepicker'); if (picker) { let currentMonth = parseInt(picker.dataset.month); let currentYear = parseInt(picker.dataset.year); const view = picker.dataset.view || 'days'; if (view === 'days') { currentMonth--; if (currentMonth < 0) { currentMonth = 11; currentYear--; } picker.dataset.month = currentMonth; picker.dataset.year = currentYear; } else if (view === 'months') { currentYear--; picker.dataset.year = currentYear; } else if (view === 'years') { currentYear -= 12; picker.dataset.year = currentYear; } renderCalendar(picker); } return; } // Next Month / Year / Decade const nextBtn = event.target.closest('.datepicker-next'); if (nextBtn) { const picker = nextBtn.closest('.custom-datepicker'); if (picker) { let currentMonth = parseInt(picker.dataset.month); let currentYear = parseInt(picker.dataset.year); const view = picker.dataset.view || 'days'; if (view === 'days') { currentMonth++; if (currentMonth > 11) { currentMonth = 0; currentYear++; } picker.dataset.month = currentMonth; picker.dataset.year = currentYear; } else if (view === 'months') { currentYear++; picker.dataset.year = currentYear; } else if (view === 'years') { currentYear += 12; picker.dataset.year = currentYear; } renderCalendar(picker); } return; } // Header click (switch view mode) const headerBtn = event.target.closest('.datepicker-month-year'); if (headerBtn) { const picker = headerBtn.closest('.custom-datepicker'); if (picker) { const view = picker.dataset.view || 'days'; if (view === 'days') { picker.dataset.view = 'months'; } else if (view === 'months') { picker.dataset.view = 'years'; } renderCalendar(picker); } return; } // Day click const dayBtn = event.target.closest('.datepicker-days button[data-date]'); if (dayBtn) { const picker = dayBtn.closest('.custom-datepicker'); const valueInput = picker.querySelector('.datepicker-value'); const textLabel = picker.querySelector('.datepicker-text'); const popover = picker.querySelector('.datepicker-popover'); const selectedDate = dayBtn.dataset.date; valueInput.value = selectedDate; textLabel.textContent = formatDateLabel(selectedDate); renderCalendar(picker); popover.classList.add('hidden'); valueInput.dispatchEvent(new Event('change', { bubbles: true })); return; } // Month click const monthBtn = event.target.closest('.datepicker-days button[data-month-val]'); if (monthBtn) { const picker = monthBtn.closest('.custom-datepicker'); if (picker) { const monthVal = parseInt(monthBtn.dataset.monthVal); picker.dataset.month = monthVal; picker.dataset.view = 'days'; renderCalendar(picker); } return; } // Year click const yearBtn = event.target.closest('.datepicker-days button[data-year-val]'); if (yearBtn) { const picker = yearBtn.closest('.custom-datepicker'); if (picker) { const yearVal = parseInt(yearBtn.dataset.yearVal); picker.dataset.year = yearVal; picker.dataset.view = 'months'; renderCalendar(picker); } return; } // Close outside const openPickerPopover = document.querySelector('.datepicker-popover:not(.hidden)'); if (openPickerPopover && !event.target.closest('.custom-datepicker')) { openPickerPopover.classList.add('hidden'); } }); // --- CUSTOM TIME PICKER LOGIC --- function initTimePicker(picker) { const hoursCol = picker.querySelector('.timepicker-col-hours'); const minutesCol = picker.querySelector('.timepicker-col-minutes'); const valueInput = picker.querySelector('.timepicker-value'); if (!hoursCol || !minutesCol || !valueInput) return; if (hoursCol.children.length === 0) { for (let hr = 1; hr <= 12; hr++) { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'timepicker-btn-hour block w-full py-1.5 text-xs hover:bg-accent hover:text-accent-foreground transition text-slate-350 font-bold rounded-md'; btn.textContent = hr; hoursCol.appendChild(btn); } } if (minutesCol.children.length === 0) { for (let min = 0; min < 60; min += 5) { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'timepicker-btn-minute block w-full py-1.5 text-xs hover:bg-accent hover:text-accent-foreground transition text-slate-350 font-bold rounded-md'; btn.textContent = String(min).padStart(2, '0'); minutesCol.appendChild(btn); } } updateTimePickerActiveStates(picker); } function updateTimePickerActiveStates(picker) { const valueInput = picker.querySelector('.timepicker-value'); const textLabel = picker.querySelector('.timepicker-text'); if (!valueInput || !textLabel) return; const val = valueInput.value || "12:00 PM"; const matches = val.match(/^(\d+):(\d+)\s*(AM|PM)$/i); if (!matches) return; const hr = parseInt(matches[1]); const min = matches[2]; const ampm = matches[3].toUpperCase(); picker.querySelectorAll('.timepicker-btn-hour').forEach(btn => { if (parseInt(btn.textContent) === hr) { btn.className = 'timepicker-btn-hour block w-full py-1.5 text-xs bg-indigo-600 text-white font-bold rounded-md'; } else { btn.className = 'timepicker-btn-hour block w-full py-1.5 text-xs hover:bg-accent hover:text-accent-foreground transition text-slate-350 font-bold rounded-md'; } }); picker.querySelectorAll('.timepicker-btn-minute').forEach(btn => { if (btn.textContent === min) { btn.className = 'timepicker-btn-minute block w-full py-1.5 text-xs bg-indigo-600 text-white font-bold rounded-md'; } else { btn.className = 'timepicker-btn-minute block w-full py-1.5 text-xs hover:bg-accent hover:text-accent-foreground transition text-slate-350 font-bold rounded-md'; } }); picker.querySelectorAll('.timepicker-ampm-btn').forEach(btn => { if (btn.textContent.toUpperCase() === ampm) { btn.className = 'timepicker-ampm-btn py-1.5 rounded-lg text-xs font-bold bg-indigo-650 text-white'; } else { btn.className = 'timepicker-ampm-btn py-1.5 rounded-lg text-xs font-bold hover:bg-accent hover:text-accent-foreground transition text-slate-400'; } }); textLabel.textContent = `${hr}:${min} ${ampm}`; } document.querySelectorAll('.custom-timepicker').forEach(picker => { initTimePicker(picker); }); document.addEventListener('click', (event) => { const trigger = event.target.closest('.timepicker-trigger'); if (trigger) { const picker = trigger.closest('.custom-timepicker'); const popover = picker.querySelector('.timepicker-popover'); document.querySelectorAll('.datepicker-popover, .timepicker-popover').forEach(pop => { if (pop !== popover) pop.classList.add('hidden'); }); popover.classList.toggle('hidden'); if (!popover.classList.contains('hidden')) { setTimeout(() => { const activeHour = picker.querySelector('.timepicker-btn-hour.bg-indigo-600'); const activeMin = picker.querySelector('.timepicker-btn-minute.bg-indigo-600'); if (activeHour) activeHour.scrollIntoView({ block: 'center', behavior: 'auto' }); if (activeMin) activeMin.scrollIntoView({ block: 'center', behavior: 'auto' }); }, 10); } return; } const btnHour = event.target.closest('.timepicker-btn-hour'); const btnMinute = event.target.closest('.timepicker-btn-minute'); const btnAmpm = event.target.closest('.timepicker-ampm-btn'); if (btnHour || btnMinute || btnAmpm) { const picker = event.target.closest('.custom-timepicker'); if (!picker) return; const valueInput = picker.querySelector('.timepicker-value'); let val = valueInput.value || "12:00 PM"; const matches = val.match(/^(\d+):(\d+)\s*(AM|PM)$/i); if (!matches) return; let hr = matches[1]; let min = matches[2]; let ampm = matches[3]; if (btnHour) hr = btnHour.textContent; if (btnMinute) min = btnMinute.textContent; if (btnAmpm) ampm = btnAmpm.textContent; valueInput.value = `${hr}:${min} ${ampm}`; updateTimePickerActiveStates(picker); valueInput.dispatchEvent(new Event('change', { bubbles: true })); return; } const openTimePopover = document.querySelector('.timepicker-popover:not(.hidden)'); if (openTimePopover && !event.target.closest('.custom-timepicker')) { openTimePopover.classList.add('hidden'); } }); // --- INTERACTIVE TABS LOGIC --- document.addEventListener('click', (event) => { const tabTrigger = event.target.closest('[data-tab-target]'); if (tabTrigger) { const tabGroup = tabTrigger.getAttribute('data-tab-group'); const targetId = tabTrigger.getAttribute('data-tab-target'); if (!tabGroup || !targetId) return; // Deactivate all tab triggers in the same group document.querySelectorAll(`[data-tab-group="${tabGroup}"]`).forEach(trig => { trig.classList.remove('border-sky-500', 'text-sky-400'); trig.classList.add('border-transparent', 'text-slate-400', 'hover:text-slate-200'); }); // Activate selected tab trigger tabTrigger.classList.remove('border-transparent', 'text-slate-400', 'hover:text-slate-200'); tabTrigger.classList.add('border-sky-500', 'text-sky-400'); // Hide all tab content panes in the same group document.querySelectorAll(`[data-tab-content-group="${tabGroup}"]`).forEach(pane => { pane.classList.add('hidden'); }); // Show the targeted pane const targetPane = document.getElementById(targetId); if (targetPane) targetPane.classList.remove('hidden'); } }); // --- ACCORDION LOGIC --- document.addEventListener('click', (event) => { const header = event.target.closest('.accordion-trigger'); if (header) { const container = header.closest('.accordion-item'); const content = container.querySelector('.accordion-content'); const chevron = header.querySelector('.accordion-chevron'); if (!content) return; const isCollapsed = content.classList.contains('hidden'); // Toggle Accordion Content if (isCollapsed) { content.classList.remove('hidden'); if (chevron) chevron.classList.add('rotate-180'); } else { content.classList.add('hidden'); if (chevron) chevron.classList.remove('rotate-180'); } } }); // --- SHEET / DRAWER LOGIC --- window.openSheet = function(sheetId) { const sheet = document.getElementById(sheetId); if (!sheet) return; sheet.classList.remove('hidden'); setTimeout(() => { const content = sheet.querySelector('.sheet-content'); const backdrop = sheet.querySelector('.sheet-backdrop'); if (backdrop) backdrop.classList.remove('opacity-0'); if (content) { content.classList.remove('translate-x-full'); content.classList.add('translate-x-0'); } }, 10); }; window.closeSheet = function(sheet) { if (typeof sheet === 'string') sheet = document.getElementById(sheet); if (!sheet) return; const content = sheet.querySelector('.sheet-content'); const backdrop = sheet.querySelector('.sheet-backdrop'); if (backdrop) backdrop.classList.add('opacity-0'); if (content) { content.classList.remove('translate-x-0'); content.classList.add('translate-x-full'); } setTimeout(() => { sheet.classList.add('hidden'); }, 300); }; document.addEventListener('click', (event) => { // Open Sheet Triggers const trigger = event.target.closest('[data-sheet-target]'); if (trigger) { const targetId = trigger.getAttribute('data-sheet-target'); window.openSheet(targetId); } // Close Sheet Triggers if (event.target.closest('.sheet-close') || event.target.closest('.sheet-backdrop')) { const sheet = event.target.closest('.sheet-dialog'); window.closeSheet(sheet); } }); // --- SIDEBAR NAVIGATION ACTIVE HIGHLIGHTING --- const currentPath = window.location.pathname; document.querySelectorAll('a[data-wiki-path]').forEach(link => { const path = link.getAttribute('data-wiki-path'); if (currentPath === path) { link.className = 'flex items-center px-3 py-2 text-xs font-semibold rounded-lg bg-indigo-600/20 text-indigo-400 border border-indigo-500/10 transition'; } else { link.className = 'flex items-center px-3 py-2 text-xs font-semibold text-muted-foreground hover:text-white rounded-lg hover:bg-secondary transition'; } }); // --- CUSTOM SELECT DROPDOWN LOGIC --- document.addEventListener('click', (event) => { const trigger = event.target.closest('.select-trigger'); const item = event.target.closest('.select-item'); // Close all other select dropdowns when clicking trigger or outside if (trigger || !event.target.closest('.custom-select')) { document.querySelectorAll('.custom-select').forEach(select => { const popover = select.querySelector('.select-popover'); const chevron = select.querySelector('.select-chevron'); if (popover && (!trigger || select !== trigger.closest('.custom-select'))) { popover.classList.add('hidden'); if (chevron) chevron.classList.remove('rotate-180'); } }); } // Toggle dropdown open state if (trigger) { const select = trigger.closest('.custom-select'); const popover = select.querySelector('.select-popover'); const chevron = select.querySelector('.select-chevron'); if (popover) { const isHidden = popover.classList.toggle('hidden'); if (chevron) { if (isHidden) { chevron.classList.remove('rotate-180'); } else { chevron.classList.add('rotate-180'); } } } } // Handle item selection if (item) { const select = item.closest('.custom-select'); const triggerBtn = select.querySelector('.select-trigger'); const valueInput = select.querySelector('.select-value'); const textLabel = select.querySelector('.select-text'); const popover = select.querySelector('.select-popover'); const chevron = select.querySelector('.select-chevron'); const value = item.getAttribute('data-value'); const labelText = item.textContent.trim(); if (valueInput) valueInput.value = value; if (textLabel) textLabel.textContent = labelText; // Mark selected item visually select.querySelectorAll('.select-item').forEach(i => { i.classList.remove('bg-accent', 'text-accent-foreground', 'font-semibold'); }); item.classList.add('bg-accent', 'text-accent-foreground', 'font-semibold'); // Close dropdown if (popover) popover.classList.add('hidden'); if (chevron) chevron.classList.remove('rotate-180'); if (triggerBtn) triggerBtn.focus(); // Trigger change event on input if (valueInput) { valueInput.dispatchEvent(new Event('change', { bubbles: true })); } } }); // Keyboard support for custom select triggers document.addEventListener('keydown', (event) => { const trigger = event.target.closest('.select-trigger'); const item = event.target.closest('.select-item'); if (trigger) { const select = trigger.closest('.custom-select'); const popover = select.querySelector('.select-popover'); if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') { event.preventDefault(); if (popover) { popover.classList.remove('hidden'); const chevron = select.querySelector('.select-chevron'); if (chevron) chevron.classList.add('rotate-180'); } const firstItem = select.querySelector('.select-item'); if (firstItem) firstItem.focus(); } return; } if (item) { const select = item.closest('.custom-select'); const triggerBtn = select.querySelector('.select-trigger'); const items = Array.from(select.querySelectorAll('.select-item')); const index = items.indexOf(item); if (event.key === 'ArrowDown') { event.preventDefault(); const next = items[index + 1] || items[0]; if (next) next.focus(); } else if (event.key === 'ArrowUp') { event.preventDefault(); const prev = items[index - 1] || items[items.length - 1]; if (prev) prev.focus(); } else if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); item.click(); } else if (event.key === 'Escape') { event.preventDefault(); const popover = select.querySelector('.select-popover'); const chevron = select.querySelector('.select-chevron'); if (popover) popover.classList.add('hidden'); if (chevron) chevron.classList.remove('rotate-180'); if (triggerBtn) triggerBtn.focus(); } } }); // Global keydown listener for Escape to dismiss modals document.addEventListener('keydown', (event) => { if (event.key === 'Escape') { const openDialog = document.querySelector('.modal-dialog:not(.hidden)'); if (openDialog) { window.closeModal(openDialog); } } }); // --- COPY CODE SNIPPETS HELPER --- window.copyCodeSnippet = function(button) { const pre = button.closest('.relative').querySelector('pre'); if (!pre) return; const code = pre.querySelector('code'); const text = code ? code.innerText : pre.innerText; navigator.clipboard.writeText(text).then(() => { const originalText = button.innerHTML; button.innerHTML = ` Copied! `; button.classList.add('border-sky-500/30', 'bg-sky-500/5'); if (window.showToast) { window.showToast('Snippet copied to clipboard!'); } setTimeout(() => { button.innerHTML = originalText; button.classList.remove('border-sky-500/30', 'bg-sky-500/5'); }, 2000); }).catch(err => { console.error('Failed to copy text: ', err); if (window.showToast) { window.showToast('Failed to copy to clipboard', 'error'); } }); }; });