UNPKG

mcp-quiz-server

Version:

🧠 AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.

209 lines • 8.04 kB
import { TourService } from '../services/TourService'; import { DOMUtils } from '../utils/index'; import { Component } from './Component'; export class TourModal extends Component { constructor() { super('#tour-modal'); this.currentStep = null; this.currentState = null; this.tourService = TourService.getInstance(); this.tourService.setTourModal(this); } render() { } bindEvents() { this.element.addEventListener('click', e => { if (e.target === this.element) { this.tourService.skipTour(); } }); const prevBtn = this.element.querySelector('#tour-prev-btn'); const nextBtn = this.element.querySelector('#tour-next-btn'); const skipBtn = this.element.querySelector('#tour-skip-btn'); const closeBtn = this.element.querySelector('#tour-close-btn'); prevBtn?.addEventListener('click', () => { this.tourService.previousStep(); }); nextBtn?.addEventListener('click', () => { this.tourService.nextStep(); }); skipBtn?.addEventListener('click', () => { this.tourService.skipTour(); }); closeBtn?.addEventListener('click', () => { this.tourService.skipTour(); }); document.addEventListener('keydown', this.handleKeydown.bind(this)); const video = this.element.querySelector('#tour-video'); if (video) { video.addEventListener('ended', () => { const autoAdvance = this.element.querySelector('#auto-advance-toggle'); if (autoAdvance?.checked && this.currentState?.canGoNext) { setTimeout(() => this.tourService.nextStep(), 1000); } }); } } handleKeydown(e) { if (!this.currentState?.isActive) return; switch (e.key) { case 'Escape': this.tourService.skipTour(); break; case 'ArrowLeft': if (this.currentState.canGoBack) { e.preventDefault(); this.tourService.previousStep(); } break; case 'ArrowRight': case 'Enter': case ' ': if (this.currentState.canGoNext) { e.preventDefault(); this.tourService.nextStep(); } else if (!this.currentState.canGoNext && this.currentState.currentStep === this.currentState.totalSteps) { e.preventDefault(); this.tourService.completeTour(); } break; } } showStep(step, state) { this.currentStep = step; this.currentState = state; this.updateContent(step); this.updateNavigation(state); this.updateProgress(state); this.show(); const nextBtn = this.element.querySelector('#tour-next-btn'); const skipBtn = this.element.querySelector('#tour-skip-btn'); (nextBtn || skipBtn)?.focus(); } updateContent(step) { const title = this.element.querySelector('#tour-title'); if (title) { title.textContent = step.title; } const content = this.element.querySelector('#tour-content'); if (content) { content.innerHTML = DOMUtils.escapeHtml(step.content); } const videoSection = this.element.querySelector('#tour-video-section'); const videoElement = this.element.querySelector('#tour-video'); if (step.video && videoSection) { videoSection.classList.remove('hidden'); if (videoElement) { videoElement.src = step.video; videoElement.load(); } } else if (videoSection) { videoSection.classList.add('hidden'); } } updateNavigation(state) { const prevBtn = this.element.querySelector('#tour-prev-btn'); const nextBtn = this.element.querySelector('#tour-next-btn'); const skipBtn = this.element.querySelector('#tour-skip-btn'); if (prevBtn) { prevBtn.disabled = !state.canGoBack; prevBtn.classList.toggle('opacity-50', !state.canGoBack); prevBtn.classList.toggle('cursor-not-allowed', !state.canGoBack); } if (nextBtn) { nextBtn.disabled = !state.canGoNext; nextBtn.classList.toggle('opacity-50', !state.canGoNext); nextBtn.classList.toggle('cursor-not-allowed', !state.canGoNext); if (state.currentStep === state.totalSteps) { nextBtn.textContent = 'Finish'; nextBtn.classList.add('bg-green-600', 'hover:bg-green-700'); nextBtn.classList.remove('bg-primary-600', 'hover:bg-primary-700'); } else { nextBtn.textContent = 'Next'; nextBtn.classList.remove('bg-green-600', 'hover:bg-green-700'); nextBtn.classList.add('bg-primary-600', 'hover:bg-primary-700'); } } if (skipBtn) { skipBtn.classList.toggle('hidden', !state.canSkip); } } updateProgress(state) { const stepCounter = this.element.querySelector('#tour-step-counter'); if (stepCounter) { stepCounter.textContent = `${state.currentStep} of ${state.totalSteps}`; } const progressBar = this.element.querySelector('#tour-progress-bar'); if (progressBar) { const percentage = (state.currentStep / state.totalSteps) * 100; progressBar.style.width = `${percentage}%`; } const dots = this.element.querySelectorAll('.tour-progress-dot'); dots.forEach((dot, index) => { if (index < state.currentStep) { dot.classList.add('bg-primary-600'); dot.classList.remove('bg-surface-300'); } else { dot.classList.remove('bg-primary-600'); dot.classList.add('bg-surface-300'); } }); } loadVideo(videoUrl) { const video = this.element.querySelector('#tour-video'); if (!video) return; video.src = videoUrl; video.load(); const playButton = this.element.querySelector('#video-play-btn'); if (playButton) { playButton.classList.remove('hidden'); playButton.addEventListener('click', () => { video.play(); playButton.classList.add('hidden'); }); } video.addEventListener('play', () => { video.controls = true; }); } show() { this.element.classList.remove('hidden'); this.element.classList.add('flex'); setTimeout(() => { const content = this.element.querySelector('.modal-content'); content?.classList.remove('translate-y-full', 'md:translate-y-0'); content?.classList.add('translate-y-0'); }, 10); document.body.style.overflow = 'hidden'; } hide() { const content = this.element.querySelector('.modal-content'); content?.classList.add('translate-y-full', 'md:translate-y-0'); content?.classList.remove('translate-y-0'); setTimeout(() => { this.element.classList.add('hidden'); this.element.classList.remove('flex'); document.body.style.overflow = ''; const video = this.element.querySelector('#tour-video'); if (video) { video.pause(); video.currentTime = 0; video.removeAttribute('src'); } }, 300); } getCurrentStep() { return this.currentStep; } getCurrentState() { return this.currentState; } } //# sourceMappingURL=TourModal.js.map