aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
558 lines (555 loc) • 16.6 kB
JavaScript
'use client';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { useReducedMotion, useInView, AnimatePresence, motion } from 'framer-motion';
import React, { useState, useEffect, useRef, useMemo, createContext, useContext } from 'react';
import { cn } from '../../lib/utilsComprehensive.js';
import { createGlassStyle } from '../../core/mixins/glassMixins.js';
const PerformanceContext = /*#__PURE__*/createContext(null);
function GlassPerformanceProvider({
children,
adaptivePerformance = true
}) {
const [performanceMode, setPerformanceMode] = useState('balanced');
const [batteryLevel, setBatteryLevel] = useState();
const [cpuLoad, setCpuLoad] = useState(0);
const [gpuAcceleration, setGpuAcceleration] = useState(true);
const [lazyLoading, setLazyLoading] = useState(true);
const reducedMotion = useReducedMotion() || false;
// Battery API monitoring
useEffect(() => {
if (typeof navigator !== 'undefined' && 'getBattery' in navigator) {
navigator.getBattery().then(battery => {
const updateBatteryInfo = () => {
setBatteryLevel(Math.round(battery.level * 100));
};
updateBatteryInfo();
battery.addEventListener('levelchange', updateBatteryInfo);
battery.addEventListener('chargingchange', updateBatteryInfo);
return () => {
battery.removeEventListener('levelchange', updateBatteryInfo);
battery.removeEventListener('chargingchange', updateBatteryInfo);
};
});
}
}, []);
// CPU load estimation (simplified)
useEffect(() => {
let frameCount = 0;
let lastTime = performance.now();
const measurePerformance = () => {
frameCount++;
const currentTime = performance.now();
if (currentTime - lastTime >= 1000) {
const fps = Math.round(frameCount * 1000 / (currentTime - lastTime));
const load = Math.max(0, Math.min(100, 100 - fps / 60 * 100));
setCpuLoad(load);
frameCount = 0;
lastTime = currentTime;
}
requestAnimationFrame(measurePerformance);
};
const animationFrame = requestAnimationFrame(measurePerformance);
return () => cancelAnimationFrame(animationFrame);
}, []);
// Adaptive performance adjustments
useEffect(() => {
if (!adaptivePerformance) return;
let newMode = performanceMode;
// Battery-based adjustments
if (batteryLevel !== undefined && batteryLevel < 20) {
newMode = 'battery-saver';
} else if (batteryLevel !== undefined && batteryLevel > 80 && cpuLoad < 30) {
newMode = 'high';
} else {
newMode = 'balanced';
}
// CPU load adjustments
if (cpuLoad > 70) {
newMode = 'battery-saver';
setGpuAcceleration(false);
} else if (cpuLoad < 30) {
setGpuAcceleration(true);
}
if (newMode !== performanceMode) {
setPerformanceMode(newMode);
}
}, [batteryLevel, cpuLoad, adaptivePerformance, performanceMode]);
const contextValue = {
performanceMode,
gpuAcceleration,
reducedMotion,
lazyLoading,
setPerformanceMode,
batteryLevel,
cpuLoad
};
return jsx(PerformanceContext.Provider, {
value: contextValue,
children: children
});
}
function useGlassPerformance() {
const context = useContext(PerformanceContext);
if (!context) {
throw new Error('useGlassPerformance must be used within a GlassPerformanceProvider');
}
return context;
}
function EfficientGlassRendering({
children,
className = '',
enableGPU = true,
virtualizeContent = false,
deferRender = false,
renderDistance = 100,
style = {}
}) {
const {
performanceMode,
gpuAcceleration
} = useGlassPerformance();
const [isVisible, setIsVisible] = useState(!deferRender);
const containerRef = useRef(null);
const isInView = useInView(containerRef, {
margin: `${renderDistance}px`,
once: false
});
useEffect(() => {
if (deferRender) {
setIsVisible(isInView);
}
}, [isInView, deferRender]);
// Performance-based glass styles
const getOptimizedGlassStyles = useMemo(() => {
return createGlassStyle({
intent: "neutral",
elevation: "level2"
});
}, [performanceMode, enableGPU, gpuAcceleration, style]);
if (!isVisible && deferRender) {
return jsx("div", {
ref: containerRef,
className: cn('glass-surface-placeholder glass-border-dashed', className),
style: {
minHeight: '100px',
background: 'transparent',
border: '1px dashed rgba(var(--glass-color-black) / var(--glass-opacity-10))'
}
});
}
return jsx("div", {
ref: containerRef,
className: cn('glass-surface-primary glass-blur-backdrop', className),
style: getOptimizedGlassStyles,
children: virtualizeContent ? jsx(VirtualizedContent, {
children: children
}) : children
});
}
function LazyGlassLoading({
children,
placeholder,
threshold = 0.1,
rootMargin = '50px',
className = '',
onLoad
}) {
const [isLoaded, setIsLoaded] = useState(false);
const containerRef = useRef(null);
const isInView = useInView(containerRef, {
amount: threshold,
margin: rootMargin,
once: true
});
useEffect(() => {
if (isInView && !isLoaded) {
// Simulate async glass effect loading
const timer = setTimeout(() => {
setIsLoaded(true);
onLoad?.();
}, 100);
return () => clearTimeout(timer);
}
}, [isInView, isLoaded, onLoad]);
const defaultPlaceholder = jsx("div", {
className: cn('glass-surface-placeholder glass-animate-pulse'),
style: {
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */',
backgroundSize: '200% 100%',
animation: 'shimmer 1.5s infinite',
borderRadius: '12px',
minHeight: '100px'
}
});
return jsx("div", {
ref: containerRef,
className: className,
children: jsx(AnimatePresence, {
mode: "wait",
children: !isLoaded ? jsx(motion.div, {
initial: {
opacity: 0
},
animate: {
opacity: 1
},
exit: {
opacity: 0
},
transition: {
duration: 0.3
},
children: placeholder || defaultPlaceholder
}, "placeholder") : jsx(motion.div, {
initial: {
opacity: 0,
y: 10
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.4
},
children: children
}, "content")
})
});
}
function ReducedMotionGlass({
children,
className = '',
staticAlternative,
respectUserPreference = true
}) {
const {
reducedMotion
} = useGlassPerformance();
const shouldReduceMotion = respectUserPreference && reducedMotion;
if (shouldReduceMotion && staticAlternative) {
return jsx("div", {
className: cn('glass-surface-primary glass-reduced-motion', className),
children: staticAlternative
});
}
const motionProps = shouldReduceMotion ? {
// Disable animations when reduced motion is preferred
animate: undefined,
transition: {
duration: 0
},
whileHover: undefined,
whileTap: undefined
} : {
// Normal animation props
initial: {
opacity: 0,
scale: 0.95
},
animate: {
opacity: 1,
scale: 1
},
transition: {
duration: 0.3,
type: 'spring'
},
whileHover: {
scale: 1.02,
y: -2
},
whileTap: {
scale: 0.98
}
};
return jsx(motion.div, {
className: cn('glass-surface-primary glass-reduced-motion', className),
style: createGlassStyle({
intent: "neutral",
elevation: "level2"
}),
...motionProps,
children: children
});
}
function BatteryAwareGlass({
children,
className = '',
energyThresholds = {
high: 50,
medium: 25,
low: 10
}
}) {
const {
batteryLevel,
performanceMode
} = useGlassPerformance();
const getEnergyEfficientStyles = () => {
const level = batteryLevel || 100;
if (level > energyThresholds.high && performanceMode !== 'battery-saver') {
// Full effects
return createGlassStyle({
intent: "neutral",
elevation: "level2"
});
} else if (level > energyThresholds.medium) {
// Reduced effects
return createGlassStyle({
intent: "neutral",
elevation: "level2"
});
} else {
// Minimal effects
return createGlassStyle({
intent: "neutral",
elevation: "level2"
});
}
};
return jsxs(motion.div, {
className: cn('glass-surface-adaptive glass-border-radius-lg', className),
style: {
borderRadius: '12px',
transition: 'all 0.3s ease-in-out',
...getEnergyEfficientStyles()
},
layout: true,
children: [children, process.env.NODE_ENV === 'development' && batteryLevel !== undefined && jsxs("div", {
className: cn('glass-absolute glass-top-2 glass-left-2 glass-text-xs glass-surface-debug glass-text-on-debug glass-px-2 glass-py-1 glass-radius-sm glass-opacity-50'),
children: ["Battery: ", batteryLevel, "%"]
})]
});
}
function ProgressiveGlassEnhancement({
children,
tiers = {
basic: {
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */',
border: '1px solid var(--glass-border-default)',
borderRadius: '8px'
},
enhanced: createGlassStyle({
intent: "neutral",
elevation: "level2"
}),
premium: createGlassStyle({
intent: "neutral",
elevation: "level2"
})
},
className = '',
autoDetect = true
}) {
const {
performanceMode,
gpuAcceleration,
cpuLoad
} = useGlassPerformance();
const getTierStyles = () => {
if (!autoDetect) {
return tiers.enhanced; // Default to enhanced if not auto-detecting
}
// Determine tier based on performance indicators
if (performanceMode === 'battery-saver' || cpuLoad > 70 || !gpuAcceleration) {
return tiers.basic;
} else if (performanceMode === 'high' && cpuLoad < 30) {
return tiers.premium;
} else {
return tiers.enhanced;
}
};
return jsx(motion.div, {
className: cn('glass-surface-progressive', className),
style: getTierStyles(),
layout: true,
transition: {
duration: 0.3
},
children: children
});
}
// Virtualized Content Helper
function VirtualizedContent({
children
}) {
const [visibleRange, setVisibleRange] = useState({
start: 0,
end: 10
});
const containerRef = useRef(null);
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const handleScroll = () => {
const containerHeight = container.clientHeight;
const scrollTop = container.scrollTop;
const itemHeight = 100; // Approximate item height
const start = Math.floor(scrollTop / itemHeight);
const end = Math.ceil((scrollTop + containerHeight) / itemHeight);
setVisibleRange({
start: Math.max(0, start - 2),
end: end + 2
});
};
container.addEventListener('scroll', handleScroll);
return () => container.removeEventListener('scroll', handleScroll);
}, []);
const childArray = React.Children.toArray(children);
const visibleChildren = childArray.slice(visibleRange.start, visibleRange.end);
return jsxs("div", {
ref: containerRef,
className: cn('glass-virtualized-content glass-h-400 glass-overflow-y-auto'),
children: [jsx("div", {
style: {
height: visibleRange.start * 100
}
}), " ", visibleChildren, jsx("div", {
style: {
height: (childArray.length - visibleRange.end) * 100
}
}), " "]
});
}
// Performance Monitor Component
function GlassPerformanceMonitor({
className = ''
}) {
const {
performanceMode,
batteryLevel,
cpuLoad,
gpuAcceleration
} = useGlassPerformance();
return jsxs(motion.div, {
className: cn('glass-performance-monitor glass-fixed glass-top-10 glass-right-10 glass-z-max', className),
style: createGlassStyle({
intent: "neutral",
elevation: "level2"
}),
initial: {
opacity: 0,
x: 50
},
animate: {
opacity: 1,
x: 0
},
children: [jsxs("div", {
children: ["Mode: ", performanceMode]
}), batteryLevel !== undefined && jsxs("div", {
children: ["Battery: ", batteryLevel, "%"]
}), jsxs("div", {
children: ["CPU: ", cpuLoad.toFixed(1), "%"]
}), jsxs("div", {
children: ["GPU: ", gpuAcceleration ? 'ON' : 'OFF']
})]
});
}
function PerformanceSummaryCard() {
const {
performanceMode,
batteryLevel,
cpuLoad,
lazyLoading
} = useGlassPerformance();
const metrics = [{
label: 'Mode',
value: performanceMode.replace('-', ' ')
}, {
label: 'Battery',
value: batteryLevel !== undefined ? `${batteryLevel}%` : '—'
}, {
label: 'CPU Load',
value: `${cpuLoad.toFixed(0)}%`
}, {
label: 'Lazy Loading',
value: lazyLoading ? 'enabled' : 'disabled'
}];
return jsxs("div", {
className: "glass-surface-primary glass-radius-2xl glass-p-6 glass-space-y-4 glass-border glass-border-white/10",
children: [jsxs("div", {
children: [jsx("p", {
className: "glass-text-xs glass-text-tertiary uppercase tracking-wide",
children: "Performance profile"
}), jsx("h2", {
className: "glass-text-2xl glass-text-primary font-semibold",
children: "Adaptive glass effects"
})]
}), jsx("div", {
className: "glass-grid glass-grid-cols-2 glass-gap-3",
children: metrics.map(metric => jsxs("div", {
className: "glass-surface-subtle glass-radius-xl glass-p-4",
children: [jsx("p", {
className: "glass-text-xs glass-text-tertiary mb-1",
children: metric.label
}), jsx("p", {
className: "glass-text-lg glass-text-primary font-semibold",
children: metric.value
})]
}, metric.label))
}), jsx("p", {
className: "glass-text-xs glass-text-secondary",
children: "The engine continuously balances fidelity with resource usage."
})]
});
}
const DemoPerformanceGrid = () => jsxs("div", {
className: "glass-grid md:grid-cols-2 glass-gap-4",
children: [jsxs(EfficientGlassRendering, {
className: "glass-p-4 glass-radius-xl",
children: [jsx("h3", {
className: "glass-text-lg glass-text-primary font-semibold",
children: "Efficient rendering"
}), jsx("p", {
className: "glass-text-sm glass-text-secondary",
children: "Defers heavy effects when out of view."
})]
}), jsxs(BatteryAwareGlass, {
className: "glass-p-4 glass-radius-xl",
children: [jsx("h3", {
className: "glass-text-lg glass-text-primary font-semibold",
children: "Battery-aware styling"
}), jsx("p", {
className: "glass-text-sm glass-text-secondary",
children: "Automatically dials visuals up or down."
})]
}), jsxs(LazyGlassLoading, {
className: "glass-p-4 glass-radius-xl",
children: [jsx("h3", {
className: "glass-text-lg glass-text-primary font-semibold",
children: "Lazy loading"
}), jsx("p", {
className: "glass-text-sm glass-text-secondary",
children: "Streams content just in time."
})]
}), jsxs(ReducedMotionGlass, {
className: "glass-p-4 glass-radius-xl",
children: [jsx("h3", {
className: "glass-text-lg glass-text-primary font-semibold",
children: "Motion aware"
}), jsx("p", {
className: "glass-text-sm glass-text-secondary",
children: "Respects prefers-reduced-motion automatically."
})]
})]
});
const GlassPerformanceOptimization = ({
adaptivePerformance = true,
className,
children,
showMonitor = false,
...rest
}) => jsx(GlassPerformanceProvider, {
adaptivePerformance: adaptivePerformance,
children: jsxs("div", {
className: cn('glass-performance-optimization glass-space-y-6', className),
...rest,
children: [children ?? jsxs(Fragment, {
children: [jsx(PerformanceSummaryCard, {}), jsx(DemoPerformanceGrid, {})]
}), showMonitor && jsx(GlassPerformanceMonitor, {})]
})
});
export { BatteryAwareGlass, EfficientGlassRendering, GlassPerformanceMonitor, GlassPerformanceOptimization, GlassPerformanceProvider, LazyGlassLoading, ProgressiveGlassEnhancement, ReducedMotionGlass, GlassPerformanceOptimization as default, useGlassPerformance };
//# sourceMappingURL=GlassPerformanceOptimization.js.map