ai-progress-controls 0.1.0
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/LICENSE +21 -0
- package/README.md +823 -0
- package/dist/ai-progress-controls.es.js +7191 -0
- package/dist/ai-progress-controls.es.js.map +1 -0
- package/dist/ai-progress-controls.umd.js +2 -0
- package/dist/ai-progress-controls.umd.js.map +1 -0
- package/dist/index.d.ts +2212 -0
- package/package.json +105 -0
- package/src/__tests__/setup.ts +93 -0
- package/src/core/base/AIControl.ts +230 -0
- package/src/core/base/index.ts +3 -0
- package/src/core/base/types.ts +77 -0
- package/src/core/base/utils.ts +168 -0
- package/src/core/batch-progress/BatchProgress.test.ts +458 -0
- package/src/core/batch-progress/BatchProgress.ts +760 -0
- package/src/core/batch-progress/index.ts +14 -0
- package/src/core/batch-progress/styles.ts +480 -0
- package/src/core/batch-progress/types.ts +169 -0
- package/src/core/model-loader/ModelLoader.test.ts +311 -0
- package/src/core/model-loader/ModelLoader.ts +673 -0
- package/src/core/model-loader/index.ts +2 -0
- package/src/core/model-loader/styles.ts +496 -0
- package/src/core/model-loader/types.ts +127 -0
- package/src/core/parameter-panel/ParameterPanel.test.ts +856 -0
- package/src/core/parameter-panel/ParameterPanel.ts +877 -0
- package/src/core/parameter-panel/index.ts +14 -0
- package/src/core/parameter-panel/styles.ts +323 -0
- package/src/core/parameter-panel/types.ts +278 -0
- package/src/core/parameter-slider/ParameterSlider.test.ts +299 -0
- package/src/core/parameter-slider/ParameterSlider.ts +653 -0
- package/src/core/parameter-slider/index.ts +8 -0
- package/src/core/parameter-slider/styles.ts +493 -0
- package/src/core/parameter-slider/types.ts +107 -0
- package/src/core/queue-progress/QueueProgress.test.ts +344 -0
- package/src/core/queue-progress/QueueProgress.ts +563 -0
- package/src/core/queue-progress/index.ts +5 -0
- package/src/core/queue-progress/styles.ts +469 -0
- package/src/core/queue-progress/types.ts +130 -0
- package/src/core/retry-progress/RetryProgress.test.ts +397 -0
- package/src/core/retry-progress/RetryProgress.ts +957 -0
- package/src/core/retry-progress/index.ts +6 -0
- package/src/core/retry-progress/styles.ts +530 -0
- package/src/core/retry-progress/types.ts +176 -0
- package/src/core/stream-progress/StreamProgress.test.ts +531 -0
- package/src/core/stream-progress/StreamProgress.ts +517 -0
- package/src/core/stream-progress/index.ts +2 -0
- package/src/core/stream-progress/styles.ts +349 -0
- package/src/core/stream-progress/types.ts +82 -0
- package/src/index.ts +19 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-progress-controls.umd.js","sources":["../src/core/base/AIControl.ts","../src/core/base/utils.ts","../src/core/stream-progress/StreamProgress.ts","../src/core/model-loader/ModelLoader.ts","../src/core/parameter-slider/ParameterSlider.ts","../src/core/parameter-panel/ParameterPanel.ts","../src/core/queue-progress/QueueProgress.ts","../src/core/retry-progress/RetryProgress.ts","../src/core/batch-progress/BatchProgress.ts"],"sourcesContent":["import type { AIControlConfig, ThemeConfig } from './types';\n\n/**\n * Base class for all AI Progress Controls\n * Provides common functionality for Web Components including:\n * - Theme management\n * - Event handling\n * - Accessibility features\n * - Debug logging\n *\n * @example\n * ```typescript\n * class MyControl extends AIControl {\n * constructor() {\n * super();\n * this.attachShadow({ mode: 'open' });\n * }\n *\n * protected render() {\n * // Your rendering logic\n * }\n * }\n * ```\n */\nexport abstract class AIControl extends HTMLElement {\n protected config: AIControlConfig;\n protected _disabled: boolean = false;\n protected startTime: number = 0;\n\n constructor(config: AIControlConfig = {}) {\n super();\n this.config = {\n debug: false,\n disabled: false,\n ...config,\n };\n this._disabled = this.config.disabled ?? false;\n }\n\n /**\n * Called when the element is connected to the DOM\n */\n connectedCallback(): void {\n this.log('Component connected to DOM');\n this.applyTheme();\n this.setupAccessibility();\n this.render();\n }\n\n /**\n * Called when the element is disconnected from the DOM\n */\n disconnectedCallback(): void {\n this.log('Component disconnected from DOM');\n this.cleanup();\n }\n\n /**\n * Called when an observed attribute changes\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string): void {\n this.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);\n this.handleAttributeChange(name, oldValue, newValue);\n }\n\n /**\n * Apply theme using CSS custom properties\n */\n protected applyTheme(theme?: ThemeConfig): void {\n if (!theme) return;\n\n const root = this.shadowRoot?.host as HTMLElement;\n if (!root) return;\n\n Object.entries(theme).forEach(([key, value]) => {\n const cssVarName = `--ai-${key.replaceAll(/([A-Z])/g, '-$1').toLowerCase()}`;\n root.style.setProperty(cssVarName, value);\n });\n }\n\n /**\n * Set up accessibility features (ARIA attributes, keyboard navigation)\n */\n protected setupAccessibility(): void {\n // Set role if not already set\n if (!this.getAttribute('role')) {\n this.setAttribute('role', this.getDefaultRole());\n }\n\n // Set aria-label if configured\n if (this.config.ariaLabel) {\n this.setAttribute('aria-label', this.config.ariaLabel);\n }\n\n // Set disabled state\n if (this._disabled) {\n this.setAttribute('aria-disabled', 'true');\n }\n }\n\n /**\n * Emit a custom event\n */\n protected emit<T>(eventName: string, detail?: T): void {\n const event = new CustomEvent(eventName, {\n detail,\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n this.log(`Event emitted: ${eventName}`, detail);\n }\n\n /**\n * Log debug messages (only if debug mode is enabled)\n */\n protected log(message: string, ...args: unknown[]): void {\n if (this.config.debug) {\n console.log(`[${this.constructor.name}] ${message}`, ...args);\n }\n }\n\n /**\n * Log errors (always logged)\n */\n protected logError(message: string, error?: Error): void {\n console.error(`[${this.constructor.name}] ERROR: ${message}`, error);\n }\n\n /**\n * Start timing an operation\n */\n protected startTimer(): void {\n this.startTime = Date.now();\n }\n\n /**\n * Get elapsed time since timer started\n */\n protected getElapsedTime(): number {\n return Date.now() - this.startTime;\n }\n\n /**\n * Format numbers for display (e.g., 1234 -> \"1.2K\")\n */\n protected formatNumber(num: number): string {\n if (num >= 1_000_000) {\n return `${(num / 1_000_000).toFixed(1)}M`;\n }\n if (num >= 1_000) {\n return `${(num / 1_000).toFixed(1)}K`;\n }\n return num.toString();\n }\n\n /**\n * Format duration in milliseconds to human-readable string\n */\n protected formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n }\n\n /**\n * Calculate percentage safely\n */\n protected calculatePercentage(current: number, total: number): number {\n if (total === 0) return 0;\n return Math.min(100, Math.max(0, (current / total) * 100));\n }\n\n /**\n * Get/Set disabled state\n */\n get disabled(): boolean {\n return this._disabled;\n }\n\n set disabled(value: boolean) {\n this._disabled = value;\n if (value) {\n this.setAttribute('aria-disabled', 'true');\n this.setAttribute('disabled', '');\n } else {\n this.setAttribute('aria-disabled', 'false');\n this.removeAttribute('disabled');\n }\n this.render();\n }\n\n /**\n * Abstract method to render the component\n * Must be implemented by subclasses\n */\n protected abstract render(): void;\n\n /**\n * Get the default ARIA role for this component\n * Can be overridden by subclasses\n */\n protected getDefaultRole(): string {\n return 'region';\n }\n\n /**\n * Handle attribute changes\n * Can be overridden by subclasses to handle specific attributes\n */\n protected handleAttributeChange(_name: string, _oldValue: string, _newValue: string): void {\n // Override in subclasses\n }\n\n /**\n * Cleanup resources when component is destroyed\n * Can be overridden by subclasses\n */\n protected cleanup(): void {\n // Override in subclasses\n }\n}\n","/**\n * Utility functions for AI Progress Controls\n */\n\n/**\n * Debounce function calls\n */\nexport function debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return function (this: any, ...args: Parameters<T>) {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => func.apply(this, args), wait);\n };\n}\n\n/**\n * Throttle function calls\n */\nexport function throttle<T extends (...args: any[]) => any>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle: boolean;\n return function (this: any, ...args: Parameters<T>) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\n/**\n * Clamp a number between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Linear interpolation\n */\nexport function lerp(start: number, end: number, t: number): number {\n return start + (end - start) * t;\n}\n\n/**\n * Easing function for smooth animations\n */\nexport function easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\n}\n\n/**\n * Generate a unique ID\n */\nexport function generateId(prefix: string = 'ai-control'): string {\n return `${prefix}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\n/**\n * Check if reduced motion is preferred\n */\nexport function prefersReducedMotion(): boolean {\n return globalThis.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Format bytes to human-readable string\n */\nexport function formatBytes(bytes: number, decimals: number = 2): string {\n if (bytes === 0) return '0 Bytes';\n\n const k = 1024;\n const dm = Math.max(0, decimals);\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n}\n\n/**\n * Format currency (USD)\n */\nexport function formatCurrency(amount: number, decimals: number = 4): string {\n return `$${amount.toFixed(decimals)}`;\n}\n\n/**\n * Format seconds to human-readable time string\n */\nexport function formatTime(seconds: number): string {\n if (seconds < 60) {\n return `${Math.round(seconds)}s`;\n }\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.round(seconds % 60);\n if (minutes < 60) {\n return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n const remainingMinutes = minutes % 60;\n return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;\n}\n\n/**\n * Calculate estimated time remaining\n */\nexport function calculateETA(current: number, total: number, startTime: number): number {\n if (current === 0) return 0;\n\n const elapsed = Date.now() - startTime;\n const rate = current / elapsed;\n const remaining = total - current;\n\n return remaining / rate;\n}\n\n/**\n * Parse CSS color to RGB\n */\nexport function parseColor(color: string): { r: number; g: number; b: number } | null {\n const div = document.createElement('div');\n div.style.color = color;\n document.body.appendChild(div);\n\n const computedColor = getComputedStyle(div).color;\n div.remove();\n\n const regex = /^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$/;\n const match = regex.exec(computedColor);\n if (match?.[1] && match?.[2] && match?.[3]) {\n return {\n r: Number.parseInt(match[1], 10),\n g: Number.parseInt(match[2], 10),\n b: Number.parseInt(match[3], 10),\n };\n }\n\n return null;\n}\n\n/**\n * Create a style element with CSS\n */\nexport function createStyle(css: string): HTMLStyleElement {\n const style = document.createElement('style');\n style.textContent = css;\n return style;\n}\n\n/**\n * Check if an element is in viewport\n */\nexport function isInViewport(element: HTMLElement): boolean {\n const rect = element.getBoundingClientRect();\n return (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (globalThis.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (globalThis.innerWidth || document.documentElement.clientWidth)\n );\n}\n","import { AIControl } from '../base/AIControl';\nimport { throttle, formatCurrency } from '../base/utils';\nimport type {\n StreamProgressConfig,\n StreamProgressState,\n StreamProgressUpdate,\n StreamCompleteEvent,\n StreamCancelEvent,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * StreamProgress Component\n *\n * Displays real-time progress for streaming AI responses (e.g., LLM token generation).\n * Shows token count, generation rate, cost estimation, and provides cancel functionality.\n *\n * @example\n * ```typescript\n * // Create the component\n * const progress = new StreamProgress({\n * maxTokens: 2000,\n * costPerToken: 0.00002,\n * showRate: true,\n * showCost: true,\n * });\n *\n * document.body.appendChild(progress);\n *\n * // Start streaming\n * progress.start();\n *\n * // Update as tokens stream in\n * progress.update({\n * tokensGenerated: 150,\n * tokensPerSecond: 25,\n * message: 'Generating response...'\n * });\n *\n * // Complete the stream\n * progress.complete();\n *\n * // Listen to events\n * progress.addEventListener('cancel', (e) => {\n * console.log('Stream cancelled', e.detail);\n * });\n * ```\n *\n * @fires streamstart - Fired when streaming starts\n * @fires streamupdate - Fired when progress is updated\n * @fires streamcomplete - Fired when streaming completes\n * @fires streamcancel - Fired when streaming is cancelled\n */\nexport class StreamProgress extends AIControl {\n protected override config: Required<StreamProgressConfig>;\n private state: StreamProgressState;\n private readonly updateThrottled: (update: StreamProgressUpdate) => void;\n private animationFrame: number = 0;\n private displayTokens: number = 0;\n\n static get observedAttributes() {\n return ['max-tokens', 'cost-per-token', 'disabled', 'size', 'variant', 'animation'];\n }\n\n constructor(config: StreamProgressConfig = {}) {\n super({\n debug: config.debug ?? false,\n className: config.className,\n ariaLabel: config.ariaLabel ?? 'AI Stream Progress',\n });\n\n // Set default configuration\n this.config = {\n maxTokens: config.maxTokens ?? 4000,\n costPerToken: config.costPerToken ?? 0.00002,\n currency: config.currency ?? '$',\n showRate: config.showRate ?? true,\n showCost: config.showCost ?? true,\n showProgressBar: config.showProgressBar ?? true,\n showCancelButton: config.showCancelButton ?? true,\n smoothProgress: config.smoothProgress ?? true,\n updateThrottle: config.updateThrottle ?? 100,\n cancelLabel: config.cancelLabel ?? 'Cancel',\n debug: config.debug ?? false,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? 'AI Stream Progress',\n cursorFeedback: config.cursorFeedback ?? true,\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n // Initialize state\n this.state = {\n tokensGenerated: 0,\n tokensPerSecond: 0,\n totalCost: 0,\n isStreaming: false,\n isPaused: false,\n isCancelled: false,\n startTime: 0,\n lastUpdateTime: 0,\n };\n\n // Create throttled update function\n this.updateThrottled = throttle(this._updateInternal.bind(this), this.config.updateThrottle);\n\n // Attach shadow DOM\n this.attachShadow({ mode: 'open' });\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.log('StreamProgress mounted');\n }\n\n override disconnectedCallback(): void {\n this.cleanup();\n super.disconnectedCallback();\n }\n\n protected override cleanup(): void {\n if (this.animationFrame) {\n cancelAnimationFrame(this.animationFrame);\n }\n }\n\n /**\n * Update cursor based on component state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback) return;\n\n if (this.state.isStreaming && !this.state.isPaused) {\n this.style.cursor = 'progress';\n } else if (this.state.isCancelled) {\n this.style.cursor = 'not-allowed';\n } else {\n this.style.cursor = 'default';\n }\n }\n\n protected override getDefaultRole(): string {\n return 'progressbar';\n }\n\n protected override handleAttributeChange(\n name: string,\n _oldValue: string,\n newValue: string\n ): void {\n switch (name) {\n case 'max-tokens':\n this.config.maxTokens = Number.parseInt(newValue, 10) || 4000;\n this.render();\n break;\n case 'cost-per-token':\n this.config.costPerToken = Number.parseFloat(newValue) || 0.00002;\n this.render();\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n this.render();\n break;\n case 'size':\n this.config.size = newValue as any;\n this.render();\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n }\n }\n\n /**\n * Start streaming\n */\n public start(message?: string): void {\n if (this.state.isStreaming) {\n this.log('Already streaming');\n return;\n }\n\n this.state = {\n ...this.state,\n isStreaming: true,\n isPaused: false,\n isCancelled: false,\n tokensGenerated: 0,\n tokensPerSecond: 0,\n totalCost: 0,\n startTime: Date.now(),\n lastUpdateTime: Date.now(),\n message,\n };\n\n this.displayTokens = 0;\n this.startTimer();\n this.render();\n this.updateCursor();\n this.emit('streamstart', { startTime: this.state.startTime, message });\n this.log('Stream started', this.state);\n }\n\n /**\n * Update progress\n */\n public update(update: StreamProgressUpdate): void {\n if (!this.state.isStreaming || this.state.isCancelled) {\n return;\n }\n\n this.updateThrottled(update);\n }\n\n private _updateInternal(update: StreamProgressUpdate): void {\n const now = Date.now();\n const tokensGenerated = update.tokensGenerated;\n\n // Calculate rate if not provided\n let tokensPerSecond = update.tokensPerSecond ?? 0;\n if (!tokensPerSecond && this.state.lastUpdateTime) {\n const timeDiff = (now - this.state.lastUpdateTime) / 1000;\n const tokenDiff = tokensGenerated - this.state.tokensGenerated;\n tokensPerSecond = timeDiff > 0 ? tokenDiff / timeDiff : 0;\n }\n\n // Calculate cost\n const totalCost = tokensGenerated * this.config.costPerToken;\n\n // Update state\n this.state = {\n ...this.state,\n tokensGenerated,\n tokensPerSecond,\n totalCost,\n lastUpdateTime: now,\n message: update.message ?? this.state.message,\n };\n\n // Smooth animation\n if (this.config.smoothProgress) {\n this.animateProgress();\n } else {\n this.displayTokens = tokensGenerated;\n this.render();\n }\n\n // Update ARIA attributes\n this.setAttribute('aria-valuenow', tokensGenerated.toString());\n this.setAttribute('aria-valuemax', this.config.maxTokens.toString());\n\n this.emit('streamupdate', this.state);\n this.log('Progress updated', this.state);\n }\n\n /**\n * Smooth animation for progress\n */\n private animateProgress(): void {\n const animate = () => {\n const diff = this.state.tokensGenerated - this.displayTokens;\n if (Math.abs(diff) < 0.1) {\n this.displayTokens = this.state.tokensGenerated;\n this.render();\n return;\n }\n\n this.displayTokens += diff * 0.2;\n this.render();\n this.animationFrame = requestAnimationFrame(animate);\n };\n\n if (this.animationFrame) {\n cancelAnimationFrame(this.animationFrame);\n }\n this.animationFrame = requestAnimationFrame(animate);\n }\n\n /**\n * Complete streaming\n */\n public complete(): void {\n if (!this.state.isStreaming) {\n return;\n }\n\n const duration = this.getElapsedTime();\n const averageRate = this.state.tokensGenerated / (duration / 1000);\n\n const event: StreamCompleteEvent = {\n tokensGenerated: this.state.tokensGenerated,\n duration,\n totalCost: this.state.totalCost,\n averageRate,\n };\n\n this.state = {\n ...this.state,\n isStreaming: false,\n };\n\n this.render();\n this.updateCursor();\n this.emit('streamcomplete', event);\n this.log('Stream completed', event);\n }\n\n /**\n * Cancel streaming\n */\n public cancel(reason: 'user' | 'error' | 'timeout' = 'user'): void {\n if (!this.state.isStreaming || this.state.isCancelled) {\n return;\n }\n\n const duration = this.getElapsedTime();\n\n const event: StreamCancelEvent = {\n tokensGenerated: this.state.tokensGenerated,\n duration,\n reason,\n };\n\n this.state = {\n ...this.state,\n isStreaming: false,\n isCancelled: true,\n };\n\n this.render();\n this.updateCursor();\n this.emit('streamcancel', event);\n this.log('Stream cancelled', event);\n }\n\n /**\n * Reset the component\n */\n public reset(): void {\n this.state = {\n tokensGenerated: 0,\n tokensPerSecond: 0,\n totalCost: 0,\n isStreaming: false,\n isPaused: false,\n isCancelled: false,\n startTime: 0,\n lastUpdateTime: 0,\n };\n\n this.displayTokens = 0;\n if (this.animationFrame) {\n cancelAnimationFrame(this.animationFrame);\n }\n\n this.render();\n this.updateCursor();\n this.log('Component reset');\n }\n\n /**\n * Sync config attributes to host element\n */\n private _syncAttributes(): void {\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n }\n\n /**\n * Get progress bar HTML\n */\n private _getProgressBarHtml(percentage: number): string {\n if (!this.config.showProgressBar) {\n return '';\n }\n return `\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" style=\"width: ${percentage}%\"></div>\n </div>\n `;\n }\n\n /**\n * Get stats HTML\n */\n private _getStatsHtml(tokensDisplay: number, rateDisplay: number, costDisplay: string): string {\n const rateHtml = this.config.showRate\n ? `\n <div class=\"stat-item\">\n <span class=\"stat-label\">Rate:</span>\n <span class=\"stat-value\">${rateDisplay} tokens/s</span>\n </div>\n `\n : '';\n\n const costHtml = this.config.showCost\n ? `\n <div class=\"stat-item\">\n <span class=\"stat-label\">Cost:</span>\n <span class=\"stat-value\">${costDisplay}</span>\n </div>\n `\n : '';\n\n return `\n <div class=\"stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Tokens:</span>\n <span class=\"stat-value\">${tokensDisplay} / ${this.config.maxTokens}</span>\n </div>\n ${rateHtml}\n ${costHtml}\n </div>\n `;\n }\n\n /**\n * Get cancel button HTML\n */\n private _getCancelButtonHtml(): string {\n if (!this.config.showCancelButton || !this.state.isStreaming) {\n return '';\n }\n return `\n <button class=\"cancel-button\" aria-label=\"Cancel streaming\">\n ${this.config.cancelLabel}\n </button>\n `;\n }\n\n /**\n * Get status CSS class\n */\n private _getStatusClass(): string {\n if (this.state.isCancelled) return 'cancelled';\n if (this.state.isStreaming) return 'streaming';\n return 'idle';\n }\n\n /**\n * Attach event listeners to rendered elements\n */\n private _attachEventListeners(): void {\n if (!this.config.showCancelButton) return;\n\n const cancelBtn = this.shadowRoot?.querySelector('.cancel-button');\n if (cancelBtn) {\n cancelBtn.addEventListener('click', () => this.cancel('user'));\n }\n }\n\n /**\n * Render the component\n */\n protected render(): void {\n if (!this.shadowRoot) return;\n\n this._syncAttributes();\n\n const percentage = this.calculatePercentage(this.displayTokens, this.config.maxTokens);\n const tokensDisplay = Math.round(this.displayTokens);\n const rateDisplay = Math.round(this.state.tokensPerSecond);\n const costDisplay = formatCurrency(this.state.totalCost);\n\n const progressBarHtml = this._getProgressBarHtml(percentage);\n const statsHtml = this._getStatsHtml(tokensDisplay, rateDisplay, costDisplay);\n const messageHtml = this.state.message\n ? `<div class=\"message\">${this.state.message}</div>`\n : '';\n const cancelButtonHtml = this._getCancelButtonHtml();\n const statusClass = this._getStatusClass();\n\n this.shadowRoot.innerHTML = `\n ${styles}\n <div class=\"stream-progress ${statusClass} ${this.config.className}\">\n ${messageHtml}\n ${progressBarHtml}\n ${statsHtml}\n ${cancelButtonHtml}\n </div>\n `;\n\n this._attachEventListeners();\n }\n\n /**\n * Get current state (for debugging/inspection)\n */\n public getState(): Readonly<StreamProgressState> {\n return { ...this.state };\n }\n\n /**\n * Get current configuration\n */\n public getConfig(): Readonly<Required<StreamProgressConfig>> {\n return { ...this.config };\n }\n}\n\n// Register the custom element\nif (!customElements.get('stream-progress')) {\n customElements.define('stream-progress', StreamProgress);\n}\n","import { AIControl } from '../base/AIControl';\nimport { throttle, formatBytes } from '../base/utils';\nimport type {\n ModelLoaderConfig,\n ModelLoaderState,\n ModelStage,\n StageState,\n StageStatus,\n StageUpdate,\n StageChangeEvent,\n LoadCompleteEvent,\n LoadErrorEvent,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * ModelLoader Component\n *\n * Displays multi-stage progress for AI model loading operations.\n * Shows download progress, initialization stages, memory usage, and ETA.\n *\n * @example\n * ```typescript\n * // Create the component\n * const loader = new ModelLoader({\n * modelName: 'GPT-4 Vision',\n * stages: ['download', 'load', 'initialize', 'ready'],\n * showBytes: true,\n * showMemoryUsage: true,\n * showETA: true,\n * });\n *\n * document.body.appendChild(loader);\n *\n * // Start loading\n * loader.start();\n *\n * // Update download stage\n * loader.updateStage('download', {\n * bytesLoaded: 50000000,\n * totalBytes: 100000000,\n * message: 'Downloading model weights...'\n * });\n *\n * // Move to next stage\n * loader.setStage('load', { message: 'Loading into memory...' });\n *\n * // Complete\n * loader.complete();\n *\n * // Listen to events\n * loader.addEventListener('stagechange', (e) => {\n * console.log('Stage changed', e.detail);\n * });\n * ```\n *\n * @fires loadstart - Fired when loading starts\n * @fires stagechange - Fired when stage changes\n * @fires stageupdate - Fired when stage progress updates\n * @fires loadcomplete - Fired when loading completes\n * @fires loaderror - Fired when an error occurs\n */\nexport class ModelLoader extends AIControl {\n protected override config: Required<ModelLoaderConfig>;\n private state: ModelLoaderState;\n private readonly updateThrottled: (update: StageUpdate) => void;\n\n static get observedAttributes() {\n return ['model-name', 'disabled', 'size', 'variant', 'animation'];\n }\n\n constructor(config: ModelLoaderConfig = {}) {\n super({\n debug: config.debug ?? false,\n className: config.className,\n ariaLabel: config.ariaLabel ?? 'Model Loading Progress',\n cursorFeedback: config.cursorFeedback ?? true,\n });\n\n // Set default configuration\n this.config = {\n stages: config.stages ?? ['download', 'load', 'initialize', 'ready'],\n modelName: config.modelName ?? 'AI Model',\n showBytes: config.showBytes ?? true,\n showMemoryUsage: config.showMemoryUsage ?? true,\n showETA: config.showETA ?? true,\n showRetryButton: config.showRetryButton ?? true,\n smoothProgress: config.smoothProgress ?? true,\n updateThrottle: config.updateThrottle ?? 100,\n retryLabel: config.retryLabel ?? 'Retry',\n cursorFeedback: config.cursorFeedback ?? true,\n debug: config.debug ?? false,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? 'Model Loading Progress',\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n // Initialize state\n const initialStages: Record<ModelStage, StageState> = {\n download: { status: 'pending', progress: 0 },\n load: { status: 'pending', progress: 0 },\n initialize: { status: 'pending', progress: 0 },\n ready: { status: 'pending', progress: 0 },\n };\n\n this.state = {\n currentStage: this.config.stages[0]!,\n stages: initialStages,\n isLoading: false,\n hasError: false,\n startTime: 0,\n };\n\n // Create throttled update function\n this.updateThrottled = throttle(\n this._updateStageInternal.bind(this),\n this.config.updateThrottle\n );\n\n // Attach shadow DOM\n this.attachShadow({ mode: 'open' });\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.log('ModelLoader mounted');\n }\n\n protected override getDefaultRole(): string {\n return 'progressbar';\n }\n\n /**\n * Update cursor based on component state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback) return;\n\n if (this.state.isLoading) {\n this.style.cursor = 'progress';\n } else if (this.state.hasError) {\n this.style.cursor = 'not-allowed';\n } else {\n this.style.cursor = 'default';\n }\n }\n\n protected override handleAttributeChange(\n name: string,\n _oldValue: string,\n newValue: string\n ): void {\n switch (name) {\n case 'model-name':\n this.config.modelName = newValue || 'AI Model';\n this.render();\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n this.render();\n break;\n case 'size':\n this.config.size = newValue as any;\n this.render();\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n }\n }\n\n /**\n * Start loading\n */\n public start(initialMessage?: string): void {\n if (this.state.isLoading) {\n this.log('Already loading');\n return;\n }\n\n // Reset all stages\n const resetStages: Record<ModelStage, StageState> = {\n download: { status: 'pending', progress: 0 },\n load: { status: 'pending', progress: 0 },\n initialize: { status: 'pending', progress: 0 },\n ready: { status: 'pending', progress: 0 },\n };\n\n // Set first stage to in-progress\n const firstStage = this.config.stages[0]!;\n resetStages[firstStage] = {\n status: 'in-progress',\n progress: 0,\n message: initialMessage,\n startTime: Date.now(),\n };\n\n this.state = {\n currentStage: firstStage,\n stages: resetStages,\n isLoading: true,\n hasError: false,\n startTime: Date.now(),\n };\n\n this.startTimer();\n this.render();\n this.updateCursor();\n this.emit('loadstart', { stage: firstStage, timestamp: Date.now() });\n this.log('Loading started', this.state);\n }\n\n /**\n * Update current stage progress\n */\n public updateStage(stage: ModelStage, update: Omit<StageUpdate, 'stage'>): void {\n if (!this.state.isLoading || this.state.hasError) {\n return;\n }\n\n this.updateThrottled({ stage, ...update });\n }\n\n private _updateStageInternal(update: StageUpdate): void {\n const { stage, progress, bytesLoaded, totalBytes, message, memoryUsage } = update;\n\n if (!this.state.stages[stage]) {\n this.logError(`Invalid stage: ${stage}`);\n return;\n }\n\n // Calculate progress if bytes are provided\n let calculatedProgress = progress;\n if (calculatedProgress === undefined && bytesLoaded !== undefined && totalBytes !== undefined) {\n calculatedProgress = this.calculatePercentage(bytesLoaded, totalBytes);\n }\n\n // Update stage state\n const currentStageState = this.state.stages[stage];\n const updatedStage: StageState = {\n ...currentStageState,\n progress: calculatedProgress ?? currentStageState.progress,\n message,\n bytesLoaded,\n totalBytes,\n };\n\n this.state = {\n ...this.state,\n stages: {\n ...this.state.stages,\n [stage]: updatedStage,\n },\n memoryUsage: memoryUsage ?? this.state.memoryUsage,\n };\n\n this.render();\n this.emit('stageupdate', { stage, ...updatedStage });\n this.log('Stage updated', stage, updatedStage);\n }\n\n /**\n * Move to a specific stage\n */\n public setStage(stage: ModelStage, options: { message?: string; progress?: number } = {}): void {\n if (!this.state.isLoading || this.state.hasError) {\n return;\n }\n\n if (!this.config.stages.includes(stage)) {\n this.logError(`Stage ${stage} not in configured stages`);\n return;\n }\n\n const previousStage = this.state.currentStage;\n\n // Mark previous stage as completed\n const prevStageState = this.state.stages[previousStage];\n this.state.stages[previousStage] = {\n ...prevStageState,\n status: 'completed',\n progress: 100,\n endTime: Date.now(),\n };\n\n // Set new stage as in-progress\n const newStageState = this.state.stages[stage];\n this.state.stages[stage] = {\n ...newStageState,\n status: 'in-progress',\n progress: options.progress ?? 0,\n message: options.message,\n startTime: Date.now(),\n };\n\n this.state = {\n ...this.state,\n currentStage: stage,\n };\n\n this.render();\n\n const event: StageChangeEvent = {\n previousStage,\n currentStage: stage,\n timestamp: Date.now(),\n };\n\n this.emit('stagechange', event);\n this.log('Stage changed', event);\n }\n\n /**\n * Mark current stage as completed and move to next\n */\n public completeStage(nextMessage?: string): void {\n const currentStageIndex = this.config.stages.indexOf(this.state.currentStage);\n const nextStage = this.config.stages[currentStageIndex + 1];\n\n if (!nextStage) {\n // No more stages, complete loading\n this.complete();\n return;\n }\n\n this.setStage(nextStage, { message: nextMessage });\n }\n\n /**\n * Complete loading\n */\n public complete(): void {\n if (!this.state.isLoading) {\n return;\n }\n\n const duration = this.getElapsedTime();\n\n // Mark all stages as completed\n const completedStages: Record<ModelStage, StageState> = { ...this.state.stages };\n this.config.stages.forEach((stage) => {\n const stageState = completedStages[stage];\n completedStages[stage] = {\n ...stageState,\n status: 'completed',\n progress: 100,\n endTime: stageState.endTime ?? Date.now(),\n };\n });\n\n this.state = {\n ...this.state,\n stages: completedStages,\n isLoading: false,\n currentStage: 'ready',\n };\n\n const event: LoadCompleteEvent = {\n duration,\n memoryUsage: this.state.memoryUsage,\n stages: this.state.stages,\n };\n\n this.render();\n this.updateCursor();\n this.emit('loadcomplete', event);\n this.log('Loading completed', event);\n }\n\n /**\n * Set error state\n */\n public error(message: string, stage?: ModelStage): void {\n const errorStage = stage ?? this.state.currentStage;\n const errorStageState = this.state.stages[errorStage];\n\n this.state = {\n ...this.state,\n hasError: true,\n errorMessage: message,\n isLoading: false,\n stages: {\n ...this.state.stages,\n [errorStage]: {\n ...errorStageState,\n status: 'error',\n },\n },\n };\n\n const event: LoadErrorEvent = {\n stage: errorStage,\n message,\n timestamp: Date.now(),\n };\n\n this.render();\n this.updateCursor();\n this.emit('loaderror', event);\n this.logError('Loading error', new Error(message));\n }\n\n /**\n * Retry loading from the beginning\n */\n public retry(): void {\n this.start();\n this.emit('loadretry', { timestamp: Date.now() });\n this.log('Retrying load');\n }\n\n /**\n * Reset the component\n */\n public reset(): void {\n const resetStages: Record<ModelStage, StageState> = {\n download: { status: 'pending', progress: 0 },\n load: { status: 'pending', progress: 0 },\n initialize: { status: 'pending', progress: 0 },\n ready: { status: 'pending', progress: 0 },\n };\n\n this.state = {\n currentStage: this.config.stages[0]!,\n stages: resetStages,\n isLoading: false,\n hasError: false,\n startTime: 0,\n };\n\n this.render();\n this.log('Component reset');\n }\n\n /**\n * Get status icon for a stage\n */\n private getStageIcon(status: StageStatus): string {\n switch (status) {\n case 'pending':\n return '○';\n case 'in-progress':\n return '◐';\n case 'completed':\n return '✓';\n case 'error':\n return '✕';\n default:\n return '○';\n }\n }\n\n /**\n * Calculate ETA for remaining stages\n */\n private calculateETA(): string {\n if (!this.state.isLoading || this.state.hasError) {\n return '--';\n }\n\n const elapsed = this.getElapsedTime();\n const currentStageIndex = this.config.stages.indexOf(this.state.currentStage);\n const totalStages = this.config.stages.length;\n const completedStages = currentStageIndex;\n const currentProgress = this.state.stages[this.state.currentStage]?.progress ?? 0;\n\n if (completedStages === 0 && currentProgress === 0) {\n return '--';\n }\n\n // Estimate based on completed stages + current progress\n const effectiveProgress = (completedStages + currentProgress / 100) / totalStages;\n\n if (effectiveProgress === 0) {\n return '--';\n }\n\n const estimatedTotal = elapsed / effectiveProgress;\n const remaining = estimatedTotal - elapsed;\n\n return this.formatDuration(Math.max(0, remaining));\n }\n\n /**\n * Get overall status for rendering\n */\n private getOverallStatus(): string {\n if (this.state.hasError) return 'error';\n if (this.state.isLoading) return 'loading';\n if (!this.state.isLoading && this.state.stages.ready?.status === 'completed')\n return 'completed';\n return 'idle';\n }\n\n /**\n * Get status badge text\n */\n private getStatusBadgeText(overallStatus: string): string {\n if (this.state.hasError) return 'Error';\n if (this.state.isLoading) return 'Loading';\n if (overallStatus === 'completed') return 'Ready';\n return 'Idle';\n }\n\n /**\n * Generate HTML for all stages\n */\n private generateStagesHtml(): string {\n return this.config.stages\n .map((stage) => {\n const stageState = this.state.stages[stage];\n if (!stageState) return '';\n\n const icon = this.getStageIcon(stageState.status);\n const progressText = `${Math.round(stageState.progress)}%`;\n const messageHtml = stageState.message\n ? `<div class=\"stage-message\">${stageState.message}</div>`\n : '';\n\n return `\n <div class=\"stage ${stageState.status}\">\n <div class=\"stage-header\">\n <div class=\"stage-info\">\n <div class=\"stage-icon ${stageState.status}\">${icon}</div>\n <span class=\"stage-name\">${stage}</span>\n </div>\n <span class=\"stage-progress-text\">${progressText}</span>\n </div>\n ${messageHtml}\n <div class=\"progress-bar\">\n <div class=\"progress-fill ${stageState.status === 'error' ? 'error' : ''}\" style=\"width: ${stageState.progress}%\"></div>\n </div>\n </div>\n `;\n })\n .join('');\n }\n\n /**\n * Generate HTML for stats section\n */\n private generateStatsHtml(): string {\n const statsItems = [];\n\n // Bytes (for download stage)\n if (this.config.showBytes && this.state.stages.download) {\n const { bytesLoaded, totalBytes } = this.state.stages.download;\n if (bytesLoaded !== undefined && totalBytes !== undefined) {\n statsItems.push(`\n <div class=\"stat-item\">\n <span class=\"stat-label\">Downloaded</span>\n <span class=\"stat-value\">${formatBytes(bytesLoaded)} / ${formatBytes(totalBytes)}</span>\n </div>\n `);\n }\n }\n\n // Memory usage\n if (this.config.showMemoryUsage && this.state.memoryUsage !== undefined) {\n statsItems.push(`\n <div class=\"stat-item\">\n <span class=\"stat-label\">Memory</span>\n <span class=\"stat-value\">${this.state.memoryUsage.toFixed(0)} MB</span>\n </div>\n `);\n }\n\n // ETA\n if (this.config.showETA && this.state.isLoading) {\n statsItems.push(`\n <div class=\"stat-item\">\n <span class=\"stat-label\">ETA</span>\n <span class=\"stat-value\">${this.calculateETA()}</span>\n </div>\n `);\n }\n\n return statsItems.length > 0 ? `<div class=\"stats\">${statsItems.join('')}</div>` : '';\n }\n\n /**\n * Render the component\n */\n protected render(): void {\n if (!this.shadowRoot) return;\n\n // Sync attributes to host element for CSS selectors\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n\n const overallStatus = this.getOverallStatus();\n const statusBadgeText = this.getStatusBadgeText(overallStatus);\n const stagesHtml = this.generateStagesHtml();\n const statsHtml = this.generateStatsHtml();\n\n // Error message\n const errorHtml = this.state.hasError\n ? `\n <div class=\"error-message\">\n <div class=\"error-icon\">⚠</div>\n <div class=\"error-text\">${this.state.errorMessage}</div>\n </div>\n `\n : '';\n\n // Retry button\n const retryButtonHtml =\n this.config.showRetryButton && this.state.hasError\n ? `\n <button class=\"retry-button\" aria-label=\"Retry loading\">\n ${this.config.retryLabel}\n </button>\n `\n : '';\n\n this.shadowRoot.innerHTML = `\n ${styles}\n <div class=\"model-loader ${overallStatus} ${this.config.className}\">\n <div class=\"header\">\n <div class=\"model-name\">${this.config.modelName}</div>\n <div class=\"status-badge ${overallStatus}\">${statusBadgeText}</div>\n </div>\n <div class=\"stages\">\n ${stagesHtml}\n </div>\n ${statsHtml}\n ${errorHtml}\n ${retryButtonHtml}\n </div>\n `;\n\n // Attach event listeners\n if (this.config.showRetryButton && this.state.hasError) {\n const retryBtn = this.shadowRoot.querySelector('.retry-button');\n if (retryBtn) {\n retryBtn.addEventListener('click', () => this.retry());\n }\n }\n }\n\n /**\n * Get current state (for debugging/inspection)\n */\n public getState(): Readonly<ModelLoaderState> {\n return { ...this.state };\n }\n\n /**\n * Get current configuration\n */\n public getConfig(): Readonly<Required<ModelLoaderConfig>> {\n return { ...this.config };\n }\n}\n\n// Register the custom element\nif (!customElements.get('model-loader')) {\n customElements.define('model-loader', ModelLoader);\n}\n","import { AIControl } from '../base/AIControl';\nimport { clamp } from '../base/utils';\nimport type {\n ParameterSliderConfig,\n ParameterSliderState,\n PresetValue,\n ValueChangeEvent,\n PresetSelectEvent,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * ParameterSlider Component\n *\n * Interactive slider for AI parameter configuration (temperature, top-p, penalties, etc.).\n * Supports presets, manual input, keyboard navigation, and accessibility.\n *\n * @example\n * ```typescript\n * // Create temperature slider\n * const slider = new ParameterSlider({\n * label: 'Temperature',\n * min: 0,\n * max: 2,\n * value: 0.7,\n * step: 0.1,\n * description: 'Controls randomness in responses',\n * presets: [\n * { value: 0, label: 'Focused' },\n * { value: 0.7, label: 'Balanced' },\n * { value: 1.5, label: 'Creative' }\n * ]\n * });\n *\n * document.body.appendChild(slider);\n *\n * // Listen to value changes\n * slider.addEventListener('valuechange', (e) => {\n * console.log('New value:', e.detail.value);\n * });\n *\n * // Get current value\n * const value = slider.getValue();\n *\n * // Set value programmatically\n * slider.setValue(1.2);\n * ```\n *\n * @fires valuechange - Fired when value changes\n * @fires presetselect - Fired when preset is selected\n */\nexport class ParameterSlider extends AIControl {\n protected override config: Required<ParameterSliderConfig>;\n private readonly state: ParameterSliderState;\n private sliderTrack: HTMLElement | null = null;\n private sliderThumb: HTMLElement | null = null;\n\n static get observedAttributes() {\n return ['label', 'min', 'max', 'value', 'disabled', 'size', 'variant', 'animation'];\n }\n\n constructor(config: ParameterSliderConfig = {}) {\n super({\n debug: config.debug ?? false,\n className: config.className,\n ariaLabel: config.ariaLabel ?? `${config.label ?? 'Parameter'} Slider`,\n });\n\n // Set default configuration\n this.config = {\n label: config.label ?? 'Parameter',\n min: config.min ?? 0,\n max: config.max ?? 1,\n value: config.value ?? 0.5,\n defaultValue: config.defaultValue ?? config.value ?? 0.5,\n step: config.step ?? 0.01,\n decimals: config.decimals ?? 2,\n description: config.description ?? '',\n showPresets: config.showPresets ?? true,\n presets: config.presets ?? [],\n showInput: config.showInput ?? true,\n showReset: config.showReset ?? true,\n showRangeLabels: config.showRangeLabels ?? true,\n unit: config.unit ?? '',\n cursorFeedback: config.cursorFeedback ?? true,\n disabled: config.disabled ?? false,\n debug: config.debug ?? false,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? `${config.label ?? 'Parameter'} Slider`,\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n // Initialize state\n this.state = {\n currentValue: clamp(this.config.value, this.config.min, this.config.max),\n isDragging: false,\n isFocused: false,\n };\n\n // Attach shadow DOM\n this.attachShadow({ mode: 'open' });\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.render();\n this.attachEventListeners();\n this.log('ParameterSlider mounted');\n }\n\n override disconnectedCallback(): void {\n this.removeEventListeners();\n super.disconnectedCallback();\n }\n\n protected override getDefaultRole(): string {\n return 'slider';\n }\n\n protected override handleAttributeChange(\n name: string,\n _oldValue: string,\n newValue: string\n ): void {\n switch (name) {\n case 'label':\n this.config.label = newValue || 'Parameter';\n this.render();\n break;\n case 'min':\n this.config.min = Number.parseFloat(newValue) || 0;\n this.render();\n break;\n case 'max':\n this.config.max = Number.parseFloat(newValue) || 1;\n this.render();\n break;\n case 'value':\n this.setValue(Number.parseFloat(newValue) || 0.5);\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n this.render();\n break;\n case 'size':\n this.config.size = newValue as any;\n this.render();\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n }\n }\n\n /**\n * Get current value\n */\n public getValue(): number {\n return this.state.currentValue;\n }\n\n /**\n * Set value programmatically\n */\n public setValue(value: number, source: 'slider' | 'input' | 'preset' | 'reset' = 'slider'): void {\n const previousValue = this.state.currentValue;\n const clampedValue = clamp(value, this.config.min, this.config.max);\n\n // Round to step\n const steppedValue = Math.round(clampedValue / this.config.step) * this.config.step;\n const finalValue = Number.parseFloat(steppedValue.toFixed(this.config.decimals));\n\n if (finalValue === this.state.currentValue) return;\n\n this.state.currentValue = finalValue;\n this.updateSliderPosition();\n\n const event: ValueChangeEvent = {\n value: finalValue,\n previousValue,\n source,\n timestamp: Date.now(),\n };\n\n this.emit('valuechange', event);\n this.log('Value changed', event);\n }\n\n /**\n * Reset to default value\n */\n public reset(): void {\n this.setValue(this.config.defaultValue, 'reset');\n }\n\n /**\n * Select a preset value\n */\n public selectPreset(preset: PresetValue): void {\n const previousValue = this.state.currentValue;\n this.setValue(preset.value, 'preset');\n\n const event: PresetSelectEvent = {\n preset,\n previousValue,\n timestamp: Date.now(),\n };\n\n this.emit('presetselect', event);\n this.log('Preset selected', event);\n }\n\n /**\n * Attach event listeners to slider elements\n */\n private attachEventListeners(): void {\n if (!this.shadowRoot) return;\n\n // Slider track and thumb\n this.sliderTrack = this.shadowRoot.querySelector('.slider-track');\n this.sliderThumb = this.shadowRoot.querySelector('.slider-thumb');\n\n if (this.sliderTrack) {\n this.sliderTrack.addEventListener('click', this.handleTrackClick.bind(this));\n }\n\n if (this.sliderThumb) {\n this.sliderThumb.addEventListener('mousedown', this.handleThumbMouseDown.bind(this));\n this.sliderThumb.addEventListener('touchstart', this.handleThumbTouchStart.bind(this), {\n passive: false,\n });\n this.sliderThumb.addEventListener('keydown', this.handleThumbKeyDown.bind(this));\n }\n\n // Value input\n const input = this.shadowRoot.querySelector('.value-input') as HTMLInputElement;\n if (input) {\n input.addEventListener('change', this.handleInputChange.bind(this));\n input.addEventListener('blur', this.handleInputBlur.bind(this));\n }\n\n // Reset button\n const resetBtn = this.shadowRoot.querySelector('.reset-button');\n if (resetBtn) {\n resetBtn.addEventListener('click', () => this.reset());\n }\n\n // Preset buttons\n const presetButtons = this.shadowRoot.querySelectorAll('.preset-button');\n presetButtons.forEach((btn, index) => {\n btn.addEventListener('click', () => {\n const preset = this.config.presets[index];\n if (preset) this.selectPreset(preset);\n });\n });\n }\n\n /**\n * Remove event listeners\n */\n private removeEventListeners(): void {\n document.removeEventListener('mousemove', this.handleThumbMouseMove);\n document.removeEventListener('mouseup', this.handleThumbMouseUp);\n document.removeEventListener('touchmove', this.handleThumbTouchMove);\n document.removeEventListener('touchend', this.handleThumbTouchEnd);\n }\n\n /**\n * Handle track click\n */\n private handleTrackClick(e: MouseEvent): void {\n if (!this.sliderTrack || this.config.disabled) return;\n\n const rect = this.sliderTrack.getBoundingClientRect();\n const percent = (e.clientX - rect.left) / rect.width;\n const value = this.config.min + percent * (this.config.max - this.config.min);\n\n this.setValue(value, 'slider');\n }\n\n /**\n * Handle thumb mouse down\n */\n private handleThumbMouseDown(e: MouseEvent): void {\n if (this.config.disabled) return;\n\n e.preventDefault();\n this.state.isDragging = true;\n this.sliderThumb?.classList.add('dragging');\n\n document.addEventListener('mousemove', this.handleThumbMouseMove);\n document.addEventListener('mouseup', this.handleThumbMouseUp);\n }\n\n /**\n * Handle thumb mouse move\n */\n private readonly handleThumbMouseMove = (e: MouseEvent): void => {\n if (!this.state.isDragging || !this.sliderTrack) return;\n\n const rect = this.sliderTrack.getBoundingClientRect();\n const percent = clamp((e.clientX - rect.left) / rect.width, 0, 1);\n const value = this.config.min + percent * (this.config.max - this.config.min);\n\n this.setValue(value, 'slider');\n };\n\n /**\n * Handle thumb mouse up\n */\n private readonly handleThumbMouseUp = (): void => {\n this.state.isDragging = false;\n this.sliderThumb?.classList.remove('dragging');\n\n document.removeEventListener('mousemove', this.handleThumbMouseMove);\n document.removeEventListener('mouseup', this.handleThumbMouseUp);\n };\n\n /**\n * Handle thumb touch start\n */\n private handleThumbTouchStart(e: TouchEvent): void {\n if (this.config.disabled) return;\n\n e.preventDefault();\n this.state.isDragging = true;\n this.sliderThumb?.classList.add('dragging');\n\n document.addEventListener('touchmove', this.handleThumbTouchMove, { passive: false });\n document.addEventListener('touchend', this.handleThumbTouchEnd);\n }\n\n /**\n * Handle thumb touch move\n */\n private readonly handleThumbTouchMove = (e: TouchEvent): void => {\n if (!this.state.isDragging || !this.sliderTrack) return;\n\n e.preventDefault();\n const touch = e.touches[0];\n if (!touch) return;\n\n const rect = this.sliderTrack.getBoundingClientRect();\n const percent = clamp((touch.clientX - rect.left) / rect.width, 0, 1);\n const value = this.config.min + percent * (this.config.max - this.config.min);\n\n this.setValue(value, 'slider');\n };\n\n /**\n * Handle thumb touch end\n */\n private readonly handleThumbTouchEnd = (): void => {\n this.state.isDragging = false;\n this.sliderThumb?.classList.remove('dragging');\n\n document.removeEventListener('touchmove', this.handleThumbTouchMove);\n document.removeEventListener('touchend', this.handleThumbTouchEnd);\n };\n\n /**\n * Handle keyboard navigation\n */\n private handleThumbKeyDown(e: KeyboardEvent): void {\n if (this.config.disabled) return;\n\n let delta = 0;\n const largeStep = this.config.step * 10;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n delta = this.config.step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n delta = -this.config.step;\n break;\n case 'PageUp':\n delta = largeStep;\n break;\n case 'PageDown':\n delta = -largeStep;\n break;\n case 'Home':\n this.setValue(this.config.min, 'slider');\n e.preventDefault();\n return;\n case 'End':\n this.setValue(this.config.max, 'slider');\n e.preventDefault();\n return;\n default:\n return;\n }\n\n e.preventDefault();\n this.setValue(this.state.currentValue + delta, 'slider');\n }\n\n /**\n * Handle input field change\n */\n private handleInputChange(e: Event): void {\n const input = e.target as HTMLInputElement;\n const value = Number.parseFloat(input.value);\n\n if (!Number.isNaN(value)) {\n this.setValue(value, 'input');\n }\n }\n\n /**\n * Handle input field blur (validate)\n */\n private handleInputBlur(e: Event): void {\n const input = e.target as HTMLInputElement;\n input.value = this.state.currentValue.toFixed(this.config.decimals);\n }\n\n /**\n * Update slider thumb position based on current value\n */\n private updateSliderPosition(): void {\n if (!this.sliderThumb || !this.shadowRoot) return;\n\n const percent =\n ((this.state.currentValue - this.config.min) / (this.config.max - this.config.min)) * 100;\n this.sliderThumb.style.left = `${percent}%`;\n\n const fill = this.shadowRoot.querySelector('.slider-fill') as HTMLElement;\n if (fill) {\n fill.style.width = `${percent}%`;\n }\n\n // Update value display\n const valueDisplay = this.shadowRoot.querySelector('.current-value');\n if (valueDisplay) {\n valueDisplay.textContent = this.state.currentValue.toFixed(this.config.decimals);\n }\n\n // Update input field\n const input = this.shadowRoot.querySelector('.value-input') as HTMLInputElement;\n if (input && document.activeElement !== input) {\n input.value = this.state.currentValue.toFixed(this.config.decimals);\n }\n\n // Update active preset\n this.updateActivePreset();\n this.updateCursor();\n }\n\n /**\n * Update cursor based on slider state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback || !this.sliderThumb) return;\n\n if (this.config.disabled) {\n this.sliderThumb.style.cursor = 'not-allowed';\n } else if (this.state.isDragging) {\n this.sliderThumb.style.cursor = 'grabbing';\n } else {\n this.sliderThumb.style.cursor = 'grab';\n }\n }\n\n /**\n * Update active preset button\n */\n private updateActivePreset(): void {\n if (!this.shadowRoot) return;\n\n const presetButtons = this.shadowRoot.querySelectorAll('.preset-button');\n presetButtons.forEach((btn, index) => {\n const preset = this.config.presets[index];\n if (preset && Math.abs(preset.value - this.state.currentValue) < this.config.step / 2) {\n btn.classList.add('active');\n } else {\n btn.classList.remove('active');\n }\n });\n }\n\n /**\n * Render input controls section\n */\n private renderInputControls(): string {\n if (!this.config.showInput && !this.config.showReset) return '';\n\n const disabledAttr = this.config.disabled ? 'disabled' : '';\n let controlsHtml = '';\n\n if (this.config.showInput) {\n controlsHtml += `\n <span class=\"input-label\">Value:</span>\n <input \n type=\"number\" \n class=\"value-input\"\n value=\"${this.state.currentValue.toFixed(this.config.decimals)}\"\n min=\"${this.config.min}\"\n max=\"${this.config.max}\"\n step=\"${this.config.step}\"\n ${disabledAttr}\n />\n `;\n }\n\n if (this.config.showReset) {\n controlsHtml += `\n <button class=\"reset-button\" type=\"button\" ${disabledAttr}>\n Reset\n </button>\n `;\n }\n\n return `\n <div class=\"input-container\">\n ${controlsHtml}\n </div>\n `;\n }\n\n /**\n * Render the component\n */\n protected render(): void {\n if (!this.shadowRoot) return;\n\n // Sync attributes to host element for CSS selectors\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n\n const disabledClass = this.config.disabled ? 'disabled' : '';\n\n // Header with label and current value\n const headerHtml = `\n <div class=\"header\">\n <div class=\"label-section\">\n <label class=\"label\">${this.config.label}</label>\n ${this.config.description ? `<div class=\"description\">${this.config.description}</div>` : ''}\n </div>\n <div class=\"value-display\">\n <span class=\"current-value\">${this.state.currentValue.toFixed(this.config.decimals)}</span>\n ${this.config.unit ? `<span class=\"unit\">${this.config.unit}</span>` : ''}\n </div>\n </div>\n `;\n\n // Slider\n const percent =\n ((this.state.currentValue - this.config.min) / (this.config.max - this.config.min)) * 100;\n const sliderHtml = `\n <div class=\"slider-container\">\n <div class=\"slider-track\" role=\"presentation\">\n <div class=\"slider-fill\" style=\"width: ${percent}%\"></div>\n <div \n class=\"slider-thumb\" \n style=\"left: ${percent}%\"\n role=\"slider\"\n tabindex=\"${this.config.disabled ? -1 : 0}\"\n aria-valuemin=\"${this.config.min}\"\n aria-valuemax=\"${this.config.max}\"\n aria-valuenow=\"${this.state.currentValue}\"\n aria-label=\"${this.config.ariaLabel}\"\n ></div>\n </div>\n ${\n this.config.showRangeLabels\n ? `\n <div class=\"range-labels\">\n <span class=\"range-label\">${this.config.min.toFixed(this.config.decimals)}</span>\n <span class=\"range-label\">${this.config.max.toFixed(this.config.decimals)}</span>\n </div>\n `\n : ''\n }\n </div>\n `;\n\n // Presets\n const presetsHtml =\n this.config.showPresets && this.config.presets.length > 0\n ? `\n <div class=\"presets\">\n ${this.config.presets\n .map(\n (preset) => `\n <button class=\"preset-button\" type=\"button\">\n <span class=\"preset-value\">${preset.value}</span>\n <span class=\"preset-label\">${preset.label}</span>\n </button>\n `\n )\n .join('')}\n </div>\n `\n : '';\n\n // Input and reset\n const inputHtml = this.renderInputControls();\n\n this.shadowRoot.innerHTML = `\n ${styles}\n <div class=\"parameter-slider ${disabledClass} ${this.config.className}\">\n ${headerHtml}\n ${sliderHtml}\n ${presetsHtml}\n ${inputHtml}\n </div>\n `;\n\n // Store references after render\n this.sliderTrack = this.shadowRoot.querySelector('.slider-track');\n this.sliderThumb = this.shadowRoot.querySelector('.slider-thumb');\n\n // Reattach event listeners\n this.attachEventListeners();\n }\n\n /**\n * Get current state (for debugging)\n */\n public getState(): Readonly<ParameterSliderState> {\n return { ...this.state };\n }\n\n /**\n * Get current configuration\n */\n public getConfig(): Readonly<Required<ParameterSliderConfig>> {\n return { ...this.config };\n }\n}\n\n// Register the custom element\nif (!customElements.get('parameter-slider')) {\n customElements.define('parameter-slider', ParameterSlider);\n}\n","import { AIControl } from '../base/AIControl';\nimport { ParameterSlider } from '../parameter-slider/ParameterSlider';\nimport type {\n ParameterPanelConfig,\n ParameterPanelState,\n ParameterDefinition,\n PanelChangeEvent,\n PresetLoadEvent,\n ConfigExportEvent,\n ConfigImportEvent,\n PanelResetEvent,\n ValidationErrorEvent,\n ExportedConfig,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * ParameterPanel Component\n *\n * Manages multiple AI parameters as a coordinated group with presets, validation, and export/import.\n * Automatically creates and manages child ParameterSlider instances.\n *\n * @example\n * ```typescript\n * // Create LLM configuration panel\n * const panel = new ParameterPanel({\n * title: 'Model Configuration',\n * parameters: [\n * { id: 'temperature', label: 'Temperature', min: 0, max: 2, value: 0.7, step: 0.1 },\n * { id: 'topP', label: 'Top-P', min: 0, max: 1, value: 0.9, step: 0.05 },\n * { id: 'maxTokens', label: 'Max Tokens', min: 100, max: 4000, value: 2000, step: 100 }\n * ],\n * presets: {\n * chatgpt: {\n * name: 'ChatGPT',\n * description: 'Balanced configuration',\n * values: { temperature: 0.7, topP: 0.9, maxTokens: 2000 }\n * },\n * code: {\n * name: 'Code Generation',\n * description: 'More focused for code',\n * values: { temperature: 0.2, topP: 0.8, maxTokens: 1000 }\n * }\n * }\n * });\n *\n * document.body.appendChild(panel);\n *\n * // Get all values\n * const config = panel.getAllValues();\n * // { temperature: 0.7, topP: 0.9, maxTokens: 2000 }\n *\n * // Load preset\n * panel.loadPreset('code');\n *\n * // Listen to changes\n * panel.addEventListener('panelchange', (e) => {\n * console.log('Changed parameter:', e.detail.parameterId);\n * console.log('All values:', e.detail.allValues);\n * });\n * ```\n *\n * @fires panelchange - Fired when any parameter changes\n * @fires presetload - Fired when preset is loaded\n * @fires configexport - Fired when configuration is exported\n * @fires configimport - Fired when configuration is imported\n * @fires panelreset - Fired when panel is reset\n * @fires validationerror - Fired when validation fails\n */\nexport class ParameterPanel extends AIControl {\n private readonly state: ParameterPanelState;\n private readonly parameters: Map<string, ParameterSlider> = new Map();\n private readonly parameterDefinitions: Map<string, ParameterDefinition> = new Map();\n private readonly presets: Map<\n string,\n { name: string; description?: string; values: Record<string, number>; isBuiltIn: boolean }\n >;\n private readonly panelConfig: ParameterPanelConfig;\n\n constructor(config: ParameterPanelConfig) {\n super({ debug: config.debug, disabled: config.disabled });\n\n this.panelConfig = config;\n\n if (!config.parameters || config.parameters.length === 0) {\n throw new Error('ParameterPanel requires at least one parameter');\n }\n\n // Store parameter definitions\n config.parameters.forEach((param) => {\n this.parameterDefinitions.set(param.id, param);\n });\n\n // Initialize presets\n this.presets = new Map();\n if (config.presets) {\n Object.entries(config.presets).forEach(([id, preset]) => {\n this.presets.set(id, { ...preset, isBuiltIn: preset.isBuiltIn ?? false });\n });\n }\n\n // Initialize state\n const initialValues: Record<string, number> = {};\n config.parameters.forEach((param) => {\n initialValues[param.id] = param.value;\n });\n\n this.state = {\n values: initialValues,\n activePreset: null,\n isCollapsed: Boolean(this.panelConfig.collapsible && this.panelConfig.startCollapsed),\n errors: {},\n isDirty: false,\n };\n\n this.attachShadow({ mode: 'open' });\n\n // Load persisted values if enabled\n if (this.panelConfig.persistValues) {\n this.loadFromStorage();\n }\n\n // Load persisted presets if enabled\n if (this.panelConfig.persistPresets) {\n this.loadPresetsFromStorage();\n }\n }\n\n /**\n * Get all parameter values\n */\n getAllValues(): Record<string, number> {\n return { ...this.state.values };\n }\n\n /**\n * Get specific parameter value\n */\n getValue(parameterId: string): number | undefined {\n return this.state.values[parameterId];\n }\n\n /**\n * Set specific parameter value\n */\n setValue(\n parameterId: string,\n value: number,\n source: 'slider' | 'input' | 'preset' | 'reset' | 'import' = 'slider'\n ): void {\n const paramDef = this.parameterDefinitions.get(parameterId);\n if (!paramDef) {\n this.log(`Parameter ${parameterId} not found`, 'warn');\n return;\n }\n\n // Clamp value to range\n value = Math.max(paramDef.min, Math.min(paramDef.max, value));\n\n // Validate if enabled (but not during reset/import)\n if (\n this.panelConfig.validateOnChange &&\n paramDef.validate &&\n source !== 'reset' &&\n source !== 'import'\n ) {\n const validationResult = paramDef.validate(value, this.state.values);\n if (validationResult !== true) {\n this.state.errors[parameterId] =\n typeof validationResult === 'string' ? validationResult : 'Validation failed';\n this.dispatchValidationError(parameterId, this.state.errors[parameterId]);\n this.render();\n return;\n }\n }\n\n // Clear error for this parameter\n delete this.state.errors[parameterId];\n\n // Update value\n const oldValue = this.state.values[parameterId];\n this.state.values[parameterId] = value;\n\n // Only mark dirty and clear preset for non-reset/import sources\n if (source !== 'reset' && source !== 'import' && source !== 'preset') {\n this.state.isDirty = true;\n this.state.activePreset = null; // Clear active preset when manually changed\n }\n\n // Update child component if it exists\n const slider = this.parameters.get(parameterId);\n if (slider && oldValue !== value) {\n // Map 'import' to 'reset' since ParameterSlider doesn't support 'import'\n const sliderSource = source === 'import' ? 'reset' : source;\n slider.setValue(value, sliderSource);\n }\n\n // Persist if enabled\n if (this.panelConfig.persistValues) {\n this.saveToStorage();\n }\n\n // Emit change event (only if called programmatically, not from child slider)\n if (this.panelConfig.emitChangeEvents && oldValue !== value) {\n this.dispatchPanelChange(parameterId, value, oldValue ?? paramDef.min, source);\n }\n\n // Re-render to update UI\n this.render();\n }\n\n /**\n * Load preset values\n */\n loadPreset(presetId: string): void {\n const preset = this.presets.get(presetId);\n if (!preset) {\n this.log(`Preset ${presetId} not found`, 'warn');\n return;\n }\n\n const previousValues = { ...this.state.values };\n\n // Apply all preset values\n Object.entries(preset.values).forEach(([parameterId, value]) => {\n if (this.parameterDefinitions.has(parameterId)) {\n this.setValue(parameterId, value, 'preset');\n }\n });\n\n this.state.activePreset = presetId;\n this.state.isDirty = false;\n\n // Emit preset load event\n this.dispatchPresetLoad(presetId, preset, previousValues);\n\n this.render();\n }\n\n /**\n * Reset all parameters to default values\n */\n resetAll(): void {\n this.parameterDefinitions.forEach((paramDef, parameterId) => {\n const defaultValue = paramDef.value;\n this.setValue(parameterId, defaultValue, 'reset');\n });\n\n this.state.activePreset = null;\n this.state.isDirty = false;\n this.state.errors = {};\n\n // Emit reset event\n this.dispatchPanelReset();\n\n this.render();\n }\n\n /**\n * Export configuration as JSON\n */\n exportConfig(): ExportedConfig {\n const parameters: Record<string, number> = {};\n\n this.parameterDefinitions.forEach((_, parameterId) => {\n parameters[parameterId] = this.state.values[parameterId] ?? 0;\n });\n\n const config: ExportedConfig = {\n version: '1.0',\n parameters,\n };\n\n if (this.state.activePreset) {\n config.preset = this.state.activePreset;\n }\n\n config.metadata = {\n created: new Date().toISOString(),\n name: (this.config as any).title || 'Parameters',\n };\n\n // Emit export event\n this.dispatchConfigExport(config);\n\n return config;\n }\n\n /**\n * Import configuration from JSON\n */\n importConfig(config: ExportedConfig): void {\n if (!config.parameters) {\n this.log('Invalid config: missing parameters', 'warn');\n return;\n }\n\n // Apply imported values\n Object.entries(config.parameters).forEach(([parameterId, value]) => {\n if (this.parameterDefinitions.has(parameterId)) {\n this.setValue(parameterId, value, 'import');\n }\n });\n\n // Load active preset if specified\n if (config.preset && this.presets.has(config.preset)) {\n this.state.activePreset = config.preset;\n } else {\n this.state.activePreset = null;\n }\n\n this.state.isDirty = false;\n\n // Emit import event\n this.dispatchConfigImport(config);\n\n this.render();\n }\n\n /**\n * Toggle collapsed state\n */\n toggleCollapse(): void {\n if (!this.panelConfig.collapsible) return;\n\n this.state.isCollapsed = !this.state.isCollapsed;\n this.render();\n }\n\n /**\n * Validate all parameters\n */\n validateAll(): boolean {\n let isValid = true;\n this.state.errors = {};\n\n this.parameterDefinitions.forEach((paramDef, parameterId) => {\n if (paramDef.validate) {\n const value = this.state.values[parameterId] ?? paramDef.min;\n const validationResult = paramDef.validate(value, this.state.values);\n if (validationResult !== true) {\n isValid = false;\n this.state.errors[parameterId] =\n typeof validationResult === 'string' ? validationResult : 'Validation failed';\n this.dispatchValidationError(parameterId, this.state.errors[parameterId]);\n }\n }\n });\n\n if (!isValid) {\n this.render();\n }\n\n return isValid;\n }\n\n /**\n * Add custom preset\n */\n addPreset(id: string, name: string, values: Record<string, number>, description?: string): void {\n this.presets.set(id, { name, description, values, isBuiltIn: false });\n\n if (this.panelConfig.persistPresets) {\n this.savePresetsToStorage();\n }\n\n this.render();\n }\n\n /**\n * Remove custom preset\n */\n removePreset(id: string): void {\n const preset = this.presets.get(id);\n if (preset && !preset.isBuiltIn) {\n this.presets.delete(id);\n\n if (this.state.activePreset === id) {\n this.state.activePreset = null;\n }\n\n if (this.panelConfig.persistPresets) {\n this.savePresetsToStorage();\n }\n\n this.render();\n }\n }\n\n // Event dispatchers\n private dispatchPanelChange(\n parameterId: string,\n value: number,\n oldValue: number,\n source: 'slider' | 'input' | 'preset' | 'reset' | 'import'\n ): void {\n const event = new CustomEvent<PanelChangeEvent>('panelchange', {\n detail: {\n parameterId,\n value,\n previousValue: oldValue,\n allValues: this.getAllValues(),\n source,\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private dispatchPresetLoad(\n presetId: string,\n preset: { name: string; description?: string; values: Record<string, number> },\n previousValues: Record<string, number>\n ): void {\n const event = new CustomEvent<PresetLoadEvent>('presetload', {\n detail: {\n presetId,\n preset: {\n name: preset.name,\n description: preset.description,\n values: preset.values,\n },\n previousValues,\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private dispatchConfigExport(config: ExportedConfig): void {\n const event = new CustomEvent<ConfigExportEvent>('configexport', {\n detail: {\n config,\n format: 'json',\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private dispatchConfigImport(config: ExportedConfig): void {\n const previousValues = { ...this.state.values };\n const event = new CustomEvent<ConfigImportEvent>('configimport', {\n detail: {\n config,\n previousValues,\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private dispatchPanelReset(): void {\n const previousValues = { ...this.state.values };\n const newValues: Record<string, number> = {};\n this.parameterDefinitions.forEach((param, id) => {\n newValues[id] = param.value;\n });\n\n const event = new CustomEvent<PanelResetEvent>('panelreset', {\n detail: {\n previousValues,\n newValues,\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n private dispatchValidationError(parameterId: string, message: string): void {\n const event = new CustomEvent<ValidationErrorEvent>('validationerror', {\n detail: {\n parameterId,\n error: message,\n value: this.state.values[parameterId] || 0,\n timestamp: Date.now(),\n },\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(event);\n }\n\n // Storage methods\n private saveToStorage(): void {\n try {\n const data = {\n values: this.state.values,\n activePreset: this.state.activePreset,\n };\n localStorage.setItem(this.panelConfig.storageKey as string, JSON.stringify(data));\n } catch (error) {\n this.log('Failed to save to storage', 'error', error);\n }\n }\n\n private loadFromStorage(): void {\n try {\n const data = localStorage.getItem(this.panelConfig.storageKey as string);\n if (data) {\n const parsed = JSON.parse(data);\n if (parsed.values) {\n Object.entries(parsed.values).forEach(([parameterId, value]) => {\n if (this.parameterDefinitions.has(parameterId)) {\n this.state.values[parameterId] = value as number;\n }\n });\n }\n if (parsed.activePreset && this.presets.has(parsed.activePreset)) {\n this.state.activePreset = parsed.activePreset;\n }\n }\n } catch (error) {\n this.log('Failed to load from storage', 'error', error);\n }\n }\n\n private savePresetsToStorage(): void {\n try {\n const customPresets = Array.from(this.presets.entries())\n .filter(([_, preset]) => !preset.isBuiltIn)\n .reduce(\n (acc, [id, preset]) => {\n acc[id] = { name: preset.name, description: preset.description, values: preset.values };\n return acc;\n },\n {} as Record<string, any>\n );\n\n localStorage.setItem(`${this.panelConfig.storageKey}-presets`, JSON.stringify(customPresets));\n } catch (error) {\n this.log('Failed to save presets', 'error', error);\n }\n }\n\n private loadPresetsFromStorage(): void {\n try {\n const data = localStorage.getItem(`${this.panelConfig.storageKey}-presets`);\n if (data) {\n const customPresets = JSON.parse(data);\n Object.entries(customPresets).forEach(([id, preset]: [string, any]) => {\n this.presets.set(id, { ...preset, isBuiltIn: false });\n });\n }\n } catch (error) {\n this.log('Failed to load presets', 'error', error);\n }\n }\n\n // Rendering\n protected render(): void {\n if (!this.shadowRoot) return;\n\n const hasErrors = Object.keys(this.state.errors).length > 0;\n\n this.shadowRoot.innerHTML = `\n <style>${styles}</style>\n <div class=\"container\" style=\"--grid-columns: ${this.panelConfig.columns}\">\n ${this.renderHeader()}\n <div class=\"content ${this.state.isCollapsed ? 'collapsed' : ''}\">\n ${hasErrors ? this.renderErrors() : ''}\n ${this.panelConfig.showPresets && this.presets.size > 0 ? this.renderPresets() : ''}\n ${this.renderParameters()}\n ${this.panelConfig.showResetAll || this.panelConfig.showExportImport ? this.renderActions() : ''}\n </div>\n </div>\n `;\n\n // Attach event listeners\n this.attachEventListeners();\n\n // Create and attach parameter sliders\n this.createParameterSliders();\n }\n\n private renderHeader(): string {\n const collapsedClass = this.state.isCollapsed ? 'collapsed' : '';\n const showTitle = this.panelConfig.title !== undefined && this.panelConfig.title !== null;\n\n return `\n <div class=\"header ${this.panelConfig.collapsible ? 'collapsible' : ''}\" id=\"header\">\n ${\n showTitle\n ? `\n <div class=\"title-section\">\n <h3 class=\"title\">${this.panelConfig.title}</h3>\n <span class=\"dirty-indicator ${this.state.isDirty ? 'show' : ''}\"></span>\n </div>\n `\n : `\n <div class=\"title-section\">\n <span class=\"dirty-indicator ${this.state.isDirty ? 'show' : ''}\"></span>\n </div>\n `\n }\n ${\n this.panelConfig.collapsible\n ? `\n <span class=\"collapse-icon ${collapsedClass}\">▼</span>\n `\n : ''\n }\n </div>\n `;\n }\n\n private renderErrors(): string {\n const errorEntries = Object.entries(this.state.errors);\n if (errorEntries.length === 0) return '';\n\n return `\n <div class=\"validation-errors show\">\n ${errorEntries\n .map(\n ([parameterId, message]) => `\n <div class=\"error-item\">\n <span class=\"error-icon\">⚠</span>\n <span>${this.parameterDefinitions.get(parameterId)?.label || parameterId}: ${message}</span>\n </div>\n `\n )\n .join('')}\n </div>\n `;\n }\n\n private renderPresets(): string {\n return `\n <div class=\"presets-section\">\n <div class=\"presets-label\">Presets</div>\n <div class=\"presets-buttons\">\n ${Array.from(this.presets.entries())\n .map(\n ([id, preset]) => `\n <button \n class=\"preset-btn ${this.state.activePreset === id ? 'active' : ''}\" \n data-preset-id=\"${id}\"\n title=\"${preset.description || preset.name}\"\n >\n ${preset.name}\n </button>\n `\n )\n .join('')}\n </div>\n </div>\n `;\n }\n\n private renderParameters(): string {\n return `\n <div class=\"parameters-section\">\n <div class=\"parameters-grid layout-${this.panelConfig.layout}\">\n ${Array.from(this.parameterDefinitions.keys())\n .map(\n (id) => `\n <div class=\"parameter-wrapper\" data-parameter-id=\"${id}\"></div>\n `\n )\n .join('')}\n </div>\n </div>\n `;\n }\n\n private renderActions(): string {\n return `\n <div class=\"actions-section\">\n <div class=\"actions-left\">\n ${\n this.panelConfig.showResetAll\n ? `\n <button class=\"action-btn danger\" id=\"reset-btn\">\n <span>↻</span>\n <span>Reset All</span>\n </button>\n `\n : ''\n }\n </div>\n <div class=\"actions-right\">\n ${\n this.panelConfig.showExportImport\n ? `\n <button class=\"action-btn\" id=\"import-btn\">\n <span>📥</span>\n <span>Import</span>\n </button>\n <button class=\"action-btn primary\" id=\"export-btn\">\n <span>📤</span>\n <span>Export</span>\n </button>\n `\n : ''\n }\n </div>\n </div>\n `;\n }\n\n private attachEventListeners(): void {\n if (!this.shadowRoot) return;\n\n // Header click for collapse\n if (this.panelConfig.collapsible) {\n const header = this.shadowRoot.getElementById('header');\n header?.addEventListener('click', () => this.toggleCollapse());\n }\n\n // Preset buttons\n const presetButtons = this.shadowRoot.querySelectorAll('.preset-btn');\n presetButtons.forEach((btn) => {\n btn.addEventListener('click', () => {\n const presetId = (btn as HTMLElement).dataset.presetId;\n if (presetId) this.loadPreset(presetId);\n });\n });\n\n // Reset button\n const resetBtn = this.shadowRoot.getElementById('reset-btn');\n resetBtn?.addEventListener('click', () => this.resetAll());\n\n // Export button\n const exportBtn = this.shadowRoot.getElementById('export-btn');\n exportBtn?.addEventListener('click', () => this.handleExport());\n\n // Import button\n const importBtn = this.shadowRoot.getElementById('import-btn');\n importBtn?.addEventListener('click', () => this.handleImport());\n }\n\n private createParameterSliders(): void {\n if (!this.shadowRoot) return;\n\n // Clear existing sliders\n this.parameters.clear();\n\n // Create slider for each parameter\n this.parameterDefinitions.forEach((paramDef, parameterId) => {\n const wrapper = this.shadowRoot!.querySelector(`[data-parameter-id=\"${parameterId}\"]`);\n if (!wrapper) return;\n\n // Create ParameterSlider instance\n const slider = new ParameterSlider({\n label: paramDef.label,\n min: paramDef.min,\n max: paramDef.max,\n value: this.state.values[parameterId],\n step: paramDef.step,\n unit: paramDef.unit,\n description: paramDef.description,\n presets: paramDef.presets,\n showInput: paramDef.showInput,\n disabled: paramDef.disabled || this._disabled,\n });\n\n // Listen to value changes from child slider (user interaction only)\n slider.addEventListener('valuechange', ((e: CustomEvent) => {\n // Stop propagation to prevent event bubbling\n e.stopPropagation();\n\n // Update our state and emit our own event\n const paramDef = this.parameterDefinitions.get(parameterId);\n if (!paramDef) return;\n\n const value = e.detail.value;\n const source = e.detail.source;\n\n // Clamp value to range\n const clampedValue = Math.max(paramDef.min, Math.min(paramDef.max, value));\n\n // Validate if enabled\n if (this.panelConfig.validateOnChange && paramDef.validate) {\n const validationResult = paramDef.validate(clampedValue, this.state.values);\n if (validationResult !== true) {\n this.state.errors[parameterId] =\n typeof validationResult === 'string' ? validationResult : 'Validation failed';\n this.dispatchValidationError(parameterId, this.state.errors[parameterId]);\n this.render();\n return;\n }\n }\n\n // Clear error\n delete this.state.errors[parameterId];\n\n // Update value\n const oldValue = this.state.values[parameterId];\n this.state.values[parameterId] = clampedValue;\n\n // Mark dirty and clear preset for user changes\n if (source !== 'reset' && source !== 'import' && source !== 'preset') {\n this.state.isDirty = true;\n this.state.activePreset = null;\n }\n\n // Persist if enabled\n if (this.panelConfig.persistValues) {\n this.saveToStorage();\n }\n\n // Emit change event\n if (this.panelConfig.emitChangeEvents && oldValue !== clampedValue) {\n this.dispatchPanelChange(parameterId, clampedValue, oldValue ?? paramDef.min, source);\n }\n\n // Re-render to update UI\n this.render();\n }) as EventListener);\n\n // Append to wrapper\n wrapper.appendChild(slider);\n\n // Store reference\n this.parameters.set(parameterId, slider);\n });\n }\n\n private handleExport(): void {\n const config = this.exportConfig();\n const json = JSON.stringify(config, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${this.panelConfig.title}-config.json`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n private handleImport(): void {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.json';\n input.onchange = (e) => {\n const file = (e.target as HTMLInputElement).files?.[0];\n if (!file) return;\n\n file\n .text()\n .then((text) => {\n try {\n const config = JSON.parse(text);\n this.importConfig(config);\n } catch (error) {\n this.log('Failed to parse config file', 'error', error);\n }\n })\n .catch((error) => {\n this.log('Failed to read config file', 'error', error);\n });\n };\n input.click();\n }\n\n /**\n * Clean up when component is removed\n */\n override disconnectedCallback(): void {\n this.parameters.clear();\n }\n}\n\n// Register custom element\nif (!customElements.get('ai-parameter-panel')) {\n customElements.define('ai-parameter-panel', ParameterPanel);\n}\n","import { AIControl } from '../base/AIControl';\nimport { throttle, formatTime } from '../base/utils';\nimport type {\n QueueProgressConfig,\n QueueProgressState,\n QueueStatus,\n QueueUpdate,\n PositionChangeEvent,\n QueueStartEvent,\n QueueCompleteEvent,\n QueueErrorEvent,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * QueueProgress Component\n *\n * Displays queue position and estimated wait time for rate-limited AI APIs.\n * Shows position updates, processing rate, and estimated wait time.\n *\n * @example\n * ```typescript\n * // Create the component\n * const queue = new QueueProgress({\n * position: 47,\n * queueSize: 120,\n * estimatedWait: 180, // 3 minutes\n * processingRate: 3, // 3 requests per second\n * });\n *\n * document.body.appendChild(queue);\n *\n * // Start tracking\n * queue.start();\n *\n * // Update position\n * queue.update({\n * position: 25,\n * estimatedWait: 90\n * });\n *\n * // Complete\n * queue.complete();\n *\n * // Listen to events\n * queue.addEventListener('positionchange', (e) => {\n * console.log('Position changed', e.detail);\n * });\n * ```\n *\n * @fires queuestart - Fired when queue tracking starts\n * @fires positionchange - Fired when position updates\n * @fires queuecomplete - Fired when processing begins\n * @fires queueerror - Fired when an error occurs\n */\nexport class QueueProgress extends AIControl {\n protected override config: Required<QueueProgressConfig>;\n private state: QueueProgressState;\n private readonly updateThrottled: (update: QueueUpdate) => void;\n private timerInterval: ReturnType<typeof setInterval> | undefined;\n private initialPosition: number = 0;\n\n static get observedAttributes() {\n return ['position', 'queue-size', 'disabled', 'size', 'variant', 'animation'];\n }\n\n constructor(config: QueueProgressConfig = {}) {\n super({\n debug: config.debug ?? false,\n className: config.className,\n ariaLabel: config.ariaLabel ?? 'Queue Progress',\n });\n\n // Set default configuration\n this.config = {\n position: config.position ?? 0,\n queueSize: config.queueSize ?? 0,\n estimatedWait: config.estimatedWait ?? 0,\n processingRate: config.processingRate ?? 1,\n showPosition: config.showPosition ?? true,\n showWaitTime: config.showWaitTime ?? true,\n showRate: config.showRate ?? true,\n showQueueSize: config.showQueueSize ?? true,\n showProgressBar: config.showProgressBar ?? true,\n message: config.message ?? 'You are in the queue',\n animate: config.animate ?? true,\n updateThrottle: config.updateThrottle ?? 100,\n cursorFeedback: config.cursorFeedback ?? true,\n debug: config.debug ?? false,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? 'Queue Progress',\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n // Initialize state\n this.state = {\n status: 'waiting',\n position: this.config.position,\n queueSize: this.config.queueSize,\n estimatedWait: this.config.estimatedWait,\n processingRate: this.config.processingRate,\n startTime: 0,\n message: this.config.message,\n elapsedTime: 0,\n };\n\n this.initialPosition = this.config.position;\n\n // Create throttled update function\n this.updateThrottled = throttle(this._updateInternal.bind(this), this.config.updateThrottle);\n\n // Attach shadow DOM\n this.attachShadow({ mode: 'open' });\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.log('QueueProgress mounted');\n }\n\n override disconnectedCallback(): void {\n this.stopTimer();\n super.disconnectedCallback();\n }\n\n protected override getDefaultRole(): string {\n return 'status';\n }\n\n protected override handleAttributeChange(\n name: string,\n _oldValue: string,\n newValue: string\n ): void {\n switch (name) {\n case 'position':\n this.update({ position: Number.parseInt(newValue, 10) || 0 });\n break;\n case 'queue-size':\n this.update({ queueSize: Number.parseInt(newValue, 10) || 0 });\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n this.render();\n break;\n case 'size':\n this.config.size = newValue as any;\n this.render();\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n }\n }\n\n /**\n * Start queue tracking\n */\n public start(message?: string): void {\n this.state = {\n ...this.state,\n status: 'waiting',\n startTime: Date.now(),\n elapsedTime: 0,\n message: message || this.config.message,\n };\n\n this.initialPosition = this.state.position;\n this.startTimer();\n this.render();\n this.updateCursor();\n this.emit('queuestart', {\n position: this.state.position,\n queueSize: this.state.queueSize,\n estimatedWait: this.state.estimatedWait,\n timestamp: Date.now(),\n } as QueueStartEvent);\n this.log('Queue tracking started', this.state);\n }\n\n /**\n * Update queue position\n */\n public update(update: QueueUpdate): void {\n if (this.state.status === 'completed' || this.state.status === 'error') {\n return;\n }\n\n this.updateThrottled(update);\n }\n\n private _updateInternal(update: QueueUpdate): void {\n const previousPosition = this.state.position;\n\n this.state = {\n ...this.state,\n position: update.position ?? this.state.position,\n queueSize: update.queueSize ?? this.state.queueSize,\n estimatedWait: update.estimatedWait ?? this.state.estimatedWait,\n processingRate: update.processingRate ?? this.state.processingRate,\n message: update.message ?? this.state.message,\n };\n\n // Animate position number if changed\n if (update.position !== undefined && update.position !== previousPosition) {\n const positionEl = this.shadowRoot?.querySelector('.position-number');\n if (positionEl && this.config.animate) {\n positionEl.classList.add('changing');\n setTimeout(() => positionEl.classList.remove('changing'), 500);\n }\n\n this.emit('positionchange', {\n previousPosition,\n currentPosition: this.state.position,\n queueSize: this.state.queueSize,\n estimatedWait: this.state.estimatedWait,\n timestamp: Date.now(),\n } as PositionChangeEvent);\n }\n\n this.render();\n this.log('Position updated', this.state);\n }\n\n /**\n * Mark as processing (reached front of queue)\n */\n public complete(): void {\n this.state = {\n ...this.state,\n status: 'completed',\n position: 0,\n };\n\n this.stopTimer();\n this.render();\n this.updateCursor();\n\n const totalWaitTime = this.state.startTime > 0 ? Date.now() - this.state.startTime : 0;\n\n this.emit('queuecomplete', {\n totalWaitTime,\n startPosition: this.initialPosition,\n timestamp: Date.now(),\n } as QueueCompleteEvent);\n\n this.log('Queue completed', { totalWaitTime });\n }\n\n /**\n * Cancel queue\n */\n public cancel(reason: string = 'Cancelled by user'): void {\n this.state = {\n ...this.state,\n status: 'cancelled',\n message: reason,\n };\n\n this.stopTimer();\n this.render();\n this.updateCursor();\n this.log('Queue cancelled', reason);\n }\n\n /**\n * Handle error\n */\n public error(errorMessage: string): void {\n this.state = {\n ...this.state,\n status: 'error',\n message: errorMessage,\n };\n\n this.stopTimer();\n this.render();\n this.updateCursor();\n\n this.emit('queueerror', {\n message: errorMessage,\n position: this.state.position,\n timestamp: Date.now(),\n } as QueueErrorEvent);\n\n this.logError('Queue error', new Error(errorMessage));\n }\n\n /**\n * Reset to initial state\n */\n public reset(): void {\n this.stopTimer();\n\n this.state = {\n status: 'waiting',\n position: this.config.position,\n queueSize: this.config.queueSize,\n estimatedWait: this.config.estimatedWait,\n processingRate: this.config.processingRate,\n startTime: 0,\n message: this.config.message,\n elapsedTime: 0,\n };\n\n this.initialPosition = this.config.position;\n this.render();\n this.log('Queue reset');\n }\n\n /**\n * Get current position\n */\n public getPosition(): number {\n return this.state.position;\n }\n\n /**\n * Get current status\n */\n public getStatus(): QueueStatus {\n return this.state.status;\n }\n\n /**\n * Start elapsed time timer\n */\n protected override startTimer(): void {\n this.stopTimer();\n this.timerInterval = globalThis.setInterval(() => {\n if (this.state.startTime > 0) {\n this.state.elapsedTime = Date.now() - this.state.startTime;\n this.render();\n }\n }, 1000);\n }\n\n /**\n * Stop timer\n */\n private stopTimer(): void {\n if (this.timerInterval) {\n clearInterval(this.timerInterval);\n this.timerInterval = undefined;\n }\n }\n\n /**\n * Calculate progress percentage\n */\n private getProgressPercentage(): number {\n if (this.state.queueSize === 0 || this.initialPosition === 0) return 0;\n const processed = this.initialPosition - this.state.position;\n return Math.min(100, Math.max(0, (processed / this.initialPosition) * 100));\n }\n\n /**\n * Update cursor based on queue state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback) return;\n\n if (this.state.status === 'waiting') {\n this.style.cursor = 'wait';\n } else if (this.state.status === 'error' || this.state.status === 'cancelled') {\n this.style.cursor = 'not-allowed';\n } else {\n this.style.cursor = 'default';\n }\n }\n\n /**\n * Render metrics section\n */\n private renderMetrics(): string {\n if (this.state.status !== 'waiting') return '';\n\n let metricsHtml = '';\n\n if (this.config.showQueueSize) {\n metricsHtml += `\n <div class=\"metric\">\n <div class=\"metric-value\">${this.state.queueSize}</div>\n <div class=\"metric-label\">Queue Size</div>\n </div>\n `;\n }\n\n if (this.config.showWaitTime) {\n metricsHtml += `\n <div class=\"metric\">\n <div class=\"metric-value\">${formatTime(Math.round(this.state.estimatedWait))}</div>\n <div class=\"metric-label\">Est. Wait</div>\n </div>\n `;\n }\n\n if (this.config.showRate) {\n metricsHtml += `\n <div class=\"metric\">\n <div class=\"metric-value\">${this.state.processingRate.toFixed(1)}/s</div>\n <div class=\"metric-label\">Processing Rate</div>\n </div>\n `;\n }\n\n return metricsHtml\n ? `\n <div class=\"queue-metrics\">\n ${metricsHtml}\n </div>\n `\n : '';\n }\n\n /**\n * Render component\n */\n protected override render(): void {\n if (!this.shadowRoot) return;\n\n // Sync attributes to host element for CSS selectors\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n\n const progress = this.getProgressPercentage();\n const statusClass = this.state.status;\n const statusText = this.getStatusText();\n\n this.shadowRoot.innerHTML = `\n <style>${styles}</style>\n <div class=\"queue-container\">\n <div class=\"queue-header\">\n <div class=\"queue-icon\">${this.getStatusIcon()}</div>\n <div class=\"queue-title\">\n <h3 class=\"queue-status\">${statusText}</h3>\n <p class=\"queue-message\">${this.state.message || ''}</p>\n </div>\n <span class=\"queue-badge ${statusClass}\">${this.state.status}</span>\n </div>\n\n ${\n this.config.showPosition && this.state.status === 'waiting'\n ? `\n <div class=\"queue-position\">\n <div class=\"position-number\">${this.state.position}</div>\n <div class=\"position-label\">Position in Queue</div>\n </div>\n `\n : ''\n }\n\n ${this.renderMetrics()}\n\n ${\n this.config.showProgressBar && this.state.status === 'waiting' && this.initialPosition > 0\n ? `\n <div class=\"progress-container\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" style=\"width: ${progress}%\"></div>\n </div>\n <div class=\"progress-label\">\n <span>${Math.round(progress)}% through queue</span>\n <span>${formatTime(Math.round(this.state.elapsedTime / 1000))} elapsed</span>\n </div>\n </div>\n `\n : ''\n }\n\n ${\n this.state.status === 'waiting' && this.state.position <= 5\n ? `\n <div class=\"queue-info\">\n <span class=\"info-icon\">🎯</span>\n <p class=\"info-text\">You're almost there! Processing will begin shortly.</p>\n </div>\n `\n : ''\n }\n\n ${\n this.state.status === 'completed'\n ? `\n <div class=\"queue-info\">\n <span class=\"info-icon\">✅</span>\n <p class=\"info-text\">Your request is now being processed!</p>\n </div>\n `\n : ''\n }\n\n ${\n this.state.status === 'error'\n ? `\n <div class=\"error-message\">\n <span class=\"error-icon\">⚠️</span>\n <p class=\"error-text\">${this.state.message}</p>\n </div>\n `\n : ''\n }\n </div>\n `;\n\n // Update ARIA attributes\n this.setAttribute('aria-valuenow', this.state.position.toString());\n this.setAttribute('aria-valuetext', `Position ${this.state.position} in queue`);\n }\n\n private getStatusIcon(): string {\n switch (this.state.status) {\n case 'waiting':\n return '⏳';\n case 'processing':\n return '⚙️';\n case 'completed':\n return '✅';\n case 'cancelled':\n return '🚫';\n case 'error':\n return '❌';\n default:\n return '⏳';\n }\n }\n\n private getStatusText(): string {\n switch (this.state.status) {\n case 'waiting':\n return 'Waiting in Queue';\n case 'processing':\n return 'Processing Your Request';\n case 'completed':\n return 'Processing Started';\n case 'cancelled':\n return 'Queue Cancelled';\n case 'error':\n return 'Queue Error';\n default:\n return 'Queue Status';\n }\n }\n}\n\n// Register the custom element\nif (!customElements.get('queue-progress')) {\n customElements.define('queue-progress', QueueProgress);\n}\n","import { AIControl } from '../base/AIControl';\nimport { formatTime } from '../base/utils';\nimport type {\n RetryProgressConfig,\n RetryProgressState,\n RetryAttemptUpdate,\n RetryStatus,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * RetryProgress Component\n *\n * Displays retry progress with exponential backoff, attempt tracking, and error handling.\n * Perfect for handling transient failures in API calls, network requests, or AI operations.\n *\n * @example\n * ```typescript\n * // Create the component\n * const retry = new RetryProgress({\n * maxAttempts: 5,\n * initialDelay: 1000,\n * strategy: 'exponential',\n * allowManualRetry: true,\n * });\n *\n * document.body.appendChild(retry);\n *\n * // Start first attempt\n * retry.attempt('Connecting to API...');\n *\n * // If it fails, start waiting for retry\n * retry.waitForRetry({\n * attempt: 2,\n * error: new Error('Connection timeout'),\n * });\n *\n * // On success\n * retry.success('Connected successfully!');\n *\n * // Listen to events\n * retry.addEventListener('retryattempt', (e) => {\n * console.log('Attempting:', e.detail);\n * });\n * ```\n *\n * @fires retryattempt - Fired when a retry attempt starts\n * @fires retrywaiting - Fired when waiting for next retry\n * @fires retrysuccess - Fired when operation succeeds\n * @fires retryfailure - Fired when max attempts reached\n * @fires retrycancel - Fired when retry is cancelled\n * @fires manualretry - Fired when user manually triggers retry\n */\nexport class RetryProgress extends AIControl {\n protected override config: Required<RetryProgressConfig>;\n private state: RetryProgressState;\n private waitTimer?: ReturnType<typeof setTimeout>;\n private elapsedTimer?: ReturnType<typeof setInterval>;\n private progressTimer?: ReturnType<typeof setInterval>;\n\n constructor(config: RetryProgressConfig = {}) {\n super(config);\n\n this.config = {\n attempt: config.attempt ?? 1,\n maxAttempts: config.maxAttempts ?? 3,\n initialDelay: config.initialDelay ?? 1000,\n maxDelay: config.maxDelay ?? 30000,\n backoffMultiplier: config.backoffMultiplier ?? 2,\n strategy: config.strategy ?? 'exponential',\n message: config.message ?? 'Retrying operation...',\n showAttemptCount: config.showAttemptCount ?? true,\n showNextRetry: config.showNextRetry ?? true,\n showProgressBar: config.showProgressBar ?? true,\n showElapsedTime: config.showElapsedTime ?? true,\n allowManualRetry: config.allowManualRetry ?? false,\n allowCancel: config.allowCancel ?? true,\n animate: config.animate ?? true,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? 'Retry Progress',\n cursorFeedback: config.cursorFeedback ?? true,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n this.state = {\n status: 'idle',\n attempt: this.config.attempt,\n maxAttempts: this.config.maxAttempts,\n currentDelay: this.config.initialDelay,\n nextRetryTime: 0,\n startTime: 0,\n elapsedTime: 0,\n message: this.config.message,\n };\n\n this.attachShadow({ mode: 'open' });\n }\n\n /**\n * Read max-attempts attribute\n */\n private _readMaxAttemptsAttribute(): void {\n if (!this.hasAttribute('max-attempts')) return;\n\n const val = Number.parseInt(this.getAttribute('max-attempts') || '', 10);\n if (!Number.isNaN(val)) {\n this.config.maxAttempts = val;\n this.state.maxAttempts = val;\n }\n }\n\n /**\n * Read initial-delay attribute\n */\n private _readInitialDelayAttribute(): void {\n if (!this.hasAttribute('initial-delay')) return;\n\n const val = Number.parseInt(this.getAttribute('initial-delay') || '', 10);\n if (!Number.isNaN(val)) {\n this.config.initialDelay = val;\n }\n }\n\n /**\n * Read max-delay attribute\n */\n private _readMaxDelayAttribute(): void {\n if (!this.hasAttribute('max-delay')) return;\n\n const val = Number.parseInt(this.getAttribute('max-delay') || '', 10);\n if (!Number.isNaN(val)) {\n this.config.maxDelay = val;\n }\n }\n\n /**\n * Read backoff-multiplier attribute\n */\n private _readBackoffMultiplierAttribute(): void {\n if (!this.hasAttribute('backoff-multiplier')) return;\n\n const val = Number.parseFloat(this.getAttribute('backoff-multiplier') || '');\n if (!Number.isNaN(val)) {\n this.config.backoffMultiplier = val;\n }\n }\n\n /**\n * Read strategy attribute\n */\n private _readStrategyAttribute(): void {\n if (!this.hasAttribute('strategy')) return;\n\n const strategy = this.getAttribute('strategy') as RetryStatus;\n if (['exponential', 'linear', 'fixed', 'fibonacci'].includes(strategy)) {\n this.config.strategy = strategy as any;\n }\n }\n\n /**\n * Read boolean attributes\n */\n private _readBooleanAttributes(): void {\n if (this.hasAttribute('allow-manual-retry')) {\n this.config.allowManualRetry = this.getAttribute('allow-manual-retry') === 'true';\n }\n if (this.hasAttribute('allow-cancel')) {\n this.config.allowCancel = this.getAttribute('allow-cancel') === 'true';\n }\n if (this.hasAttribute('show-attempt-count')) {\n this.config.showAttemptCount = this.getAttribute('show-attempt-count') === 'true';\n }\n if (this.hasAttribute('show-progress-bar')) {\n this.config.showProgressBar = this.getAttribute('show-progress-bar') === 'true';\n }\n }\n\n /**\n * Connected callback - read initial attributes\n */\n override connectedCallback(): void {\n super.connectedCallback();\n\n this._readMaxAttemptsAttribute();\n this._readInitialDelayAttribute();\n this._readMaxDelayAttribute();\n this._readBackoffMultiplierAttribute();\n this._readStrategyAttribute();\n this._readBooleanAttributes();\n\n this.render();\n }\n\n /**\n * Calculate delay for retry attempt based on strategy\n */\n private calculateDelay(attempt: number): number {\n const { strategy, initialDelay, backoffMultiplier, maxDelay } = this.config;\n\n let delay: number;\n\n switch (strategy) {\n case 'exponential':\n delay = initialDelay * Math.pow(backoffMultiplier, attempt - 1);\n break;\n\n case 'linear':\n delay = initialDelay * attempt;\n break;\n\n case 'fibonacci':\n delay = initialDelay * this.fibonacci(attempt);\n break;\n\n case 'fixed':\n default:\n delay = initialDelay;\n break;\n }\n\n return Math.min(delay, maxDelay);\n }\n\n /**\n * Calculate fibonacci number\n */\n private fibonacci(n: number): number {\n if (n <= 1) return 1;\n let a = 1,\n b = 1;\n for (let i = 2; i < n; i++) {\n [a, b] = [b, a + b];\n }\n return b;\n }\n\n /**\n * Start a retry attempt\n */\n public attempt(message?: string): void {\n this.stopTimers();\n\n const attemptMessage = message || `Attempt ${this.state.attempt} of ${this.state.maxAttempts}`;\n\n this.setState({\n status: 'attempting',\n message: attemptMessage,\n startTime: this.state.startTime || Date.now(),\n });\n\n this.startElapsedTimer();\n\n this.dispatchEvent(\n new CustomEvent('retryattempt', {\n detail: {\n attempt: this.state.attempt,\n maxAttempts: this.state.maxAttempts,\n message: attemptMessage,\n timestamp: Date.now(),\n },\n })\n );\n\n this.log(`Retry attempt ${this.state.attempt}/${this.state.maxAttempts}: ${attemptMessage}`);\n }\n\n /**\n * Wait for next retry with optional error\n */\n public waitForRetry(update: RetryAttemptUpdate = {}): void {\n const nextAttempt = update.attempt ?? this.state.attempt + 1;\n\n if (nextAttempt > this.state.maxAttempts) {\n this.failure(update.error);\n return;\n }\n\n const delay = update.delay ?? this.calculateDelay(nextAttempt);\n const nextRetryTime = Date.now() + delay;\n\n this.setState({\n status: 'waiting',\n attempt: nextAttempt,\n currentDelay: delay,\n nextRetryTime,\n message: update.message || `Retrying in ${formatTime(Math.ceil(delay / 1000))}...`,\n errorMessage: update.error?.message,\n lastError: update.error,\n });\n\n this.startWaitTimer(delay);\n this.startProgressTimer(delay);\n\n this.dispatchEvent(\n new CustomEvent('retrywaiting', {\n detail: {\n attempt: nextAttempt,\n delay,\n nextRetryTime,\n strategy: this.config.strategy,\n timestamp: Date.now(),\n },\n })\n );\n\n this.log(`Waiting ${delay}ms before retry ${nextAttempt}/${this.state.maxAttempts}`);\n }\n\n /**\n * Mark operation as successful\n */\n public success(message?: string): void {\n this.stopTimers();\n\n const successMessage = message || 'Operation successful!';\n\n this.setState({\n status: 'success',\n message: successMessage,\n });\n\n this.dispatchEvent(\n new CustomEvent('retrysuccess', {\n detail: {\n attempt: this.state.attempt,\n totalAttempts: this.state.attempt,\n elapsedTime: this.state.elapsedTime,\n message: successMessage,\n timestamp: Date.now(),\n },\n })\n );\n\n this.log(`Success after ${this.state.attempt} attempts (${this.state.elapsedTime}ms)`);\n }\n\n /**\n * Mark operation as failed (max attempts reached)\n */\n public failure(error?: Error): void {\n this.stopTimers();\n\n this.setState({\n status: 'failed',\n message: 'Maximum retry attempts reached',\n errorMessage: error?.message || 'Operation failed',\n lastError: error,\n });\n\n this.dispatchEvent(\n new CustomEvent('retryfailure', {\n detail: {\n totalAttempts: this.state.attempt,\n lastError: error,\n elapsedTime: this.state.elapsedTime,\n timestamp: Date.now(),\n },\n })\n );\n\n this.logError('Retry failed', error || new Error('Maximum attempts reached'));\n }\n\n /**\n * Cancel retry operation\n */\n public cancel(reason?: string): void {\n this.stopTimers();\n\n this.setState({\n status: 'cancelled',\n message: reason || 'Operation cancelled',\n });\n\n this.dispatchEvent(\n new CustomEvent('retrycancel', {\n detail: {\n attempt: this.state.attempt,\n reason,\n timestamp: Date.now(),\n },\n })\n );\n\n this.log(`Retry cancelled: ${reason || 'User cancelled'}`);\n }\n\n /**\n * Reset to initial state\n */\n public reset(): void {\n this.stopTimers();\n\n this.state = {\n status: 'idle',\n attempt: this.config.attempt,\n maxAttempts: this.config.maxAttempts,\n currentDelay: this.config.initialDelay,\n nextRetryTime: 0,\n startTime: 0,\n elapsedTime: 0,\n message: this.config.message,\n };\n\n this.render();\n this.log('Reset to initial state');\n }\n\n /**\n * Get current attempt number\n */\n public getAttempt(): number {\n return this.state.attempt;\n }\n\n /**\n * Get current status\n */\n public getStatus(): RetryStatus {\n return this.state.status;\n }\n\n /**\n * Get time until next retry (ms)\n */\n public getTimeUntilRetry(): number {\n if (this.state.status !== 'waiting') return 0;\n return Math.max(0, this.state.nextRetryTime - Date.now());\n }\n\n /**\n * Start elapsed time timer\n */\n private startElapsedTimer(): void {\n this.elapsedTimer = globalThis.setInterval(() => {\n if (this.state.startTime > 0) {\n this.state.elapsedTime = Date.now() - this.state.startTime;\n this.render();\n }\n }, 1000);\n }\n\n /**\n * Start wait timer for automatic retry\n */\n private startWaitTimer(delay: number): void {\n this.waitTimer = globalThis.setTimeout(() => {\n if (this.state.status === 'waiting') {\n this.attempt();\n }\n }, delay);\n }\n\n /**\n * Start progress bar timer\n */\n private startProgressTimer(_totalDelay: number): void {\n this.progressTimer = globalThis.setInterval(() => {\n if (this.state.status === 'waiting') {\n const remaining = Math.max(0, this.state.nextRetryTime - Date.now());\n this.state.message = `Retrying in ${formatTime(Math.ceil(remaining / 1000))}...`;\n this.render();\n }\n }, 100);\n }\n\n /**\n * Stop all timers\n */\n private stopTimers(): void {\n if (this.waitTimer) {\n globalThis.clearTimeout(this.waitTimer);\n this.waitTimer = undefined;\n }\n if (this.elapsedTimer) {\n globalThis.clearInterval(this.elapsedTimer);\n this.elapsedTimer = undefined;\n }\n if (this.progressTimer) {\n globalThis.clearInterval(this.progressTimer);\n this.progressTimer = undefined;\n }\n }\n\n /**\n * Handle manual retry button click\n */\n private handleManualRetry(): void {\n if (this.state.status !== 'waiting' && this.state.status !== 'failed') return;\n\n this.dispatchEvent(\n new CustomEvent('manualretry', {\n detail: {\n attempt: this.state.attempt,\n timestamp: Date.now(),\n },\n })\n );\n\n this.attempt();\n }\n\n /**\n * Handle cancel button click\n */\n private handleCancel(): void {\n this.cancel('User cancelled operation');\n }\n\n /**\n * Update state and re-render\n */\n private setState(update: Partial<RetryProgressState>): void {\n Object.assign(this.state, update);\n this.render();\n this.updateCursor();\n\n // Update ARIA attributes\n const progress = ((this.state.attempt / this.state.maxAttempts) * 100).toFixed(0);\n this.setAttribute('aria-valuenow', this.state.attempt.toString());\n this.setAttribute('aria-valuemax', this.state.maxAttempts.toString());\n this.setAttribute(\n 'aria-valuetext',\n `Attempt ${this.state.attempt} of ${this.state.maxAttempts}, ${progress}% complete`\n );\n }\n\n /**\n * Update cursor based on retry state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback) return;\n\n if (this.state.status === 'attempting') {\n this.style.cursor = 'progress';\n } else if (this.state.status === 'waiting') {\n this.style.cursor = 'wait';\n } else if (this.state.status === 'failed' || this.state.status === 'cancelled') {\n this.style.cursor = 'not-allowed';\n } else {\n this.style.cursor = 'default';\n }\n }\n\n /**\n * Get status icon\n */\n private getStatusIcon(): string {\n switch (this.state.status) {\n case 'attempting':\n return '🔄';\n case 'waiting':\n return '⏳';\n case 'success':\n return '✅';\n case 'failed':\n return '❌';\n case 'cancelled':\n return '🚫';\n default:\n return '⏸️';\n }\n }\n\n /**\n * Get status text\n */\n private getStatusText(): string {\n switch (this.state.status) {\n case 'attempting':\n return 'Attempting';\n case 'waiting':\n return 'Waiting';\n case 'success':\n return 'Success';\n case 'failed':\n return 'Failed';\n case 'cancelled':\n return 'Cancelled';\n default:\n return 'Idle';\n }\n }\n\n /**\n * Calculate progress percentage\n */\n private getProgressPercentage(): number {\n if (this.state.status !== 'waiting') return 0;\n\n const elapsed = Date.now() - (this.state.nextRetryTime - this.state.currentDelay);\n return Math.min(100, (elapsed / this.state.currentDelay) * 100);\n }\n\n /**\n * Render success message\n */\n private renderSuccessMessage(status: RetryStatus, attempt: number): string {\n if (status !== 'success') return '';\n\n const attemptText = attempt > 1 ? 's' : '';\n return `\n <div class=\"success-message\">\n <div class=\"success-icon\">🎉</div>\n <div class=\"success-text\">Success!</div>\n <div class=\"success-details\">Completed in ${attempt} attempt${attemptText}</div>\n </div>\n `;\n }\n\n /**\n * Render action buttons\n */\n private renderActions(\n status: RetryStatus,\n allowManualRetry: boolean,\n allowCancel: boolean,\n disabled: boolean\n ): string {\n if (status === 'success' || (!allowManualRetry && !allowCancel)) return '';\n\n const showRetryButton = allowManualRetry && (status === 'waiting' || status === 'failed');\n const showCancelButton = allowCancel && status !== 'cancelled' && status !== 'failed';\n\n if (!showRetryButton && !showCancelButton) return '';\n\n const retryButtonText = status === 'failed' ? 'Try Again' : 'Retry Now';\n const disabledAttr = disabled ? 'disabled' : '';\n\n let buttonsHtml = '';\n if (showRetryButton) {\n buttonsHtml += `\n <button class=\"retry-button\" id=\"manual-retry\" ${disabledAttr}>\n ${retryButtonText}\n </button>\n `;\n }\n if (showCancelButton) {\n buttonsHtml += `\n <button class=\"cancel-button\" id=\"cancel-btn\" ${disabledAttr}>\n Cancel\n </button>\n `;\n }\n\n return `\n <div class=\"actions\">\n ${buttonsHtml}\n </div>\n `;\n }\n\n /**\n * Sync config attributes to host element\n */\n private _syncAttributes(): void {\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n }\n\n /**\n * Get attempt counter HTML\n */\n private _getAttemptCounterHtml(\n showAttemptCount: boolean,\n attempt: number,\n maxAttempts: number,\n status: RetryStatus\n ): string {\n if (!showAttemptCount) {\n return '';\n }\n return `\n <div class=\"attempt-counter\">\n <div class=\"attempt-number ${status}\">${attempt}</div>\n <div class=\"attempt-label\">of ${maxAttempts} attempts</div>\n </div>\n `;\n }\n\n /**\n * Get metrics grid HTML\n */\n private _getMetricsGridHtml(\n showNextRetry: boolean,\n showElapsedTime: boolean,\n status: RetryStatus,\n remainingTime: number,\n elapsedTime: number,\n strategy: string\n ): string {\n const nextRetryHtml =\n showNextRetry && status === 'waiting'\n ? `\n <div class=\"metric\">\n <div class=\"metric-value\">${formatTime(Math.ceil(remainingTime / 1000))}</div>\n <div class=\"metric-label\">Next Retry</div>\n </div>\n `\n : '';\n\n const elapsedHtml =\n showElapsedTime && elapsedTime > 0\n ? `\n <div class=\"metric\">\n <div class=\"metric-value\">${formatTime(Math.ceil(elapsedTime / 1000))}</div>\n <div class=\"metric-label\">Elapsed</div>\n </div>\n `\n : '';\n\n return `\n <div class=\"metrics-grid\">\n ${nextRetryHtml}\n ${elapsedHtml}\n <div class=\"metric\">\n <div class=\"metric-value\">${strategy}</div>\n <div class=\"metric-label\">Strategy</div>\n </div>\n </div>\n `;\n }\n\n /**\n * Get progress bar HTML\n */\n private _getProgressBarHtml(\n showProgressBar: boolean,\n status: RetryStatus,\n progressPercentage: number\n ): string {\n if (!showProgressBar || status !== 'waiting') {\n return '';\n }\n return `\n <div class=\"progress-bar-container\">\n <div class=\"progress-label\">Time until next attempt</div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" style=\"width: ${progressPercentage}%\"></div>\n </div>\n </div>\n `;\n }\n\n /**\n * Get error display HTML\n */\n private _getErrorDisplayHtml(errorMessage: string | undefined, status: RetryStatus): string {\n if (!errorMessage || (status !== 'waiting' && status !== 'failed')) {\n return '';\n }\n return `\n <div class=\"error-display\">\n <div class=\"error-title\">Last Error</div>\n <div class=\"error-message\">${errorMessage}</div>\n </div>\n `;\n }\n\n /**\n * Attach event listeners to rendered elements\n */\n private _attachEventListeners(allowManualRetry: boolean, allowCancel: boolean): void {\n if (allowManualRetry) {\n const retryBtn = this.shadowRoot?.getElementById('manual-retry');\n retryBtn?.addEventListener('click', () => this.handleManualRetry());\n }\n\n if (allowCancel) {\n const cancelBtn = this.shadowRoot?.getElementById('cancel-btn');\n cancelBtn?.addEventListener('click', () => this.handleCancel());\n }\n }\n\n /**\n * Render component\n */\n protected override render(): void {\n if (!this.shadowRoot) return;\n\n this._syncAttributes();\n\n const { status, attempt, maxAttempts, message, errorMessage, elapsedTime } = this.state;\n const {\n showAttemptCount,\n showNextRetry,\n showProgressBar,\n showElapsedTime,\n allowManualRetry,\n allowCancel,\n disabled,\n } = this.config;\n\n const remainingTime = this.getTimeUntilRetry();\n const progressPercentage = this.getProgressPercentage();\n\n const attemptCounterHtml = this._getAttemptCounterHtml(\n showAttemptCount,\n attempt,\n maxAttempts,\n status\n );\n const metricsGridHtml = this._getMetricsGridHtml(\n showNextRetry,\n showElapsedTime,\n status,\n remainingTime,\n elapsedTime,\n this.config.strategy\n );\n const progressBarHtml = this._getProgressBarHtml(showProgressBar, status, progressPercentage);\n const errorDisplayHtml = this._getErrorDisplayHtml(errorMessage, status);\n const successMessageHtml = this.renderSuccessMessage(status, attempt);\n const actionsHtml = this.renderActions(status, allowManualRetry, allowCancel, disabled);\n\n this.shadowRoot.innerHTML = `\n <style>${styles}</style>\n <div class=\"retry-container ${disabled ? 'disabled' : ''}\" role=\"status\">\n <div class=\"retry-header\">\n <div class=\"retry-icon ${status}\">${this.getStatusIcon()}</div>\n <div class=\"retry-info\">\n <h3 class=\"retry-title\">${this.getStatusText()}</h3>\n <p class=\"retry-message\">${message}</p>\n </div>\n <span class=\"status-badge ${status}\">${this.getStatusText()}</span>\n </div>\n\n ${attemptCounterHtml}\n ${metricsGridHtml}\n ${progressBarHtml}\n ${errorDisplayHtml}\n ${successMessageHtml}\n ${actionsHtml}\n </div>\n `;\n\n this._attachEventListeners(allowManualRetry, allowCancel);\n }\n\n /**\n * Cleanup on disconnect\n */\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.stopTimers();\n }\n\n /**\n * Observed attributes\n */\n static get observedAttributes(): string[] {\n return [\n 'attempt',\n 'max-attempts',\n 'initial-delay',\n 'max-delay',\n 'backoff-multiplier',\n 'strategy',\n 'allow-manual-retry',\n 'allow-cancel',\n 'show-attempt-count',\n 'show-progress-bar',\n 'disabled',\n 'size',\n 'variant',\n 'animation',\n ];\n }\n\n /**\n * Handle attribute changes\n */\n protected override handleAttributeChange(\n name: string,\n _oldValue: string,\n newValue: string\n ): void {\n switch (name) {\n case 'attempt': {\n this.state.attempt = Number.parseInt(newValue, 10) || 1;\n break;\n }\n case 'max-attempts': {\n const maxAttempts = Number.parseInt(newValue, 10) || 3;\n this.state.maxAttempts = maxAttempts;\n this.config.maxAttempts = maxAttempts;\n break;\n }\n case 'initial-delay': {\n const initialDelay = Number.parseInt(newValue, 10);\n if (Number.isNaN(initialDelay) === false) this.config.initialDelay = initialDelay;\n break;\n }\n case 'max-delay': {\n const maxDelay = Number.parseInt(newValue, 10);\n if (Number.isNaN(maxDelay) === false) this.config.maxDelay = maxDelay;\n break;\n }\n case 'backoff-multiplier': {\n const multiplier = Number.parseFloat(newValue);\n if (Number.isNaN(multiplier) === false) this.config.backoffMultiplier = multiplier;\n break;\n }\n case 'strategy': {\n if (['exponential', 'linear', 'fixed', 'fibonacci'].includes(newValue)) {\n this.config.strategy = newValue as any;\n }\n break;\n }\n case 'allow-manual-retry': {\n this.config.allowManualRetry = newValue === 'true';\n break;\n }\n case 'allow-cancel': {\n this.config.allowCancel = newValue === 'true';\n break;\n }\n case 'show-attempt-count':\n this.config.showAttemptCount = newValue === 'true';\n break;\n case 'show-progress-bar':\n this.config.showProgressBar = newValue === 'true';\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n break;\n case 'size':\n this.config.size = newValue as any;\n break;\n }\n this.render();\n }\n}\n\n// Register custom element\nif (!customElements.get('retry-progress')) {\n customElements.define('retry-progress', RetryProgress);\n}\n","import { AIControl } from '../base/AIControl';\nimport type {\n BatchProgressConfig,\n BatchProgressState,\n BatchProgressUpdate,\n BatchItem,\n BatchItemStatus,\n BatchStartEvent,\n BatchItemUpdateEvent,\n BatchCompleteEvent,\n BatchCancelEvent,\n BatchItemCompleteEvent,\n BatchItemFailedEvent,\n} from './types';\nimport { styles } from './styles';\n\n/**\n * BatchProgress Component\n *\n * Displays progress for batch operations processing multiple items.\n * Perfect for processing multiple AI requests, documents, or images in parallel.\n *\n * @example\n * ```typescript\n * // Create batch progress\n * const batch = new BatchProgress({\n * totalItems: 50,\n * concurrency: 5,\n * showItems: true,\n * showStats: true\n * });\n *\n * document.body.appendChild(batch);\n *\n * // Start batch\n * batch.start();\n *\n * // Add items\n * for (let i = 0; i < 50; i++) {\n * batch.addItem(`item-${i}`, `Process item ${i}`);\n * }\n *\n * // Update item progress\n * batch.updateItem({\n * itemId: 'item-0',\n * status: 'processing',\n * progress: 50\n * });\n *\n * // Complete item\n * batch.completeItem('item-0', { result: 'success' });\n *\n * // Listen to events\n * batch.addEventListener('batchcomplete', (e) => {\n * console.log(`Completed ${e.detail.successCount}/${e.detail.totalItems}`);\n * });\n * ```\n *\n * @fires batchstart - Fired when batch processing starts\n * @fires itemupdate - Fired when batch item is updated\n * @fires itemcomplete - Fired when batch item completes\n * @fires itemfailed - Fired when batch item fails\n * @fires batchcomplete - Fired when all items are processed\n * @fires batchcancel - Fired when batch is cancelled\n */\nexport class BatchProgress extends AIControl {\n protected override config: Required<BatchProgressConfig>;\n private readonly state: BatchProgressState;\n private updateThrottleTimer: ReturnType<typeof setTimeout> | null = null;\n\n static get observedAttributes() {\n return ['total-items', 'disabled', 'size', 'variant', 'animation'];\n }\n\n constructor(config: BatchProgressConfig = {}) {\n super({\n debug: config.debug ?? false,\n className: config.className,\n ariaLabel: config.ariaLabel ?? 'Batch Progress',\n });\n\n this.config = {\n totalItems: config.totalItems ?? 0,\n concurrency: config.concurrency ?? 5,\n showItems: config.showItems ?? true,\n maxDisplayItems: config.maxDisplayItems ?? 100,\n showProgressBar: config.showProgressBar ?? true,\n showStats: config.showStats ?? true,\n showTime: config.showTime ?? true,\n showRate: config.showRate ?? true,\n allowCancel: config.allowCancel ?? true,\n cancelLabel: config.cancelLabel ?? 'Cancel Batch',\n collapseCompleted: config.collapseCompleted ?? false,\n message: config.message ?? 'Processing batch...',\n disabled: config.disabled ?? false,\n debug: config.debug ?? false,\n className: config.className ?? '',\n ariaLabel: config.ariaLabel ?? 'Batch Progress',\n cursorFeedback: config.cursorFeedback ?? true,\n size: config.size ?? 'default',\n variant: config.variant ?? 'default',\n animation: config.animation ?? 'none',\n };\n\n this.state = {\n status: 'idle',\n items: new Map(),\n totalItems: this.config.totalItems,\n completedCount: 0,\n failedCount: 0,\n successCount: 0,\n currentConcurrency: 0,\n startTime: null,\n endTime: null,\n message: this.config.message,\n };\n\n this.attachShadow({ mode: 'open' });\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.render();\n }\n\n override attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null\n ): void {\n if (oldValue === newValue) return;\n\n switch (name) {\n case 'total-items':\n this.state.totalItems = Number.parseInt(newValue || '0', 10);\n this.render();\n break;\n case 'disabled':\n this._disabled = newValue !== null;\n this.render();\n break;\n case 'size':\n this.config.size = newValue as any;\n this.render();\n break;\n case 'variant':\n this.config.variant = newValue as any;\n this.render();\n break;\n case 'animation':\n this.config.animation = newValue as any;\n this.render();\n break;\n }\n }\n\n /**\n * Update cursor based on component state\n */\n private updateCursor(): void {\n if (!this.config.cursorFeedback) return;\n\n if (this.state.status === 'processing') {\n this.style.cursor = 'progress';\n } else if (this.state.status === 'cancelled') {\n this.style.cursor = 'not-allowed';\n } else {\n this.style.cursor = 'default';\n }\n }\n\n /**\n * Start batch processing\n */\n public start(message?: string): void {\n if (this.config.disabled) return;\n\n this.state.status = 'processing';\n this.state.startTime = Date.now();\n this.state.message = message || this.config.message;\n this.state.completedCount = 0;\n this.state.failedCount = 0;\n this.state.successCount = 0;\n\n this.render();\n this.updateCursor();\n\n const event: BatchStartEvent = {\n totalItems: this.state.totalItems,\n startTime: this.state.startTime,\n };\n\n this.dispatchEvent(\n new CustomEvent('batchstart', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n\n this.log('Batch started', event);\n }\n\n /**\n * Add item to batch\n */\n public addItem(itemId: string, label?: string): void {\n const item: BatchItem = {\n id: itemId,\n label: label || itemId,\n status: 'pending',\n progress: 0,\n };\n\n this.state.items.set(itemId, item);\n this.state.totalItems = this.state.items.size;\n this.render();\n\n this.log('Item added', item);\n }\n\n /**\n * Update batch item\n */\n public updateItem(update: BatchProgressUpdate): void {\n const item = this.state.items.get(update.itemId);\n if (!item) {\n this.log(`Item not found: ${update.itemId}`);\n return;\n }\n\n if (update.status) item.status = update.status;\n if (update.progress !== undefined) item.progress = update.progress;\n if (update.error) item.error = update.error;\n if (update.result !== undefined) item.result = update.result;\n if (update.label) item.label = update.label;\n\n // Track status changes\n if (update.status === 'completed') {\n item.endTime = Date.now();\n this.state.completedCount++;\n if (!item.error) this.state.successCount++;\n } else if (update.status === 'failed') {\n item.endTime = Date.now();\n this.state.completedCount++;\n this.state.failedCount++;\n }\n\n this.throttledRender();\n\n const overallProgress = this.getOverallProgress();\n\n const event: BatchItemUpdateEvent = {\n ...item,\n totalCompleted: this.state.completedCount,\n totalFailed: this.state.failedCount,\n overallProgress,\n };\n\n this.dispatchEvent(\n new CustomEvent('itemupdate', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n\n // Check if batch is complete\n if (this.state.completedCount === this.state.totalItems && this.state.status === 'processing') {\n this.complete();\n }\n }\n\n /**\n * Complete a batch item\n */\n public completeItem(itemId: string, result?: any): void {\n this.updateItem({\n itemId,\n status: 'completed',\n progress: 100,\n result,\n });\n\n const item = this.state.items.get(itemId);\n if (!item) return;\n\n const event: BatchItemCompleteEvent = {\n item,\n totalCompleted: this.state.completedCount,\n remainingItems: this.state.totalItems - this.state.completedCount,\n };\n\n this.dispatchEvent(\n new CustomEvent('itemcomplete', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /**\n * Fail a batch item\n */\n public failItem(itemId: string, error: string): void {\n this.updateItem({\n itemId,\n status: 'failed',\n error,\n });\n\n const item = this.state.items.get(itemId);\n if (!item) return;\n\n const event: BatchItemFailedEvent = {\n item,\n error,\n totalFailed: this.state.failedCount,\n };\n\n this.dispatchEvent(\n new CustomEvent('itemfailed', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /**\n * Complete batch processing\n */\n public complete(): void {\n this.state.status = 'completed';\n this.state.endTime = Date.now();\n\n this.render();\n this.updateCursor();\n\n const duration = this.state.endTime - (this.state.startTime || 0);\n const averageRate = this.state.totalItems / (duration / 1000);\n\n const event: BatchCompleteEvent = {\n totalItems: this.state.totalItems,\n successCount: this.state.successCount,\n failedCount: this.state.failedCount,\n duration,\n averageRate,\n startTime: this.state.startTime!,\n endTime: this.state.endTime,\n };\n\n this.dispatchEvent(\n new CustomEvent('batchcomplete', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n\n this.log('Batch completed', event);\n }\n\n /**\n * Cancel batch processing\n */\n public cancel(reason?: string): void {\n this.state.status = 'cancelled';\n this.state.endTime = Date.now();\n\n // Cancel all pending items\n let cancelledCount = 0;\n this.state.items.forEach((item) => {\n if (item.status === 'pending' || item.status === 'processing') {\n item.status = 'cancelled';\n cancelledCount++;\n }\n });\n\n this.render();\n this.updateCursor();\n\n const event: BatchCancelEvent = {\n completedCount: this.state.completedCount,\n failedCount: this.state.failedCount,\n cancelledCount,\n reason,\n };\n\n this.dispatchEvent(\n new CustomEvent('batchcancel', {\n detail: event,\n bubbles: true,\n composed: true,\n })\n );\n\n this.log('Batch cancelled', event);\n }\n\n /**\n * Reset batch to initial state\n */\n public reset(): void {\n this.state.status = 'idle';\n this.state.items.clear();\n this.state.totalItems = this.config.totalItems;\n this.state.completedCount = 0;\n this.state.failedCount = 0;\n this.state.successCount = 0;\n this.state.currentConcurrency = 0;\n this.state.startTime = null;\n this.state.endTime = null;\n this.state.message = this.config.message;\n\n this.render();\n this.log('Batch reset');\n }\n\n /**\n * Get overall progress percentage\n */\n public getOverallProgress(): number {\n if (this.state.totalItems === 0) return 0;\n return (this.state.completedCount / this.state.totalItems) * 100;\n }\n\n /**\n * Get processing rate (items/second)\n */\n public getRate(): number {\n if (!this.state.startTime || this.state.completedCount === 0) return 0;\n const elapsed = (Date.now() - this.state.startTime) / 1000;\n return this.state.completedCount / elapsed;\n }\n\n /**\n * Get batch statistics\n */\n public getStats() {\n return {\n total: this.state.totalItems,\n completed: this.state.completedCount,\n success: this.state.successCount,\n failed: this.state.failedCount,\n pending: this.state.totalItems - this.state.completedCount,\n progress: this.getOverallProgress(),\n rate: this.getRate(),\n duration: this._calculateDuration(),\n };\n }\n\n /**\n * Throttled render to avoid excessive updates\n */\n private throttledRender(): void {\n if (this.updateThrottleTimer) return;\n\n this.updateThrottleTimer = globalThis.setTimeout(() => {\n this.render();\n this.updateThrottleTimer = null;\n }, 100);\n }\n\n /**\n * Calculate duration based on state\n */\n private _calculateDuration(): number {\n if (this.state.endTime) {\n return this.state.endTime - (this.state.startTime || 0);\n }\n if (this.state.startTime) {\n return Date.now() - this.state.startTime;\n }\n return 0;\n }\n\n /**\n * Get rate display HTML\n */\n private _getRateDisplay(rate: number): string {\n if (!this.config.showRate) {\n return '';\n }\n return `\n <div class=\"stat-item\">\n <span class=\"stat-label\">Rate</span>\n <span class=\"stat-value rate\">${rate.toFixed(1)}/s</span>\n </div>\n `;\n }\n\n /**\n * Sync config attributes to host element\n */\n private _syncAttributes(): void {\n if (this.config.size && this.getAttribute('size') !== this.config.size) {\n this.setAttribute('size', this.config.size);\n }\n if (this.config.variant && this.getAttribute('variant') !== this.config.variant) {\n this.setAttribute('variant', this.config.variant);\n }\n if (this.config.animation && this.getAttribute('animation') !== this.config.animation) {\n this.setAttribute('animation', this.config.animation);\n }\n }\n\n /**\n * Get status badge CSS class\n */\n private _getStatusBadgeClass(status: string): string {\n switch (status) {\n case 'processing':\n return 'processing';\n case 'completed':\n return 'completed';\n case 'cancelled':\n return 'cancelled';\n default:\n return '';\n }\n }\n\n /**\n * Get status display text\n */\n private _getStatusText(status: string): string {\n switch (status) {\n case 'idle':\n return 'Ready';\n case 'processing':\n return 'Processing';\n case 'completed':\n return 'Completed';\n case 'cancelled':\n return 'Cancelled';\n default:\n return '';\n }\n }\n\n /**\n * Get stats section HTML\n */\n private _getStatsHtml(stats: ReturnType<typeof this.getStats>, rate: number): string {\n if (!this.config.showStats) {\n return '';\n }\n return `\n <div class=\"stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total</span>\n <span class=\"stat-value\">${stats.total}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Success</span>\n <span class=\"stat-value success\">${stats.success}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Failed</span>\n <span class=\"stat-value error\">${stats.failed}</span>\n </div>\n ${this._getRateDisplay(rate)}\n </div>\n `;\n }\n\n /**\n * Get progress bar HTML\n */\n private _getProgressBarHtml(\n overallProgress: number,\n stats: ReturnType<typeof this.getStats>\n ): string {\n if (!this.config.showProgressBar) {\n return '';\n }\n return `\n <div class=\"overall-progress\">\n <div class=\"progress-header\">\n <span>Overall Progress</span>\n <span>${stats.completed} / ${stats.total} (${overallProgress.toFixed(0)}%)</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" style=\"width: ${overallProgress}%\"></div>\n </div>\n </div>\n `;\n }\n\n /**\n * Get controls HTML\n */\n private _getControlsHtml(): string {\n if (!this.config.allowCancel || this.state.status !== 'processing') {\n return '';\n }\n const disabledAttr = this.config.disabled ? 'disabled' : '';\n return `\n <div class=\"controls\">\n <button class=\"cancel-btn\" id=\"cancel-btn\" ${disabledAttr}>\n ${this.config.cancelLabel}\n </button>\n </div>\n `;\n }\n\n /**\n * Attach event listeners to rendered elements\n */\n private _attachEventListeners(): void {\n if (!this.config.allowCancel) return;\n\n const cancelBtn = this.shadowRoot?.getElementById('cancel-btn');\n if (cancelBtn) {\n cancelBtn.addEventListener('click', () => this.cancel('User cancelled'));\n }\n }\n\n /**\n * Render the component\n */\n protected render(): void {\n if (!this.shadowRoot) return;\n\n this._syncAttributes();\n\n const overallProgress = this.getOverallProgress();\n const rate = this.getRate();\n const stats = this.getStats();\n const statusBadgeClass = this._getStatusBadgeClass(this.state.status);\n const statusText = this._getStatusText(this.state.status);\n\n const statsHtml = this._getStatsHtml(stats, rate);\n const progressHtml = this._getProgressBarHtml(overallProgress, stats);\n const itemsHtml = this.config.showItems ? this.renderItems() : '';\n const controlsHtml = this._getControlsHtml();\n\n this.shadowRoot.innerHTML = `\n <style>${styles}</style>\n <div class=\"container\">\n <div class=\"header\">\n <div class=\"status-message\">${this.state.message}</div>\n ${statusBadgeClass ? `<span class=\"status-badge ${statusBadgeClass}\">${statusText}</span>` : ''}\n </div>\n ${statsHtml}\n ${progressHtml}\n ${itemsHtml}\n ${controlsHtml}\n </div>\n `;\n\n this._attachEventListeners();\n }\n\n /**\n * Render batch items\n */\n private renderItems(): string {\n if (this.state.items.size === 0) {\n return `\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">📦</div>\n <div>No items in batch</div>\n </div>\n `;\n }\n\n const items = Array.from(this.state.items.values());\n const displayItems = items.slice(0, this.config.maxDisplayItems);\n\n const itemsHtml = displayItems\n .map((item) => {\n const statusIcon = this.getStatusIcon(item.status);\n const collapsed =\n this.config.collapseCompleted && item.status === 'completed' ? 'collapsed' : '';\n\n const progressBarHtml =\n item.status === 'processing' && item.progress !== undefined\n ? `\n <div class=\"item-progress-bar\">\n <div class=\"item-progress-fill\" style=\"width: ${item.progress}%\"></div>\n </div>\n `\n : '';\n\n const errorHtml = item.error\n ? `\n <div class=\"item-error\">\n ${item.error}\n </div>\n `\n : '';\n\n return `\n <div class=\"batch-item ${item.status} ${collapsed}\">\n <div class=\"item-header\">\n <span class=\"item-label\">${item.label || item.id}</span>\n <span class=\"item-status ${item.status}\">\n <span class=\"item-status-icon\">${statusIcon}</span>\n ${item.status}\n </span>\n </div>\n ${progressBarHtml}\n ${errorHtml}\n </div>\n `;\n })\n .join('');\n\n return `\n <div class=\"items-container\">\n ${itemsHtml}\n </div>\n `;\n }\n\n /**\n * Get status icon\n */\n private getStatusIcon(status: BatchItemStatus): string {\n switch (status) {\n case 'pending':\n return '⏳';\n case 'processing':\n return '<span class=\"spinner\"></span>';\n case 'completed':\n return '✅';\n case 'failed':\n return '❌';\n case 'cancelled':\n return '⛔';\n default:\n return '';\n }\n }\n\n /**\n * Get/set disabled state\n */\n override get disabled(): boolean {\n return this.config.disabled;\n }\n\n override set disabled(value: boolean) {\n this.config.disabled = value;\n if (value) {\n this.setAttribute('disabled', '');\n } else {\n this.removeAttribute('disabled');\n }\n this.render();\n }\n}\n\n// Define custom element\nif (!customElements.get('batch-progress')) {\n customElements.define('batch-progress', BatchProgress);\n}\n"],"names":["AIControl","HTMLElement","constructor","config","super","__publicField","this","debug","disabled","_disabled","connectedCallback","log","applyTheme","setupAccessibility","render","disconnectedCallback","cleanup","attributeChangedCallback","name","oldValue","newValue","handleAttributeChange","theme","root","_a","shadowRoot","host","Object","entries","forEach","key","value","cssVarName","replaceAll","toLowerCase","style","setProperty","getAttribute","setAttribute","getDefaultRole","ariaLabel","emit","eventName","detail","event","CustomEvent","bubbles","composed","dispatchEvent","message","args","console","logError","error","startTimer","startTime","Date","now","getElapsedTime","formatNumber","num","toFixed","toString","formatDuration","ms","seconds","Math","floor","minutes","hours","calculatePercentage","current","total","min","max","removeAttribute","_name","_oldValue","_newValue","throttle","func","limit","inThrottle","apply","setTimeout","clamp","formatBytes","bytes","decimals","dm","i","Number","parseFloat","pow","formatCurrency","amount","formatTime","round","remainingSeconds","remainingMinutes","StreamProgress","className","maxTokens","costPerToken","currency","showRate","showCost","showProgressBar","showCancelButton","smoothProgress","updateThrottle","cancelLabel","cursorFeedback","size","variant","animation","state","tokensGenerated","tokensPerSecond","totalCost","isStreaming","isPaused","isCancelled","lastUpdateTime","updateThrottled","_updateInternal","bind","attachShadow","mode","observedAttributes","animationFrame","cancelAnimationFrame","updateCursor","cursor","parseInt","start","displayTokens","update","timeDiff","tokenDiff","animateProgress","animate","diff","abs","requestAnimationFrame","complete","duration","averageRate","cancel","reason","reset","_syncAttributes","_getProgressBarHtml","percentage","_getStatsHtml","tokensDisplay","rateDisplay","costDisplay","rateHtml","costHtml","_getCancelButtonHtml","_getStatusClass","_attachEventListeners","cancelBtn","querySelector","addEventListener","progressBarHtml","statsHtml","messageHtml","cancelButtonHtml","statusClass","innerHTML","getState","getConfig","customElements","get","define","ModelLoader","stages","modelName","showBytes","showMemoryUsage","showETA","showRetryButton","retryLabel","currentStage","download","status","progress","load","initialize","ready","isLoading","hasError","_updateStageInternal","initialMessage","resetStages","firstStage","stage","timestamp","updateStage","bytesLoaded","totalBytes","memoryUsage","calculatedProgress","currentStageState","updatedStage","setStage","options","includes","previousStage","prevStageState","endTime","newStageState","completeStage","nextMessage","currentStageIndex","indexOf","nextStage","completedStages","stageState","errorStage","errorStageState","errorMessage","Error","retry","getStageIcon","calculateETA","elapsed","totalStages","length","currentProgress","effectiveProgress","remaining","getOverallStatus","getStatusBadgeText","overallStatus","generateStagesHtml","map","icon","progressText","join","generateStatsHtml","statsItems","push","statusBadgeText","stagesHtml","errorHtml","retryButtonHtml","retryBtn","ParameterSlider","label","e","isDragging","sliderTrack","rect","getBoundingClientRect","percent","clientX","left","width","setValue","sliderThumb","classList","remove","document","removeEventListener","handleThumbMouseMove","handleThumbMouseUp","preventDefault","touch","touches","handleThumbTouchMove","handleThumbTouchEnd","defaultValue","step","description","showPresets","presets","showInput","showReset","showRangeLabels","unit","currentValue","isFocused","attachEventListeners","removeEventListeners","getValue","source","previousValue","clampedValue","steppedValue","finalValue","updateSliderPosition","selectPreset","preset","handleTrackClick","handleThumbMouseDown","handleThumbTouchStart","passive","handleThumbKeyDown","input","handleInputChange","handleInputBlur","resetBtn","querySelectorAll","btn","index","add","delta","largeStep","target","isNaN","fill","valueDisplay","textContent","activeElement","updateActivePreset","renderInputControls","disabledAttr","controlsHtml","disabledClass","headerHtml","sliderHtml","presetsHtml","inputHtml","ParameterPanel","Map","panelConfig","parameters","param","parameterDefinitions","set","id","isBuiltIn","initialValues","values","activePreset","isCollapsed","Boolean","collapsible","startCollapsed","errors","isDirty","persistValues","loadFromStorage","persistPresets","loadPresetsFromStorage","getAllValues","parameterId","paramDef","validateOnChange","validate","validationResult","dispatchValidationError","slider","sliderSource","saveToStorage","emitChangeEvents","dispatchPanelChange","loadPreset","presetId","previousValues","has","dispatchPresetLoad","resetAll","dispatchPanelReset","exportConfig","_","version","metadata","created","toISOString","title","dispatchConfigExport","importConfig","dispatchConfigImport","toggleCollapse","validateAll","isValid","addPreset","savePresetsToStorage","removePreset","delete","allValues","format","newValues","data","localStorage","setItem","storageKey","JSON","stringify","getItem","parsed","parse","customPresets","Array","from","filter","reduce","acc","hasErrors","keys","columns","renderHeader","renderErrors","renderPresets","renderParameters","showResetAll","showExportImport","renderActions","createParameterSliders","collapsedClass","showTitle","errorEntries","layout","header","getElementById","dataset","exportBtn","handleExport","importBtn","handleImport","clear","wrapper","stopPropagation","appendChild","json","blob","Blob","type","url","URL","createObjectURL","a","createElement","href","click","revokeObjectURL","accept","onchange","file","files","text","then","catch","QueueProgress","position","queueSize","estimatedWait","processingRate","showPosition","showWaitTime","showQueueSize","elapsedTime","initialPosition","stopTimer","previousPosition","positionEl","currentPosition","totalWaitTime","startPosition","getPosition","getStatus","timerInterval","globalThis","setInterval","clearInterval","getProgressPercentage","processed","renderMetrics","metricsHtml","statusText","getStatusText","getStatusIcon","RetryProgress","attempt","maxAttempts","initialDelay","maxDelay","backoffMultiplier","strategy","showAttemptCount","showNextRetry","showElapsedTime","allowManualRetry","allowCancel","currentDelay","nextRetryTime","_readMaxAttemptsAttribute","hasAttribute","val","_readInitialDelayAttribute","_readMaxDelayAttribute","_readBackoffMultiplierAttribute","_readStrategyAttribute","_readBooleanAttributes","calculateDelay","delay","fibonacci","n","b","stopTimers","attemptMessage","setState","startElapsedTimer","waitForRetry","nextAttempt","failure","ceil","lastError","startWaitTimer","startProgressTimer","success","successMessage","totalAttempts","getAttempt","getTimeUntilRetry","elapsedTimer","waitTimer","_totalDelay","progressTimer","clearTimeout","handleManualRetry","handleCancel","assign","renderSuccessMessage","buttonsHtml","_getAttemptCounterHtml","_getMetricsGridHtml","remainingTime","progressPercentage","_getErrorDisplayHtml","_b","attemptCounterHtml","metricsGridHtml","errorDisplayHtml","successMessageHtml","actionsHtml","multiplier","BatchProgress","totalItems","concurrency","showItems","maxDisplayItems","showStats","showTime","collapseCompleted","items","completedCount","failedCount","successCount","currentConcurrency","addItem","itemId","item","updateItem","result","throttledRender","overallProgress","getOverallProgress","totalCompleted","totalFailed","completeItem","remainingItems","failItem","cancelledCount","getRate","getStats","completed","failed","pending","rate","_calculateDuration","updateThrottleTimer","_getRateDisplay","_getStatusBadgeClass","_getStatusText","stats","_getControlsHtml","statusBadgeClass","progressHtml","itemsHtml","renderItems","slice","statusIcon","collapsed","css","wait","timeout","t","prefix","random","element","top","bottom","innerHeight","documentElement","clientHeight","right","innerWidth","clientWidth","end","color","div","body","computedColor","getComputedStyle","match","exec","r","g","matchMedia","matches"],"mappings":"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"}
|