aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
460 lines (457 loc) • 13.2 kB
JavaScript
import { detectDevice } from './deviceCapabilities.js';
/**
* Production utilities for AuraGlass components
* These utilities are optimized for production environments
*/
// === Environment Detection ===
const isProduction = () => {
return process.env.NODE_ENV === 'production';
};
const isDevelopment = () => {
return process.env.NODE_ENV === 'development';
};
// === Logging Utilities ===
const logger = {
error: (message, ...args) => {
if (isDevelopment()) {
console.error(`[AuraGlass Error]: ${message}`, ...args);
}
},
warn: (message, ...args) => {
if (isDevelopment()) {
console.warn(`[AuraGlass Warning]: ${message}`, ...args);
}
},
info: (message, ...args) => {
if (isDevelopment()) {
console.info(`[AuraGlass Info]: ${message}`, ...args);
}
},
debug: (message, ...args) => {
if (isDevelopment()) {
console.debug(`[AuraGlass Debug]: ${message}`, ...args);
}
}
};
// === Performance Utilities ===
const performance = {
measure: (name, fn) => {
if (!isDevelopment()) {
fn();
return 0;
}
const start = Date.now();
fn();
const end = Date.now();
const duration = end - start;
logger.debug(`Performance: ${name} took ${duration}ms`);
return duration;
},
measureAsync: async (name, fn) => {
if (!isDevelopment()) {
await fn();
return 0;
}
const start = Date.now();
await fn();
const end = Date.now();
const duration = end - start;
logger.debug(`Performance: ${name} took ${duration}ms`);
return duration;
}
};
// === Error Handling ===
const safeExecute = (fn, fallback, errorMessage) => {
try {
return fn();
} catch (error) {
logger.error(errorMessage || 'Safe execution failed', error);
return fallback;
}
};
const safeExecuteAsync = async (fn, fallback, errorMessage) => {
try {
return await fn();
} catch (error) {
logger.error(errorMessage || 'Safe async execution failed', error);
return fallback;
}
};
// === Feature Detection ===
const features = {
supportsIntersectionObserver: () => {
return typeof IntersectionObserver !== 'undefined';
},
supportsResizeObserver: () => {
return typeof ResizeObserver !== 'undefined';
},
supportsBackdropFilter: () => {
if (typeof CSS === 'undefined') return false;
return CSS.supports('backdrop-filter', 'blur(1px)') || CSS.supports('-webkit-backdrop-filter', 'blur(1px)');
},
supportsWebGL: () => {
if (typeof window === 'undefined') return false;
// Use cached device detection to avoid creating contexts repeatedly
return detectDevice().capabilities.webgl;
},
supportsWebP: () => {
if (typeof CSS === 'undefined') return false;
return CSS.supports('image-format', 'webp');
},
supportsAVIF: () => {
if (typeof CSS === 'undefined') return false;
return CSS.supports('image-format', 'avif');
},
supportsContainerQueries: () => {
if (typeof CSS === 'undefined') return false;
return CSS.supports('container-type', 'inline-size');
}
};
// === Memory Management ===
const memory = {
cleanup: refs => {
refs.forEach(ref => {
if (ref.current) {
ref.current = null;
}
});
},
debounce: (func, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(null, args), wait);
};
},
throttle: (func, limit) => {
let inThrottle;
return (...args) => {
if (!inThrottle) {
func.apply(null, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
};
// === Validation ===
const validate = {
isValidHexColor: color => {
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
},
isValidRgbaColor: color => {
return /^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+)?\s*\)$/.test(color);
},
isValidCSSUnit: value => {
return /^-?\d+(\.\d+)?(px|em|rem|%|vh|vw|vmin|vmax|ch|ex)$/.test(value);
},
isValidEmail: email => {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
},
isValidUrl: url => {
try {
new URL(url);
return true;
} catch {
return false;
}
}
};
// === Data Utilities ===
const data = {
generateId: (prefix = 'glass') => {
return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
},
deepClone: obj => {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Array) return obj.map(data.deepClone);
if (typeof obj === 'object') {
const cloned = {};
for (const key in obj) {
cloned[key] = data.deepClone(obj[key]);
}
return cloned;
}
return obj;
},
isEqual: (a, b) => {
if (a === b) return true;
if (a == null || b == null) return false;
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((val, index) => data.isEqual(val, b[index]));
}
if (typeof a === 'object' && typeof b === 'object') {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
return keysA.every(key => data.isEqual(a[key], b[key]));
}
return false;
},
omit: (obj, keys) => {
const result = {
...obj
};
keys.forEach(key => delete result[key]);
return result;
},
pick: (obj, keys) => {
const result = {};
keys.forEach(key => {
if (key in obj) {
result[key] = obj[key];
}
});
return result;
}
};
// === CSS Utilities ===
const css = {
classNames: (...classes) => {
return classes.filter(Boolean).join(' ');
},
mergeStyles: (...styles) => {
return styles.filter(style => style !== undefined).reduce((merged, style) => ({
...merged,
...style
}), {});
},
pxToRem: (px, baseFontSize = 16) => {
return `${px / baseFontSize}rem`;
},
hexToRgba: (hex, alpha) => {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
};
// === Browser Utilities ===
const browser = {
isChrome: () => {
return /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
},
isFirefox: () => {
return /Firefox/.test(navigator.userAgent);
},
isSafari: () => {
return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
},
isEdge: () => {
return /Edg/.test(navigator.userAgent);
},
isMobile: () => {
return /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
},
isTouch: () => {
return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
},
getViewportSize: () => {
return {
width: window.innerWidth,
height: window.innerHeight
};
},
getDevicePixelRatio: () => {
return window.devicePixelRatio || 1;
}
};
// === Storage Utilities ===
const storage = {
set: (key, value) => {
safeExecute(() => {
localStorage.setItem(key, JSON.stringify(value));
}, undefined, `Failed to save to localStorage: ${key}`);
},
get: (key, fallback) => {
return safeExecute(() => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : fallback;
}, fallback, `Failed to read from localStorage: ${key}`);
},
remove: key => {
safeExecute(() => {
localStorage.removeItem(key);
}, undefined, `Failed to remove from localStorage: ${key}`);
},
clear: () => {
safeExecute(() => {
localStorage.clear();
}, undefined, 'Failed to clear localStorage');
}
};
// === Analytics Utilities ===
const analytics = {
track: (event, properties) => {
if (isProduction()) {
// Integration point for analytics service
// Example: analyticsService.track(event, properties);
safeExecute(() => {
// Your analytics implementation here
if (isDevelopment()) {
logger.debug(`Analytics: ${event}`, properties);
}
}, undefined, `Failed to track analytics event: ${event}`);
}
},
page: (page, properties) => {
if (isProduction()) {
// Integration point for page tracking
// Example: analyticsService.page(page, properties);
safeExecute(() => {
// Your page tracking implementation here
if (isDevelopment()) {
logger.debug(`Page: ${page}`, properties);
}
}, undefined, `Failed to track page view: ${page}`);
}
},
identify: (userId, traits) => {
if (isProduction()) {
// Integration point for user identification
// Example: analyticsService.identify(userId, traits);
safeExecute(() => {
// Your user identification implementation here
if (isDevelopment()) {
logger.debug(`Identify: ${userId}`, traits);
}
}, undefined, `Failed to identify user: ${userId}`);
}
}
};
// === Production Configuration ===
const productionConfig = {
// Error reporting configuration
errorReporting: {
enabled: isProduction(),
endpoint: process.env.REACT_APP_ERROR_ENDPOINT || '',
apiKey: process.env.REACT_APP_ERROR_API_KEY || '',
maxRetries: 3,
retryDelay: 1000
},
// Analytics configuration
analytics: {
enabled: isProduction(),
trackingId: process.env.REACT_APP_ANALYTICS_ID || '',
sampleRate: 1.0,
enableAutoPageTracking: true
},
// Performance configuration
performance: {
enableMonitoring: isProduction(),
sampleRate: 0.1,
// Monitor 10% of sessions
thresholds: {
renderTime: 16,
// 60fps
memoryUsage: 0.8,
// 80% of available memory
bundleSize: 150 * 1024 // 150KB
}
},
// Feature flags
features: {
enableAdvancedAnimations: true,
enableVirtualization: true,
enableLazyLoading: true,
enableA11yAuditing: isDevelopment(),
enablePerformanceMonitoring: true
}
};
// === Health Checks ===
const health = {
checkGlassSupport: () => {
const issues = [];
if (!features.supportsBackdropFilter()) {
issues.push('Backdrop filter not supported');
}
if (!features.supportsIntersectionObserver()) {
issues.push('Intersection Observer not supported');
}
if (!features.supportsResizeObserver()) {
issues.push('Resize Observer not supported');
}
return {
supported: issues.length === 0,
issues
};
},
checkPerformance: () => {
const recommendations = [];
let score = 100;
// Check device capabilities
if (!features.supportsWebGL()) {
score -= 20;
recommendations.push('Enable GPU acceleration for better performance');
}
if (browser.isMobile()) {
score -= 10;
recommendations.push('Consider reduced effects for mobile devices');
}
// Check memory
const memory = performance.memory;
if (memory && memory.usedJSHeapSize / memory.jsHeapSizeLimit > 0.8) {
score -= 30;
recommendations.push('High memory usage detected - enable virtualization');
}
return {
score,
recommendations
};
}
};
// === Production Initialization ===
const initializeProduction = () => {
if (!isProduction()) return;
// Set up error handling
window.addEventListener('error', event => {
logger.error('Unhandled error:', event.error);
});
window.addEventListener('unhandledrejection', event => {
logger.error('Unhandled promise rejection:', event.reason);
});
// Check glass support
const glassSupport = health.checkGlassSupport();
if (!glassSupport.supported) {
logger.warn('Glass effects may not work properly:', glassSupport.issues);
}
// Check performance
const performanceCheck = health.checkPerformance();
if (performanceCheck.score < 70) {
logger.warn('Performance issues detected:', performanceCheck.recommendations);
}
logger.info('AuraGlass production mode initialized');
};
// === Development Helpers ===
const dev = {
logComponentRender: (componentName, props) => {
if (isDevelopment()) {
logger.debug(`Render: ${componentName}`, props);
}
},
logPerformanceWarning: (componentName, metric, value, threshold) => {
if (isDevelopment() && value > threshold) {
logger.warn(`Performance: ${componentName} ${metric} (${value}) exceeds threshold (${threshold})`);
}
},
validateProps: (props, schema) => {
if (!isDevelopment()) return true;
const errors = [];
Object.entries(schema).forEach(([key, validator]) => {
const value = props[key];
const validatorFn = validator;
if (value !== undefined && !validatorFn(value)) {
errors.push(`Invalid prop: ${key}`);
}
});
if (errors.length > 0) {
logger.error('Prop validation failed:', errors);
return false;
}
return true;
}
};
export { analytics, browser, css, data, dev, features, health, initializeProduction, isDevelopment, isProduction, logger, memory, performance, productionConfig, safeExecute, safeExecuteAsync, storage, validate };
//# sourceMappingURL=productionUtils.js.map