@supernal/tts-widget 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -1
- package/dist/loader.js +6 -6
- package/dist/loader.js.map +3 -3
- package/dist/widget.d.ts +11 -0
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +6 -6
- package/dist/widget.js.map +3 -3
- package/package.json +1 -1
package/dist/loader.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/widget.ts", "../src/loader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Supernal TTS Widget\n * Embeddable text-to-speech widget for blogs and websites\n */\n\nexport interface SupernalTTSOptions {\n apiUrl?: string;\n voice?: string;\n provider?: string;\n speed?: number; // Default speed for all widgets (1.0 = normal)\n autoHash?: boolean;\n cacheExpiry?: number;\n apiKey?: string;\n showBranding?: boolean;\n version?: string;\n devMode?: boolean;\n clientSideSpeed?: boolean; // Use HTML5 playbackRate for speed adjustment (default: true)\n generationMode?: 'standard' | 'progressive' | 'realtime'; // Generation mode (default: 'standard')\n progressiveThreshold?: number; // Character count threshold to use progressive mode (default: 2000)\n}\n\nexport interface TTSGenerateOptions {\n provider: string;\n voice: string;\n speed: number;\n format?: string;\n quality?: string;\n cache?: boolean;\n}\n\nexport interface TTSResponse {\n audioUrl: string;\n hash: string;\n cached: boolean;\n duration?: number;\n cost?: number;\n}\n\nexport interface CachedAudio {\n audioUrl: string;\n metadata: Record<string, any>;\n expiry: number;\n timestamp: number;\n}\n\nexport interface WidgetData {\n text: string;\n voice: string;\n provider: string;\n speed: number;\n hash: string;\n playButton: HTMLButtonElement;\n stopButton?: HTMLButtonElement;\n voiceSelect?: HTMLSelectElement;\n speedSlider?: HTMLInputElement;\n progressSlider?: HTMLInputElement;\n advanced?: boolean;\n}\n\nexport interface WidgetConfig {\n text: string;\n voices: string[]; // Array of available voices (empty = no voice control)\n enableSpeed: boolean; // Show speed control\n enableProgress: boolean; // Show progress bar\n speed: number;\n provider: string;\n voice: string;\n apiKey?: string; // Optional per-widget API key\n}\n\nexport class SupernalTTS {\n private apiUrl: string;\n private defaultVoice: string;\n private defaultProvider: string;\n private defaultSpeed: number;\n private autoHash: boolean;\n private cacheExpiry: number;\n private apiKey?: string;\n private showBranding: boolean;\n private version: string;\n private devMode: boolean;\n private clientSideSpeed: boolean;\n private generationMode: 'standard' | 'progressive' | 'realtime';\n private progressiveThreshold: number;\n \n private cache: Map<string, CachedAudio>;\n private currentAudio: HTMLAudioElement | null = null;\n private currentButton: HTMLButtonElement | null = null;\n private currentWidget?: WidgetData;\n private isProcessing: boolean = false;\n private lastClickTime: number = 0;\n private debounceDelay: number = 300;\n private progressUpdateInterval: number | null = null; // Track interval globally\n private audioQueue: Uint8Array[] = []; // Queue for progressive streaming chunks\n\n constructor(options: SupernalTTSOptions = {}) {\n this.apiUrl = options.apiUrl || 'https://www.tts.supernal.ai';\n this.defaultVoice = options.voice || 'default';\n this.defaultProvider = options.provider || 'openai';\n this.defaultSpeed = options.speed || 1.0;\n this.autoHash = options.autoHash !== false;\n this.cacheExpiry = options.cacheExpiry || 7 * 24 * 60 * 60 * 1000; // 7 days\n this.apiKey = options.apiKey;\n console.log('[TTS Widget] Constructor - API Key provided:', !!options.apiKey);\n console.log('[TTS Widget] Constructor - API Key saved:', !!this.apiKey);\n this.showBranding = options.showBranding !== false;\n this.version = options.version || '1.0.0';\n // devMode must be explicitly enabled now (not auto-enabled by localhost)\n this.devMode = options.devMode === true;\n this.clientSideSpeed = options.clientSideSpeed !== false; // Default to true for cost savings\n this.generationMode = options.generationMode || 'standard';\n this.progressiveThreshold = options.progressiveThreshold || 2000;\n\n this.cache = new Map();\n this.loadCacheFromStorage();\n\n this.init();\n }\n\n private init(): void {\n // Auto-initialize widgets on page load\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => this.initializeWidgets());\n } else {\n this.initializeWidgets();\n }\n \n // Set up MutationObserver to detect dynamically added widgets\n // This handles client-side routing (SPA navigation) and dynamic content\n this.observeDOM();\n }\n\n private observeDOM(): void {\n // Watch for new elements being added to the DOM\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n // Check if the added node is an element\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n \n // Check if it's a widget or contains widgets\n if (element.classList?.contains('supernal-tts-widget')) {\n this.setupWidget(element);\n } else {\n // Check for widgets within the added element\n const widgets = element.querySelectorAll?.('.supernal-tts-widget');\n widgets?.forEach((widget) => this.setupWidget(widget as HTMLElement));\n }\n }\n });\n });\n });\n\n // Start observing the document body for changes\n observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n private initializeWidgets(): void {\n const widgets = document.querySelectorAll<HTMLElement>('.supernal-tts-widget');\n widgets.forEach(widget => this.setupWidget(widget));\n\n // Add dev mode cache clear button only if widgets exist and devMode is enabled\n if (this.devMode && widgets.length > 0) {\n this.addDevModeClearButton();\n }\n }\n\n private setupWidget(element: HTMLElement): void {\n // Check if already initialized to prevent duplicates\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n\n // Parse widget configuration from data attributes\n const config = this.parseWidgetConfig(element);\n \n if (!config.text) {\n console.warn('TTS Widget: No text found for widget', element);\n return;\n }\n\n // Generate hash for caching\n const hash = this.generateHash(config.text, { \n voice: config.voice, \n provider: config.provider, \n speed: config.speed \n });\n\n // Check for legacy controls attribute for backwards compatibility\n const controls = element.dataset.controls;\n if (controls === 'advanced' || controls === 'true') {\n this.setupAdvancedWidget(element, config.text, {\n voice: config.voice,\n provider: config.provider,\n speed: config.speed,\n hash,\n apiKey: config.apiKey\n });\n return;\n } else if (controls === 'compact') {\n this.setupCompactWidget(element, config.text, {\n voice: config.voice,\n provider: config.provider,\n speed: config.speed,\n hash,\n apiKey: config.apiKey\n });\n return;\n }\n\n // Use new modular widget setup\n this.setupModularWidget(element, config, hash);\n }\n\n /**\n * Parse widget configuration from data attributes\n */\n private parseWidgetConfig(element: HTMLElement): WidgetConfig {\n const text = element.dataset.text || element.textContent?.trim() || '';\n const voice = element.dataset.voice || this.defaultVoice;\n const provider = element.dataset.provider || this.defaultProvider;\n const speed = element.dataset.speed ? parseFloat(element.dataset.speed) : this.defaultSpeed;\n \n // Parse voices list (comma-separated)\n const voicesAttr = element.dataset.voices || '';\n const voices = voicesAttr ? voicesAttr.split(',').map(v => v.trim()).filter(Boolean) : [];\n \n // Parse boolean flags\n const enableSpeed = element.dataset.enableSpeed === 'true';\n const enableProgress = element.dataset.enableProgress === 'true';\n \n // Check for widget-specific API key (overrides global)\n const apiKey = element.dataset.apiKey || this.apiKey;\n\n return {\n text,\n voices,\n enableSpeed,\n enableProgress,\n speed,\n provider,\n voice,\n apiKey, // Include API key in config\n };\n }\n\n private setupBasicWidget(element: HTMLElement, text: string, options: any): void {\n const { voice, provider, speed, hash, apiKey } = options;\n \n // Check if already initialized to prevent duplicates\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n \n // Create container for button and branding\n const buttonContainer = document.createElement('div');\n buttonContainer.className = 'supernal-tts-button-container';\n \n // Create or find play button\n let playButton = element.querySelector<HTMLButtonElement>('.supernal-tts-play');\n if (!playButton) {\n playButton = this.createPlayButton();\n }\n \n buttonContainer.appendChild(playButton);\n\n // Add branding badge if enabled (only once)\n if (this.showBranding && !element.querySelector('.supernal-badge')) {\n const badge = this.createBrandingBadge();\n buttonContainer.appendChild(badge);\n }\n \n element.appendChild(buttonContainer);\n\n // Add widget styling\n element.classList.add('supernal-tts-widget-initialized');\n \n // Setup event listeners\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash, apiKey });\n });\n\n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton\n };\n }\n\n private setupCompactWidget(element: HTMLElement, text: string, options: any): void {\n const { hash, apiKey } = options;\n let { voice, provider, speed } = options;\n \n // Check if already initialized\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n \n // Create container for compact controls\n const container = document.createElement('div');\n container.className = 'supernal-tts-compact-widget';\n \n // Top row: Play button + Voice selector\n const topRow = document.createElement('div');\n topRow.className = 'supernal-tts-top-row';\n \n const playButton = this.createPlayButton();\n \n // Voice selector (compact)\n const voiceSelect = document.createElement('select');\n voiceSelect.className = 'supernal-tts-voice-select';\n voiceSelect.innerHTML = `\n <option value=\"alloy\" ${voice === 'alloy' ? 'selected' : ''}>Alloy</option>\n <option value=\"echo\" ${voice === 'echo' ? 'selected' : ''}>Echo</option>\n <option value=\"fable\" ${voice === 'fable' ? 'selected' : ''}>Fable</option>\n <option value=\"onyx\" ${voice === 'onyx' ? 'selected' : ''}>Onyx</option>\n <option value=\"nova\" ${voice === 'nova' ? 'selected' : ''}>Nova</option>\n <option value=\"shimmer\" ${voice === 'shimmer' ? 'selected' : ''}>Shimmer</option>\n <option value=\"coral\" ${voice === 'coral' ? 'selected' : ''}>Coral</option>\n `;\n \n topRow.appendChild(playButton);\n topRow.appendChild(voiceSelect);\n \n // Add branding badge if enabled\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n topRow.appendChild(badge);\n }\n \n // Bottom row: Speed control\n const speedControl = document.createElement('div');\n speedControl.className = 'supernal-tts-speed-control';\n speedControl.innerHTML = `\n <label>Speed: <span class=\"supernal-tts-speed-value\">${speed}x</span></label>\n <input type=\"range\" class=\"supernal-tts-speed-slider\" min=\"0.25\" max=\"4.0\" step=\"0.25\" value=\"${speed}\">\n `;\n \n // Assemble widget\n container.appendChild(topRow);\n container.appendChild(speedControl);\n \n element.innerHTML = '';\n element.appendChild(container);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-compact');\n \n // Setup event listeners\n const speedSlider = speedControl.querySelector<HTMLInputElement>('.supernal-tts-speed-slider')!;\n const speedValue = speedControl.querySelector<HTMLSpanElement>('.supernal-tts-speed-value')!;\n\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n speed = parseFloat(speedSlider.value);\n voice = voiceSelect.value;\n const newHash = this.generateHash(text, { voice, provider, speed });\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash: newHash, apiKey });\n });\n \n speedSlider.addEventListener('input', (e) => {\n speed = parseFloat((e.target as HTMLInputElement).value);\n speedValue.textContent = `${speed}x`;\n });\n \n voiceSelect.addEventListener('change', () => {\n voice = voiceSelect.value;\n });\n \n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton,\n compact: true\n };\n }\n\n private setupAdvancedWidget(element: HTMLElement, text: string, options: any): void {\n const { hash, apiKey } = options;\n let { voice, provider, speed } = options;\n \n // Create controls container\n const container = document.createElement('div');\n container.className = 'supernal-tts-advanced-widget';\n \n // Create play/pause/stop buttons\n const buttonGroup = document.createElement('div');\n buttonGroup.className = 'supernal-tts-button-group';\n \n const playButton = this.createPlayButton();\n const stopButton = this.createStopButton();\n \n buttonGroup.appendChild(playButton);\n buttonGroup.appendChild(stopButton);\n \n // Create voice selector\n const voiceSelect = document.createElement('select');\n voiceSelect.className = 'supernal-tts-voice-select';\n voiceSelect.innerHTML = `\n <option value=\"alloy\" ${voice === 'alloy' ? 'selected' : ''}>Alloy</option>\n <option value=\"echo\" ${voice === 'echo' ? 'selected' : ''}>Echo</option>\n <option value=\"fable\" ${voice === 'fable' ? 'selected' : ''}>Fable</option>\n <option value=\"onyx\" ${voice === 'onyx' ? 'selected' : ''}>Onyx</option>\n <option value=\"nova\" ${voice === 'nova' ? 'selected' : ''}>Nova</option>\n <option value=\"shimmer\" ${voice === 'shimmer' ? 'selected' : ''}>Shimmer</option>\n <option value=\"coral\" ${voice === 'coral' ? 'selected' : ''}>Coral</option>\n `;\n \n // Create speed control\n const speedControl = document.createElement('div');\n speedControl.className = 'supernal-tts-speed-control';\n speedControl.innerHTML = `\n <label>Speed: <span class=\"supernal-tts-speed-value\">${speed}x</span></label>\n <input type=\"range\" class=\"supernal-tts-speed-slider\" min=\"0.25\" max=\"4.0\" step=\"0.25\" value=\"${speed}\">\n `;\n \n // Create progress bar\n const progressBar = document.createElement('div');\n progressBar.className = 'supernal-tts-progress';\n progressBar.innerHTML = `\n <input type=\"range\" class=\"supernal-tts-progress-slider\" min=\"0\" max=\"100\" value=\"0\" step=\"0.1\">\n <div class=\"supernal-tts-time\"><span class=\"supernal-tts-current-time\">0:00</span> / <span class=\"supernal-tts-duration\">0:00</span></div>\n `;\n \n // Assemble widget\n container.appendChild(buttonGroup);\n container.appendChild(voiceSelect);\n container.appendChild(speedControl);\n container.appendChild(progressBar);\n \n // Add branding badge if enabled\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n container.appendChild(badge);\n }\n \n element.innerHTML = '';\n element.appendChild(container);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-advanced');\n \n // Setup event listeners\n const speedSlider = speedControl.querySelector<HTMLInputElement>('.supernal-tts-speed-slider')!;\n const speedValue = speedControl.querySelector<HTMLSpanElement>('.supernal-tts-speed-value')!;\n const progressSlider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider')!;\n\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n speed = parseFloat(speedSlider.value);\n voice = voiceSelect.value;\n const newHash = this.generateHash(text, { voice, provider, speed });\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash: newHash, apiKey });\n });\n \n stopButton.addEventListener('click', (e) => {\n e.preventDefault();\n this.stopAudio();\n });\n \n speedSlider.addEventListener('input', (e) => {\n speed = parseFloat((e.target as HTMLInputElement).value);\n speedValue.textContent = `${speed}x`;\n });\n \n voiceSelect.addEventListener('change', () => {\n voice = voiceSelect.value;\n });\n \n progressSlider.addEventListener('input', (e) => {\n if (this.currentAudio) {\n const percent = parseFloat((e.target as HTMLInputElement).value) / 100;\n this.currentAudio.currentTime = this.currentAudio.duration * percent;\n }\n });\n \n // Update progress bar during playback\n const updateProgress = () => {\n if (this.currentAudio && (element as any)._ttsWidget === this.currentWidget) {\n const percent = (this.currentAudio.currentTime / this.currentAudio.duration) * 100;\n progressSlider.value = percent.toString();\n \n const currentTime = this.formatTime(this.currentAudio.currentTime);\n const duration = this.formatTime(this.currentAudio.duration);\n progressBar.querySelector('.supernal-tts-current-time')!.textContent = currentTime;\n progressBar.querySelector('.supernal-tts-duration')!.textContent = duration;\n }\n };\n \n setInterval(updateProgress, 100);\n \n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton,\n stopButton,\n voiceSelect,\n speedSlider,\n progressSlider,\n advanced: true\n };\n \n this.currentWidget = (element as any)._ttsWidget;\n }\n\n /**\n * Setup modular widget with conditional features based on config\n */\n private setupModularWidget(element: HTMLElement, config: WidgetConfig, hash: string): void {\n let currentVoice = config.voice;\n let currentSpeed = config.speed;\n const { text, voices, enableSpeed, enableProgress, provider, apiKey } = config;\n let savedPosition: number = 0; // Track playback position for voice/speed changes\n\n // Create main container\n const container = document.createElement('div');\n container.className = 'supernal-tts-modular-widget';\n\n // Create controls row\n const controlsRow = document.createElement('div');\n controlsRow.className = 'supernal-tts-controls-row';\n\n // 1. Play button (compact - icon only)\n const playButton = this.createPlayButton(true);\n controlsRow.appendChild(playButton);\n\n // 2. Voice dropdown (conditional)\n let voiceDropdown: HTMLElement | null = null;\n if (voices.length > 0) {\n voiceDropdown = this.createVoiceDropdown(voices, currentVoice);\n controlsRow.appendChild(voiceDropdown);\n \n // Listen for voice changes\n voiceDropdown.addEventListener('voice-changed', ((e: CustomEvent) => {\n const newVoice = e.detail.voice;\n \n // If voice changed while playing, save position and regenerate\n if (newVoice !== currentVoice && this.currentButton === playButton && this.currentAudio) {\n currentVoice = newVoice;\n \n // Save current playback position as percentage\n if (this.currentAudio.duration > 0) {\n savedPosition = this.currentAudio.currentTime / this.currentAudio.duration;\n }\n \n // Get the progress bar reference\n const widgetData = (element as any)._ttsWidget;\n const progressBar = widgetData?.progressBar;\n \n // Clean stop: clear audio and intervals, but keep progress bar visible\n this.cleanStopAudioKeepProgress(progressBar);\n \n // Trigger new playback with updated voice and saved position\n setTimeout(() => {\n this.handlePlayClickFromPosition(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed }),\n progressBar,\n apiKey\n }, savedPosition);\n }, 50);\n } else {\n currentVoice = newVoice;\n }\n }) as EventListener);\n }\n\n // 3. Speed dropdown (conditional)\n let speedDropdown: HTMLElement | null = null;\n if (enableSpeed) {\n speedDropdown = this.createSpeedDropdown(currentSpeed);\n controlsRow.appendChild(speedDropdown);\n \n // Listen for speed changes\n speedDropdown.addEventListener('speed-changed', ((e: CustomEvent) => {\n const newSpeed = e.detail.speed;\n \n if (newSpeed !== currentSpeed) {\n currentSpeed = newSpeed;\n \n // Client-side speed adjustment: use HTML5 playbackRate with pitch preservation\n if (this.clientSideSpeed && this.currentAudio && this.currentButton === playButton) {\n // Instant speed change via playbackRate with pitch preservation - no regeneration needed!\n // The browser's time-stretching algorithm maintains pitch quality\n this.currentAudio.playbackRate = newSpeed;\n } \n // Server-side speed adjustment: regenerate audio (expensive but higher quality)\n else if (!this.clientSideSpeed && this.currentButton === playButton && this.currentAudio) {\n // Save current playback position as percentage\n if (this.currentAudio.duration > 0) {\n savedPosition = this.currentAudio.currentTime / this.currentAudio.duration;\n }\n \n // Get the progress bar reference\n const widgetData = (element as any)._ttsWidget;\n const progressBar = widgetData?.progressBar;\n \n // Clean stop: clear audio and intervals, but keep progress bar visible\n this.cleanStopAudioKeepProgress(progressBar);\n \n // Trigger new playback with updated speed and saved position\n setTimeout(() => {\n this.handlePlayClickFromPosition(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed }),\n progressBar,\n apiKey\n }, savedPosition);\n }, 50);\n }\n }\n }) as EventListener);\n }\n\n // 4. Branding badge\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n controlsRow.appendChild(badge);\n }\n\n container.appendChild(controlsRow);\n\n // 5. Progress bar (conditional)\n let progressBar: HTMLElement | null = null;\n if (enableProgress) {\n progressBar = this.createProgressBar();\n container.appendChild(progressBar);\n }\n\n // IMPORTANT: Prepend controls, keep original content\n element.insertBefore(container, element.firstChild);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-modular');\n \n // Add has-progress class if progress bar is enabled\n if (enableProgress) {\n element.classList.add('has-progress');\n }\n\n // Setup play button handler\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n const newHash = this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed });\n this.handlePlayClick(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: newHash,\n progressBar,\n apiKey\n });\n });\n\n // Store reference\n (element as any)._ttsWidget = {\n text,\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash,\n playButton,\n voiceDropdown,\n speedDropdown,\n progressBar\n };\n }\n\n /**\n * Create voice dropdown with person icon button\n */\n private createVoiceDropdown(voices: string[], selectedVoice: string): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-voice-control';\n\n // Person icon toggle button (no background)\n const toggleButton = document.createElement('button');\n toggleButton.className = 'supernal-tts-voice-toggle';\n toggleButton.setAttribute('aria-label', 'Select voice');\n toggleButton.setAttribute('aria-expanded', 'false');\n toggleButton.innerHTML = `\n <svg class=\"supernal-tts-voice-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z\"/>\n </svg>\n `;\n\n // Dropdown menu (hidden by default)\n const dropdown = document.createElement('div');\n dropdown.className = 'supernal-tts-voice-dropdown hidden';\n dropdown.setAttribute('role', 'menu');\n\n voices.forEach(voice => {\n const option = document.createElement('button');\n option.className = 'supernal-tts-voice-option';\n option.textContent = this.formatVoiceName(voice);\n option.dataset.voice = voice;\n option.setAttribute('role', 'menuitem');\n \n if (voice === selectedVoice) {\n option.classList.add('active');\n }\n\n option.addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n \n // Update active state\n dropdown.querySelectorAll('.supernal-tts-voice-option').forEach(opt => {\n opt.classList.remove('active');\n });\n option.classList.add('active');\n\n // Emit change event\n container.dispatchEvent(new CustomEvent('voice-changed', { \n detail: { voice } \n }));\n });\n\n dropdown.appendChild(option);\n });\n\n let hideTimeout: number | null = null;\n\n // Show dropdown on hover with smart positioning\n container.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n dropdown.classList.remove('hidden');\n toggleButton.setAttribute('aria-expanded', 'true');\n \n // Smart positioning: check if dropdown would go off-screen\n setTimeout(() => {\n const rect = dropdown.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n \n if (rect.bottom > viewportHeight && rect.top > rect.height) {\n // Not enough space below, position above\n dropdown.style.bottom = '100%';\n dropdown.style.top = 'auto';\n } else {\n // Default: position below\n dropdown.style.top = 'calc(100% + 4px)';\n dropdown.style.bottom = 'auto';\n }\n }, 0);\n });\n\n container.addEventListener('mouseleave', (e) => {\n // Delay hiding to allow moving to dropdown\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n toggleButton.setAttribute('aria-expanded', 'false');\n }, 150);\n });\n\n // Keep dropdown open when hovering over it\n dropdown.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n });\n\n dropdown.addEventListener('mouseleave', () => {\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n toggleButton.setAttribute('aria-expanded', 'false');\n }, 150);\n });\n\n // Also allow click to toggle\n toggleButton.addEventListener('click', (e) => {\n e.stopPropagation();\n const isHidden = dropdown.classList.contains('hidden');\n dropdown.classList.toggle('hidden');\n toggleButton.setAttribute('aria-expanded', isHidden ? 'true' : 'false');\n });\n\n container.appendChild(toggleButton);\n container.appendChild(dropdown);\n\n return container;\n }\n\n /**\n * Create speed dropdown with preset values (hover to reveal)\n */\n private createSpeedDropdown(selectedSpeed: number): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-speed-control';\n\n // Speedometer/gauge icon button (no background)\n const button = document.createElement('button');\n button.className = 'supernal-tts-speed-toggle';\n button.setAttribute('aria-label', 'Adjust playback speed');\n button.innerHTML = `\n <svg class=\"supernal-tts-speed-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z\"/>\n <path d=\"M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z\"/>\n </svg>\n `;\n\n // Dropdown menu (hidden by default, shows on hover)\n const dropdown = document.createElement('div');\n dropdown.className = 'supernal-tts-speed-dropdown hidden';\n dropdown.setAttribute('role', 'menu');\n\n // Speed range: 0.6 to 3.0 in steps of 0.2\n const speeds: number[] = [];\n for (let speed = 0.6; speed <= 3.0; speed += 0.2) {\n speeds.push(Math.round(speed * 10) / 10); // Round to 1 decimal\n }\n \n speeds.forEach(speed => {\n const option = document.createElement('button');\n option.className = 'supernal-tts-speed-option';\n option.textContent = `${speed.toFixed(1)}x`;\n option.dataset.speed = speed.toString();\n option.setAttribute('role', 'menuitem');\n\n if (Math.abs(speed - selectedSpeed) < 0.01) {\n option.classList.add('active');\n }\n\n option.addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n\n // Update active state\n dropdown.querySelectorAll('.supernal-tts-speed-option').forEach(opt => {\n opt.classList.remove('active');\n });\n option.classList.add('active');\n\n // Emit change event\n container.dispatchEvent(new CustomEvent('speed-changed', { \n detail: { speed } \n }));\n });\n\n dropdown.appendChild(option);\n });\n\n let hideTimeout: number | null = null;\n\n // Show dropdown on hover with smart positioning\n container.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n dropdown.classList.remove('hidden');\n \n // Smart positioning: check if dropdown would go off-screen\n setTimeout(() => {\n const rect = dropdown.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n \n if (rect.bottom > viewportHeight && rect.top > rect.height) {\n // Not enough space below, position above\n dropdown.style.bottom = '100%';\n dropdown.style.top = 'auto';\n } else {\n // Default: position below\n dropdown.style.top = 'calc(100% + 4px)';\n dropdown.style.bottom = 'auto';\n }\n }, 0);\n });\n\n container.addEventListener('mouseleave', () => {\n // Delay hiding to allow moving to dropdown\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n }, 150);\n });\n\n // Keep dropdown open when hovering over it\n dropdown.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n });\n\n dropdown.addEventListener('mouseleave', () => {\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n }, 150);\n });\n\n container.appendChild(button);\n container.appendChild(dropdown);\n\n return container;\n }\n\n /**\n * Create seekable progress bar with time display\n */\n private createProgressBar(): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-progress-container';\n\n const slider = document.createElement('input');\n slider.type = 'range';\n slider.className = 'supernal-tts-progress-slider';\n slider.min = '0';\n slider.max = '100';\n slider.value = '0';\n slider.step = '0.1';\n slider.setAttribute('aria-label', 'Seek audio position');\n\n const timeDisplay = document.createElement('div');\n timeDisplay.className = 'supernal-tts-time-display';\n timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n\n // Seeking functionality\n slider.addEventListener('input', (e) => {\n if (this.currentAudio) {\n const percentage = parseFloat((e.target as HTMLInputElement).value);\n this.currentAudio.currentTime = (percentage / 100) * this.currentAudio.duration;\n }\n });\n\n container.appendChild(slider);\n container.appendChild(timeDisplay);\n\n return container;\n }\n\n /**\n * Format seconds to MM:SS\n */\n private formatTime(seconds: number): string {\n if (!seconds || isNaN(seconds)) return '0:00';\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n }\n\n /**\n * Format voice name for display\n */\n private formatVoiceName(voice: string): string {\n // Capitalize first letter and replace dashes/underscores with spaces\n return voice\n .replace(/[-_]/g, ' ')\n .split(' ')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n private createStopButton(): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'supernal-tts-stop';\n button.innerHTML = `\n <svg class=\"supernal-tts-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\"/>\n </svg>\n <span class=\"supernal-tts-text\">Stop</span>\n `;\n button.setAttribute('aria-label', 'Stop text-to-speech');\n return button;\n }\n\n private createPlayButton(compact: boolean = false): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'supernal-tts-play';\n \n if (compact) {\n // Compact mode: icon only, circular button\n button.classList.add('supernal-tts-play-compact');\n button.innerHTML = `\n <svg class=\"supernal-tts-icon supernal-tts-play-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n <svg class=\"supernal-tts-icon supernal-tts-loading-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n `;\n } else {\n // Full mode: icon + text\n button.innerHTML = `\n <svg class=\"supernal-tts-icon supernal-tts-play-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n <svg class=\"supernal-tts-icon supernal-tts-loading-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span class=\"supernal-tts-text\">Listen</span>\n `;\n }\n \n button.setAttribute('aria-label', 'Play text-to-speech');\n return button;\n }\n\n private createBrandingBadge(): HTMLAnchorElement {\n const badge = document.createElement('a');\n badge.className = 'supernal-badge';\n badge.href = 'https://www.tts.supernal.ai';\n badge.target = '_blank';\n badge.rel = 'noopener noreferrer';\n badge.title = 'Powered by Supernal TTS';\n badge.setAttribute('aria-label', 'Powered by Supernal TTS');\n\n // Use new TTS logo (~+) from brand-kit hosted on CDN\n const img = document.createElement('img');\n img.src = 'https://unpkg.com/@supernal/tts-widget@latest/dist/supernal-tts-logo.svg';\n img.alt = 'Supernal TTS';\n img.className = 'supernal-logo-img';\n img.style.display = 'block';\n img.style.width = '24px';\n img.style.height = '24px';\n\n // Fallback to ~+ text if image fails to load\n img.onerror = () => {\n badge.innerHTML = '~+';\n badge.style.fontSize = '16px';\n badge.style.fontWeight = '700';\n badge.style.display = 'flex';\n badge.style.color = '#0066ff';\n };\n\n badge.appendChild(img);\n return badge;\n }\n\n /**\n * Dev Mode Cache Clear Button\n * Adds a minimizable floating button in dev mode to clear local cache\n * Only appears on pages that have TTS widgets\n */\n private addDevModeClearButton(): void {\n // Only add once\n if (document.getElementById('supernal-tts-dev-clear-cache')) {\n return;\n }\n\n // Create container\n const container = document.createElement('div');\n container.id = 'supernal-tts-dev-clear-cache';\n container.style.cssText = `\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 100;\n font-family: system-ui, -apple-system, sans-serif;\n `;\n\n // Minimized button (trash icon only)\n const minimizedBtn = document.createElement('button');\n minimizedBtn.className = 'supernal-tts-dev-button-minimized';\n minimizedBtn.innerHTML = '\uD83D\uDDD1\uFE0F';\n minimizedBtn.title = 'Clear TTS Cache (Dev Mode)';\n minimizedBtn.style.cssText = `\n display: none;\n background: #6c757d;\n color: white;\n border: none;\n padding: 8px;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n font-size: 16px;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n transition: all 0.2s ease;\n `;\n\n // Full button\n const fullBtn = document.createElement('button');\n fullBtn.className = 'supernal-tts-dev-button';\n fullBtn.style.cssText = `\n background: #dc3545;\n color: white;\n border: none;\n padding: 8px 12px;\n border-radius: 5px;\n font-size: 12px;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n `;\n fullBtn.innerHTML = `\n <span>\uD83D\uDDD1\uFE0F</span>\n <span>Clear Cache</span>\n <span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>\n `;\n\n // Hover effects\n const addHoverEffect = (btn: HTMLButtonElement) => {\n btn.addEventListener('mouseenter', () => {\n btn.style.transform = 'scale(1.05)';\n btn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.4)';\n });\n\n btn.addEventListener('mouseleave', () => {\n btn.style.transform = 'scale(1)';\n btn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)';\n });\n };\n\n addHoverEffect(fullBtn);\n addHoverEffect(minimizedBtn);\n\n // Clear cache handler\n const clearCache = () => {\n const count = this.cache.size;\n this.cache.clear();\n localStorage.removeItem('supernal-tts-cache');\n\n // Visual feedback\n fullBtn.innerHTML = `<span>\u2713</span><span>Cleared ${count}</span><span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>`;\n fullBtn.style.background = '#28a745';\n\n setTimeout(() => {\n fullBtn.innerHTML = `<span>\uD83D\uDDD1\uFE0F</span><span>Clear Cache</span><span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>`;\n fullBtn.style.background = '#dc3545';\n }, 2000);\n\n console.log(`[Supernal TTS Dev] Cleared ${count} cached items`);\n };\n\n // Minimize handler\n fullBtn.addEventListener('click', (e) => {\n e.preventDefault();\n const clickX = e.clientX - (e.target as HTMLElement).getBoundingClientRect().left;\n const btnWidth = fullBtn.getBoundingClientRect().width;\n\n // If clicked on the \u00D7 (right 20% of button), minimize\n if (clickX > btnWidth * 0.8) {\n fullBtn.style.display = 'none';\n minimizedBtn.style.display = 'block';\n localStorage.setItem('supernal-tts-dev-minimized', 'true');\n } else {\n clearCache();\n }\n });\n\n // Expand handler\n minimizedBtn.addEventListener('click', (e) => {\n e.preventDefault();\n minimizedBtn.style.display = 'none';\n fullBtn.style.display = 'flex';\n localStorage.setItem('supernal-tts-dev-minimized', 'false');\n });\n\n // Restore minimized state\n const isMinimized = localStorage.getItem('supernal-tts-dev-minimized') === 'true';\n if (isMinimized) {\n fullBtn.style.display = 'none';\n minimizedBtn.style.display = 'block';\n }\n\n container.appendChild(fullBtn);\n container.appendChild(minimizedBtn);\n\n // Add to DOM when ready\n if (document.body) {\n document.body.appendChild(container);\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n document.body.appendChild(container);\n });\n }\n }\n\n private async handlePlayClick(button: HTMLButtonElement, text: string, options: any): Promise<void> {\n const { hash, progressBar } = options;\n \n // If currently playing this button, pause it\n if (button.classList.contains('supernal-tts-playing') && this.currentButton === button) {\n this.pauseAudio();\n return;\n }\n \n // If currently paused on this button, resume it\n if (button.classList.contains('supernal-tts-paused') && this.currentButton === button) {\n this.resumeAudio();\n return;\n }\n \n // Don't allow starting new audio while processing\n if (this.isProcessing) {\n return;\n }\n \n // If another button is playing, stop it first\n if (this.currentAudio && this.currentButton && this.currentButton !== button) {\n this.stopAudio();\n }\n\n try {\n this.isProcessing = true;\n \n // Update button state\n this.setButtonState(button, 'loading');\n \n // Check cache first\n let audioUrl = this.getCachedAudioUrl(hash);\n \n if (!audioUrl) {\n // Determine if we should use progressive mode\n const useProgressive = (\n this.generationMode === 'progressive' || \n (this.generationMode === 'standard' && text.length > this.progressiveThreshold)\n );\n \n if (useProgressive) {\n // Use progressive SSE streaming\n await this.generateAudioProgressive(text, options, button, progressBar);\n return; // generateAudioProgressive handles playback\n } else {\n // Standard generation\n const response = await this.generateAudio(text, options);\n // Convert relative audioUrl to absolute URL\n audioUrl = response.audioUrl.startsWith('http') \n ? response.audioUrl \n : `${this.apiUrl}${response.audioUrl}`;\n \n // Cache the result\n this.cacheAudioUrl(hash, audioUrl, response);\n }\n }\n \n // Play audio with progress bar updates\n await this.playAudio(audioUrl, button, progressBar);\n \n } catch (error) {\n console.error('TTS Error:', error);\n this.setButtonState(button, 'error');\n \n // Show user-friendly error\n this.showError(button, (error as Error).message);\n \n setTimeout(() => this.setButtonState(button, 'ready'), 3000);\n this.isProcessing = false;\n }\n }\n\n private async generateAudio(text: string, options: any): Promise<TTSResponse> {\n const body = {\n text,\n options: {\n provider: options.provider,\n voice: options.voice,\n speed: options.speed || 1.0\n }\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n };\n\n // Use widget-specific API key if provided, otherwise use global\n const apiKey = options.apiKey || this.apiKey;\n console.log('[TTS Widget] Generate Audio - API Key present:', !!apiKey);\n console.log('[TTS Widget] Generate Audio - this.apiKey:', !!this.apiKey);\n console.log('[TTS Widget] Generate Audio - options.apiKey:', !!options.apiKey);\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n console.log('[TTS Widget] Generate Audio - Authorization header added');\n } else {\n console.warn('[TTS Widget] Generate Audio - NO API KEY, Authorization header NOT added');\n }\n\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/generate`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n audioUrl: `${this.apiUrl}${data.audioUrl}`,\n hash: data.hash,\n cached: data.cached,\n duration: data.duration,\n cost: data.cost\n };\n } catch (error) {\n // Log the actual error for debugging\n console.error('TTS generation failed:', error);\n \n // Re-throw with more context but preserve the original error\n if ((error as Error).message.includes('Failed to fetch') || (error as Error).message.includes('NetworkError')) {\n const originalMessage = (error as Error).message;\n throw new Error(`TTS API unreachable: ${originalMessage}. Check if ${this.apiUrl} is accessible.`);\n }\n \n // Re-throw other errors as-is\n throw error;\n }\n }\n\n /**\n * Generate audio using progressive SSE streaming\n * Updates progress bar in real-time as chunks complete\n */\n private async generateAudioProgressive(\n text: string, \n options: any, \n button: HTMLButtonElement, \n progressBar?: HTMLElement | null\n ): Promise<void> {\n const body = {\n text,\n options: {\n provider: options.provider,\n voice: options.voice,\n speed: options.speed || 1.0\n }\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'text/event-stream'\n };\n\n const apiKey = options.apiKey || this.apiKey;\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/generate-progressive`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('No response body for SSE stream');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let totalChunks = 0;\n let completedChunks = 0;\n\n // Update progress bar if available\n const updateProgress = (completed: number, total: number) => {\n if (progressBar) {\n const percentage = (completed / total) * 100;\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) {\n slider.value = percentage.toString();\n }\n \n const currentSpan = progressBar.querySelector<HTMLElement>('.current');\n if (currentSpan) {\n currentSpan.textContent = `Chunk ${completed}/${total}`;\n }\n }\n };\n\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) break;\n \n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n\\n');\n buffer = lines.pop() || '';\n \n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n \n try {\n const event = JSON.parse(line.substring(6));\n \n switch (event.type) {\n case 'started':\n totalChunks = event.totalChunks;\n console.log(`[Progressive TTS] Started: ${totalChunks} chunks`);\n this.setButtonState(button, 'loading');\n break;\n \n case 'progress':\n completedChunks = event.completed;\n console.log(`[Progressive TTS] Progress: ${completedChunks}/${totalChunks}`);\n updateProgress(completedChunks, totalChunks);\n break;\n \n case 'complete':\n console.log(`[Progressive TTS] Complete:`, event);\n const audioUrl = event.audioUrl.startsWith('http') \n ? event.audioUrl \n : `${this.apiUrl}${event.audioUrl}`;\n \n // Cache the final result\n this.cacheAudioUrl(options.hash, audioUrl, {\n hash: event.hash,\n cached: false,\n duration: event.duration,\n cost: event.cost\n });\n \n // Play the final stitched audio\n await this.playAudio(audioUrl, button, progressBar);\n break;\n \n case 'error':\n throw new Error(event.message || 'Progressive generation failed');\n }\n } catch (parseError) {\n console.warn('[Progressive TTS] Failed to parse event:', line, parseError);\n }\n }\n }\n } catch (error) {\n console.error('Progressive TTS generation failed:', error);\n this.isProcessing = false;\n throw error;\n }\n }\n\n private async playAudio(audioUrl: string, button: HTMLButtonElement, progressBar?: HTMLElement | null, playbackSpeed?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const audio = new Audio(audioUrl);\n this.currentAudio = audio;\n this.currentButton = button;\n \n // Enable pitch preservation for client-side speed control\n // This uses native browser time-stretching to maintain pitch quality\n if (this.clientSideSpeed) {\n audio.preservesPitch = true;\n // Fallback for older browsers\n (audio as any).mozPreservesPitch = true;\n (audio as any).webkitPreservesPitch = true;\n }\n \n // Set playback rate if provided (for client-side speed control)\n if (playbackSpeed !== undefined && this.clientSideSpeed) {\n audio.playbackRate = playbackSpeed;\n }\n \n // Clear any existing interval before starting new one\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n audio.addEventListener('loadstart', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'loading');\n }\n });\n \n audio.addEventListener('canplay', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'playing');\n this.isProcessing = false;\n const playPromise = audio.play();\n if (playPromise !== undefined) {\n playPromise.catch(error => {\n console.error('Audio play failed:', error);\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n this.isProcessing = false;\n reject(new Error('Audio playback failed'));\n }\n });\n }\n \n // Start progress bar updates using global interval\n if (progressBar) {\n progressBar.classList.add('playing');\n this.progressUpdateInterval = window.setInterval(() => {\n this.updateProgressBar(audio, progressBar);\n }, 100);\n }\n }\n });\n \n audio.addEventListener('ended', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'ready');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n // Reset progress bar\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) slider.value = '0';\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n \n resolve();\n }\n });\n \n audio.addEventListener('error', (e) => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n }\n \n reject(new Error('Audio playback failed'));\n }\n });\n \n audio.load();\n });\n }\n\n /**\n * Update progress bar during playback\n */\n private updateProgressBar(audio: HTMLAudioElement, progressBar: HTMLElement): void {\n if (!audio || !progressBar) return;\n \n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n const currentTimeSpan = progressBar.querySelector<HTMLElement>('.current');\n const durationSpan = progressBar.querySelector<HTMLElement>('.duration');\n \n if (slider && !isNaN(audio.duration)) {\n const percentage = (audio.currentTime / audio.duration) * 100;\n slider.value = percentage.toString();\n }\n \n if (currentTimeSpan) {\n currentTimeSpan.textContent = this.formatTime(audio.currentTime);\n }\n \n if (durationSpan && !isNaN(audio.duration)) {\n durationSpan.textContent = this.formatTime(audio.duration);\n }\n }\n\n private pauseAudio(): void {\n if (this.currentAudio && !this.currentAudio.paused) {\n this.currentAudio.pause();\n }\n \n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'paused');\n }\n }\n\n private resumeAudio(): void {\n if (this.currentAudio && this.currentAudio.paused) {\n const playPromise = this.currentAudio.play();\n if (playPromise !== undefined) {\n playPromise.then(() => {\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'playing');\n }\n }).catch(error => {\n console.error('Audio resume failed:', error);\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'error');\n }\n });\n }\n }\n }\n\n private stopAudio(): void {\n // Clear interval first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'ready');\n this.currentButton = null;\n }\n \n this.isProcessing = false;\n }\n\n /**\n * Clean stop audio with proper progress bar cleanup\n * Used when regenerating audio with different parameters\n */\n private cleanStopAudio(progressBar?: HTMLElement | null): void {\n // Clear interval first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n // Stop and clear audio\n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n // Reset button state\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'ready');\n this.currentButton = null;\n }\n \n // Clean up progress bar immediately\n if (progressBar) {\n progressBar.classList.remove('playing');\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) {\n slider.value = '0';\n }\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) {\n timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n }\n \n this.isProcessing = false;\n }\n\n /**\n * Clean stop audio but keep progress bar at current position (for voice/speed changes)\n */\n private cleanStopAudioKeepProgress(progressBar?: HTMLElement | null): void {\n // Clear any existing progress update intervals first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n // Stop and clear audio\n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n // Reset button state but don't clear currentButton yet (we're regenerating)\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'loading');\n }\n \n // Keep progress bar visible but stop updates\n // Progress position is maintained by not resetting the slider value\n \n this.isProcessing = false;\n }\n\n /**\n * Handle play click and seek to a specific position (used for voice/speed changes)\n */\n private async handlePlayClickFromPosition(button: HTMLButtonElement, text: string, options: any, positionPercent: number): Promise<void> {\n const { hash, progressBar } = options;\n \n // Don't allow starting new audio while processing\n if (this.isProcessing) {\n return;\n }\n\n try {\n this.isProcessing = true;\n \n // Update button state\n this.setButtonState(button, 'loading');\n \n // Check cache first\n let audioUrl = this.getCachedAudioUrl(hash);\n \n if (!audioUrl) {\n // Generate new audio\n const response = await this.generateAudio(text, options);\n // Convert relative audioUrl to absolute URL\n audioUrl = response.audioUrl.startsWith('http') \n ? response.audioUrl \n : `${this.apiUrl}${response.audioUrl}`;\n \n // Cache the result\n this.cacheAudioUrl(hash, audioUrl, response);\n }\n \n // Play audio with progress bar updates and seek to saved position\n await this.playAudioFromPosition(audioUrl, button, progressBar, positionPercent);\n \n } catch (error) {\n console.error('TTS Error:', error);\n this.setButtonState(button, 'error');\n \n // Show user-friendly error\n this.showError(button, (error as Error).message);\n \n setTimeout(() => this.setButtonState(button, 'ready'), 3000);\n this.isProcessing = false;\n }\n }\n\n /**\n * Play audio starting from a specific position\n */\n private async playAudioFromPosition(audioUrl: string, button: HTMLButtonElement, progressBar: HTMLElement | null | undefined, positionPercent: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const audio = new Audio(audioUrl);\n this.currentAudio = audio;\n this.currentButton = button;\n \n // Enable pitch preservation for client-side speed control\n // This uses native browser time-stretching to maintain pitch quality\n if (this.clientSideSpeed) {\n audio.preservesPitch = true;\n // Fallback for older browsers\n (audio as any).mozPreservesPitch = true;\n (audio as any).webkitPreservesPitch = true;\n }\n \n // Clear any existing interval before starting new one\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n let hasSeekCompleted = false;\n \n audio.addEventListener('loadstart', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'loading');\n }\n });\n \n audio.addEventListener('loadedmetadata', () => {\n // Once we know the duration, seek to the saved position\n if (this.currentAudio === audio && !hasSeekCompleted && positionPercent > 0) {\n audio.currentTime = audio.duration * positionPercent;\n hasSeekCompleted = true;\n }\n });\n \n audio.addEventListener('canplay', () => {\n if (this.currentAudio === audio) {\n // Seek again if metadata wasn't ready earlier\n if (!hasSeekCompleted && positionPercent > 0 && audio.duration > 0) {\n audio.currentTime = audio.duration * positionPercent;\n hasSeekCompleted = true;\n }\n \n this.setButtonState(button, 'playing');\n this.isProcessing = false;\n const playPromise = audio.play();\n if (playPromise !== undefined) {\n playPromise.catch(error => {\n console.error('Audio play failed:', error);\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n this.isProcessing = false;\n reject(new Error('Audio playback failed'));\n }\n });\n }\n \n // Start progress bar updates using global interval\n if (progressBar) {\n progressBar.classList.add('playing');\n this.progressUpdateInterval = window.setInterval(() => {\n this.updateProgressBar(audio, progressBar);\n }, 100);\n }\n }\n });\n \n audio.addEventListener('ended', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'ready');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n // Reset progress bar\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) slider.value = '0';\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n \n resolve();\n }\n });\n \n audio.addEventListener('error', (e) => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n }\n \n reject(new Error('Audio playback failed'));\n }\n });\n \n audio.load();\n });\n }\n\n private setButtonState(button: HTMLButtonElement, state: string): void {\n button.classList.remove('supernal-tts-loading', 'supernal-tts-playing', 'supernal-tts-paused', 'supernal-tts-error');\n \n const playIcon = button.querySelector<SVGElement>('.supernal-tts-play-icon');\n const text = button.querySelector<HTMLSpanElement>('.supernal-tts-text');\n \n switch (state) {\n case 'loading':\n button.classList.add('supernal-tts-loading');\n button.disabled = true;\n // Loading spinner shown via CSS\n if (text) text.textContent = 'Loading...';\n break;\n \n case 'playing':\n button.classList.add('supernal-tts-playing');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<rect x=\"6\" y=\"4\" width=\"4\" height=\"16\"/><rect x=\"14\" y=\"4\" width=\"4\" height=\"16\"/>';\n if (text) text.textContent = 'Pause';\n break;\n \n case 'paused':\n button.classList.add('supernal-tts-paused');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M8 5v14l11-7z\"/>';\n if (text) text.textContent = 'Resume';\n break;\n \n case 'error':\n button.classList.add('supernal-tts-error');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z\"/>';\n if (text) text.textContent = 'Error';\n break;\n \n default: // ready\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M8 5v14l11-7z\"/>';\n if (text) text.textContent = 'Listen';\n break;\n }\n }\n\n private showError(button: HTMLButtonElement, message: string): void {\n const tooltip = document.createElement('div');\n tooltip.className = 'supernal-tts-error-tooltip';\n \n if (message.includes('development mode')) {\n tooltip.textContent = message;\n } else if (message.includes('Failed to fetch')) {\n tooltip.textContent = 'Service unavailable (dev mode)';\n } else {\n tooltip.textContent = 'Audio generation failed';\n }\n \n button.parentNode?.appendChild(tooltip);\n \n setTimeout(() => {\n if (tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n }\n }, 3000);\n }\n\n private generateHash(text: string, options: any = {}): string {\n const str = text + JSON.stringify(options);\n let hash = 0;\n \n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n \n return Math.abs(hash).toString(36);\n }\n\n private getCachedAudioUrl(hash: string): string | null {\n const cached = this.cache.get(hash);\n \n if (!cached) return null;\n \n if (Date.now() > cached.expiry) {\n this.cache.delete(hash);\n this.saveCacheToStorage();\n return null;\n }\n \n const audioUrl = cached.audioUrl;\n return audioUrl.startsWith('http') \n ? audioUrl \n : `${this.apiUrl}${audioUrl}`;\n }\n\n private cacheAudioUrl(hash: string, audioUrl: string, metadata: any = {}): void {\n this.cache.set(hash, {\n audioUrl,\n metadata,\n expiry: Date.now() + this.cacheExpiry,\n timestamp: Date.now()\n });\n \n this.saveCacheToStorage();\n }\n\n private loadCacheFromStorage(): void {\n try {\n const stored = localStorage.getItem('supernal-tts-cache');\n if (stored) {\n const data = JSON.parse(stored);\n this.cache = new Map(Object.entries(data));\n }\n } catch (error) {\n console.warn('Failed to load TTS cache:', error);\n }\n }\n\n private saveCacheToStorage(): void {\n try {\n const data = Object.fromEntries(this.cache);\n localStorage.setItem('supernal-tts-cache', JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save TTS cache:', error);\n }\n }\n\n // Public API methods\n public static init(options?: SupernalTTSOptions): SupernalTTS {\n if ((window as any).SupernalTTSInstance) {\n console.debug('SupernalTTS already initialized, returning existing instance');\n return (window as any).SupernalTTSInstance;\n }\n \n (window as any).SupernalTTSInstance = new SupernalTTS(options);\n return (window as any).SupernalTTSInstance;\n }\n\n public static getInstance(): SupernalTTS | undefined {\n return (window as any).SupernalTTSInstance;\n }\n\n public addWidget(element: HTMLElement | string, text: string, options: any = {}): void {\n let el: HTMLElement | null = null;\n \n if (typeof element === 'string') {\n el = document.querySelector<HTMLElement>(element);\n } else {\n el = element;\n }\n \n if (!el) {\n console.error('TTS Widget: Element not found');\n return;\n }\n \n el.classList.add('supernal-tts-widget');\n el.dataset.text = text;\n \n if (options.voice) el.dataset.voice = options.voice;\n if (options.provider) el.dataset.provider = options.provider;\n \n this.setupWidget(el);\n }\n}\n\n// Auto-initialize if configuration is found\nif (typeof window !== 'undefined') {\n if (!(window as any).SupernalTTS) {\n (window as any).SupernalTTS = SupernalTTS;\n \n const autoInitScript = document.querySelector<HTMLScriptElement>('script[data-supernal-tts-auto-init]');\n if (autoInitScript && autoInitScript.dataset) {\n const config = JSON.parse(autoInitScript.dataset.supernalTtsAutoInit || '{}');\n SupernalTTS.init(config);\n }\n } else {\n console.debug('SupernalTTS already loaded, skipping redeclaration');\n }\n}\n\nexport default SupernalTTS;\n\n", "/**\n * Smart Widget Loader\n *\n * Dynamically loads the latest compatible widget version from unpkg CDN\n * with automatic fallback to bundled version for CSP/firewall scenarios.\n *\n * @example\n * ```typescript\n * import { WidgetLoader } from '@supernal-tts/widget';\n *\n * // Default: CDN @1 with fallback\n * const widget = await WidgetLoader.load();\n *\n * // Force bundled (CSP-safe)\n * const widget = await WidgetLoader.load({ mode: 'bundled' });\n *\n * // Pin specific version\n * const widget = await WidgetLoader.load({ version: '1.2.1' });\n * ```\n */\n\nexport interface LoaderOptions {\n /**\n * Version strategy:\n * - 'major': Load latest v1.x.x (default, recommended)\n * - 'latest': Load absolute latest (risky, may break)\n * - '1.2.1': Pin to specific version\n */\n version?: 'latest' | 'major' | string;\n\n /**\n * Loading mode:\n * - 'auto': Try CDN, fallback to bundled (default)\n * - 'cdn': Force CDN load, error if unavailable\n * - 'bundled': Always use bundled version (CSP-safe)\n */\n mode?: 'cdn' | 'bundled' | 'auto';\n\n /**\n * Custom CDN URL (default: https://unpkg.com/@supernal/tts-widget)\n */\n cdnUrl?: string;\n\n /**\n * CDN fetch timeout in milliseconds (default: 3000)\n */\n timeout?: number;\n\n /**\n * Callback when CDN load fails and fallback is used\n */\n onCdnFail?: (error: Error) => void;\n\n /**\n * Callback when CDN load succeeds\n */\n onCdnSuccess?: () => void;\n}\n\nexport interface SupernalTTSModule {\n SupernalTTS: any;\n}\n\n// Package version injected at build time\ndeclare const __PACKAGE_VERSION__: string;\n\nexport class WidgetLoader {\n private static instance: any = null;\n private static loadPromise: Promise<any> | null = null;\n\n /**\n * Load the Supernal TTS widget with smart CDN loading and fallback\n */\n static async load(options: LoaderOptions = {}): Promise<any> {\n // Return cached instance if already loaded\n if (this.instance) {\n return this.instance;\n }\n\n // Return existing load promise if already loading\n if (this.loadPromise) {\n return this.loadPromise;\n }\n\n const {\n version = 'major',\n mode = 'auto',\n cdnUrl = 'https://unpkg.com/@supernal/tts-widget',\n timeout = 3000,\n onCdnFail,\n onCdnSuccess\n } = options;\n\n // Start loading process\n this.loadPromise = this.loadWidget({\n version,\n mode,\n cdnUrl,\n timeout,\n onCdnFail,\n onCdnSuccess\n });\n\n return this.loadPromise;\n }\n\n private static async loadWidget(options: {\n mode: 'cdn' | 'bundled' | 'auto';\n version: string;\n cdnUrl: string;\n timeout: number;\n onCdnFail?: (error: Error) => void;\n onCdnSuccess?: () => void;\n }): Promise<any> {\n const { mode, version, cdnUrl, timeout, onCdnFail, onCdnSuccess } = options;\n\n // Force bundled mode (CSP-safe, offline-safe)\n if (mode === 'bundled') {\n console.log('[TTS Widget] Loading bundled version (mode: bundled)');\n return this.loadBundled();\n }\n\n // Try CDN first (mode === 'cdn' or 'auto')\n if (mode === 'cdn' || mode === 'auto') {\n try {\n console.log('[TTS Widget] Attempting CDN load...');\n const widget = await this.loadFromCdn(cdnUrl, version, timeout);\n\n console.log('[TTS Widget] CDN load successful');\n onCdnSuccess?.();\n\n this.instance = widget;\n return widget;\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.warn('[TTS Widget] CDN load failed:', errorMessage);\n\n onCdnFail?.(error instanceof Error ? error : new Error(errorMessage));\n\n // In 'cdn' mode, throw the error (no fallback)\n if (mode === 'cdn') {\n throw new Error(`Failed to load widget from CDN: ${errorMessage}`);\n }\n\n // In 'auto' mode, fallback to bundled\n console.log('[TTS Widget] Falling back to bundled version');\n return this.loadBundled();\n }\n }\n\n // Should never reach here, but fallback to bundled just in case\n return this.loadBundled();\n }\n\n private static async loadFromCdn(\n cdnUrl: string,\n version: string,\n timeout: number\n ): Promise<any> {\n const versionPath = this.resolveVersionPath(version);\n const url = `${cdnUrl}${versionPath}/dist/widget.js`;\n\n console.log(`[TTS Widget] Loading from CDN: ${url}`);\n\n // Create timeout controller\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n // Dynamic import with timeout\n // Note: AbortController support in dynamic import is limited, so we use a race\n const modulePromise = import(/* @vite-ignore */ url);\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error(`CDN load timeout after ${timeout}ms`)), timeout);\n });\n\n const module = await Promise.race([modulePromise, timeoutPromise]) as SupernalTTSModule;\n\n clearTimeout(timeoutId);\n\n if (!module || !module.SupernalTTS) {\n throw new Error('CDN module missing SupernalTTS export');\n }\n\n this.instance = module.SupernalTTS;\n return this.instance;\n\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n private static async loadBundled(): Promise<any> {\n try {\n // Import bundled widget\n const module = await import('./widget.js') as SupernalTTSModule;\n\n if (!module || !module.SupernalTTS) {\n throw new Error('Bundled widget missing SupernalTTS export');\n }\n\n this.instance = module.SupernalTTS;\n return this.instance;\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load bundled widget: ${errorMessage}`);\n }\n }\n\n private static resolveVersionPath(version: string): string {\n // Major version (e.g., \"1\" from \"1.2.1\")\n if (version === 'major') {\n const majorVersion = this.getMajorVersion();\n return `@${majorVersion}`;\n }\n\n // Always latest (risky)\n if (version === 'latest') {\n return '@latest';\n }\n\n // Specific version (e.g., \"1.2.1\")\n return `@${version}`;\n }\n\n private static getMajorVersion(): string {\n // Try to read from injected package version\n if (typeof __PACKAGE_VERSION__ !== 'undefined') {\n const match = __PACKAGE_VERSION__.match(/^(\\d+)\\./);\n if (match) {\n return match[1];\n }\n }\n\n // Fallback to hardcoded major version\n // This will be replaced by the build process\n return '1';\n }\n\n /**\n * Reset the loader (useful for testing)\n */\n static reset(): void {\n this.instance = null;\n this.loadPromise = null;\n }\n\n /**\n * Get current loaded instance (if any)\n */\n static getInstance(): any | null {\n return this.instance;\n }\n}\n\n// Default export for convenience\nexport default WidgetLoader;\n"],
|
|
5
|
-
"mappings": "6HAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,YAAAC,IAAA,IAsEaD,EA47DNC,EAlgEPC,EAAAC,EAAA,kBAsEaH,EAAN,MAAMI,CAAY,CAyBvB,YAAYC,EAA8B,CAAC,EAAG,CAT9C,KAAQ,aAAwC,KAChD,KAAQ,cAA0C,KAElD,KAAQ,aAAwB,GAChC,KAAQ,cAAwB,EAChC,KAAQ,cAAwB,IAChC,KAAQ,uBAAwC,KAChD,KAAQ,WAA2B,CAAC,EAGlC,KAAK,OAASA,EAAQ,QAAU,8BAChC,KAAK,aAAeA,EAAQ,OAAS,UACrC,KAAK,gBAAkBA,EAAQ,UAAY,SAC3C,KAAK,aAAeA,EAAQ,OAAS,EACrC,KAAK,SAAWA,EAAQ,WAAa,GACrC,KAAK,YAAcA,EAAQ,aAAe,EAAI,GAAK,GAAK,GAAK,IAC7D,KAAK,OAASA,EAAQ,OACtB,QAAQ,IAAI,+CAAgD,CAAC,CAACA,EAAQ,MAAM,EAC5E,QAAQ,IAAI,4CAA6C,CAAC,CAAC,KAAK,MAAM,EACtE,KAAK,aAAeA,EAAQ,eAAiB,GAC7C,KAAK,QAAUA,EAAQ,SAAW,QAElC,KAAK,QAAUA,EAAQ,UAAY,GACnC,KAAK,gBAAkBA,EAAQ,kBAAoB,GACnD,KAAK,eAAiBA,EAAQ,gBAAkB,WAChD,KAAK,qBAAuBA,EAAQ,sBAAwB,IAE5D,KAAK,MAAQ,IAAI,IACjB,KAAK,qBAAqB,EAE1B,KAAK,KAAK,CACZ,CAEQ,MAAa,CAEf,SAAS,aAAe,UAC1B,SAAS,iBAAiB,mBAAoB,IAAM,KAAK,kBAAkB,CAAC,EAE5E,KAAK,kBAAkB,EAKzB,KAAK,WAAW,CAClB,CAEQ,YAAmB,CAER,IAAI,iBAAkBC,GAAc,CACnDA,EAAU,QAASC,GAAa,CAC9BA,EAAS,WAAW,QAASC,GAAS,CAEpC,GAAIA,EAAK,WAAa,KAAK,aAAc,CACvC,IAAMC,EAAUD,EAGZC,EAAQ,WAAW,SAAS,qBAAqB,EACnD,KAAK,YAAYA,CAAO,EAGRA,EAAQ,mBAAmB,sBAAsB,GACxD,QAASC,GAAW,KAAK,YAAYA,CAAqB,CAAC,CAExE,CACF,CAAC,CACH,CAAC,CACH,CAAC,EAGQ,QAAQ,SAAS,KAAM,CAC9B,UAAW,GACX,QAAS,EACX,CAAC,CACH,CAEQ,mBAA0B,CAChC,IAAMC,EAAU,SAAS,iBAA8B,sBAAsB,EAC7EA,EAAQ,QAAQD,GAAU,KAAK,YAAYA,CAAM,CAAC,EAG9C,KAAK,SAAWC,EAAQ,OAAS,GACnC,KAAK,sBAAsB,CAE/B,CAEQ,YAAYF,EAA4B,CAE9C,GAAIA,EAAQ,UAAU,SAAS,iCAAiC,EAC9D,OAIF,IAAMG,EAAS,KAAK,kBAAkBH,CAAO,EAE7C,GAAI,CAACG,EAAO,KAAM,CAChB,QAAQ,KAAK,uCAAwCH,CAAO,EAC5D,MACF,CAGA,IAAMI,EAAO,KAAK,aAAaD,EAAO,KAAM,CAC1C,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,MAAOA,EAAO,KAChB,CAAC,EAGKE,EAAWL,EAAQ,QAAQ,SACjC,GAAIK,IAAa,YAAcA,IAAa,OAAQ,CAClD,KAAK,oBAAoBL,EAASG,EAAO,KAAM,CAC7C,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,MAAOA,EAAO,MACd,KAAAC,EACA,OAAQD,EAAO,MACjB,CAAC,EACD,MACF,SAAWE,IAAa,UAAW,CACjC,KAAK,mBAAmBL,EAASG,EAAO,KAAM,CAC5C,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,MAAOA,EAAO,MACd,KAAAC,EACA,OAAQD,EAAO,MACjB,CAAC,EACD,MACF,CAGA,KAAK,mBAAmBH,EAASG,EAAQC,CAAI,CAC/C,CAKQ,kBAAkBJ,EAAoC,CAC5D,IAAMM,EAAON,EAAQ,QAAQ,MAAQA,EAAQ,aAAa,KAAK,GAAK,GAC9DO,EAAQP,EAAQ,QAAQ,OAAS,KAAK,aACtCQ,EAAWR,EAAQ,QAAQ,UAAY,KAAK,gBAC5CS,EAAQT,EAAQ,QAAQ,MAAQ,WAAWA,EAAQ,QAAQ,KAAK,EAAI,KAAK,aAGzEU,EAAaV,EAAQ,QAAQ,QAAU,GACvCW,EAASD,EAAaA,EAAW,MAAM,GAAG,EAAE,IAAIE,GAAKA,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,EAAI,CAAC,EAGlFC,EAAcb,EAAQ,QAAQ,cAAgB,OAC9Cc,EAAiBd,EAAQ,QAAQ,iBAAmB,OAGpDe,EAASf,EAAQ,QAAQ,QAAU,KAAK,OAE9C,MAAO,CACL,KAAAM,EACA,OAAAK,EACA,YAAAE,EACA,eAAAC,EACA,MAAAL,EACA,SAAAD,EACA,MAAAD,EACA,OAAAQ,CACF,CACF,CAEQ,iBAAiBf,EAAsBM,EAAcV,EAAoB,CAC/E,GAAM,CAAE,MAAAW,EAAO,SAAAC,EAAU,MAAAC,EAAO,KAAAL,EAAM,OAAAW,CAAO,EAAInB,EAGjD,GAAII,EAAQ,UAAU,SAAS,iCAAiC,EAC9D,OAIF,IAAMgB,EAAkB,SAAS,cAAc,KAAK,EACpDA,EAAgB,UAAY,gCAG5B,IAAIC,EAAajB,EAAQ,cAAiC,oBAAoB,EAQ9E,GAPKiB,IACHA,EAAa,KAAK,iBAAiB,GAGrCD,EAAgB,YAAYC,CAAU,EAGlC,KAAK,cAAgB,CAACjB,EAAQ,cAAc,iBAAiB,EAAG,CAClE,IAAMkB,EAAQ,KAAK,oBAAoB,EACvCF,EAAgB,YAAYE,CAAK,CACnC,CAEAlB,EAAQ,YAAYgB,CAAe,EAGnChB,EAAQ,UAAU,IAAI,iCAAiC,EAGvDiB,EAAW,iBAAiB,QAAUE,GAAM,CAC1CA,EAAE,eAAe,EACjB,KAAK,gBAAgBF,EAAYX,EAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,MAAAC,EAAO,KAAAL,EAAM,OAAAW,CAAO,CAAC,CACjF,CAAC,EAGAf,EAAgB,WAAa,CAC5B,KAAAM,EACA,MAAAC,EACA,SAAAC,EACA,MAAAC,EACA,KAAAL,EACA,WAAAa,CACF,CACF,CAEQ,mBAAmBjB,EAAsBM,EAAcV,EAAoB,CACjF,GAAM,CAAE,KAAAQ,EAAM,OAAAW,CAAO,EAAInB,EACrB,CAAE,MAAAW,EAAO,SAAAC,EAAU,MAAAC,CAAM,EAAIb,EAGjC,GAAII,EAAQ,UAAU,SAAS,iCAAiC,EAC9D,OAIF,IAAMoB,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,8BAGtB,IAAMC,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,uBAEnB,IAAMJ,EAAa,KAAK,iBAAiB,EAGnCK,EAAc,SAAS,cAAc,QAAQ,EAgBnD,GAfAA,EAAY,UAAY,4BACxBA,EAAY,UAAY;AAAA,8BACEf,IAAU,QAAU,WAAa,EAAE;AAAA,6BACpCA,IAAU,OAAS,WAAa,EAAE;AAAA,8BACjCA,IAAU,QAAU,WAAa,EAAE;AAAA,6BACpCA,IAAU,OAAS,WAAa,EAAE;AAAA,6BAClCA,IAAU,OAAS,WAAa,EAAE;AAAA,gCAC/BA,IAAU,UAAY,WAAa,EAAE;AAAA,8BACvCA,IAAU,QAAU,WAAa,EAAE;AAAA,MAG7Dc,EAAO,YAAYJ,CAAU,EAC7BI,EAAO,YAAYC,CAAW,EAG1B,KAAK,aAAc,CACrB,IAAMJ,EAAQ,KAAK,oBAAoB,EACvCG,EAAO,YAAYH,CAAK,CAC1B,CAGA,IAAMK,EAAe,SAAS,cAAc,KAAK,EACjDA,EAAa,UAAY,6BACzBA,EAAa,UAAY;AAAA,6DACgCd,CAAK;AAAA,sGACoCA,CAAK;AAAA,MAIvGW,EAAU,YAAYC,CAAM,EAC5BD,EAAU,YAAYG,CAAY,EAElCvB,EAAQ,UAAY,GACpBA,EAAQ,YAAYoB,CAAS,EAC7BpB,EAAQ,UAAU,IAAI,kCAAmC,6BAA6B,EAGtF,IAAMwB,EAAcD,EAAa,cAAgC,4BAA4B,EACvFE,EAAaF,EAAa,cAA+B,2BAA2B,EAE1FN,EAAW,iBAAiB,QAAUE,GAAM,CAC1CA,EAAE,eAAe,EACjBV,EAAQ,WAAWe,EAAY,KAAK,EACpCjB,EAAQe,EAAY,MACpB,IAAMI,EAAU,KAAK,aAAapB,EAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,MAAAC,CAAM,CAAC,EAClE,KAAK,gBAAgBQ,EAAYX,EAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,MAAAC,EAAO,KAAMiB,EAAS,OAAAX,CAAO,CAAC,CAC1F,CAAC,EAEDS,EAAY,iBAAiB,QAAUL,GAAM,CAC3CV,EAAQ,WAAYU,EAAE,OAA4B,KAAK,EACvDM,EAAW,YAAc,GAAGhB,CAAK,GACnC,CAAC,EAEDa,EAAY,iBAAiB,SAAU,IAAM,CAC3Cf,EAAQe,EAAY,KACtB,CAAC,EAGAtB,EAAgB,WAAa,CAC5B,KAAAM,EACA,MAAAC,EACA,SAAAC,EACA,MAAAC,EACA,KAAAL,EACA,WAAAa,EACA,QAAS,EACX,CACF,CAEQ,oBAAoBjB,EAAsBM,EAAcV,EAAoB,CAClF,GAAM,CAAE,KAAAQ,EAAM,OAAAW,CAAO,EAAInB,EACrB,CAAE,MAAAW,EAAO,SAAAC,EAAU,MAAAC,CAAM,EAAIb,EAG3BwB,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,+BAGtB,IAAMO,EAAc,SAAS,cAAc,KAAK,EAChDA,EAAY,UAAY,4BAExB,IAAMV,EAAa,KAAK,iBAAiB,EACnCW,EAAa,KAAK,iBAAiB,EAEzCD,EAAY,YAAYV,CAAU,EAClCU,EAAY,YAAYC,CAAU,EAGlC,IAAMN,EAAc,SAAS,cAAc,QAAQ,EACnDA,EAAY,UAAY,4BACxBA,EAAY,UAAY;AAAA,8BACEf,IAAU,QAAU,WAAa,EAAE;AAAA,6BACpCA,IAAU,OAAS,WAAa,EAAE;AAAA,8BACjCA,IAAU,QAAU,WAAa,EAAE;AAAA,6BACpCA,IAAU,OAAS,WAAa,EAAE;AAAA,6BAClCA,IAAU,OAAS,WAAa,EAAE;AAAA,gCAC/BA,IAAU,UAAY,WAAa,EAAE;AAAA,8BACvCA,IAAU,QAAU,WAAa,EAAE;AAAA,MAI7D,IAAMgB,EAAe,SAAS,cAAc,KAAK,EACjDA,EAAa,UAAY,6BACzBA,EAAa,UAAY;AAAA,6DACgCd,CAAK;AAAA,sGACoCA,CAAK;AAAA,MAIvG,IAAMoB,EAAc,SAAS,cAAc,KAAK,EAchD,GAbAA,EAAY,UAAY,wBACxBA,EAAY,UAAY;AAAA;AAAA;AAAA,MAMxBT,EAAU,YAAYO,CAAW,EACjCP,EAAU,YAAYE,CAAW,EACjCF,EAAU,YAAYG,CAAY,EAClCH,EAAU,YAAYS,CAAW,EAG7B,KAAK,aAAc,CACrB,IAAMX,EAAQ,KAAK,oBAAoB,EACvCE,EAAU,YAAYF,CAAK,CAC7B,CAEAlB,EAAQ,UAAY,GACpBA,EAAQ,YAAYoB,CAAS,EAC7BpB,EAAQ,UAAU,IAAI,kCAAmC,8BAA8B,EAGvF,IAAMwB,EAAcD,EAAa,cAAgC,4BAA4B,EACvFE,EAAaF,EAAa,cAA+B,2BAA2B,EACpFO,EAAiBD,EAAY,cAAgC,+BAA+B,EAElGZ,EAAW,iBAAiB,QAAUE,GAAM,CAC1CA,EAAE,eAAe,EACjBV,EAAQ,WAAWe,EAAY,KAAK,EACpCjB,EAAQe,EAAY,MACpB,IAAMI,EAAU,KAAK,aAAapB,EAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,MAAAC,CAAM,CAAC,EAClE,KAAK,gBAAgBQ,EAAYX,EAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,MAAAC,EAAO,KAAMiB,EAAS,OAAAX,CAAO,CAAC,CAC1F,CAAC,EAEDa,EAAW,iBAAiB,QAAUT,GAAM,CAC1CA,EAAE,eAAe,EACjB,KAAK,UAAU,CACjB,CAAC,EAEDK,EAAY,iBAAiB,QAAUL,GAAM,CAC3CV,EAAQ,WAAYU,EAAE,OAA4B,KAAK,EACvDM,EAAW,YAAc,GAAGhB,CAAK,GACnC,CAAC,EAEDa,EAAY,iBAAiB,SAAU,IAAM,CAC3Cf,EAAQe,EAAY,KACtB,CAAC,EAEDQ,EAAe,iBAAiB,QAAUX,GAAM,CAC9C,GAAI,KAAK,aAAc,CACrB,IAAMY,EAAU,WAAYZ,EAAE,OAA4B,KAAK,EAAI,IACnE,KAAK,aAAa,YAAc,KAAK,aAAa,SAAWY,CAC/D,CACF,CAAC,EAeD,YAZuB,IAAM,CAC3B,GAAI,KAAK,cAAiB/B,EAAgB,aAAe,KAAK,cAAe,CAC3E,IAAM+B,EAAW,KAAK,aAAa,YAAc,KAAK,aAAa,SAAY,IAC/ED,EAAe,MAAQC,EAAQ,SAAS,EAExC,IAAMC,EAAc,KAAK,WAAW,KAAK,aAAa,WAAW,EAC3DC,EAAW,KAAK,WAAW,KAAK,aAAa,QAAQ,EAC3DJ,EAAY,cAAc,4BAA4B,EAAG,YAAcG,EACvEH,EAAY,cAAc,wBAAwB,EAAG,YAAcI,CACrE,CACF,EAE4B,GAAG,EAG9BjC,EAAgB,WAAa,CAC5B,KAAAM,EACA,MAAAC,EACA,SAAAC,EACA,MAAAC,EACA,KAAAL,EACA,WAAAa,EACA,WAAAW,EACA,YAAAN,EACA,YAAAE,EACA,eAAAM,EACA,SAAU,EACZ,EAEA,KAAK,cAAiB9B,EAAgB,UACxC,CAKQ,mBAAmBA,EAAsBG,EAAsBC,EAAoB,CACzF,IAAI8B,EAAe/B,EAAO,MACtBgC,EAAehC,EAAO,MACpB,CAAE,KAAAG,EAAM,OAAAK,EAAQ,YAAAE,EAAa,eAAAC,EAAgB,SAAAN,EAAU,OAAAO,CAAO,EAAIZ,EACpEiC,EAAwB,EAGtBhB,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,8BAGtB,IAAMiB,EAAc,SAAS,cAAc,KAAK,EAChDA,EAAY,UAAY,4BAGxB,IAAMpB,EAAa,KAAK,iBAAiB,EAAI,EAC7CoB,EAAY,YAAYpB,CAAU,EAGlC,IAAIqB,EAAoC,KACpC3B,EAAO,OAAS,IAClB2B,EAAgB,KAAK,oBAAoB3B,EAAQuB,CAAY,EAC7DG,EAAY,YAAYC,CAAa,EAGrCA,EAAc,iBAAiB,gBAAmBnB,GAAmB,CACnE,IAAMoB,EAAWpB,EAAE,OAAO,MAG1B,GAAIoB,IAAaL,GAAgB,KAAK,gBAAkBjB,GAAc,KAAK,aAAc,CACvFiB,EAAeK,EAGX,KAAK,aAAa,SAAW,IAC/BH,EAAgB,KAAK,aAAa,YAAc,KAAK,aAAa,UAKpE,IAAMP,EADc7B,EAAgB,YACJ,YAGhC,KAAK,2BAA2B6B,CAAW,EAG3C,WAAW,IAAM,CACf,KAAK,4BAA4BZ,EAAYX,EAAM,CACjD,MAAO4B,EACP,SAAA1B,EACA,MAAO2B,EACP,KAAM,KAAK,aAAa7B,EAAM,CAAE,MAAO4B,EAAc,SAAA1B,EAAU,MAAO2B,CAAa,CAAC,EACpF,YAAAN,EACA,OAAAd,CACF,EAAGqB,CAAa,CAClB,EAAG,EAAE,CACP,MACEF,EAAeK,CAEnB,CAAmB,GAIrB,IAAIC,EAAoC,KAiDxC,GAhDI3B,IACF2B,EAAgB,KAAK,oBAAoBL,CAAY,EACrDE,EAAY,YAAYG,CAAa,EAGrCA,EAAc,iBAAiB,gBAAmBrB,GAAmB,CACnE,IAAMsB,EAAWtB,EAAE,OAAO,MAE1B,GAAIsB,IAAaN,GAIf,GAHAA,EAAeM,EAGX,KAAK,iBAAmB,KAAK,cAAgB,KAAK,gBAAkBxB,EAGtE,KAAK,aAAa,aAAewB,UAG1B,CAAC,KAAK,iBAAmB,KAAK,gBAAkBxB,GAAc,KAAK,aAAc,CAEpF,KAAK,aAAa,SAAW,IAC/BmB,EAAgB,KAAK,aAAa,YAAc,KAAK,aAAa,UAKpE,IAAMP,EADc7B,EAAgB,YACJ,YAGhC,KAAK,2BAA2B6B,CAAW,EAG3C,WAAW,IAAM,CACf,KAAK,4BAA4BZ,EAAYX,EAAM,CACjD,MAAO4B,EACP,SAAA1B,EACA,MAAO2B,EACP,KAAM,KAAK,aAAa7B,EAAM,CAAE,MAAO4B,EAAc,SAAA1B,EAAU,MAAO2B,CAAa,CAAC,EACpF,YAAAN,EACA,OAAAd,CACF,EAAGqB,CAAa,CAClB,EAAG,EAAE,CACP,EAEJ,CAAmB,GAIjB,KAAK,aAAc,CACrB,IAAMlB,EAAQ,KAAK,oBAAoB,EACvCmB,EAAY,YAAYnB,CAAK,CAC/B,CAEAE,EAAU,YAAYiB,CAAW,EAGjC,IAAIR,EAAkC,KAClCf,IACFe,EAAc,KAAK,kBAAkB,EACrCT,EAAU,YAAYS,CAAW,GAInC7B,EAAQ,aAAaoB,EAAWpB,EAAQ,UAAU,EAClDA,EAAQ,UAAU,IAAI,kCAAmC,6BAA6B,EAGlFc,GACFd,EAAQ,UAAU,IAAI,cAAc,EAItCiB,EAAW,iBAAiB,QAAUE,GAAM,CAC1CA,EAAE,eAAe,EACjB,IAAMO,EAAU,KAAK,aAAapB,EAAM,CAAE,MAAO4B,EAAc,SAAA1B,EAAU,MAAO2B,CAAa,CAAC,EAC9F,KAAK,gBAAgBlB,EAAYX,EAAM,CACrC,MAAO4B,EACP,SAAA1B,EACA,MAAO2B,EACP,KAAMT,EACN,YAAAG,EACA,OAAAd,CACF,CAAC,CACH,CAAC,EAGAf,EAAgB,WAAa,CAC5B,KAAAM,EACA,MAAO4B,EACP,SAAA1B,EACA,MAAO2B,EACP,KAAA/B,EACA,WAAAa,EACA,cAAAqB,EACA,cAAAE,EACA,YAAAX,CACF,CACF,CAKQ,oBAAoBlB,EAAkB+B,EAAoC,CAChF,IAAMtB,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,6BAGtB,IAAMuB,EAAe,SAAS,cAAc,QAAQ,EACpDA,EAAa,UAAY,4BACzBA,EAAa,aAAa,aAAc,cAAc,EACtDA,EAAa,aAAa,gBAAiB,OAAO,EAClDA,EAAa,UAAY;AAAA;AAAA;AAAA;AAAA,MAOzB,IAAMC,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,qCACrBA,EAAS,aAAa,OAAQ,MAAM,EAEpCjC,EAAO,QAAQJ,GAAS,CACtB,IAAMsC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,UAAY,4BACnBA,EAAO,YAAc,KAAK,gBAAgBtC,CAAK,EAC/CsC,EAAO,QAAQ,MAAQtC,EACvBsC,EAAO,aAAa,OAAQ,UAAU,EAElCtC,IAAUmC,GACZG,EAAO,UAAU,IAAI,QAAQ,EAG/BA,EAAO,iBAAiB,QAAU1B,GAAM,CACtCA,EAAE,gBAAgB,EAClBA,EAAE,eAAe,EAGjByB,EAAS,iBAAiB,4BAA4B,EAAE,QAAQE,GAAO,CACrEA,EAAI,UAAU,OAAO,QAAQ,CAC/B,CAAC,EACDD,EAAO,UAAU,IAAI,QAAQ,EAG7BzB,EAAU,cAAc,IAAI,YAAY,gBAAiB,CACvD,OAAQ,CAAE,MAAAb,CAAM,CAClB,CAAC,CAAC,CACJ,CAAC,EAEDqC,EAAS,YAAYC,CAAM,CAC7B,CAAC,EAED,IAAIE,EAA6B,KAGjC,OAAA3B,EAAU,iBAAiB,aAAc,IAAM,CACzC2B,IACF,aAAaA,CAAW,EACxBA,EAAc,MAEhBH,EAAS,UAAU,OAAO,QAAQ,EAClCD,EAAa,aAAa,gBAAiB,MAAM,EAGjD,WAAW,IAAM,CACf,IAAMK,EAAOJ,EAAS,sBAAsB,EACtCK,EAAiB,OAAO,YAE1BD,EAAK,OAASC,GAAkBD,EAAK,IAAMA,EAAK,QAElDJ,EAAS,MAAM,OAAS,OACxBA,EAAS,MAAM,IAAM,SAGrBA,EAAS,MAAM,IAAM,mBACrBA,EAAS,MAAM,OAAS,OAE5B,EAAG,CAAC,CACN,CAAC,EAEDxB,EAAU,iBAAiB,aAAeD,GAAM,CAE9C4B,EAAc,OAAO,WAAW,IAAM,CACpCH,EAAS,UAAU,IAAI,QAAQ,EAC/BD,EAAa,aAAa,gBAAiB,OAAO,CACpD,EAAG,GAAG,CACR,CAAC,EAGDC,EAAS,iBAAiB,aAAc,IAAM,CACxCG,IACF,aAAaA,CAAW,EACxBA,EAAc,KAElB,CAAC,EAEDH,EAAS,iBAAiB,aAAc,IAAM,CAC5CG,EAAc,OAAO,WAAW,IAAM,CACpCH,EAAS,UAAU,IAAI,QAAQ,EAC/BD,EAAa,aAAa,gBAAiB,OAAO,CACpD,EAAG,GAAG,CACR,CAAC,EAGDA,EAAa,iBAAiB,QAAUxB,GAAM,CAC5CA,EAAE,gBAAgB,EAClB,IAAM+B,EAAWN,EAAS,UAAU,SAAS,QAAQ,EACrDA,EAAS,UAAU,OAAO,QAAQ,EAClCD,EAAa,aAAa,gBAAiBO,EAAW,OAAS,OAAO,CACxE,CAAC,EAED9B,EAAU,YAAYuB,CAAY,EAClCvB,EAAU,YAAYwB,CAAQ,EAEvBxB,CACT,CAKQ,oBAAoB+B,EAAoC,CAC9D,IAAM/B,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,6BAGtB,IAAMgC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,UAAY,4BACnBA,EAAO,aAAa,aAAc,uBAAuB,EACzDA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA,MAQnB,IAAMR,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAY,qCACrBA,EAAS,aAAa,OAAQ,MAAM,EAGpC,IAAMS,EAAmB,CAAC,EAC1B,QAAS5C,EAAQ,GAAKA,GAAS,EAAKA,GAAS,GAC3C4C,EAAO,KAAK,KAAK,MAAM5C,EAAQ,EAAE,EAAI,EAAE,EAGzC4C,EAAO,QAAQ5C,GAAS,CACtB,IAAMoC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,UAAY,4BACnBA,EAAO,YAAc,GAAGpC,EAAM,QAAQ,CAAC,CAAC,IACxCoC,EAAO,QAAQ,MAAQpC,EAAM,SAAS,EACtCoC,EAAO,aAAa,OAAQ,UAAU,EAElC,KAAK,IAAIpC,EAAQ0C,CAAa,EAAI,KACpCN,EAAO,UAAU,IAAI,QAAQ,EAG/BA,EAAO,iBAAiB,QAAU1B,GAAM,CACtCA,EAAE,gBAAgB,EAClBA,EAAE,eAAe,EAGjByB,EAAS,iBAAiB,4BAA4B,EAAE,QAAQE,GAAO,CACrEA,EAAI,UAAU,OAAO,QAAQ,CAC/B,CAAC,EACDD,EAAO,UAAU,IAAI,QAAQ,EAG7BzB,EAAU,cAAc,IAAI,YAAY,gBAAiB,CACvD,OAAQ,CAAE,MAAAX,CAAM,CAClB,CAAC,CAAC,CACJ,CAAC,EAEDmC,EAAS,YAAYC,CAAM,CAC7B,CAAC,EAED,IAAIE,EAA6B,KAGjC,OAAA3B,EAAU,iBAAiB,aAAc,IAAM,CACzC2B,IACF,aAAaA,CAAW,EACxBA,EAAc,MAEhBH,EAAS,UAAU,OAAO,QAAQ,EAGlC,WAAW,IAAM,CACf,IAAMI,EAAOJ,EAAS,sBAAsB,EACtCK,EAAiB,OAAO,YAE1BD,EAAK,OAASC,GAAkBD,EAAK,IAAMA,EAAK,QAElDJ,EAAS,MAAM,OAAS,OACxBA,EAAS,MAAM,IAAM,SAGrBA,EAAS,MAAM,IAAM,mBACrBA,EAAS,MAAM,OAAS,OAE5B,EAAG,CAAC,CACN,CAAC,EAEDxB,EAAU,iBAAiB,aAAc,IAAM,CAE7C2B,EAAc,OAAO,WAAW,IAAM,CACpCH,EAAS,UAAU,IAAI,QAAQ,CACjC,EAAG,GAAG,CACR,CAAC,EAGDA,EAAS,iBAAiB,aAAc,IAAM,CACxCG,IACF,aAAaA,CAAW,EACxBA,EAAc,KAElB,CAAC,EAEDH,EAAS,iBAAiB,aAAc,IAAM,CAC5CG,EAAc,OAAO,WAAW,IAAM,CACpCH,EAAS,UAAU,IAAI,QAAQ,CACjC,EAAG,GAAG,CACR,CAAC,EAEDxB,EAAU,YAAYgC,CAAM,EAC5BhC,EAAU,YAAYwB,CAAQ,EAEvBxB,CACT,CAKQ,mBAAiC,CACvC,IAAMA,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,UAAY,kCAEtB,IAAMkC,EAAS,SAAS,cAAc,OAAO,EAC7CA,EAAO,KAAO,QACdA,EAAO,UAAY,+BACnBA,EAAO,IAAM,IACbA,EAAO,IAAM,MACbA,EAAO,MAAQ,IACfA,EAAO,KAAO,MACdA,EAAO,aAAa,aAAc,qBAAqB,EAEvD,IAAMC,EAAc,SAAS,cAAc,KAAK,EAChD,OAAAA,EAAY,UAAY,4BACxBA,EAAY,UAAY,yEAGxBD,EAAO,iBAAiB,QAAUnC,GAAM,CACtC,GAAI,KAAK,aAAc,CACrB,IAAMqC,EAAa,WAAYrC,EAAE,OAA4B,KAAK,EAClE,KAAK,aAAa,YAAeqC,EAAa,IAAO,KAAK,aAAa,QACzE,CACF,CAAC,EAEDpC,EAAU,YAAYkC,CAAM,EAC5BlC,EAAU,YAAYmC,CAAW,EAE1BnC,CACT,CAKQ,WAAWqC,EAAyB,CAC1C,GAAI,CAACA,GAAW,MAAMA,CAAO,EAAG,MAAO,OACvC,IAAMC,EAAO,KAAK,MAAMD,EAAU,EAAE,EAC9BE,EAAO,KAAK,MAAMF,EAAU,EAAE,EACpC,MAAO,GAAGC,CAAI,IAAIC,EAAK,SAAS,EAAE,SAAS,EAAG,GAAG,CAAC,EACpD,CAKQ,gBAAgBpD,EAAuB,CAE7C,OAAOA,EACJ,QAAQ,QAAS,GAAG,EACpB,MAAM,GAAG,EACT,IAAIqD,GAAQA,EAAK,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAK,MAAM,CAAC,CAAC,EACxD,KAAK,GAAG,CACb,CAEQ,kBAAsC,CAC5C,IAAMR,EAAS,SAAS,cAAc,QAAQ,EAC9C,OAAAA,EAAO,UAAY,oBACnBA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA,MAMnBA,EAAO,aAAa,aAAc,qBAAqB,EAChDA,CACT,CAEQ,iBAAiBS,EAAmB,GAA0B,CACpE,IAAMT,EAAS,SAAS,cAAc,QAAQ,EAC9C,OAAAA,EAAO,UAAY,oBAEfS,GAEFT,EAAO,UAAU,IAAI,2BAA2B,EAChDA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAWnBA,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYrBA,EAAO,aAAa,aAAc,qBAAqB,EAChDA,CACT,CAEQ,qBAAyC,CAC/C,IAAMlC,EAAQ,SAAS,cAAc,GAAG,EACxCA,EAAM,UAAY,iBAClBA,EAAM,KAAO,8BACbA,EAAM,OAAS,SACfA,EAAM,IAAM,sBACZA,EAAM,MAAQ,0BACdA,EAAM,aAAa,aAAc,yBAAyB,EAG1D,IAAM4C,EAAM,SAAS,cAAc,KAAK,EACxC,OAAAA,EAAI,IAAM,2EACVA,EAAI,IAAM,eACVA,EAAI,UAAY,oBAChBA,EAAI,MAAM,QAAU,QACpBA,EAAI,MAAM,MAAQ,OAClBA,EAAI,MAAM,OAAS,OAGnBA,EAAI,QAAU,IAAM,CAClB5C,EAAM,UAAY,KAClBA,EAAM,MAAM,SAAW,OACvBA,EAAM,MAAM,WAAa,MACzBA,EAAM,MAAM,QAAU,OACtBA,EAAM,MAAM,MAAQ,SACtB,EAEAA,EAAM,YAAY4C,CAAG,EACd5C,CACT,CAOQ,uBAA8B,CAEpC,GAAI,SAAS,eAAe,8BAA8B,EACxD,OAIF,IAAME,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,GAAK,+BACfA,EAAU,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAS1B,IAAM2C,EAAe,SAAS,cAAc,QAAQ,EACpDA,EAAa,UAAY,oCACzBA,EAAa,UAAY,kBACzBA,EAAa,MAAQ,6BACrBA,EAAa,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgB7B,IAAMC,EAAU,SAAS,cAAc,QAAQ,EAC/CA,EAAQ,UAAY,0BACpBA,EAAQ,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcxBA,EAAQ,UAAY;AAAA;AAAA;AAAA;AAAA,MAOpB,IAAMC,EAAkBC,GAA2B,CACjDA,EAAI,iBAAiB,aAAc,IAAM,CACvCA,EAAI,MAAM,UAAY,cACtBA,EAAI,MAAM,UAAY,4BACxB,CAAC,EAEDA,EAAI,iBAAiB,aAAc,IAAM,CACvCA,EAAI,MAAM,UAAY,WACtBA,EAAI,MAAM,UAAY,2BACxB,CAAC,CACH,EAEAD,EAAeD,CAAO,EACtBC,EAAeF,CAAY,EAG3B,IAAMI,EAAa,IAAM,CACvB,IAAMC,EAAQ,KAAK,MAAM,KACzB,KAAK,MAAM,MAAM,EACjB,aAAa,WAAW,oBAAoB,EAG5CJ,EAAQ,UAAY,oCAA+BI,CAAK,kEACxDJ,EAAQ,MAAM,WAAa,UAE3B,WAAW,IAAM,CACfA,EAAQ,UAAY,+GACpBA,EAAQ,MAAM,WAAa,SAC7B,EAAG,GAAI,EAEP,QAAQ,IAAI,8BAA8BI,CAAK,eAAe,CAChE,EAGAJ,EAAQ,iBAAiB,QAAU7C,GAAM,CACvCA,EAAE,eAAe,EACjB,IAAMkD,EAASlD,EAAE,QAAWA,EAAE,OAAuB,sBAAsB,EAAE,KACvEmD,EAAWN,EAAQ,sBAAsB,EAAE,MAG7CK,EAASC,EAAW,IACtBN,EAAQ,MAAM,QAAU,OACxBD,EAAa,MAAM,QAAU,QAC7B,aAAa,QAAQ,6BAA8B,MAAM,GAEzDI,EAAW,CAEf,CAAC,EAGDJ,EAAa,iBAAiB,QAAU5C,GAAM,CAC5CA,EAAE,eAAe,EACjB4C,EAAa,MAAM,QAAU,OAC7BC,EAAQ,MAAM,QAAU,OACxB,aAAa,QAAQ,6BAA8B,OAAO,CAC5D,CAAC,EAGmB,aAAa,QAAQ,4BAA4B,IAAM,SAEzEA,EAAQ,MAAM,QAAU,OACxBD,EAAa,MAAM,QAAU,SAG/B3C,EAAU,YAAY4C,CAAO,EAC7B5C,EAAU,YAAY2C,CAAY,EAG9B,SAAS,KACX,SAAS,KAAK,YAAY3C,CAAS,EAEnC,SAAS,iBAAiB,mBAAoB,IAAM,CAClD,SAAS,KAAK,YAAYA,CAAS,CACrC,CAAC,CAEL,CAEA,MAAc,gBAAgBgC,EAA2B9C,EAAcV,EAA6B,CAClG,GAAM,CAAE,KAAAQ,EAAM,YAAAyB,CAAY,EAAIjC,EAG9B,GAAIwD,EAAO,UAAU,SAAS,sBAAsB,GAAK,KAAK,gBAAkBA,EAAQ,CACtF,KAAK,WAAW,EAChB,MACF,CAGA,GAAIA,EAAO,UAAU,SAAS,qBAAqB,GAAK,KAAK,gBAAkBA,EAAQ,CACrF,KAAK,YAAY,EACjB,MACF,CAGA,GAAI,MAAK,aAKT,CAAI,KAAK,cAAgB,KAAK,eAAiB,KAAK,gBAAkBA,GACpE,KAAK,UAAU,EAGjB,GAAI,CACF,KAAK,aAAe,GAGpB,KAAK,eAAeA,EAAQ,SAAS,EAGrC,IAAImB,EAAW,KAAK,kBAAkBnE,CAAI,EAE1C,GAAI,CAACmE,EAOH,GAJE,KAAK,iBAAmB,eACvB,KAAK,iBAAmB,YAAcjE,EAAK,OAAS,KAAK,qBAGxC,CAElB,MAAM,KAAK,yBAAyBA,EAAMV,EAASwD,EAAQvB,CAAW,EACtE,MACF,KAAO,CAEL,IAAM2C,EAAW,MAAM,KAAK,cAAclE,EAAMV,CAAO,EAEvD2E,EAAWC,EAAS,SAAS,WAAW,MAAM,EAC1CA,EAAS,SACT,GAAG,KAAK,MAAM,GAAGA,EAAS,QAAQ,GAGtC,KAAK,cAAcpE,EAAMmE,EAAUC,CAAQ,CAC7C,CAIF,MAAM,KAAK,UAAUD,EAAUnB,EAAQvB,CAAW,CAEpD,OAAS4C,EAAO,CACd,QAAQ,MAAM,aAAcA,CAAK,EACjC,KAAK,eAAerB,EAAQ,OAAO,EAGnC,KAAK,UAAUA,EAASqB,EAAgB,OAAO,EAE/C,WAAW,IAAM,KAAK,eAAerB,EAAQ,OAAO,EAAG,GAAI,EAC3D,KAAK,aAAe,EACtB,EACF,CAEA,MAAc,cAAc9C,EAAcV,EAAoC,CAC5E,IAAM8E,EAAO,CACX,KAAApE,EACA,QAAS,CACP,SAAUV,EAAQ,SAClB,MAAOA,EAAQ,MACf,MAAOA,EAAQ,OAAS,CAC1B,CACF,EAEM+E,EAAkC,CACtC,eAAgB,kBAClB,EAGM5D,EAASnB,EAAQ,QAAU,KAAK,OACtC,QAAQ,IAAI,iDAAkD,CAAC,CAACmB,CAAM,EACtE,QAAQ,IAAI,6CAA8C,CAAC,CAAC,KAAK,MAAM,EACvE,QAAQ,IAAI,gDAAiD,CAAC,CAACnB,EAAQ,MAAM,EACzEmB,GACF4D,EAAQ,cAAmB,UAAU5D,CAAM,GAC3C,QAAQ,IAAI,0DAA0D,GAEtE,QAAQ,KAAK,0EAA0E,EAGzF,GAAI,CACF,IAAMyD,EAAW,MAAM,MAAM,GAAG,KAAK,MAAM,mBAAoB,CAC7D,OAAQ,OACR,QAAAG,EACA,KAAM,KAAK,UAAUD,CAAI,CAC3B,CAAC,EAED,GAAI,CAACF,EAAS,GAAI,CAChB,IAAMC,EAAQ,MAAMD,EAAS,KAAK,EAAE,MAAM,KAAO,CAAC,EAAE,EACpD,MAAM,IAAI,MAAMC,EAAM,OAAS,QAAQD,EAAS,MAAM,KAAKA,EAAS,UAAU,EAAE,CAClF,CAEA,IAAMI,EAAO,MAAMJ,EAAS,KAAK,EAEjC,MAAO,CACL,SAAU,GAAG,KAAK,MAAM,GAAGI,EAAK,QAAQ,GACxC,KAAMA,EAAK,KACX,OAAQA,EAAK,OACb,SAAUA,EAAK,SACf,KAAMA,EAAK,IACb,CACF,OAASH,EAAO,CAKd,GAHA,QAAQ,MAAM,yBAA0BA,CAAK,EAGxCA,EAAgB,QAAQ,SAAS,iBAAiB,GAAMA,EAAgB,QAAQ,SAAS,cAAc,EAAG,CAC7G,IAAMI,EAAmBJ,EAAgB,QACzC,MAAM,IAAI,MAAM,wBAAwBI,CAAe,cAAc,KAAK,MAAM,iBAAiB,CACnG,CAGA,MAAMJ,CACR,CACF,CAMA,MAAc,yBACZnE,EACAV,EACAwD,EACAvB,EACe,CACf,IAAM6C,EAAO,CACX,KAAApE,EACA,QAAS,CACP,SAAUV,EAAQ,SAClB,MAAOA,EAAQ,MACf,MAAOA,EAAQ,OAAS,CAC1B,CACF,EAEM+E,EAAkC,CACtC,eAAgB,mBAChB,OAAU,mBACZ,EAEM5D,EAASnB,EAAQ,QAAU,KAAK,OAClCmB,IACF4D,EAAQ,cAAmB,UAAU5D,CAAM,IAG7C,GAAI,CACF,IAAMyD,EAAW,MAAM,MAAM,GAAG,KAAK,MAAM,+BAAgC,CACzE,OAAQ,OACR,QAAAG,EACA,KAAM,KAAK,UAAUD,CAAI,CAC3B,CAAC,EAED,GAAI,CAACF,EAAS,GAAI,CAChB,IAAMC,EAAQ,MAAMD,EAAS,KAAK,EAAE,MAAM,KAAO,CAAC,EAAE,EACpD,MAAM,IAAI,MAAMC,EAAM,OAAS,QAAQD,EAAS,MAAM,KAAKA,EAAS,UAAU,EAAE,CAClF,CAEA,GAAI,CAACA,EAAS,KACZ,MAAM,IAAI,MAAM,iCAAiC,EAGnD,IAAMM,EAASN,EAAS,KAAK,UAAU,EACjCO,EAAU,IAAI,YAChBC,EAAS,GACTC,EAAc,EACdC,EAAkB,EAGhBC,EAAiB,CAACC,EAAmBC,IAAkB,CAC3D,GAAIxD,EAAa,CACf,IAAM2B,EAAc4B,EAAYC,EAAS,IACnC/B,EAASzB,EAAY,cAAgC,+BAA+B,EACtFyB,IACFA,EAAO,MAAQE,EAAW,SAAS,GAGrC,IAAM8B,EAAczD,EAAY,cAA2B,UAAU,EACjEyD,IACFA,EAAY,YAAc,SAASF,CAAS,IAAIC,CAAK,GAEzD,CACF,EAEA,OAAa,CACX,GAAM,CAAE,KAAAE,EAAM,MAAAC,CAAM,EAAI,MAAMV,EAAO,KAAK,EAE1C,GAAIS,EAAM,MAEVP,GAAUD,EAAQ,OAAOS,EAAO,CAAE,OAAQ,EAAK,CAAC,EAChD,IAAMC,EAAQT,EAAO,MAAM;AAAA;AAAA,CAAM,EACjCA,EAASS,EAAM,IAAI,GAAK,GAExB,QAAWC,KAAQD,EACjB,GAAKC,EAAK,WAAW,QAAQ,EAE7B,GAAI,CACF,IAAMC,EAAQ,KAAK,MAAMD,EAAK,UAAU,CAAC,CAAC,EAE1C,OAAQC,EAAM,KAAM,CAClB,IAAK,UACHV,EAAcU,EAAM,YACpB,QAAQ,IAAI,8BAA8BV,CAAW,SAAS,EAC9D,KAAK,eAAe7B,EAAQ,SAAS,EACrC,MAEF,IAAK,WACH8B,EAAkBS,EAAM,UACxB,QAAQ,IAAI,+BAA+BT,CAAe,IAAID,CAAW,EAAE,EAC3EE,EAAeD,EAAiBD,CAAW,EAC3C,MAEF,IAAK,WACH,QAAQ,IAAI,8BAA+BU,CAAK,EAChD,IAAMpB,EAAWoB,EAAM,SAAS,WAAW,MAAM,EAC7CA,EAAM,SACN,GAAG,KAAK,MAAM,GAAGA,EAAM,QAAQ,GAGnC,KAAK,cAAc/F,EAAQ,KAAM2E,EAAU,CACzC,KAAMoB,EAAM,KACZ,OAAQ,GACR,SAAUA,EAAM,SAChB,KAAMA,EAAM,IACd,CAAC,EAGD,MAAM,KAAK,UAAUpB,EAAUnB,EAAQvB,CAAW,EAClD,MAEF,IAAK,QACH,MAAM,IAAI,MAAM8D,EAAM,SAAW,+BAA+B,CACpE,CACF,OAASC,EAAY,CACnB,QAAQ,KAAK,2CAA4CF,EAAME,CAAU,CAC3E,CAEJ,CACF,OAASnB,EAAO,CACd,cAAQ,MAAM,qCAAsCA,CAAK,EACzD,KAAK,aAAe,GACdA,CACR,CACF,CAEA,MAAc,UAAUF,EAAkBnB,EAA2BvB,EAAkCgE,EAAuC,CAC5I,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMC,EAAQ,IAAI,MAAMzB,CAAQ,EAChC,KAAK,aAAeyB,EACpB,KAAK,cAAgB5C,EAIjB,KAAK,kBACP4C,EAAM,eAAiB,GAEtBA,EAAc,kBAAoB,GAClCA,EAAc,qBAAuB,IAIpCH,IAAkB,QAAa,KAAK,kBACtCG,EAAM,aAAeH,GAInB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAGhCG,EAAM,iBAAiB,YAAa,IAAM,CACpC,KAAK,eAAiBA,GACxB,KAAK,eAAe5C,EAAQ,SAAS,CAEzC,CAAC,EAED4C,EAAM,iBAAiB,UAAW,IAAM,CACtC,GAAI,KAAK,eAAiBA,EAAO,CAC/B,KAAK,eAAe5C,EAAQ,SAAS,EACrC,KAAK,aAAe,GACpB,IAAM6C,EAAcD,EAAM,KAAK,EAC3BC,IAAgB,QAClBA,EAAY,MAAMxB,GAAS,CACzB,QAAQ,MAAM,qBAAsBA,CAAK,EACrC,KAAK,eAAiBuB,IACxB,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KACrB,KAAK,aAAe,GACpB2C,EAAO,IAAI,MAAM,uBAAuB,CAAC,EAE7C,CAAC,EAIClE,IACFA,EAAY,UAAU,IAAI,SAAS,EACnC,KAAK,uBAAyB,OAAO,YAAY,IAAM,CACrD,KAAK,kBAAkBmE,EAAOnE,CAAW,CAC3C,EAAG,GAAG,EAEV,CACF,CAAC,EAEDmE,EAAM,iBAAiB,QAAS,IAAM,CACpC,GAAI,KAAK,eAAiBA,EAAO,CAU/B,GATA,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KAGjB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAE5BvB,EAAa,CACfA,EAAY,UAAU,OAAO,SAAS,EAEtC,IAAMyB,EAASzB,EAAY,cAAgC,+BAA+B,EACtFyB,IAAQA,EAAO,MAAQ,KAC3B,IAAMC,EAAc1B,EAAY,cAAc,4BAA4B,EACtE0B,IAAaA,EAAY,UAAY,yEAC3C,CAEAuC,EAAQ,CACV,CACF,CAAC,EAEDE,EAAM,iBAAiB,QAAU7E,GAAM,CACjC,KAAK,eAAiB6E,IACxB,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KAGjB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAE5BvB,GACFA,EAAY,UAAU,OAAO,SAAS,EAGxCkE,EAAO,IAAI,MAAM,uBAAuB,CAAC,EAE7C,CAAC,EAEDC,EAAM,KAAK,CACb,CAAC,CACH,CAKQ,kBAAkBA,EAAyBnE,EAAgC,CACjF,GAAI,CAACmE,GAAS,CAACnE,EAAa,OAE5B,IAAMyB,EAASzB,EAAY,cAAgC,+BAA+B,EACpFqE,EAAkBrE,EAAY,cAA2B,UAAU,EACnEsE,EAAetE,EAAY,cAA2B,WAAW,EAEvE,GAAIyB,GAAU,CAAC,MAAM0C,EAAM,QAAQ,EAAG,CACpC,IAAMxC,EAAcwC,EAAM,YAAcA,EAAM,SAAY,IAC1D1C,EAAO,MAAQE,EAAW,SAAS,CACrC,CAEI0C,IACFA,EAAgB,YAAc,KAAK,WAAWF,EAAM,WAAW,GAG7DG,GAAgB,CAAC,MAAMH,EAAM,QAAQ,IACvCG,EAAa,YAAc,KAAK,WAAWH,EAAM,QAAQ,EAE7D,CAEQ,YAAmB,CACrB,KAAK,cAAgB,CAAC,KAAK,aAAa,QAC1C,KAAK,aAAa,MAAM,EAGtB,KAAK,eACP,KAAK,eAAe,KAAK,cAAe,QAAQ,CAEpD,CAEQ,aAAoB,CAC1B,GAAI,KAAK,cAAgB,KAAK,aAAa,OAAQ,CACjD,IAAMC,EAAc,KAAK,aAAa,KAAK,EACvCA,IAAgB,QAClBA,EAAY,KAAK,IAAM,CACjB,KAAK,eACP,KAAK,eAAe,KAAK,cAAe,SAAS,CAErD,CAAC,EAAE,MAAMxB,GAAS,CAChB,QAAQ,MAAM,uBAAwBA,CAAK,EACvC,KAAK,eACP,KAAK,eAAe,KAAK,cAAe,OAAO,CAEnD,CAAC,CAEL,CACF,CAEQ,WAAkB,CAEpB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAG5B,KAAK,eACP,KAAK,aAAa,MAAM,EACxB,KAAK,aAAa,YAAc,EAChC,KAAK,aAAe,MAGlB,KAAK,gBACP,KAAK,eAAe,KAAK,cAAe,OAAO,EAC/C,KAAK,cAAgB,MAGvB,KAAK,aAAe,EACtB,CAMQ,eAAe5C,EAAwC,CAqB7D,GAnBI,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAI5B,KAAK,eACP,KAAK,aAAa,MAAM,EACxB,KAAK,aAAa,YAAc,EAChC,KAAK,aAAe,MAIlB,KAAK,gBACP,KAAK,eAAe,KAAK,cAAe,OAAO,EAC/C,KAAK,cAAgB,MAInBA,EAAa,CACfA,EAAY,UAAU,OAAO,SAAS,EACtC,IAAMyB,EAASzB,EAAY,cAAgC,+BAA+B,EACtFyB,IACFA,EAAO,MAAQ,KAEjB,IAAMC,EAAc1B,EAAY,cAAc,4BAA4B,EACtE0B,IACFA,EAAY,UAAY,yEAE5B,CAEA,KAAK,aAAe,EACtB,CAKQ,2BAA2B1B,EAAwC,CAErE,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAI5B,KAAK,eACP,KAAK,aAAa,MAAM,EACxB,KAAK,aAAa,YAAc,EAChC,KAAK,aAAe,MAIlB,KAAK,eACP,KAAK,eAAe,KAAK,cAAe,SAAS,EAMnD,KAAK,aAAe,EACtB,CAKA,MAAc,4BAA4BuB,EAA2B9C,EAAcV,EAAcwG,EAAwC,CACvI,GAAM,CAAE,KAAAhG,EAAM,YAAAyB,CAAY,EAAIjC,EAG9B,GAAI,MAAK,aAIT,GAAI,CACF,KAAK,aAAe,GAGpB,KAAK,eAAewD,EAAQ,SAAS,EAGrC,IAAImB,EAAW,KAAK,kBAAkBnE,CAAI,EAE1C,GAAI,CAACmE,EAAU,CAEb,IAAMC,EAAW,MAAM,KAAK,cAAclE,EAAMV,CAAO,EAEvD2E,EAAWC,EAAS,SAAS,WAAW,MAAM,EAC1CA,EAAS,SACT,GAAG,KAAK,MAAM,GAAGA,EAAS,QAAQ,GAGtC,KAAK,cAAcpE,EAAMmE,EAAUC,CAAQ,CAC7C,CAGA,MAAM,KAAK,sBAAsBD,EAAUnB,EAAQvB,EAAauE,CAAe,CAEjF,OAAS3B,EAAO,CACd,QAAQ,MAAM,aAAcA,CAAK,EACjC,KAAK,eAAerB,EAAQ,OAAO,EAGnC,KAAK,UAAUA,EAASqB,EAAgB,OAAO,EAE/C,WAAW,IAAM,KAAK,eAAerB,EAAQ,OAAO,EAAG,GAAI,EAC3D,KAAK,aAAe,EACtB,CACF,CAKA,MAAc,sBAAsBmB,EAAkBnB,EAA2BvB,EAA6CuE,EAAwC,CACpK,OAAO,IAAI,QAAQ,CAACN,EAASC,IAAW,CACtC,IAAMC,EAAQ,IAAI,MAAMzB,CAAQ,EAChC,KAAK,aAAeyB,EACpB,KAAK,cAAgB5C,EAIjB,KAAK,kBACP4C,EAAM,eAAiB,GAEtBA,EAAc,kBAAoB,GAClCA,EAAc,qBAAuB,IAIpC,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAGhC,IAAIK,EAAmB,GAEvBL,EAAM,iBAAiB,YAAa,IAAM,CACpC,KAAK,eAAiBA,GACxB,KAAK,eAAe5C,EAAQ,SAAS,CAEzC,CAAC,EAED4C,EAAM,iBAAiB,iBAAkB,IAAM,CAEzC,KAAK,eAAiBA,GAAS,CAACK,GAAoBD,EAAkB,IACxEJ,EAAM,YAAcA,EAAM,SAAWI,EACrCC,EAAmB,GAEvB,CAAC,EAEDL,EAAM,iBAAiB,UAAW,IAAM,CACtC,GAAI,KAAK,eAAiBA,EAAO,CAE3B,CAACK,GAAoBD,EAAkB,GAAKJ,EAAM,SAAW,IAC/DA,EAAM,YAAcA,EAAM,SAAWI,EACrCC,EAAmB,IAGrB,KAAK,eAAejD,EAAQ,SAAS,EACrC,KAAK,aAAe,GACpB,IAAM6C,EAAcD,EAAM,KAAK,EAC3BC,IAAgB,QAClBA,EAAY,MAAMxB,GAAS,CACzB,QAAQ,MAAM,qBAAsBA,CAAK,EACrC,KAAK,eAAiBuB,IACxB,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KACrB,KAAK,aAAe,GACpB2C,EAAO,IAAI,MAAM,uBAAuB,CAAC,EAE7C,CAAC,EAIClE,IACFA,EAAY,UAAU,IAAI,SAAS,EACnC,KAAK,uBAAyB,OAAO,YAAY,IAAM,CACrD,KAAK,kBAAkBmE,EAAOnE,CAAW,CAC3C,EAAG,GAAG,EAEV,CACF,CAAC,EAEDmE,EAAM,iBAAiB,QAAS,IAAM,CACpC,GAAI,KAAK,eAAiBA,EAAO,CAU/B,GATA,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KAGjB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAE5BvB,EAAa,CACfA,EAAY,UAAU,OAAO,SAAS,EAEtC,IAAMyB,EAASzB,EAAY,cAAgC,+BAA+B,EACtFyB,IAAQA,EAAO,MAAQ,KAC3B,IAAMC,EAAc1B,EAAY,cAAc,4BAA4B,EACtE0B,IAAaA,EAAY,UAAY,yEAC3C,CAEAuC,EAAQ,CACV,CACF,CAAC,EAEDE,EAAM,iBAAiB,QAAU7E,GAAM,CACjC,KAAK,eAAiB6E,IACxB,KAAK,eAAe5C,EAAQ,OAAO,EACnC,KAAK,aAAe,KACpB,KAAK,cAAgB,KAGjB,KAAK,yBACP,cAAc,KAAK,sBAAsB,EACzC,KAAK,uBAAyB,MAE5BvB,GACFA,EAAY,UAAU,OAAO,SAAS,EAGxCkE,EAAO,IAAI,MAAM,uBAAuB,CAAC,EAE7C,CAAC,EAEDC,EAAM,KAAK,CACb,CAAC,CACH,CAEQ,eAAe5C,EAA2BkD,EAAqB,CACrElD,EAAO,UAAU,OAAO,uBAAwB,uBAAwB,sBAAuB,oBAAoB,EAEnH,IAAMmD,EAAWnD,EAAO,cAA0B,yBAAyB,EACrE9C,EAAO8C,EAAO,cAA+B,oBAAoB,EAEvE,OAAQkD,EAAO,CACb,IAAK,UACHlD,EAAO,UAAU,IAAI,sBAAsB,EAC3CA,EAAO,SAAW,GAEd9C,IAAMA,EAAK,YAAc,cAC7B,MAEF,IAAK,UACH8C,EAAO,UAAU,IAAI,sBAAsB,EAC3CA,EAAO,SAAW,GACdmD,IAAUA,EAAS,UAAY,uFAC/BjG,IAAMA,EAAK,YAAc,SAC7B,MAEF,IAAK,SACH8C,EAAO,UAAU,IAAI,qBAAqB,EAC1CA,EAAO,SAAW,GACdmD,IAAUA,EAAS,UAAY,6BAC/BjG,IAAMA,EAAK,YAAc,UAC7B,MAEF,IAAK,QACH8C,EAAO,UAAU,IAAI,oBAAoB,EACzCA,EAAO,SAAW,GACdmD,IAAUA,EAAS,UAAY,iFAC/BjG,IAAMA,EAAK,YAAc,SAC7B,MAEF,QACE8C,EAAO,SAAW,GACdmD,IAAUA,EAAS,UAAY,6BAC/BjG,IAAMA,EAAK,YAAc,UAC7B,KACJ,CACF,CAEQ,UAAU8C,EAA2BoD,EAAuB,CAClE,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,6BAEhBD,EAAQ,SAAS,kBAAkB,EACrCC,EAAQ,YAAcD,EACbA,EAAQ,SAAS,iBAAiB,EAC3CC,EAAQ,YAAc,iCAEtBA,EAAQ,YAAc,0BAGxBrD,EAAO,YAAY,YAAYqD,CAAO,EAEtC,WAAW,IAAM,CACXA,EAAQ,YACVA,EAAQ,WAAW,YAAYA,CAAO,CAE1C,EAAG,GAAI,CACT,CAEQ,aAAanG,EAAcV,EAAe,CAAC,EAAW,CAC5D,IAAM8G,EAAMpG,EAAO,KAAK,UAAUV,CAAO,EACrCQ,EAAO,EAEX,QAASuG,EAAI,EAAGA,EAAID,EAAI,OAAQC,IAAK,CACnC,IAAMC,EAAOF,EAAI,WAAWC,CAAC,EAC7BvG,GAASA,GAAQ,GAAKA,EAAQwG,EAC9BxG,EAAOA,EAAOA,CAChB,CAEA,OAAO,KAAK,IAAIA,CAAI,EAAE,SAAS,EAAE,CACnC,CAEQ,kBAAkBA,EAA6B,CACrD,IAAMyG,EAAS,KAAK,MAAM,IAAIzG,CAAI,EAElC,GAAI,CAACyG,EAAQ,OAAO,KAEpB,GAAI,KAAK,IAAI,EAAIA,EAAO,OACtB,YAAK,MAAM,OAAOzG,CAAI,EACtB,KAAK,mBAAmB,EACjB,KAGT,IAAMmE,EAAWsC,EAAO,SACxB,OAAOtC,EAAS,WAAW,MAAM,EAC7BA,EACA,GAAG,KAAK,MAAM,GAAGA,CAAQ,EAC/B,CAEQ,cAAcnE,EAAcmE,EAAkBuC,EAAgB,CAAC,EAAS,CAC9E,KAAK,MAAM,IAAI1G,EAAM,CACnB,SAAAmE,EACA,SAAAuC,EACA,OAAQ,KAAK,IAAI,EAAI,KAAK,YAC1B,UAAW,KAAK,IAAI,CACtB,CAAC,EAED,KAAK,mBAAmB,CAC1B,CAEQ,sBAA6B,CACnC,GAAI,CACF,IAAMC,EAAS,aAAa,QAAQ,oBAAoB,EACxD,GAAIA,EAAQ,CACV,IAAMnC,EAAO,KAAK,MAAMmC,CAAM,EAC9B,KAAK,MAAQ,IAAI,IAAI,OAAO,QAAQnC,CAAI,CAAC,CAC3C,CACF,OAASH,EAAO,CACd,QAAQ,KAAK,4BAA6BA,CAAK,CACjD,CACF,CAEQ,oBAA2B,CACjC,GAAI,CACF,IAAMG,EAAO,OAAO,YAAY,KAAK,KAAK,EAC1C,aAAa,QAAQ,qBAAsB,KAAK,UAAUA,CAAI,CAAC,CACjE,OAASH,EAAO,CACd,QAAQ,KAAK,4BAA6BA,CAAK,CACjD,CACF,CAGA,OAAc,KAAK7E,EAA2C,CAC5D,OAAK,OAAe,qBAClB,QAAQ,MAAM,8DAA8D,EACpE,OAAe,sBAGxB,OAAe,oBAAsB,IAAID,EAAYC,CAAO,EACrD,OAAe,oBACzB,CAEA,OAAc,aAAuC,CACnD,OAAQ,OAAe,mBACzB,CAEO,UAAUI,EAA+BM,EAAcV,EAAe,CAAC,EAAS,CACrF,IAAIoH,EAAyB,KAQ7B,GANI,OAAOhH,GAAY,SACrBgH,EAAK,SAAS,cAA2BhH,CAAO,EAEhDgH,EAAKhH,EAGH,CAACgH,EAAI,CACP,QAAQ,MAAM,+BAA+B,EAC7C,MACF,CAEAA,EAAG,UAAU,IAAI,qBAAqB,EACtCA,EAAG,QAAQ,KAAO1G,EAEdV,EAAQ,QAAOoH,EAAG,QAAQ,MAAQpH,EAAQ,OAC1CA,EAAQ,WAAUoH,EAAG,QAAQ,SAAWpH,EAAQ,UAEpD,KAAK,YAAYoH,CAAE,CACrB,CACF,EAGA,GAAI,OAAO,OAAW,IACpB,GAAM,OAAe,YASnB,QAAQ,MAAM,oDAAoD,MATlC,CAC/B,OAAe,YAAczH,EAE9B,IAAM0H,EAAiB,SAAS,cAAiC,qCAAqC,EACtG,GAAIA,GAAkBA,EAAe,QAAS,CAC5C,IAAM9G,EAAS,KAAK,MAAM8G,EAAe,QAAQ,qBAAuB,IAAI,EAC5E1H,EAAY,KAAKY,CAAM,CACzB,CACF,CAKKX,EAAQD,ICh8DR,IAAM2H,EAAN,KAAmB,CACxB,YAAe,SAAgB,KAC/B,YAAe,YAAmC,KAKlD,aAAa,KAAKC,EAAyB,CAAC,EAAiB,CAE3D,GAAI,KAAK,SACP,OAAO,KAAK,SAId,GAAI,KAAK,YACP,OAAO,KAAK,YAGd,GAAM,CACJ,QAAAC,EAAU,QACV,KAAAC,EAAO,OACP,OAAAC,EAAS,yCACT,QAAAC,EAAU,IACV,UAAAC,EACA,aAAAC,CACF,EAAIN,EAGJ,YAAK,YAAc,KAAK,WAAW,CACjC,QAAAC,EACA,KAAAC,EACA,OAAAC,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,CACF,CAAC,EAEM,KAAK,WACd,CAEA,aAAqB,WAAWN,EAOf,CACf,GAAM,CAAE,KAAAE,EAAM,QAAAD,EAAS,OAAAE,EAAQ,QAAAC,EAAS,UAAAC,EAAW,aAAAC,CAAa,EAAIN,EAGpE,GAAIE,IAAS,UACX,eAAQ,IAAI,sDAAsD,EAC3D,KAAK,YAAY,EAI1B,GAAIA,IAAS,OAASA,IAAS,OAC7B,GAAI,CACF,QAAQ,IAAI,qCAAqC,EACjD,IAAMK,EAAS,MAAM,KAAK,YAAYJ,EAAQF,EAASG,CAAO,EAE9D,eAAQ,IAAI,kCAAkC,EAC9CE,IAAe,EAEf,KAAK,SAAWC,EACTA,CAET,OAASC,EAAO,CACd,IAAMC,EAAeD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EAM1E,GALA,QAAQ,KAAK,gCAAiCC,CAAY,EAE1DJ,IAAYG,aAAiB,MAAQA,EAAQ,IAAI,MAAMC,CAAY,CAAC,EAGhEP,IAAS,MACX,MAAM,IAAI,MAAM,mCAAmCO,CAAY,EAAE,EAInE,eAAQ,IAAI,8CAA8C,EACnD,KAAK,YAAY,CAC1B,CAIF,OAAO,KAAK,YAAY,CAC1B,CAEA,aAAqB,YACnBN,EACAF,EACAG,EACc,CACd,IAAMM,EAAc,KAAK,mBAAmBT,CAAO,EAC7CU,EAAM,GAAGR,CAAM,GAAGO,CAAW,kBAEnC,QAAQ,IAAI,kCAAkCC,CAAG,EAAE,EAGnD,IAAMC,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAM,EAAGR,CAAO,EAE9D,GAAI,CAGF,IAAMU,EAAgB,OAA0BH,GAC1CI,EAAiB,IAAI,QAAQ,CAACC,EAAGC,IAAW,CAChD,WAAW,IAAMA,EAAO,IAAI,MAAM,0BAA0Bb,CAAO,IAAI,CAAC,EAAGA,CAAO,CACpF,CAAC,EAEKc,EAAS,MAAM,QAAQ,KAAK,CAACJ,EAAeC,CAAc,CAAC,EAIjE,GAFA,aAAaF,CAAS,EAElB,CAACK,GAAU,CAACA,EAAO,YACrB,MAAM,IAAI,MAAM,uCAAuC,EAGzD,YAAK,SAAWA,EAAO,YAChB,KAAK,QAEd,OAASV,EAAO,CACd,mBAAaK,CAAS,EAChBL,CACR,CACF,CAEA,aAAqB,aAA4B,CAC/C,GAAI,CAEF,IAAMU,EAAS,KAAM,qCAErB,GAAI,CAACA,GAAU,CAACA,EAAO,YACrB,MAAM,IAAI,MAAM,2CAA2C,EAG7D,YAAK,SAAWA,EAAO,YAChB,KAAK,QAEd,OAASV,EAAO,CACd,IAAMC,EAAeD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EAC1E,MAAM,IAAI,MAAM,kCAAkCC,CAAY,EAAE,CAClE,CACF,CAEA,OAAe,mBAAmBR,EAAyB,CAEzD,OAAIA,IAAY,QAEP,IADc,KAAK,gBAAgB,CACnB,GAIrBA,IAAY,SACP,UAIF,IAAIA,CAAO,EACpB,CAEA,OAAe,iBAA0B,CAES,CAC9C,IAAMkB,EAAQ,QAAoB,MAAM,UAAU,EAClD,GAAIA,EACF,OAAOA,EAAM,CAAC,CAElB,CAIA,MAAO,GACT,CAKA,OAAO,OAAc,CACnB,KAAK,SAAW,KAChB,KAAK,YAAc,IACrB,CAKA,OAAO,aAA0B,CAC/B,OAAO,KAAK,QACd,CACF,EAGOC,EAAQrB",
|
|
6
|
-
"names": ["widget_exports", "__export", "SupernalTTS", "widget_default", "init_widget", "__esmMin", "_SupernalTTS", "options", "mutations", "mutation", "node", "element", "widget", "widgets", "config", "hash", "controls", "text", "voice", "provider", "speed", "voicesAttr", "voices", "v", "enableSpeed", "enableProgress", "apiKey", "buttonContainer", "playButton", "badge", "e", "container", "topRow", "voiceSelect", "speedControl", "speedSlider", "speedValue", "newHash", "buttonGroup", "stopButton", "progressBar", "progressSlider", "percent", "currentTime", "duration", "currentVoice", "currentSpeed", "savedPosition", "controlsRow", "voiceDropdown", "newVoice", "speedDropdown", "newSpeed", "selectedVoice", "toggleButton", "dropdown", "option", "opt", "hideTimeout", "rect", "viewportHeight", "isHidden", "selectedSpeed", "button", "speeds", "slider", "timeDisplay", "percentage", "seconds", "mins", "secs", "word", "compact", "img", "minimizedBtn", "fullBtn", "addHoverEffect", "btn", "clearCache", "count", "clickX", "btnWidth", "audioUrl", "response", "error", "body", "headers", "data", "originalMessage", "reader", "decoder", "buffer", "totalChunks", "completedChunks", "updateProgress", "completed", "total", "currentSpan", "done", "value", "lines", "line", "event", "parseError", "playbackSpeed", "resolve", "reject", "audio", "playPromise", "currentTimeSpan", "durationSpan", "positionPercent", "hasSeekCompleted", "state", "playIcon", "message", "tooltip", "str", "i", "char", "cached", "metadata", "stored", "el", "autoInitScript", "WidgetLoader", "options", "version", "mode", "cdnUrl", "timeout", "onCdnFail", "onCdnSuccess", "widget", "error", "errorMessage", "versionPath", "url", "controller", "timeoutId", "modulePromise", "timeoutPromise", "_", "reject", "module", "match", "loader_default"]
|
|
4
|
+
"sourcesContent": ["/**\n * Supernal TTS Widget\n * Embeddable text-to-speech widget for blogs and websites\n */\n\nexport interface SupernalTTSOptions {\n apiUrl?: string;\n voice?: string;\n provider?: string;\n speed?: number; // Default speed for all widgets (1.0 = normal)\n autoHash?: boolean;\n cacheExpiry?: number;\n apiKey?: string;\n showBranding?: boolean;\n version?: string;\n devMode?: boolean;\n clientSideSpeed?: boolean; // Use HTML5 playbackRate for speed adjustment (default: true)\n generationMode?: 'standard' | 'progressive' | 'realtime'; // Generation mode (default: 'standard')\n progressiveThreshold?: number; // Character count threshold to use progressive mode (default: 2000)\n}\n\nexport interface TTSGenerateOptions {\n provider: string;\n voice: string;\n speed: number;\n format?: string;\n quality?: string;\n cache?: boolean;\n}\n\nexport interface TTSResponse {\n audioUrl: string;\n hash: string;\n cached: boolean;\n duration?: number;\n cost?: number;\n}\n\nexport interface CachedAudio {\n audioUrl: string;\n metadata: Record<string, any>;\n expiry: number;\n timestamp: number;\n}\n\nexport interface WidgetData {\n text: string;\n voice: string;\n provider: string;\n speed: number;\n hash: string;\n playButton: HTMLButtonElement;\n stopButton?: HTMLButtonElement;\n voiceSelect?: HTMLSelectElement;\n speedSlider?: HTMLInputElement;\n progressSlider?: HTMLInputElement;\n advanced?: boolean;\n}\n\nexport interface WidgetConfig {\n text: string;\n voices: string[]; // Array of available voices (empty = no voice control)\n enableSpeed: boolean; // Show speed control\n enableProgress: boolean; // Show progress bar\n speed: number;\n provider: string;\n voice: string;\n apiKey?: string; // Optional per-widget API key\n}\n\nexport class SupernalTTS {\n private apiUrl: string;\n private defaultVoice: string;\n private defaultProvider: string;\n private defaultSpeed: number;\n private autoHash: boolean;\n private cacheExpiry: number;\n private apiKey?: string;\n private showBranding: boolean;\n private version: string;\n private devMode: boolean;\n private clientSideSpeed: boolean;\n private generationMode: 'standard' | 'progressive' | 'realtime';\n private progressiveThreshold: number;\n \n private cache: Map<string, CachedAudio>;\n private currentAudio: HTMLAudioElement | null = null;\n private currentButton: HTMLButtonElement | null = null;\n private currentWidget?: WidgetData;\n private isProcessing: boolean = false;\n private lastClickTime: number = 0;\n private debounceDelay: number = 300;\n private progressUpdateInterval: number | null = null; // Track interval globally\n private audioQueue: Uint8Array[] = []; // Queue for progressive streaming chunks\n\n constructor(options: SupernalTTSOptions = {}) {\n this.apiUrl = options.apiUrl || 'https://www.tts.supernal.ai';\n this.defaultVoice = options.voice || 'default';\n this.defaultProvider = options.provider || 'openai';\n this.defaultSpeed = options.speed || 1.0;\n this.autoHash = options.autoHash !== false;\n this.cacheExpiry = options.cacheExpiry || 7 * 24 * 60 * 60 * 1000; // 7 days\n\n // Auto-detect API key from common environment variables if not explicitly provided\n // Supports: NEXT_PUBLIC_TTS_API_KEY, VITE_TTS_API_KEY, PUBLIC_TTS_API_KEY, REACT_APP_TTS_API_KEY\n this.apiKey = options.apiKey || this.detectApiKey();\n\n this.showBranding = options.showBranding !== false;\n this.version = options.version || '1.0.0';\n // devMode must be explicitly enabled now (not auto-enabled by localhost)\n this.devMode = options.devMode === true;\n this.clientSideSpeed = options.clientSideSpeed !== false; // Default to true for cost savings\n this.generationMode = options.generationMode || 'standard';\n this.progressiveThreshold = options.progressiveThreshold || 2000;\n\n this.cache = new Map();\n this.loadCacheFromStorage();\n\n this.init();\n }\n\n /**\n * Auto-detect API key from common framework environment variables\n * Checks in order: NEXT_PUBLIC_TTS_API_KEY, VITE_TTS_API_KEY, PUBLIC_TTS_API_KEY, REACT_APP_TTS_API_KEY\n */\n private detectApiKey(): string | undefined {\n if (typeof window === 'undefined') {\n return undefined; // Server-side, no auto-detection\n }\n\n // Check common framework patterns for client-side env vars\n const envVars = [\n 'NEXT_PUBLIC_TTS_API_KEY', // Next.js\n 'VITE_TTS_API_KEY', // Vite\n 'PUBLIC_TTS_API_KEY', // SvelteKit, Astro\n 'REACT_APP_TTS_API_KEY' // Create React App\n ];\n\n for (const varName of envVars) {\n try {\n // Try process.env (bundlers often expose this at build time)\n const processEnv = (globalThis as any).process?.env;\n if (processEnv?.[varName]) {\n console.log(`[TTS Widget] Auto-detected API key from process.env.${varName}`);\n return processEnv[varName];\n }\n\n // Try import.meta.env (Vite, modern bundlers)\n const importMetaEnv = (globalThis as any).import?.meta?.env;\n if (importMetaEnv?.[varName]) {\n console.log(`[TTS Widget] Auto-detected API key from import.meta.env.${varName}`);\n return importMetaEnv[varName];\n }\n } catch (e) {\n // Silently continue if env access fails\n continue;\n }\n }\n\n return undefined;\n }\n\n private init(): void {\n // Auto-initialize widgets on page load\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => this.initializeWidgets());\n } else {\n this.initializeWidgets();\n }\n \n // Set up MutationObserver to detect dynamically added widgets\n // This handles client-side routing (SPA navigation) and dynamic content\n this.observeDOM();\n }\n\n private observeDOM(): void {\n // Watch for new elements being added to the DOM\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n // Check if the added node is an element\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n \n // Check if it's a widget or contains widgets\n if (element.classList?.contains('supernal-tts-widget')) {\n this.setupWidget(element);\n } else {\n // Check for widgets within the added element\n const widgets = element.querySelectorAll?.('.supernal-tts-widget');\n widgets?.forEach((widget) => this.setupWidget(widget as HTMLElement));\n }\n }\n });\n });\n });\n\n // Start observing the document body for changes\n observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n private initializeWidgets(): void {\n const widgets = document.querySelectorAll<HTMLElement>('.supernal-tts-widget');\n widgets.forEach(widget => this.setupWidget(widget));\n\n // Add dev mode cache clear button only if widgets exist and devMode is enabled\n if (this.devMode && widgets.length > 0) {\n this.addDevModeClearButton();\n }\n }\n\n private setupWidget(element: HTMLElement): void {\n // Check if already initialized to prevent duplicates\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n\n // Parse widget configuration from data attributes\n const config = this.parseWidgetConfig(element);\n \n if (!config.text) {\n console.warn('TTS Widget: No text found for widget', element);\n return;\n }\n\n // Generate hash for caching\n const hash = this.generateHash(config.text, { \n voice: config.voice, \n provider: config.provider, \n speed: config.speed \n });\n\n // Check for legacy controls attribute for backwards compatibility\n const controls = element.dataset.controls;\n if (controls === 'advanced' || controls === 'true') {\n this.setupAdvancedWidget(element, config.text, {\n voice: config.voice,\n provider: config.provider,\n speed: config.speed,\n hash,\n apiKey: config.apiKey\n });\n return;\n } else if (controls === 'compact') {\n this.setupCompactWidget(element, config.text, {\n voice: config.voice,\n provider: config.provider,\n speed: config.speed,\n hash,\n apiKey: config.apiKey\n });\n return;\n }\n\n // Use new modular widget setup\n this.setupModularWidget(element, config, hash);\n }\n\n /**\n * Scrub text to remove URLs and convert markdown links to plain text\n * - Markdown links [text](url) -> text\n * - Bare URLs -> \"link\"\n */\n private scrubText(text: string): string {\n if (!text) return '';\n\n let scrubbed = text;\n\n // Replace markdown links [text](url) with just the text\n // Handles various URL formats including those with/without http/https\n scrubbed = scrubbed.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '$1');\n\n // Replace bare URLs with the word \"link\"\n // Matches http://, https://, and www. URLs\n scrubbed = scrubbed.replace(/https?:\\/\\/[^\\s]+/g, 'link');\n scrubbed = scrubbed.replace(/www\\.[^\\s]+/g, 'link');\n\n return scrubbed;\n }\n\n /**\n * Parse widget configuration from data attributes\n */\n private parseWidgetConfig(element: HTMLElement): WidgetConfig {\n const rawText = element.dataset.text || element.textContent?.trim() || '';\n const text = this.scrubText(rawText);\n const voice = element.dataset.voice || this.defaultVoice;\n const provider = element.dataset.provider || this.defaultProvider;\n const speed = element.dataset.speed ? parseFloat(element.dataset.speed) : this.defaultSpeed;\n \n // Parse voices list (comma-separated)\n const voicesAttr = element.dataset.voices || '';\n const voices = voicesAttr ? voicesAttr.split(',').map(v => v.trim()).filter(Boolean) : [];\n \n // Parse boolean flags\n const enableSpeed = element.dataset.enableSpeed === 'true';\n const enableProgress = element.dataset.enableProgress === 'true';\n \n // Check for widget-specific API key (overrides global)\n const apiKey = element.dataset.apiKey || this.apiKey;\n\n return {\n text,\n voices,\n enableSpeed,\n enableProgress,\n speed,\n provider,\n voice,\n apiKey, // Include API key in config\n };\n }\n\n private setupBasicWidget(element: HTMLElement, text: string, options: any): void {\n const { voice, provider, speed, hash, apiKey } = options;\n \n // Check if already initialized to prevent duplicates\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n \n // Create container for button and branding\n const buttonContainer = document.createElement('div');\n buttonContainer.className = 'supernal-tts-button-container';\n \n // Create or find play button\n let playButton = element.querySelector<HTMLButtonElement>('.supernal-tts-play');\n if (!playButton) {\n playButton = this.createPlayButton();\n }\n \n buttonContainer.appendChild(playButton);\n\n // Add branding badge if enabled (only once)\n if (this.showBranding && !element.querySelector('.supernal-badge')) {\n const badge = this.createBrandingBadge();\n buttonContainer.appendChild(badge);\n }\n \n element.appendChild(buttonContainer);\n\n // Add widget styling\n element.classList.add('supernal-tts-widget-initialized');\n \n // Setup event listeners\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash, apiKey });\n });\n\n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton\n };\n }\n\n private setupCompactWidget(element: HTMLElement, text: string, options: any): void {\n const { hash, apiKey } = options;\n let { voice, provider, speed } = options;\n \n // Check if already initialized\n if (element.classList.contains('supernal-tts-widget-initialized')) {\n return;\n }\n \n // Create container for compact controls\n const container = document.createElement('div');\n container.className = 'supernal-tts-compact-widget';\n \n // Top row: Play button + Voice selector\n const topRow = document.createElement('div');\n topRow.className = 'supernal-tts-top-row';\n \n const playButton = this.createPlayButton();\n \n // Voice selector (compact)\n const voiceSelect = document.createElement('select');\n voiceSelect.className = 'supernal-tts-voice-select';\n voiceSelect.innerHTML = `\n <option value=\"alloy\" ${voice === 'alloy' ? 'selected' : ''}>Alloy</option>\n <option value=\"echo\" ${voice === 'echo' ? 'selected' : ''}>Echo</option>\n <option value=\"fable\" ${voice === 'fable' ? 'selected' : ''}>Fable</option>\n <option value=\"onyx\" ${voice === 'onyx' ? 'selected' : ''}>Onyx</option>\n <option value=\"nova\" ${voice === 'nova' ? 'selected' : ''}>Nova</option>\n <option value=\"shimmer\" ${voice === 'shimmer' ? 'selected' : ''}>Shimmer</option>\n <option value=\"coral\" ${voice === 'coral' ? 'selected' : ''}>Coral</option>\n `;\n \n topRow.appendChild(playButton);\n topRow.appendChild(voiceSelect);\n \n // Add branding badge if enabled\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n topRow.appendChild(badge);\n }\n \n // Bottom row: Speed control\n const speedControl = document.createElement('div');\n speedControl.className = 'supernal-tts-speed-control';\n speedControl.innerHTML = `\n <label>Speed: <span class=\"supernal-tts-speed-value\">${speed}x</span></label>\n <input type=\"range\" class=\"supernal-tts-speed-slider\" min=\"0.25\" max=\"4.0\" step=\"0.25\" value=\"${speed}\">\n `;\n \n // Assemble widget\n container.appendChild(topRow);\n container.appendChild(speedControl);\n \n element.innerHTML = '';\n element.appendChild(container);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-compact');\n \n // Setup event listeners\n const speedSlider = speedControl.querySelector<HTMLInputElement>('.supernal-tts-speed-slider')!;\n const speedValue = speedControl.querySelector<HTMLSpanElement>('.supernal-tts-speed-value')!;\n\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n speed = parseFloat(speedSlider.value);\n voice = voiceSelect.value;\n const newHash = this.generateHash(text, { voice, provider, speed });\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash: newHash, apiKey });\n });\n \n speedSlider.addEventListener('input', (e) => {\n speed = parseFloat((e.target as HTMLInputElement).value);\n speedValue.textContent = `${speed}x`;\n });\n \n voiceSelect.addEventListener('change', () => {\n voice = voiceSelect.value;\n });\n \n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton,\n compact: true\n };\n }\n\n private setupAdvancedWidget(element: HTMLElement, text: string, options: any): void {\n const { hash, apiKey } = options;\n let { voice, provider, speed } = options;\n \n // Create controls container\n const container = document.createElement('div');\n container.className = 'supernal-tts-advanced-widget';\n \n // Create play/pause/stop buttons\n const buttonGroup = document.createElement('div');\n buttonGroup.className = 'supernal-tts-button-group';\n \n const playButton = this.createPlayButton();\n const stopButton = this.createStopButton();\n \n buttonGroup.appendChild(playButton);\n buttonGroup.appendChild(stopButton);\n \n // Create voice selector\n const voiceSelect = document.createElement('select');\n voiceSelect.className = 'supernal-tts-voice-select';\n voiceSelect.innerHTML = `\n <option value=\"alloy\" ${voice === 'alloy' ? 'selected' : ''}>Alloy</option>\n <option value=\"echo\" ${voice === 'echo' ? 'selected' : ''}>Echo</option>\n <option value=\"fable\" ${voice === 'fable' ? 'selected' : ''}>Fable</option>\n <option value=\"onyx\" ${voice === 'onyx' ? 'selected' : ''}>Onyx</option>\n <option value=\"nova\" ${voice === 'nova' ? 'selected' : ''}>Nova</option>\n <option value=\"shimmer\" ${voice === 'shimmer' ? 'selected' : ''}>Shimmer</option>\n <option value=\"coral\" ${voice === 'coral' ? 'selected' : ''}>Coral</option>\n `;\n \n // Create speed control\n const speedControl = document.createElement('div');\n speedControl.className = 'supernal-tts-speed-control';\n speedControl.innerHTML = `\n <label>Speed: <span class=\"supernal-tts-speed-value\">${speed}x</span></label>\n <input type=\"range\" class=\"supernal-tts-speed-slider\" min=\"0.25\" max=\"4.0\" step=\"0.25\" value=\"${speed}\">\n `;\n \n // Create progress bar\n const progressBar = document.createElement('div');\n progressBar.className = 'supernal-tts-progress';\n progressBar.innerHTML = `\n <input type=\"range\" class=\"supernal-tts-progress-slider\" min=\"0\" max=\"100\" value=\"0\" step=\"0.1\">\n <div class=\"supernal-tts-time\"><span class=\"supernal-tts-current-time\">0:00</span> / <span class=\"supernal-tts-duration\">0:00</span></div>\n `;\n \n // Assemble widget\n container.appendChild(buttonGroup);\n container.appendChild(voiceSelect);\n container.appendChild(speedControl);\n container.appendChild(progressBar);\n \n // Add branding badge if enabled\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n container.appendChild(badge);\n }\n \n element.innerHTML = '';\n element.appendChild(container);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-advanced');\n \n // Setup event listeners\n const speedSlider = speedControl.querySelector<HTMLInputElement>('.supernal-tts-speed-slider')!;\n const speedValue = speedControl.querySelector<HTMLSpanElement>('.supernal-tts-speed-value')!;\n const progressSlider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider')!;\n\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n speed = parseFloat(speedSlider.value);\n voice = voiceSelect.value;\n const newHash = this.generateHash(text, { voice, provider, speed });\n this.handlePlayClick(playButton, text, { voice, provider, speed, hash: newHash, apiKey });\n });\n \n stopButton.addEventListener('click', (e) => {\n e.preventDefault();\n this.stopAudio();\n });\n \n speedSlider.addEventListener('input', (e) => {\n speed = parseFloat((e.target as HTMLInputElement).value);\n speedValue.textContent = `${speed}x`;\n });\n \n voiceSelect.addEventListener('change', () => {\n voice = voiceSelect.value;\n });\n \n progressSlider.addEventListener('input', (e) => {\n if (this.currentAudio) {\n const percent = parseFloat((e.target as HTMLInputElement).value) / 100;\n this.currentAudio.currentTime = this.currentAudio.duration * percent;\n }\n });\n \n // Update progress bar during playback\n const updateProgress = () => {\n if (this.currentAudio && (element as any)._ttsWidget === this.currentWidget) {\n const percent = (this.currentAudio.currentTime / this.currentAudio.duration) * 100;\n progressSlider.value = percent.toString();\n \n const currentTime = this.formatTime(this.currentAudio.currentTime);\n const duration = this.formatTime(this.currentAudio.duration);\n progressBar.querySelector('.supernal-tts-current-time')!.textContent = currentTime;\n progressBar.querySelector('.supernal-tts-duration')!.textContent = duration;\n }\n };\n \n setInterval(updateProgress, 100);\n \n // Store reference for later use\n (element as any)._ttsWidget = {\n text,\n voice,\n provider,\n speed,\n hash,\n playButton,\n stopButton,\n voiceSelect,\n speedSlider,\n progressSlider,\n advanced: true\n };\n \n this.currentWidget = (element as any)._ttsWidget;\n }\n\n /**\n * Setup modular widget with conditional features based on config\n */\n private setupModularWidget(element: HTMLElement, config: WidgetConfig, hash: string): void {\n let currentVoice = config.voice;\n let currentSpeed = config.speed;\n const { text, voices, enableSpeed, enableProgress, provider, apiKey } = config;\n let savedPosition: number = 0; // Track playback position for voice/speed changes\n\n // Create main container\n const container = document.createElement('div');\n container.className = 'supernal-tts-modular-widget';\n\n // Create controls row\n const controlsRow = document.createElement('div');\n controlsRow.className = 'supernal-tts-controls-row';\n\n // 1. Play button (compact - icon only)\n const playButton = this.createPlayButton(true);\n controlsRow.appendChild(playButton);\n\n // 2. Voice dropdown (conditional)\n let voiceDropdown: HTMLElement | null = null;\n if (voices.length > 0) {\n voiceDropdown = this.createVoiceDropdown(voices, currentVoice);\n controlsRow.appendChild(voiceDropdown);\n \n // Listen for voice changes\n voiceDropdown.addEventListener('voice-changed', ((e: CustomEvent) => {\n const newVoice = e.detail.voice;\n \n // If voice changed while playing, save position and regenerate\n if (newVoice !== currentVoice && this.currentButton === playButton && this.currentAudio) {\n currentVoice = newVoice;\n \n // Save current playback position as percentage\n if (this.currentAudio.duration > 0) {\n savedPosition = this.currentAudio.currentTime / this.currentAudio.duration;\n }\n \n // Get the progress bar reference\n const widgetData = (element as any)._ttsWidget;\n const progressBar = widgetData?.progressBar;\n \n // Clean stop: clear audio and intervals, but keep progress bar visible\n this.cleanStopAudioKeepProgress(progressBar);\n \n // Trigger new playback with updated voice and saved position\n setTimeout(() => {\n this.handlePlayClickFromPosition(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed }),\n progressBar,\n apiKey\n }, savedPosition);\n }, 50);\n } else {\n currentVoice = newVoice;\n }\n }) as EventListener);\n }\n\n // 3. Speed dropdown (conditional)\n let speedDropdown: HTMLElement | null = null;\n if (enableSpeed) {\n speedDropdown = this.createSpeedDropdown(currentSpeed);\n controlsRow.appendChild(speedDropdown);\n \n // Listen for speed changes\n speedDropdown.addEventListener('speed-changed', ((e: CustomEvent) => {\n const newSpeed = e.detail.speed;\n \n if (newSpeed !== currentSpeed) {\n currentSpeed = newSpeed;\n \n // Client-side speed adjustment: use HTML5 playbackRate with pitch preservation\n if (this.clientSideSpeed && this.currentAudio && this.currentButton === playButton) {\n // Instant speed change via playbackRate with pitch preservation - no regeneration needed!\n // The browser's time-stretching algorithm maintains pitch quality\n this.currentAudio.playbackRate = newSpeed;\n } \n // Server-side speed adjustment: regenerate audio (expensive but higher quality)\n else if (!this.clientSideSpeed && this.currentButton === playButton && this.currentAudio) {\n // Save current playback position as percentage\n if (this.currentAudio.duration > 0) {\n savedPosition = this.currentAudio.currentTime / this.currentAudio.duration;\n }\n \n // Get the progress bar reference\n const widgetData = (element as any)._ttsWidget;\n const progressBar = widgetData?.progressBar;\n \n // Clean stop: clear audio and intervals, but keep progress bar visible\n this.cleanStopAudioKeepProgress(progressBar);\n \n // Trigger new playback with updated speed and saved position\n setTimeout(() => {\n this.handlePlayClickFromPosition(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed }),\n progressBar,\n apiKey\n }, savedPosition);\n }, 50);\n }\n }\n }) as EventListener);\n }\n\n // 4. Branding badge\n if (this.showBranding) {\n const badge = this.createBrandingBadge();\n controlsRow.appendChild(badge);\n }\n\n container.appendChild(controlsRow);\n\n // 5. Progress bar (conditional)\n let progressBar: HTMLElement | null = null;\n if (enableProgress) {\n progressBar = this.createProgressBar();\n container.appendChild(progressBar);\n }\n\n // IMPORTANT: Prepend controls, keep original content\n element.insertBefore(container, element.firstChild);\n element.classList.add('supernal-tts-widget-initialized', 'supernal-tts-widget-modular');\n \n // Add has-progress class if progress bar is enabled\n if (enableProgress) {\n element.classList.add('has-progress');\n }\n\n // Setup play button handler\n playButton.addEventListener('click', (e) => {\n e.preventDefault();\n const newHash = this.generateHash(text, { voice: currentVoice, provider, speed: currentSpeed });\n this.handlePlayClick(playButton, text, {\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash: newHash,\n progressBar,\n apiKey\n });\n });\n\n // Store reference\n (element as any)._ttsWidget = {\n text,\n voice: currentVoice,\n provider,\n speed: currentSpeed,\n hash,\n playButton,\n voiceDropdown,\n speedDropdown,\n progressBar\n };\n }\n\n /**\n * Create voice dropdown with person icon button\n */\n private createVoiceDropdown(voices: string[], selectedVoice: string): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-voice-control';\n\n // Person icon toggle button (no background)\n const toggleButton = document.createElement('button');\n toggleButton.className = 'supernal-tts-voice-toggle';\n toggleButton.setAttribute('aria-label', 'Select voice');\n toggleButton.setAttribute('aria-expanded', 'false');\n toggleButton.innerHTML = `\n <svg class=\"supernal-tts-voice-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z\"/>\n </svg>\n `;\n\n // Dropdown menu (hidden by default)\n const dropdown = document.createElement('div');\n dropdown.className = 'supernal-tts-voice-dropdown hidden';\n dropdown.setAttribute('role', 'menu');\n\n voices.forEach(voice => {\n const option = document.createElement('button');\n option.className = 'supernal-tts-voice-option';\n option.textContent = this.formatVoiceName(voice);\n option.dataset.voice = voice;\n option.setAttribute('role', 'menuitem');\n \n if (voice === selectedVoice) {\n option.classList.add('active');\n }\n\n option.addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n \n // Update active state\n dropdown.querySelectorAll('.supernal-tts-voice-option').forEach(opt => {\n opt.classList.remove('active');\n });\n option.classList.add('active');\n\n // Emit change event\n container.dispatchEvent(new CustomEvent('voice-changed', { \n detail: { voice } \n }));\n });\n\n dropdown.appendChild(option);\n });\n\n let hideTimeout: number | null = null;\n\n // Show dropdown on hover with smart positioning\n container.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n dropdown.classList.remove('hidden');\n toggleButton.setAttribute('aria-expanded', 'true');\n \n // Smart positioning: check if dropdown would go off-screen\n setTimeout(() => {\n const rect = dropdown.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n \n if (rect.bottom > viewportHeight && rect.top > rect.height) {\n // Not enough space below, position above\n dropdown.style.bottom = '100%';\n dropdown.style.top = 'auto';\n } else {\n // Default: position below\n dropdown.style.top = 'calc(100% + 4px)';\n dropdown.style.bottom = 'auto';\n }\n }, 0);\n });\n\n container.addEventListener('mouseleave', (e) => {\n // Delay hiding to allow moving to dropdown\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n toggleButton.setAttribute('aria-expanded', 'false');\n }, 150);\n });\n\n // Keep dropdown open when hovering over it\n dropdown.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n });\n\n dropdown.addEventListener('mouseleave', () => {\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n toggleButton.setAttribute('aria-expanded', 'false');\n }, 150);\n });\n\n // Also allow click to toggle\n toggleButton.addEventListener('click', (e) => {\n e.stopPropagation();\n const isHidden = dropdown.classList.contains('hidden');\n dropdown.classList.toggle('hidden');\n toggleButton.setAttribute('aria-expanded', isHidden ? 'true' : 'false');\n });\n\n container.appendChild(toggleButton);\n container.appendChild(dropdown);\n\n return container;\n }\n\n /**\n * Create speed dropdown with preset values (hover to reveal)\n */\n private createSpeedDropdown(selectedSpeed: number): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-speed-control';\n\n // Speedometer/gauge icon button (no background)\n const button = document.createElement('button');\n button.className = 'supernal-tts-speed-toggle';\n button.setAttribute('aria-label', 'Adjust playback speed');\n button.innerHTML = `\n <svg class=\"supernal-tts-speed-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z\"/>\n <path d=\"M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z\"/>\n </svg>\n `;\n\n // Dropdown menu (hidden by default, shows on hover)\n const dropdown = document.createElement('div');\n dropdown.className = 'supernal-tts-speed-dropdown hidden';\n dropdown.setAttribute('role', 'menu');\n\n // Speed range: 0.6 to 3.0 in steps of 0.2\n const speeds: number[] = [];\n for (let speed = 0.6; speed <= 3.0; speed += 0.2) {\n speeds.push(Math.round(speed * 10) / 10); // Round to 1 decimal\n }\n \n speeds.forEach(speed => {\n const option = document.createElement('button');\n option.className = 'supernal-tts-speed-option';\n option.textContent = `${speed.toFixed(1)}x`;\n option.dataset.speed = speed.toString();\n option.setAttribute('role', 'menuitem');\n\n if (Math.abs(speed - selectedSpeed) < 0.01) {\n option.classList.add('active');\n }\n\n option.addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n\n // Update active state\n dropdown.querySelectorAll('.supernal-tts-speed-option').forEach(opt => {\n opt.classList.remove('active');\n });\n option.classList.add('active');\n\n // Emit change event\n container.dispatchEvent(new CustomEvent('speed-changed', { \n detail: { speed } \n }));\n });\n\n dropdown.appendChild(option);\n });\n\n let hideTimeout: number | null = null;\n\n // Show dropdown on hover with smart positioning\n container.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n dropdown.classList.remove('hidden');\n \n // Smart positioning: check if dropdown would go off-screen\n setTimeout(() => {\n const rect = dropdown.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n \n if (rect.bottom > viewportHeight && rect.top > rect.height) {\n // Not enough space below, position above\n dropdown.style.bottom = '100%';\n dropdown.style.top = 'auto';\n } else {\n // Default: position below\n dropdown.style.top = 'calc(100% + 4px)';\n dropdown.style.bottom = 'auto';\n }\n }, 0);\n });\n\n container.addEventListener('mouseleave', () => {\n // Delay hiding to allow moving to dropdown\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n }, 150);\n });\n\n // Keep dropdown open when hovering over it\n dropdown.addEventListener('mouseenter', () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n });\n\n dropdown.addEventListener('mouseleave', () => {\n hideTimeout = window.setTimeout(() => {\n dropdown.classList.add('hidden');\n }, 150);\n });\n\n container.appendChild(button);\n container.appendChild(dropdown);\n\n return container;\n }\n\n /**\n * Create seekable progress bar with time display\n */\n private createProgressBar(): HTMLElement {\n const container = document.createElement('div');\n container.className = 'supernal-tts-progress-container';\n\n const slider = document.createElement('input');\n slider.type = 'range';\n slider.className = 'supernal-tts-progress-slider';\n slider.min = '0';\n slider.max = '100';\n slider.value = '0';\n slider.step = '0.1';\n slider.setAttribute('aria-label', 'Seek audio position');\n\n const timeDisplay = document.createElement('div');\n timeDisplay.className = 'supernal-tts-time-display';\n timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n\n // Seeking functionality\n slider.addEventListener('input', (e) => {\n if (this.currentAudio) {\n const percentage = parseFloat((e.target as HTMLInputElement).value);\n this.currentAudio.currentTime = (percentage / 100) * this.currentAudio.duration;\n }\n });\n\n container.appendChild(slider);\n container.appendChild(timeDisplay);\n\n return container;\n }\n\n /**\n * Format seconds to MM:SS\n */\n private formatTime(seconds: number): string {\n if (!seconds || isNaN(seconds)) return '0:00';\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n }\n\n /**\n * Format voice name for display\n */\n private formatVoiceName(voice: string): string {\n // Capitalize first letter and replace dashes/underscores with spaces\n return voice\n .replace(/[-_]/g, ' ')\n .split(' ')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n private createStopButton(): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'supernal-tts-stop';\n button.innerHTML = `\n <svg class=\"supernal-tts-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\"/>\n </svg>\n <span class=\"supernal-tts-text\">Stop</span>\n `;\n button.setAttribute('aria-label', 'Stop text-to-speech');\n return button;\n }\n\n private createPlayButton(compact: boolean = false): HTMLButtonElement {\n const button = document.createElement('button');\n button.className = 'supernal-tts-play';\n \n if (compact) {\n // Compact mode: icon only, circular button\n button.classList.add('supernal-tts-play-compact');\n button.innerHTML = `\n <svg class=\"supernal-tts-icon supernal-tts-play-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n <svg class=\"supernal-tts-icon supernal-tts-loading-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n `;\n } else {\n // Full mode: icon + text\n button.innerHTML = `\n <svg class=\"supernal-tts-icon supernal-tts-play-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n <svg class=\"supernal-tts-icon supernal-tts-loading-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span class=\"supernal-tts-text\">Listen</span>\n `;\n }\n \n button.setAttribute('aria-label', 'Play text-to-speech');\n return button;\n }\n\n private createBrandingBadge(): HTMLAnchorElement {\n const badge = document.createElement('a');\n badge.className = 'supernal-badge';\n badge.href = 'https://www.tts.supernal.ai';\n badge.target = '_blank';\n badge.rel = 'noopener noreferrer';\n badge.title = 'Powered by Supernal TTS';\n badge.setAttribute('aria-label', 'Powered by Supernal TTS');\n\n // Use new TTS logo (~+) from brand-kit hosted on CDN\n const img = document.createElement('img');\n img.src = 'https://unpkg.com/@supernal/tts-widget@latest/dist/supernal-tts-logo.svg';\n img.alt = 'Supernal TTS';\n img.className = 'supernal-logo-img';\n img.style.display = 'block';\n img.style.width = '24px';\n img.style.height = '24px';\n\n // Fallback to ~+ text if image fails to load\n img.onerror = () => {\n badge.innerHTML = '~+';\n badge.style.fontSize = '16px';\n badge.style.fontWeight = '700';\n badge.style.display = 'flex';\n badge.style.color = '#0066ff';\n };\n\n badge.appendChild(img);\n return badge;\n }\n\n /**\n * Dev Mode Cache Clear Button\n * Adds a minimizable floating button in dev mode to clear local cache\n * Only appears on pages that have TTS widgets\n */\n private addDevModeClearButton(): void {\n // Only add once\n if (document.getElementById('supernal-tts-dev-clear-cache')) {\n return;\n }\n\n // Create container\n const container = document.createElement('div');\n container.id = 'supernal-tts-dev-clear-cache';\n container.style.cssText = `\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 100;\n font-family: system-ui, -apple-system, sans-serif;\n `;\n\n // Minimized button (trash icon only)\n const minimizedBtn = document.createElement('button');\n minimizedBtn.className = 'supernal-tts-dev-button-minimized';\n minimizedBtn.innerHTML = '\uD83D\uDDD1\uFE0F';\n minimizedBtn.title = 'Clear TTS Cache (Dev Mode)';\n minimizedBtn.style.cssText = `\n display: none;\n background: #6c757d;\n color: white;\n border: none;\n padding: 8px;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n font-size: 16px;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n transition: all 0.2s ease;\n `;\n\n // Full button\n const fullBtn = document.createElement('button');\n fullBtn.className = 'supernal-tts-dev-button';\n fullBtn.style.cssText = `\n background: #dc3545;\n color: white;\n border: none;\n padding: 8px 12px;\n border-radius: 5px;\n font-size: 12px;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n `;\n fullBtn.innerHTML = `\n <span>\uD83D\uDDD1\uFE0F</span>\n <span>Clear Cache</span>\n <span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>\n `;\n\n // Hover effects\n const addHoverEffect = (btn: HTMLButtonElement) => {\n btn.addEventListener('mouseenter', () => {\n btn.style.transform = 'scale(1.05)';\n btn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.4)';\n });\n\n btn.addEventListener('mouseleave', () => {\n btn.style.transform = 'scale(1)';\n btn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)';\n });\n };\n\n addHoverEffect(fullBtn);\n addHoverEffect(minimizedBtn);\n\n // Clear cache handler\n const clearCache = () => {\n const count = this.cache.size;\n this.cache.clear();\n localStorage.removeItem('supernal-tts-cache');\n\n // Visual feedback\n fullBtn.innerHTML = `<span>\u2713</span><span>Cleared ${count}</span><span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>`;\n fullBtn.style.background = '#28a745';\n\n setTimeout(() => {\n fullBtn.innerHTML = `<span>\uD83D\uDDD1\uFE0F</span><span>Clear Cache</span><span style=\"opacity: 0.7; font-size: 10px;\">\u00D7</span>`;\n fullBtn.style.background = '#dc3545';\n }, 2000);\n\n console.log(`[Supernal TTS Dev] Cleared ${count} cached items`);\n };\n\n // Minimize handler\n fullBtn.addEventListener('click', (e) => {\n e.preventDefault();\n const clickX = e.clientX - (e.target as HTMLElement).getBoundingClientRect().left;\n const btnWidth = fullBtn.getBoundingClientRect().width;\n\n // If clicked on the \u00D7 (right 20% of button), minimize\n if (clickX > btnWidth * 0.8) {\n fullBtn.style.display = 'none';\n minimizedBtn.style.display = 'block';\n localStorage.setItem('supernal-tts-dev-minimized', 'true');\n } else {\n clearCache();\n }\n });\n\n // Expand handler\n minimizedBtn.addEventListener('click', (e) => {\n e.preventDefault();\n minimizedBtn.style.display = 'none';\n fullBtn.style.display = 'flex';\n localStorage.setItem('supernal-tts-dev-minimized', 'false');\n });\n\n // Restore minimized state\n const isMinimized = localStorage.getItem('supernal-tts-dev-minimized') === 'true';\n if (isMinimized) {\n fullBtn.style.display = 'none';\n minimizedBtn.style.display = 'block';\n }\n\n container.appendChild(fullBtn);\n container.appendChild(minimizedBtn);\n\n // Add to DOM when ready\n if (document.body) {\n document.body.appendChild(container);\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n document.body.appendChild(container);\n });\n }\n }\n\n private async handlePlayClick(button: HTMLButtonElement, text: string, options: any): Promise<void> {\n const { hash, progressBar } = options;\n \n // If currently playing this button, pause it\n if (button.classList.contains('supernal-tts-playing') && this.currentButton === button) {\n this.pauseAudio();\n return;\n }\n \n // If currently paused on this button, resume it\n if (button.classList.contains('supernal-tts-paused') && this.currentButton === button) {\n this.resumeAudio();\n return;\n }\n \n // Don't allow starting new audio while processing\n if (this.isProcessing) {\n return;\n }\n \n // If another button is playing, stop it first\n if (this.currentAudio && this.currentButton && this.currentButton !== button) {\n this.stopAudio();\n }\n\n try {\n this.isProcessing = true;\n \n // Update button state\n this.setButtonState(button, 'loading');\n \n // Check cache first\n let audioUrl = this.getCachedAudioUrl(hash);\n \n if (!audioUrl) {\n // Determine if we should use progressive mode\n const useProgressive = (\n this.generationMode === 'progressive' || \n (this.generationMode === 'standard' && text.length > this.progressiveThreshold)\n );\n \n if (useProgressive) {\n // Use progressive SSE streaming\n await this.generateAudioProgressive(text, options, button, progressBar);\n return; // generateAudioProgressive handles playback\n } else {\n // Standard generation\n const response = await this.generateAudio(text, options);\n // Convert relative audioUrl to absolute URL\n audioUrl = response.audioUrl.startsWith('http') \n ? response.audioUrl \n : `${this.apiUrl}${response.audioUrl}`;\n \n // Cache the result\n this.cacheAudioUrl(hash, audioUrl, response);\n }\n }\n \n // Play audio with progress bar updates\n await this.playAudio(audioUrl, button, progressBar);\n \n } catch (error) {\n console.error('TTS Error:', error);\n this.setButtonState(button, 'error');\n \n // Show user-friendly error\n this.showError(button, (error as Error).message);\n \n setTimeout(() => this.setButtonState(button, 'ready'), 3000);\n this.isProcessing = false;\n }\n }\n\n private async generateAudio(text: string, options: any): Promise<TTSResponse> {\n const body = {\n text,\n options: {\n provider: options.provider,\n voice: options.voice,\n speed: options.speed || 1.0\n }\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n };\n\n // Use widget-specific API key if provided, otherwise use global\n const apiKey = options.apiKey || this.apiKey;\n console.log('[TTS Widget] Generate Audio - API Key present:', !!apiKey);\n console.log('[TTS Widget] Generate Audio - this.apiKey:', !!this.apiKey);\n console.log('[TTS Widget] Generate Audio - options.apiKey:', !!options.apiKey);\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n console.log('[TTS Widget] Generate Audio - Authorization header added');\n } else {\n console.warn('[TTS Widget] Generate Audio - NO API KEY, Authorization header NOT added');\n }\n\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/generate`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);\n }\n\n const data = await response.json();\n \n return {\n audioUrl: `${this.apiUrl}${data.audioUrl}`,\n hash: data.hash,\n cached: data.cached,\n duration: data.duration,\n cost: data.cost\n };\n } catch (error) {\n // Log the actual error for debugging\n console.error('TTS generation failed:', error);\n \n // Re-throw with more context but preserve the original error\n if ((error as Error).message.includes('Failed to fetch') || (error as Error).message.includes('NetworkError')) {\n const originalMessage = (error as Error).message;\n throw new Error(`TTS API unreachable: ${originalMessage}. Check if ${this.apiUrl} is accessible.`);\n }\n \n // Re-throw other errors as-is\n throw error;\n }\n }\n\n /**\n * Generate audio using progressive SSE streaming\n * Updates progress bar in real-time as chunks complete\n */\n private async generateAudioProgressive(\n text: string, \n options: any, \n button: HTMLButtonElement, \n progressBar?: HTMLElement | null\n ): Promise<void> {\n const body = {\n text,\n options: {\n provider: options.provider,\n voice: options.voice,\n speed: options.speed || 1.0\n }\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'text/event-stream'\n };\n\n const apiKey = options.apiKey || this.apiKey;\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n try {\n const response = await fetch(`${this.apiUrl}/api/v1/generate-progressive`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('No response body for SSE stream');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let totalChunks = 0;\n let completedChunks = 0;\n\n // Update progress bar if available\n const updateProgress = (completed: number, total: number) => {\n if (progressBar) {\n const percentage = (completed / total) * 100;\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) {\n slider.value = percentage.toString();\n }\n \n const currentSpan = progressBar.querySelector<HTMLElement>('.current');\n if (currentSpan) {\n currentSpan.textContent = `Chunk ${completed}/${total}`;\n }\n }\n };\n\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) break;\n \n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n\\n');\n buffer = lines.pop() || '';\n \n for (const line of lines) {\n if (!line.startsWith('data: ')) continue;\n \n try {\n const event = JSON.parse(line.substring(6));\n \n switch (event.type) {\n case 'started':\n totalChunks = event.totalChunks;\n console.log(`[Progressive TTS] Started: ${totalChunks} chunks`);\n this.setButtonState(button, 'loading');\n break;\n \n case 'progress':\n completedChunks = event.completed;\n console.log(`[Progressive TTS] Progress: ${completedChunks}/${totalChunks}`);\n updateProgress(completedChunks, totalChunks);\n break;\n \n case 'complete':\n console.log(`[Progressive TTS] Complete:`, event);\n const audioUrl = event.audioUrl.startsWith('http') \n ? event.audioUrl \n : `${this.apiUrl}${event.audioUrl}`;\n \n // Cache the final result\n this.cacheAudioUrl(options.hash, audioUrl, {\n hash: event.hash,\n cached: false,\n duration: event.duration,\n cost: event.cost\n });\n \n // Play the final stitched audio\n await this.playAudio(audioUrl, button, progressBar);\n break;\n \n case 'error':\n throw new Error(event.message || 'Progressive generation failed');\n }\n } catch (parseError) {\n console.warn('[Progressive TTS] Failed to parse event:', line, parseError);\n }\n }\n }\n } catch (error) {\n console.error('Progressive TTS generation failed:', error);\n this.isProcessing = false;\n throw error;\n }\n }\n\n private async playAudio(audioUrl: string, button: HTMLButtonElement, progressBar?: HTMLElement | null, playbackSpeed?: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const audio = new Audio(audioUrl);\n this.currentAudio = audio;\n this.currentButton = button;\n \n // Enable pitch preservation for client-side speed control\n // This uses native browser time-stretching to maintain pitch quality\n if (this.clientSideSpeed) {\n audio.preservesPitch = true;\n // Fallback for older browsers\n (audio as any).mozPreservesPitch = true;\n (audio as any).webkitPreservesPitch = true;\n }\n \n // Set playback rate if provided (for client-side speed control)\n if (playbackSpeed !== undefined && this.clientSideSpeed) {\n audio.playbackRate = playbackSpeed;\n }\n \n // Clear any existing interval before starting new one\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n audio.addEventListener('loadstart', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'loading');\n }\n });\n \n audio.addEventListener('canplay', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'playing');\n this.isProcessing = false;\n const playPromise = audio.play();\n if (playPromise !== undefined) {\n playPromise.catch(error => {\n console.error('Audio play failed:', error);\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n this.isProcessing = false;\n reject(new Error('Audio playback failed'));\n }\n });\n }\n \n // Start progress bar updates using global interval\n if (progressBar) {\n progressBar.classList.add('playing');\n this.progressUpdateInterval = window.setInterval(() => {\n this.updateProgressBar(audio, progressBar);\n }, 100);\n }\n }\n });\n \n audio.addEventListener('ended', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'ready');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n // Reset progress bar\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) slider.value = '0';\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n \n resolve();\n }\n });\n \n audio.addEventListener('error', (e) => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n }\n \n reject(new Error('Audio playback failed'));\n }\n });\n \n audio.load();\n });\n }\n\n /**\n * Update progress bar during playback\n */\n private updateProgressBar(audio: HTMLAudioElement, progressBar: HTMLElement): void {\n if (!audio || !progressBar) return;\n \n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n const currentTimeSpan = progressBar.querySelector<HTMLElement>('.current');\n const durationSpan = progressBar.querySelector<HTMLElement>('.duration');\n \n if (slider && !isNaN(audio.duration)) {\n const percentage = (audio.currentTime / audio.duration) * 100;\n slider.value = percentage.toString();\n }\n \n if (currentTimeSpan) {\n currentTimeSpan.textContent = this.formatTime(audio.currentTime);\n }\n \n if (durationSpan && !isNaN(audio.duration)) {\n durationSpan.textContent = this.formatTime(audio.duration);\n }\n }\n\n private pauseAudio(): void {\n if (this.currentAudio && !this.currentAudio.paused) {\n this.currentAudio.pause();\n }\n \n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'paused');\n }\n }\n\n private resumeAudio(): void {\n if (this.currentAudio && this.currentAudio.paused) {\n const playPromise = this.currentAudio.play();\n if (playPromise !== undefined) {\n playPromise.then(() => {\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'playing');\n }\n }).catch(error => {\n console.error('Audio resume failed:', error);\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'error');\n }\n });\n }\n }\n }\n\n private stopAudio(): void {\n // Clear interval first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'ready');\n this.currentButton = null;\n }\n \n this.isProcessing = false;\n }\n\n /**\n * Clean stop audio with proper progress bar cleanup\n * Used when regenerating audio with different parameters\n */\n private cleanStopAudio(progressBar?: HTMLElement | null): void {\n // Clear interval first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n // Stop and clear audio\n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n // Reset button state\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'ready');\n this.currentButton = null;\n }\n \n // Clean up progress bar immediately\n if (progressBar) {\n progressBar.classList.remove('playing');\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) {\n slider.value = '0';\n }\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) {\n timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n }\n \n this.isProcessing = false;\n }\n\n /**\n * Clean stop audio but keep progress bar at current position (for voice/speed changes)\n */\n private cleanStopAudioKeepProgress(progressBar?: HTMLElement | null): void {\n // Clear any existing progress update intervals first\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n // Stop and clear audio\n if (this.currentAudio) {\n this.currentAudio.pause();\n this.currentAudio.currentTime = 0;\n this.currentAudio = null;\n }\n \n // Reset button state but don't clear currentButton yet (we're regenerating)\n if (this.currentButton) {\n this.setButtonState(this.currentButton, 'loading');\n }\n \n // Keep progress bar visible but stop updates\n // Progress position is maintained by not resetting the slider value\n \n this.isProcessing = false;\n }\n\n /**\n * Handle play click and seek to a specific position (used for voice/speed changes)\n */\n private async handlePlayClickFromPosition(button: HTMLButtonElement, text: string, options: any, positionPercent: number): Promise<void> {\n const { hash, progressBar } = options;\n \n // Don't allow starting new audio while processing\n if (this.isProcessing) {\n return;\n }\n\n try {\n this.isProcessing = true;\n \n // Update button state\n this.setButtonState(button, 'loading');\n \n // Check cache first\n let audioUrl = this.getCachedAudioUrl(hash);\n \n if (!audioUrl) {\n // Generate new audio\n const response = await this.generateAudio(text, options);\n // Convert relative audioUrl to absolute URL\n audioUrl = response.audioUrl.startsWith('http') \n ? response.audioUrl \n : `${this.apiUrl}${response.audioUrl}`;\n \n // Cache the result\n this.cacheAudioUrl(hash, audioUrl, response);\n }\n \n // Play audio with progress bar updates and seek to saved position\n await this.playAudioFromPosition(audioUrl, button, progressBar, positionPercent);\n \n } catch (error) {\n console.error('TTS Error:', error);\n this.setButtonState(button, 'error');\n \n // Show user-friendly error\n this.showError(button, (error as Error).message);\n \n setTimeout(() => this.setButtonState(button, 'ready'), 3000);\n this.isProcessing = false;\n }\n }\n\n /**\n * Play audio starting from a specific position\n */\n private async playAudioFromPosition(audioUrl: string, button: HTMLButtonElement, progressBar: HTMLElement | null | undefined, positionPercent: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const audio = new Audio(audioUrl);\n this.currentAudio = audio;\n this.currentButton = button;\n \n // Enable pitch preservation for client-side speed control\n // This uses native browser time-stretching to maintain pitch quality\n if (this.clientSideSpeed) {\n audio.preservesPitch = true;\n // Fallback for older browsers\n (audio as any).mozPreservesPitch = true;\n (audio as any).webkitPreservesPitch = true;\n }\n \n // Clear any existing interval before starting new one\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n \n let hasSeekCompleted = false;\n \n audio.addEventListener('loadstart', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'loading');\n }\n });\n \n audio.addEventListener('loadedmetadata', () => {\n // Once we know the duration, seek to the saved position\n if (this.currentAudio === audio && !hasSeekCompleted && positionPercent > 0) {\n audio.currentTime = audio.duration * positionPercent;\n hasSeekCompleted = true;\n }\n });\n \n audio.addEventListener('canplay', () => {\n if (this.currentAudio === audio) {\n // Seek again if metadata wasn't ready earlier\n if (!hasSeekCompleted && positionPercent > 0 && audio.duration > 0) {\n audio.currentTime = audio.duration * positionPercent;\n hasSeekCompleted = true;\n }\n \n this.setButtonState(button, 'playing');\n this.isProcessing = false;\n const playPromise = audio.play();\n if (playPromise !== undefined) {\n playPromise.catch(error => {\n console.error('Audio play failed:', error);\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n this.isProcessing = false;\n reject(new Error('Audio playback failed'));\n }\n });\n }\n \n // Start progress bar updates using global interval\n if (progressBar) {\n progressBar.classList.add('playing');\n this.progressUpdateInterval = window.setInterval(() => {\n this.updateProgressBar(audio, progressBar);\n }, 100);\n }\n }\n });\n \n audio.addEventListener('ended', () => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'ready');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n // Reset progress bar\n const slider = progressBar.querySelector<HTMLInputElement>('.supernal-tts-progress-slider');\n if (slider) slider.value = '0';\n const timeDisplay = progressBar.querySelector('.supernal-tts-time-display');\n if (timeDisplay) timeDisplay.innerHTML = '<span class=\"current\">0:00</span> / <span class=\"duration\">0:00</span>';\n }\n \n resolve();\n }\n });\n \n audio.addEventListener('error', (e) => {\n if (this.currentAudio === audio) {\n this.setButtonState(button, 'error');\n this.currentAudio = null;\n this.currentButton = null;\n \n // Clear progress bar updates\n if (this.progressUpdateInterval) {\n clearInterval(this.progressUpdateInterval);\n this.progressUpdateInterval = null;\n }\n if (progressBar) {\n progressBar.classList.remove('playing');\n }\n \n reject(new Error('Audio playback failed'));\n }\n });\n \n audio.load();\n });\n }\n\n private setButtonState(button: HTMLButtonElement, state: string): void {\n button.classList.remove('supernal-tts-loading', 'supernal-tts-playing', 'supernal-tts-paused', 'supernal-tts-error');\n \n const playIcon = button.querySelector<SVGElement>('.supernal-tts-play-icon');\n const text = button.querySelector<HTMLSpanElement>('.supernal-tts-text');\n \n switch (state) {\n case 'loading':\n button.classList.add('supernal-tts-loading');\n button.disabled = true;\n // Loading spinner shown via CSS\n if (text) text.textContent = 'Loading...';\n break;\n \n case 'playing':\n button.classList.add('supernal-tts-playing');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<rect x=\"6\" y=\"4\" width=\"4\" height=\"16\"/><rect x=\"14\" y=\"4\" width=\"4\" height=\"16\"/>';\n if (text) text.textContent = 'Pause';\n break;\n \n case 'paused':\n button.classList.add('supernal-tts-paused');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M8 5v14l11-7z\"/>';\n if (text) text.textContent = 'Resume';\n break;\n \n case 'error':\n button.classList.add('supernal-tts-error');\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z\"/>';\n if (text) text.textContent = 'Error';\n break;\n \n default: // ready\n button.disabled = false;\n if (playIcon) playIcon.innerHTML = '<path d=\"M8 5v14l11-7z\"/>';\n if (text) text.textContent = 'Listen';\n break;\n }\n }\n\n private showError(button: HTMLButtonElement, message: string): void {\n const tooltip = document.createElement('div');\n tooltip.className = 'supernal-tts-error-tooltip';\n \n if (message.includes('development mode')) {\n tooltip.textContent = message;\n } else if (message.includes('Failed to fetch')) {\n tooltip.textContent = 'Service unavailable (dev mode)';\n } else {\n tooltip.textContent = 'Audio generation failed';\n }\n \n button.parentNode?.appendChild(tooltip);\n \n setTimeout(() => {\n if (tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n }\n }, 3000);\n }\n\n private generateHash(text: string, options: any = {}): string {\n const str = text + JSON.stringify(options);\n let hash = 0;\n \n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n \n return Math.abs(hash).toString(36);\n }\n\n private getCachedAudioUrl(hash: string): string | null {\n const cached = this.cache.get(hash);\n \n if (!cached) return null;\n \n if (Date.now() > cached.expiry) {\n this.cache.delete(hash);\n this.saveCacheToStorage();\n return null;\n }\n \n const audioUrl = cached.audioUrl;\n return audioUrl.startsWith('http') \n ? audioUrl \n : `${this.apiUrl}${audioUrl}`;\n }\n\n private cacheAudioUrl(hash: string, audioUrl: string, metadata: any = {}): void {\n this.cache.set(hash, {\n audioUrl,\n metadata,\n expiry: Date.now() + this.cacheExpiry,\n timestamp: Date.now()\n });\n \n this.saveCacheToStorage();\n }\n\n private loadCacheFromStorage(): void {\n try {\n const stored = localStorage.getItem('supernal-tts-cache');\n if (stored) {\n const data = JSON.parse(stored);\n this.cache = new Map(Object.entries(data));\n }\n } catch (error) {\n console.warn('Failed to load TTS cache:', error);\n }\n }\n\n private saveCacheToStorage(): void {\n try {\n const data = Object.fromEntries(this.cache);\n localStorage.setItem('supernal-tts-cache', JSON.stringify(data));\n } catch (error) {\n console.warn('Failed to save TTS cache:', error);\n }\n }\n\n // Public API methods\n public static init(options?: SupernalTTSOptions): SupernalTTS {\n if ((window as any).SupernalTTSInstance) {\n console.debug('SupernalTTS already initialized, returning existing instance');\n return (window as any).SupernalTTSInstance;\n }\n \n (window as any).SupernalTTSInstance = new SupernalTTS(options);\n return (window as any).SupernalTTSInstance;\n }\n\n public static getInstance(): SupernalTTS | undefined {\n return (window as any).SupernalTTSInstance;\n }\n\n public addWidget(element: HTMLElement | string, text: string, options: any = {}): void {\n let el: HTMLElement | null = null;\n\n if (typeof element === 'string') {\n el = document.querySelector<HTMLElement>(element);\n } else {\n el = element;\n }\n\n if (!el) {\n console.error('TTS Widget: Element not found');\n return;\n }\n\n el.classList.add('supernal-tts-widget');\n el.dataset.text = this.scrubText(text);\n \n if (options.voice) el.dataset.voice = options.voice;\n if (options.provider) el.dataset.provider = options.provider;\n \n this.setupWidget(el);\n }\n}\n\n// Auto-initialize if configuration is found\nif (typeof window !== 'undefined') {\n if (!(window as any).SupernalTTS) {\n (window as any).SupernalTTS = SupernalTTS;\n \n const autoInitScript = document.querySelector<HTMLScriptElement>('script[data-supernal-tts-auto-init]');\n if (autoInitScript && autoInitScript.dataset) {\n const config = JSON.parse(autoInitScript.dataset.supernalTtsAutoInit || '{}');\n SupernalTTS.init(config);\n }\n } else {\n console.debug('SupernalTTS already loaded, skipping redeclaration');\n }\n}\n\nexport default SupernalTTS;\n\n", "/**\n * Smart Widget Loader\n *\n * Dynamically loads the latest compatible widget version from unpkg CDN\n * with automatic fallback to bundled version for CSP/firewall scenarios.\n *\n * @example\n * ```typescript\n * import { WidgetLoader } from '@supernal-tts/widget';\n *\n * // Default: CDN @1 with fallback\n * const widget = await WidgetLoader.load();\n *\n * // Force bundled (CSP-safe)\n * const widget = await WidgetLoader.load({ mode: 'bundled' });\n *\n * // Pin specific version\n * const widget = await WidgetLoader.load({ version: '1.2.1' });\n * ```\n */\n\nexport interface LoaderOptions {\n /**\n * Version strategy:\n * - 'major': Load latest v1.x.x (default, recommended)\n * - 'latest': Load absolute latest (risky, may break)\n * - '1.2.1': Pin to specific version\n */\n version?: 'latest' | 'major' | string;\n\n /**\n * Loading mode:\n * - 'auto': Try CDN, fallback to bundled (default)\n * - 'cdn': Force CDN load, error if unavailable\n * - 'bundled': Always use bundled version (CSP-safe)\n */\n mode?: 'cdn' | 'bundled' | 'auto';\n\n /**\n * Custom CDN URL (default: https://unpkg.com/@supernal/tts-widget)\n */\n cdnUrl?: string;\n\n /**\n * CDN fetch timeout in milliseconds (default: 3000)\n */\n timeout?: number;\n\n /**\n * Callback when CDN load fails and fallback is used\n */\n onCdnFail?: (error: Error) => void;\n\n /**\n * Callback when CDN load succeeds\n */\n onCdnSuccess?: () => void;\n}\n\nexport interface SupernalTTSModule {\n SupernalTTS: any;\n}\n\n// Package version injected at build time\ndeclare const __PACKAGE_VERSION__: string;\n\nexport class WidgetLoader {\n private static instance: any = null;\n private static loadPromise: Promise<any> | null = null;\n\n /**\n * Load the Supernal TTS widget with smart CDN loading and fallback\n */\n static async load(options: LoaderOptions = {}): Promise<any> {\n // Return cached instance if already loaded\n if (this.instance) {\n return this.instance;\n }\n\n // Return existing load promise if already loading\n if (this.loadPromise) {\n return this.loadPromise;\n }\n\n const {\n version = 'major',\n mode = 'auto',\n cdnUrl = 'https://unpkg.com/@supernal/tts-widget',\n timeout = 3000,\n onCdnFail,\n onCdnSuccess\n } = options;\n\n // Start loading process\n this.loadPromise = this.loadWidget({\n version,\n mode,\n cdnUrl,\n timeout,\n onCdnFail,\n onCdnSuccess\n });\n\n return this.loadPromise;\n }\n\n private static async loadWidget(options: {\n mode: 'cdn' | 'bundled' | 'auto';\n version: string;\n cdnUrl: string;\n timeout: number;\n onCdnFail?: (error: Error) => void;\n onCdnSuccess?: () => void;\n }): Promise<any> {\n const { mode, version, cdnUrl, timeout, onCdnFail, onCdnSuccess } = options;\n\n // Force bundled mode (CSP-safe, offline-safe)\n if (mode === 'bundled') {\n console.log('[TTS Widget] Loading bundled version (mode: bundled)');\n return this.loadBundled();\n }\n\n // Try CDN first (mode === 'cdn' or 'auto')\n if (mode === 'cdn' || mode === 'auto') {\n try {\n console.log('[TTS Widget] Attempting CDN load...');\n const widget = await this.loadFromCdn(cdnUrl, version, timeout);\n\n console.log('[TTS Widget] CDN load successful');\n onCdnSuccess?.();\n\n this.instance = widget;\n return widget;\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.warn('[TTS Widget] CDN load failed:', errorMessage);\n\n onCdnFail?.(error instanceof Error ? error : new Error(errorMessage));\n\n // In 'cdn' mode, throw the error (no fallback)\n if (mode === 'cdn') {\n throw new Error(`Failed to load widget from CDN: ${errorMessage}`);\n }\n\n // In 'auto' mode, fallback to bundled\n console.log('[TTS Widget] Falling back to bundled version');\n return this.loadBundled();\n }\n }\n\n // Should never reach here, but fallback to bundled just in case\n return this.loadBundled();\n }\n\n private static async loadFromCdn(\n cdnUrl: string,\n version: string,\n timeout: number\n ): Promise<any> {\n const versionPath = this.resolveVersionPath(version);\n const url = `${cdnUrl}${versionPath}/dist/widget.js`;\n\n console.log(`[TTS Widget] Loading from CDN: ${url}`);\n\n // Create timeout controller\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n // Dynamic import with timeout\n // Note: AbortController support in dynamic import is limited, so we use a race\n const modulePromise = import(/* @vite-ignore */ url);\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error(`CDN load timeout after ${timeout}ms`)), timeout);\n });\n\n const module = await Promise.race([modulePromise, timeoutPromise]) as SupernalTTSModule;\n\n clearTimeout(timeoutId);\n\n if (!module || !module.SupernalTTS) {\n throw new Error('CDN module missing SupernalTTS export');\n }\n\n this.instance = module.SupernalTTS;\n return this.instance;\n\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n private static async loadBundled(): Promise<any> {\n try {\n // Import bundled widget\n const module = await import('./widget.js') as SupernalTTSModule;\n\n if (!module || !module.SupernalTTS) {\n throw new Error('Bundled widget missing SupernalTTS export');\n }\n\n this.instance = module.SupernalTTS;\n return this.instance;\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load bundled widget: ${errorMessage}`);\n }\n }\n\n private static resolveVersionPath(version: string): string {\n // Major version (e.g., \"1\" from \"1.2.1\")\n if (version === 'major') {\n const majorVersion = this.getMajorVersion();\n return `@${majorVersion}`;\n }\n\n // Always latest (risky)\n if (version === 'latest') {\n return '@latest';\n }\n\n // Specific version (e.g., \"1.2.1\")\n return `@${version}`;\n }\n\n private static getMajorVersion(): string {\n // Try to read from injected package version\n if (typeof __PACKAGE_VERSION__ !== 'undefined') {\n const match = __PACKAGE_VERSION__.match(/^(\\d+)\\./);\n if (match) {\n return match[1];\n }\n }\n\n // Fallback to hardcoded major version\n // This will be replaced by the build process\n return '1';\n }\n\n /**\n * Reset the loader (useful for testing)\n */\n static reset(): void {\n this.instance = null;\n this.loadPromise = null;\n }\n\n /**\n * Get current loaded instance (if any)\n */\n static getInstance(): any | null {\n return this.instance;\n }\n}\n\n// Default export for convenience\nexport default WidgetLoader;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["widget_exports", "__export", "SupernalTTS", "widget_default", "init_widget", "__esmMin", "_SupernalTTS", "options", "envVars", "varName", "processEnv", "importMetaEnv", "mutations", "mutation", "node", "element", "widget", "widgets", "config", "hash", "controls", "text", "scrubbed", "rawText", "voice", "provider", "speed", "voicesAttr", "voices", "v", "enableSpeed", "enableProgress", "apiKey", "buttonContainer", "playButton", "badge", "e", "container", "topRow", "voiceSelect", "speedControl", "speedSlider", "speedValue", "newHash", "buttonGroup", "stopButton", "progressBar", "progressSlider", "percent", "currentTime", "duration", "currentVoice", "currentSpeed", "savedPosition", "controlsRow", "voiceDropdown", "newVoice", "speedDropdown", "newSpeed", "selectedVoice", "toggleButton", "dropdown", "option", "opt", "hideTimeout", "rect", "viewportHeight", "isHidden", "selectedSpeed", "button", "speeds", "slider", "timeDisplay", "percentage", "seconds", "mins", "secs", "word", "compact", "img", "minimizedBtn", "fullBtn", "addHoverEffect", "btn", "clearCache", "count", "clickX", "btnWidth", "audioUrl", "response", "error", "body", "headers", "data", "originalMessage", "reader", "decoder", "buffer", "totalChunks", "completedChunks", "updateProgress", "completed", "total", "currentSpan", "done", "value", "lines", "line", "event", "parseError", "playbackSpeed", "resolve", "reject", "audio", "playPromise", "currentTimeSpan", "durationSpan", "positionPercent", "hasSeekCompleted", "state", "playIcon", "message", "tooltip", "str", "i", "char", "cached", "metadata", "stored", "el", "autoInitScript", "WidgetLoader", "options", "version", "mode", "cdnUrl", "timeout", "onCdnFail", "onCdnSuccess", "widget", "error", "errorMessage", "versionPath", "url", "controller", "timeoutId", "modulePromise", "timeoutPromise", "_", "reject", "module", "match", "loader_default"]
|
|
7
7
|
}
|