aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
330 lines (327 loc) • 11.2 kB
JavaScript
'use client';
import { jsxs } from 'react/jsx-runtime';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { useRef, useState, useEffect, useCallback } from 'react';
import { useMotionValue, useSpring, motion } from 'framer-motion';
import { cn } from '../../lib/utilsComprehensive.js';
function GlassContextAware({
children,
className,
adaptationSpeed = 0.5,
sensitivity = 0.7,
override,
onContextChange
}) {
useReducedMotion();
const containerRef = useRef(null);
const [environmentContext, setEnvironmentContext] = useState({
lightLevel: 0.5,
colorTemperature: 6500,
ambientNoise: 0.3,
batteryLevel: 1,
networkSpeed: 10,
cpuUsage: 0.3,
memoryUsage: 0.4,
time: {
hour: new Date().getHours(),
isWorkingHours: isWorkingTime(),
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
},
location: {
type: "unknown"
},
device: {
type: detectDeviceType(),
orientation: window.innerHeight > window.innerWidth ? "portrait" : "landscape",
pixelRatio: window.devicePixelRatio || 1,
refreshRate: 60
}
});
const [usageContext, setUsageContext] = useState({
focusMode: false,
taskType: "casual",
sessionDuration: 0,
interactionIntensity: 0.5,
stressLevel: 0.3,
productivity: 0.7
});
// Motion values for smooth transitions
const glassIntensity = useMotionValue(0.7);
const glassBlur = useMotionValue(16);
const glassOpacity = useMotionValue(0.1);
const glassContrast = useMotionValue(1);
const glassSaturation = useMotionValue(1);
// Smooth springs
const smoothIntensity = useSpring(glassIntensity, {
stiffness: 100 * adaptationSpeed,
damping: 20
});
const smoothBlur = useSpring(glassBlur, {
stiffness: 100 * adaptationSpeed,
damping: 20
});
const smoothOpacity = useSpring(glassOpacity, {
stiffness: 100 * adaptationSpeed,
damping: 20
});
const smoothContrast = useSpring(glassContrast, {
stiffness: 100 * adaptationSpeed,
damping: 20
});
const smoothSaturation = useSpring(glassSaturation, {
stiffness: 100 * adaptationSpeed,
damping: 20
});
// Detect device type
function detectDeviceType() {
if (typeof window === "undefined") return "desktop";
const ua = navigator.userAgent;
if (/mobile|android|iphone/i.test(ua)) return "mobile";
if (/tablet|ipad/i.test(ua)) return "tablet";
if (/tv|television/i.test(ua)) return "tv";
return "desktop";
}
// Check if current time is working hours
function isWorkingTime() {
const hour = new Date().getHours();
return hour >= 9 && hour <= 17;
}
// Monitor environment context
useEffect(() => {
const updateEnvironmentContext = () => {
const now = new Date();
// Update time context
const timeContext = {
hour: now.getHours(),
isWorkingHours: isWorkingTime(),
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
};
// Update device context
const deviceContext = {
...environmentContext.device,
orientation: window.innerHeight > window.innerWidth ? "portrait" : "landscape"
};
// Estimate light level based on time of day
const lightLevel = calculateLightLevel(timeContext.hour);
// Get battery info if available
const getBatteryLevel = async () => {
if ("getBattery" in navigator) {
try {
const battery = await navigator.getBattery();
return battery.level;
} catch {}
}
return 1;
};
// Get network info if available
const getNetworkSpeed = () => {
if ("connection" in navigator) {
const connection = navigator.connection;
return connection.downlink || 10;
}
return 10;
};
getBatteryLevel().then(batteryLevel => {
setEnvironmentContext(prev => ({
...prev,
lightLevel,
batteryLevel,
networkSpeed: getNetworkSpeed(),
time: timeContext,
device: deviceContext,
colorTemperature: calculateColorTemperature(timeContext.hour)
}));
});
};
updateEnvironmentContext();
const interval = setInterval(updateEnvironmentContext, 60000); // Update every minute
return () => clearInterval(interval);
}, []);
// Calculate light level based on time
function calculateLightLevel(hour) {
// Simulate natural light cycle
if (hour >= 6 && hour <= 18) {
// Daytime: peak brightness at noon
const dayProgress = (hour - 6) / 12;
return 0.3 + 0.7 * Math.sin(dayProgress * Math.PI);
} else {
// Nighttime: minimal light
return 0.1;
}
}
// Calculate color temperature based on time
function calculateColorTemperature(hour) {
// Warmer at night, cooler during day
if (hour >= 6 && hour <= 18) {
return 5500 + 1000 * Math.sin((hour - 6) / 12 * Math.PI);
} else {
return 3000; // Warm light at night
}
}
// Monitor usage patterns
useEffect(() => {
let interactionCount = 0;
let lastInteraction = Date.now();
const sessionStart = Date.now();
const trackInteraction = () => {
interactionCount++;
lastInteraction = Date.now();
// Calculate interaction intensity
const intensity = Math.min(interactionCount / 100, 1);
// Calculate session duration
const sessionDuration = (Date.now() - sessionStart) / (1000 * 60);
// Estimate stress level based on interaction frequency
const timeSinceLastInteraction = Date.now() - lastInteraction;
const stressLevel = Math.max(0, 1 - timeSinceLastInteraction / 30000); // High stress if rapid interactions
// Detect task type based on interaction patterns
const taskType = detectTaskType(interactionCount, sessionDuration);
setUsageContext(prev => ({
...prev,
interactionIntensity: intensity,
sessionDuration,
stressLevel,
taskType
}));
};
// Track various interaction events
const events = ["click", "keydown", "scroll", "mousemove", "touchstart"];
events.forEach(event => {
document.addEventListener(event, trackInteraction);
});
return () => {
events.forEach(event => {
document.removeEventListener(event, trackInteraction);
});
};
}, []);
// Detect task type based on patterns
function detectTaskType(interactions, duration) {
const interactionsPerMinute = interactions / Math.max(duration, 1);
if (interactionsPerMinute > 50) return "gaming";
if (interactionsPerMinute > 30) return "work";
if (interactionsPerMinute > 15) return "writing";
if (interactionsPerMinute > 5) return "reading";
if (duration > 30) return "media";
return "casual";
}
// Adaptive glass calculations
const calculateGlassProperties = useCallback(() => {
const context = {
...environmentContext,
...usageContext
};
// Base calculations
let intensity = 0.7;
let blur = 16;
let opacity = 0.1;
let contrast = 1;
let saturation = 1;
// Adapt to light level
intensity *= 0.5 + 0.5 * (1 - context.lightLevel); // More intense in darker environments
opacity += 0.1 * (1 - context.lightLevel);
// Adapt to time of day
if (context.time.hour < 6 || context.time.hour > 20) {
// Night mode: warmer, less intense
intensity *= 0.7;
saturation *= 0.8;
contrast *= 0.9;
}
// Adapt to battery level
if (context.batteryLevel < 0.2) {
// Low battery: reduce effects
intensity *= 0.5;
blur *= 0.7;
}
// Adapt to device performance
const performanceScore = 1 - (context.cpuUsage * 0.5 + context.memoryUsage * 0.5);
intensity *= performanceScore;
blur *= performanceScore;
// Adapt to task type
switch (context.taskType) {
case "reading":
intensity *= 0.6; // Less distraction
opacity *= 0.8;
break;
case "writing":
intensity *= 0.7;
contrast *= 1.1; // Better text contrast
break;
case "work":
if (context.focusMode) {
intensity *= 0.5; // Minimal distraction
opacity *= 0.7;
}
break;
case "gaming":
intensity *= 1.2; // More immersive
saturation *= 1.1;
break;
case "media":
intensity *= 1.1;
saturation *= 1.05;
break;
}
// Adapt to stress level
intensity *= 1 - context.stressLevel * 0.3; // Reduce intensity when stressed
// Apply sensitivity multiplier
const baseDiff = {
intensity: intensity - 0.7,
blur: blur - 16,
opacity: opacity - 0.1,
contrast: contrast - 1,
saturation: saturation - 1
};
intensity = 0.7 + baseDiff.intensity * sensitivity;
blur = 16 + baseDiff.blur * sensitivity;
opacity = 0.1 + baseDiff.opacity * sensitivity;
contrast = 1 + baseDiff.contrast * sensitivity;
saturation = 1 + baseDiff.saturation * sensitivity;
// Apply overrides
if (override) {
intensity = override.intensity ?? intensity;
blur = override.blur ?? blur;
opacity = override.opacity ?? opacity;
contrast = override.contrast ?? contrast;
saturation = override.saturation ?? saturation;
}
// Update motion values
glassIntensity.set(Math.max(0, Math.min(1, intensity)));
glassBlur.set(Math.max(0, Math.min(50, blur)));
glassOpacity.set(Math.max(0, Math.min(1, opacity)));
glassContrast.set(Math.max(0.5, Math.min(2, contrast)));
glassSaturation.set(Math.max(0, Math.min(2, saturation)));
// Notify listeners
onContextChange?.(context);
}, [environmentContext, usageContext, sensitivity, override, onContextChange]);
// Update glass properties when context changes
useEffect(() => {
calculateGlassProperties();
}, [calculateGlassProperties]);
return jsxs(motion.div, {
ref: containerRef,
className: cn("relative OptimizedGlass intensity={0.2} glassBlur={6}", "transform-gpu will-change-transform", className),
style: {
"--glass-adaptive-intensity": smoothIntensity,
"--glass-adaptive-blur": smoothBlur,
"--glass-adaptive-opacity": smoothOpacity,
"--glass-adaptive-contrast": smoothContrast,
"--glass-adaptive-saturation": smoothSaturation,
// Use createGlassStyle() instead,
backgroundColor: `rgba(255, 255, 255, ${smoothOpacity.get()})`
},
children: [children, process.env.NODE_ENV === "development" && jsxs("div", {
className: 'absolute glass-top-2 right-2 glass-text-xs glass-surface-primary glass-p-2 glass-radius-sm opacity-50',
children: [jsxs("div", {
children: ["Light: ", (environmentContext.lightLevel * 100).toFixed(0), "%"]
}), jsxs("div", {
children: ["Battery: ", (environmentContext.batteryLevel * 100).toFixed(0), "%"]
}), jsxs("div", {
children: ["Task: ", usageContext.taskType]
}), jsxs("div", {
children: ["Intensity: ", smoothIntensity.get().toFixed(2)]
})]
})]
});
}
export { GlassContextAware };
//# sourceMappingURL=GlassContextAware.js.map