import { VersionManager } from './version-manager'; export interface FallbackStrategy { feature: string; fallbacks: Array<{ condition: () => boolean; implementation: string; quality: 'native' | 'polyfill' | 'graceful' | 'minimal'; }>; } /** * Manages fallbacks for features with limited or inconsistent browser support. */ export class FeatureFallbackManager { private versionManager = VersionManager.getInstance(); private strategies: FallbackStrategy[] = [ { feature: 'houdini-paint', fallbacks: [ { condition: () => this.versionManager.isFeatureSupported('houdiniPaint'), implementation: 'native', quality: 'native' }, { condition: () => typeof CSS !== 'undefined' && CSS.supports('background: conic-gradient(red, blue)'), implementation: 'css-gradients-advanced', quality: 'graceful' }, { condition: () => typeof CSS !== 'undefined' && CSS.supports('background: linear-gradient(red, blue)'), implementation: 'css-gradients-basic', quality: 'minimal' } ] }, { feature: 'anchor-positioning', fallbacks: [ { condition: () => this.versionManager.isFeatureSupported('anchorPositioning'), implementation: 'native', quality: 'native' }, { condition: () => typeof window !== 'undefined' && 'ResizeObserver' in window, implementation: 'js-positioning-observer', quality: 'polyfill' }, { condition: () => true, implementation: 'absolute-positioning', quality: 'minimal' } ] }, { feature: 'view-transitions', fallbacks: [ { condition: () => this.versionManager.isFeatureSupported('viewTransitions'), implementation: 'native', quality: 'native' }, { condition: () => typeof CSS !== 'undefined' && CSS.supports('animation: fade 1s'), implementation: 'css-transitions', quality: 'graceful' }, { condition: () => true, implementation: 'instant-change', quality: 'minimal' } ] } ]; getBestFallback(feature: string): { implementation: string; quality: string } | null { const strategy = this.strategies.find(s => s.feature === feature); if (!strategy) return null; for (const fallback of strategy.fallbacks) { if (fallback.condition()) { return { implementation: fallback.implementation, quality: fallback.quality }; } } return null; } getFeatureReport(): Record { const report: Record = {}; for (const strategy of this.strategies) { const fallback = this.getBestFallback(strategy.feature); if (fallback) { report[strategy.feature] = { available: fallback.implementation, quality: fallback.quality }; } } return report; } /** * Generates CSS with automatic fallbacks based on browser support. */ generateFallbackCSS(feature: string, nativeCSS: string, fallbackCSS: string): string { const fallback = this.getBestFallback(feature); if (!fallback || fallback.quality === 'native') { return nativeCSS; } if (fallback.quality === 'minimal') { return fallbackCSS; } // For polyfills and graceful degradation, use both return `${fallbackCSS}\n${nativeCSS}`; } /** * Applies specific strategies for Houdini Paint worklets. */ getHoudiniPaintFallback(paintName: string): string { const fallback = this.getBestFallback('houdini-paint'); if (fallback?.implementation === 'native') { return `paint(${paintName})`; } // Professional fallbacks for all FluentGrow worklets switch (paintName) { case 'ripple': return 'radial-gradient(circle, rgba(255,255,255,0.3) 0%, transparent 70%)'; case 'wave': return 'linear-gradient(180deg, rgba(0, 120, 212, 0.1) 0%, rgba(0, 120, 212, 0) 100%)'; case 'noise': return 'url("data:image/svg+xml,%3Csvg viewBox=\'0 0 200 200\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cfilter id=\'noiseFilter\'%3E%3CfeTurbulence type=\'fractalNoise\' baseFrequency=\'0.65\' numOctaves=\'3\' stitchTiles=\'stitch\'/%3E%3C/filter%3E%3Crect width=\'100%25\' height=\'100%25\' filter=\'url(%23noiseFilter)\'/%3E%3C/svg%3E")'; case 'smooth-corners': return 'border-radius: 20%'; case 'glass-blur': return 'blur(20px)'; case 'gradient-mesh': return 'linear-gradient(45deg, #0078d4, #50e6ff, #00188f)'; default: return 'transparent'; } } }