aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
1,185 lines (1,182 loc) • 39.2 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { useRef, useState, useEffect, useCallback, useContext, createContext } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../../lib/utilsComprehensive.js';
// Multi-sensor fusion system using Kalman filtering
class SensorFusionSystem {
constructor() {
this.kalmanFilters = new Map();
this.sensorWeights = new Map();
this.fusedData = new Map();
this.dataQuality = new Map();
this.initializeFilters();
}
initializeFilters() {
// Initialize Kalman filters for key metrics
const metrics = ["lightLevel", "ambientNoise", "temperature", "humidity", "heartRate", "stressLevel", "batteryLevel", "deviceMotion"];
metrics.forEach(metric => {
this.kalmanFilters.set(metric, new KalmanFilter());
this.sensorWeights.set(metric, 1.0);
this.dataQuality.set(metric, 1.0);
});
}
fuseContextualData(context) {
const fusedContext = {
...context
};
// Fuse biometric data
if (context.biometrics.heartRate !== undefined) {
const filtered = this.kalmanFilters.get("heartRate").filter(context.biometrics.heartRate);
fusedContext.biometrics.heartRate = filtered;
}
// Fuse environmental data
const lightFiltered = this.kalmanFilters.get("lightLevel").filter(context.environment.lightLevel);
fusedContext.environment.lightLevel = lightFiltered;
const noiseFiltered = this.kalmanFilters.get("ambientNoise").filter(context.environment.ambientNoise);
fusedContext.environment.ambientNoise = noiseFiltered;
const tempFiltered = this.kalmanFilters.get("temperature").filter(context.environment.temperature);
fusedContext.environment.temperature = tempFiltered;
// Calculate overall quality based on sensor reliability
const qualityScores = Array.from(this.dataQuality.values());
fusedContext.quality = qualityScores.reduce((sum, q) => sum + q, 0) / qualityScores.length;
return fusedContext;
}
updateSensorWeights(sensorId, accuracy) {
this.sensorWeights.set(sensorId, Math.max(0.1, Math.min(1.0, accuracy)));
this.dataQuality.set(sensorId, accuracy);
}
getFusedValue(metricId) {
return this.fusedData.get(metricId);
}
}
// Kalman filter for sensor data smoothing
class KalmanFilter {
constructor(processNoise = 0.01, measurementNoise = 0.1) {
this.x = 0;
this.P = 1;
this.Q = processNoise;
this.R = measurementNoise;
this.K = 0;
}
predict() {
// Predict step
this.P = this.P + this.Q;
}
update(measurement) {
// Update step
this.K = this.P / (this.P + this.R);
this.x = this.x + this.K * (measurement - this.x);
this.P = (1 - this.K) * this.P;
}
filter(measurement) {
this.predict();
this.update(measurement);
return this.x;
}
}
// Advanced pattern recognition for contextual situations
class ContextPatternRecognizer {
constructor() {
this.patterns = new Map();
this.historicalContexts = [];
this.neuralNetwork = new ContextualNeuralNetwork();
this.initializeCommonPatterns();
}
initializeCommonPatterns() {
// Define common contextual patterns
this.patterns.set("focus-work", {
id: "focus-work",
conditions: {
environment: {
lightLevel: [400, 1000],
ambientNoise: [30, 50]
},
biometrics: {
heartRate: [60, 85],
stressLevel: [0.3, 0.7]
},
device: {
deviceMotion: "static",
batteryLevel: [0.3, 1.0]
},
timePattern: ["morning", "afternoon"]
},
confidence: 0.9,
adaptationPriority: "high"
});
this.patterns.set("relaxation", {
id: "relaxation",
conditions: {
environment: {
lightLevel: [50, 300],
ambientNoise: [20, 40]
},
biometrics: {
heartRate: [50, 75],
stressLevel: [0.0, 0.4]
},
device: {
deviceMotion: "static"
},
timePattern: ["evening", "dusk", "night"]
},
confidence: 0.85,
adaptationPriority: "medium"
});
this.patterns.set("high-stress", {
id: "high-stress",
conditions: {
biometrics: {
heartRate: [90, 150],
stressLevel: [0.7, 1.0]
},
environment: {
ambientNoise: [60, 120]
},
device: {
deviceMotion: "active"
}
},
confidence: 0.8,
adaptationPriority: "critical"
});
this.patterns.set("outdoor-bright", {
id: "outdoor-bright",
conditions: {
environment: {
lightLevel: [10000, 100000]
},
location: {
locationType: ["outdoor"]
},
device: {
screenBrightness: [0.8, 1.0]
}
},
confidence: 0.95,
adaptationPriority: "high"
});
}
analyzeContext(context) {
const matchedPatterns = [];
this.patterns.forEach((pattern, patternId) => {
const matchScore = this.calculatePatternMatch(context, pattern);
if (matchScore > 0.7) {
matchedPatterns.push(patternId);
}
});
// Use neural network for complex pattern recognition
const neuralPrediction = this.neuralNetwork.predict(context);
if (neuralPrediction.confidence > 0.8) {
matchedPatterns.push(neuralPrediction.pattern);
}
return matchedPatterns;
}
calculatePatternMatch(context, pattern) {
let totalMatch = 0;
let matchCount = 0;
// Check environmental conditions
if (pattern.conditions.environment) {
Object.entries(pattern.conditions.environment).forEach(([key, range]) => {
const value = context.environment[key];
if (value !== undefined && Array.isArray(range)) {
const match = value >= range[0] && value <= range[1] ? 1 : 0;
totalMatch += match;
matchCount++;
}
});
}
// Check biometric conditions
if (pattern.conditions.biometrics) {
Object.entries(pattern.conditions.biometrics).forEach(([key, range]) => {
const value = context.biometrics[key];
if (value !== undefined && Array.isArray(range)) {
const match = value >= range[0] && value <= range[1] ? 1 : 0;
totalMatch += match;
matchCount++;
}
});
}
// Check device conditions
if (pattern.conditions.device) {
Object.entries(pattern.conditions.device).forEach(([key, condition]) => {
const value = context.device[key];
if (value !== undefined) {
let match = 0;
if (Array.isArray(condition)) {
match = value >= condition[0] && value <= condition[1] ? 1 : 0;
} else {
match = value === condition ? 1 : 0;
}
totalMatch += match;
matchCount++;
}
});
}
// Check time pattern
if (pattern.conditions.timePattern) {
const match = pattern.conditions.timePattern.includes(context.environment.timeOfDay) ? 1 : 0;
totalMatch += match;
matchCount++;
}
return matchCount > 0 ? totalMatch / matchCount : 0;
}
learnFromContext(context, userSatisfaction) {
this.historicalContexts.push(context);
// Keep only recent contexts
if (this.historicalContexts.length > 1000) {
this.historicalContexts.shift();
}
// Train neural network
this.neuralNetwork.train(context, userSatisfaction);
}
}
// Neural network for contextual pattern learning
class ContextualNeuralNetwork {
constructor() {
this.learningRate = 0.01;
this.weights = [];
this.biases = [];
this.initializeNetwork();
}
initializeNetwork() {
// Simple 3-layer network: input -> hidden -> output
const inputSize = 20; // Context features
const hiddenSize = 40;
const outputSize = 10; // Pattern categories
this.weights = [this.randomMatrix(hiddenSize, inputSize), this.randomMatrix(outputSize, hiddenSize)];
this.biases = [this.randomArray(hiddenSize), this.randomArray(outputSize)];
}
randomMatrix(rows, cols) {
return Array.from({
length: rows
}, () => Array.from({
length: cols
}, () => Math.random() * 2 - 1));
}
randomArray(size) {
return Array.from({
length: size
}, () => Math.random() * 2 - 1);
}
contextToVector(context) {
return [context.environment.lightLevel / 100000, context.environment.ambientNoise / 100, context.environment.temperature / 40, context.environment.humidity / 100, context.biometrics.heartRate || 0 / 200, context.biometrics.stressLevel || 0, context.device.batteryLevel, context.device.accelerometer.x, context.device.accelerometer.y, context.device.accelerometer.z, context.device.gyroscope.alpha / 360, context.device.gyroscope.beta / 360, context.device.gyroscope.gamma / 360, context.location.latitude || 0 / 180, context.location.longitude || 0 / 360, context.quality,
// Time features
context.environment.timeOfDay === "morning" ? 1 : 0, context.environment.timeOfDay === "afternoon" ? 1 : 0, context.environment.timeOfDay === "evening" ? 1 : 0, context.environment.timeOfDay === "night" ? 1 : 0];
}
predict(context) {
const input = this.contextToVector(context);
const output = this.forward(input);
const maxIndex = output.indexOf(Math.max(...output));
const confidence = output[maxIndex];
const patterns = ["focus-work", "relaxation", "high-stress", "outdoor-bright", "low-light", "motion", "travel", "meeting", "exercise", "sleep"];
return {
pattern: patterns[maxIndex] || "unknown",
confidence: Math.max(0, Math.min(1, confidence))
};
}
forward(input) {
let activation = input;
for (let layer = 0; layer < this.weights.length; layer++) {
const newActivation = [];
for (let node = 0; node < this.weights[layer].length; node++) {
let sum = this.biases[layer][node];
for (let prevNode = 0; prevNode < activation.length; prevNode++) {
sum += this.weights[layer][node][prevNode] * activation[prevNode];
}
newActivation.push(this.sigmoid(sum));
}
activation = newActivation;
}
return activation;
}
sigmoid(x) {
return 1 / (1 + Math.exp(-x));
}
train(context, satisfaction) {
// Simplified training - in practice would use backpropagation
const adjustmentRate = this.learningRate * (satisfaction - 0.5);
this.weights.forEach(layer => {
layer.forEach(node => {
node.forEach((weight, index) => {
node[index] += adjustmentRate * Math.random() * 0.1;
});
});
});
}
}
// Main contextual engine
class GlassContextualEngineCore {
constructor() {
this.sensorFusion = new SensorFusionSystem();
this.patternRecognizer = new ContextPatternRecognizer();
this.currentContext = this.getDefaultContext();
this.adaptations = [];
this.contextHistory = [];
this.sensors = new ContextualSensors();
this.startContextMonitoring();
}
getDefaultContext() {
return {
biometrics: {},
environment: {
lightLevel: 300,
lightTemperature: 6500,
ambientNoise: 40,
humidity: 50,
temperature: 22,
pressure: 1013,
timeOfDay: "afternoon",
season: "summer"
},
device: {
accelerometer: {
x: 0,
y: 0,
z: 9.8
},
gyroscope: {
alpha: 0,
beta: 0,
gamma: 0
},
deviceMotion: "static",
batteryLevel: 1.0,
networkQuality: "excellent",
screenBrightness: 0.8
},
location: {
locationType: "indoor",
activityType: "stationary"
},
timestamp: Date.now(),
quality: 1.0
};
}
async startContextMonitoring() {
// Start sensor data collection
await this.sensors.initialize();
// Update context every 500ms
setInterval(() => {
this.updateContext();
}, 500);
// Generate adaptations every 2 seconds
setInterval(() => {
this.generateAdaptations();
}, 2000);
}
async updateContext() {
try {
// Gather sensor data
const environmentData = await this.sensors.getEnvironmentData();
const biometricData = await this.sensors.getBiometricData();
const deviceData = await this.sensors.getDeviceData();
const locationData = await this.sensors.getLocationData();
// Create new context
const newContext = {
biometrics: biometricData,
environment: environmentData,
device: deviceData,
location: locationData,
timestamp: Date.now(),
quality: this.calculateContextQuality(environmentData, biometricData, deviceData)
};
// Apply sensor fusion
this.currentContext = this.sensorFusion.fuseContextualData(newContext);
// Store in history
this.contextHistory.push(this.currentContext);
if (this.contextHistory.length > 200) {
this.contextHistory.shift();
}
} catch (error) {
console.warn("Failed to update context:", error);
}
}
calculateContextQuality(env, bio, device) {
let quality = 1.0;
// Reduce quality based on sensor availability
if (!bio.heartRate) quality -= 0.1;
if (!env.lightLevel) quality -= 0.05;
if (device.networkQuality === "poor") quality -= 0.2;
if (device.batteryLevel < 0.2) quality -= 0.1;
return Math.max(0.1, quality);
}
generateAdaptations() {
// Analyze current context for patterns
const matchedPatterns = this.patternRecognizer.analyzeContext(this.currentContext);
// Generate adaptations for each pattern
matchedPatterns.forEach(patternId => {
const adaptation = this.createAdaptationForPattern(patternId, this.currentContext);
if (adaptation) {
this.adaptations.push(adaptation);
}
});
// Remove old adaptations
const now = Date.now();
this.adaptations = this.adaptations.filter(adaptation => !adaptation.appliedAt || now - adaptation.appliedAt < (adaptation.duration || 30000));
// Sort by priority and confidence
this.adaptations.sort((a, b) => {
const priorityWeight = {
critical: 4,
high: 3,
medium: 2,
low: 1
};
const priorityDiff = priorityWeight[this.getPriorityFromId(b.id)] - priorityWeight[this.getPriorityFromId(a.id)];
return priorityDiff !== 0 ? priorityDiff : b.confidence - a.confidence;
});
}
createAdaptationForPattern(patternId, context) {
const adaptationId = `${patternId}-${Date.now()}`;
switch (patternId) {
case "focus-work":
return {
id: adaptationId,
priority: 3,
contextMatch: 0.9,
adaptations: {
visual: {
brightness: -0.1,
contrast: 0.1,
saturation: -0.2,
colorTemperature: 0.2,
blur: 0.0,
opacity: 1.0
},
animation: {
speed: 0.8,
intensity: 0.6,
type: "minimal",
easing: "ease-out"
},
interaction: {
sensitivity: 1.0,
hapticFeedback: 0.3,
responseDelay: 0,
gestureThreshold: 0.8
},
layout: {
density: "normal",
complexity: "standard",
spacing: 1.1,
fontSize: 1.0
},
sound: {
volume: 0.3,
frequency: 0.3,
spatialAudio: false,
environmentalAudio: false
}
},
confidence: 0.85,
duration: 300000 // 5 minutes
};
case "high-stress":
return {
id: adaptationId,
priority: 4,
contextMatch: 0.8,
adaptations: {
visual: {
brightness: -0.3,
contrast: -0.2,
saturation: -0.4,
colorTemperature: -0.3,
blur: 0.1,
opacity: 0.9
},
animation: {
speed: 0.5,
intensity: 0.3,
type: "minimal",
easing: "ease"
},
interaction: {
sensitivity: 0.8,
hapticFeedback: 0.1,
responseDelay: 100,
gestureThreshold: 0.6
},
layout: {
density: "sparse",
complexity: "minimal",
spacing: 1.5,
fontSize: 1.1
},
sound: {
volume: 0.1,
frequency: 0.2,
spatialAudio: false,
environmentalAudio: true
}
},
confidence: 0.9,
duration: 600000 // 10 minutes
};
case "outdoor-bright":
return {
id: adaptationId,
priority: 3,
contextMatch: 0.95,
adaptations: {
visual: {
brightness: 0.4,
contrast: 0.5,
saturation: 0.2,
colorTemperature: 0.0,
blur: 0.0,
opacity: 1.0
},
animation: {
speed: 1.2,
intensity: 1.5,
type: "enhanced",
easing: "ease-out"
},
interaction: {
sensitivity: 1.3,
hapticFeedback: 0.8,
responseDelay: 0,
gestureThreshold: 0.9
},
layout: {
density: "normal",
complexity: "standard",
spacing: 1.2,
fontSize: 1.2
},
sound: {
volume: 0.6,
frequency: 0.6,
spatialAudio: true,
environmentalAudio: false
}
},
confidence: 0.95,
duration: 180000 // 3 minutes
};
case "relaxation":
return {
id: adaptationId,
priority: 2,
contextMatch: 0.85,
adaptations: {
visual: {
brightness: -0.2,
contrast: -0.1,
saturation: 0.1,
colorTemperature: -0.4,
blur: 0.05,
opacity: 0.95
},
animation: {
speed: 0.6,
intensity: 0.4,
type: "minimal",
easing: "ease"
},
interaction: {
sensitivity: 0.9,
hapticFeedback: 0.2,
responseDelay: 50,
gestureThreshold: 0.7
},
layout: {
density: "sparse",
complexity: "minimal",
spacing: 1.3,
fontSize: 1.0
},
sound: {
volume: 0.2,
frequency: 0.1,
spatialAudio: true,
environmentalAudio: true
}
},
confidence: 0.8,
duration: 900000 // 15 minutes
};
}
return null;
}
getPriorityFromId(id) {
if (id.includes("stress") || id.includes("emergency")) return "critical";
if (id.includes("focus") || id.includes("outdoor")) return "high";
if (id.includes("relaxation") || id.includes("comfort")) return "medium";
return "low";
}
// Public API
getCurrentContext() {
return {
...this.currentContext
};
}
getCurrentAdaptations() {
return [...this.adaptations];
}
getTopAdaptation() {
return this.adaptations.length > 0 ? this.adaptations[0] : null;
}
provideFeedback(adaptationId, satisfaction) {
this.patternRecognizer.learnFromContext(this.currentContext, satisfaction);
}
getContextHistory() {
return [...this.contextHistory];
}
}
// Sensor data collection system
class ContextualSensors {
constructor() {
this.geolocation = null;
this.deviceMotion = null;
this.ambientLight = null;
this.battery = null;
}
async initialize() {
// CRITICAL SSR FIX: Skip all sensor initialization on server
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
console.warn('ContextualSensors: Skipping initialization on server');
return;
}
// Request permissions and initialize sensors
await this.initializeGeolocation();
await this.initializeDeviceMotion();
await this.initializeAmbientLight();
await this.initializeBattery();
}
async initializeGeolocation() {
if ("geolocation" in navigator) {
this.geolocation = navigator.geolocation;
}
}
async initializeDeviceMotion() {
if ("DeviceMotionEvent" in window) {
// Request permission for iOS 13+
if (typeof DeviceMotionEvent.requestPermission === "function") {
const permission = await DeviceMotionEvent.requestPermission();
if (permission !== "granted") return;
}
window.addEventListener("devicemotion", event => {
this.deviceMotion = event;
});
}
}
async initializeAmbientLight() {
if ("AmbientLightSensor" in window) {
try {
this.ambientLight = new window.AmbientLightSensor();
this.ambientLight.start();
} catch (error) {
console.warn("Ambient light sensor not available:", error);
}
}
}
async initializeBattery() {
if ("getBattery" in navigator) {
this.battery = await navigator.getBattery();
}
}
async getEnvironmentData() {
const now = new Date();
const hour = now.getHours();
// Determine time of day
let timeOfDay = "afternoon";
if (hour >= 5 && hour < 7) timeOfDay = "dawn";else if (hour >= 7 && hour < 12) timeOfDay = "morning";else if (hour >= 12 && hour < 14) timeOfDay = "noon";else if (hour >= 14 && hour < 18) timeOfDay = "afternoon";else if (hour >= 18 && hour < 20) timeOfDay = "evening";else if (hour >= 20 && hour < 22) timeOfDay = "dusk";else timeOfDay = "night";
// Determine season (simplified for Northern Hemisphere)
const month = now.getMonth();
let season = "summer";
if (month >= 2 && month <= 4) season = "spring";else if (month >= 5 && month <= 7) season = "summer";else if (month >= 8 && month <= 10) season = "autumn";else season = "winter";
return {
lightLevel: this.ambientLight?.illuminance || this.estimateLightLevel(timeOfDay),
lightTemperature: this.estimateLightTemperature(timeOfDay),
ambientNoise: this.estimateAmbientNoise(),
humidity: 50,
// Would come from weather API
temperature: 22,
// Would come from weather API
pressure: 1013,
// Would come from weather API
timeOfDay,
season
};
}
estimateLightLevel(timeOfDay) {
const levels = {
dawn: 100,
morning: 1000,
noon: 50000,
afternoon: 20000,
evening: 500,
dusk: 50,
night: 1
};
return levels[timeOfDay] || 300;
}
estimateLightTemperature(timeOfDay) {
const temperatures = {
dawn: 4000,
morning: 5500,
noon: 6500,
afternoon: 6000,
evening: 4500,
dusk: 3000,
night: 2700
};
return temperatures[timeOfDay] || 6500;
}
estimateAmbientNoise() {
// Simplified noise estimation based on time
const hour = new Date().getHours();
if (hour >= 22 || hour <= 6) return 25; // Night
if (hour >= 7 && hour <= 9) return 55; // Morning rush
if (hour >= 17 && hour <= 19) return 60; // Evening rush
return 40; // Normal day
}
async getBiometricData() {
// Placeholder - would integrate with wearables/fitness trackers
return {
heartRate: undefined,
// Would come from fitness trackers
stressLevel: undefined // Would be calculated from HRV
};
}
async getDeviceData() {
let deviceMotion = "static";
if (this.deviceMotion) {
const acceleration = this.deviceMotion.acceleration;
if (acceleration) {
const totalAccel = Math.sqrt(acceleration.x ** 2 + acceleration.y ** 2 + acceleration.z ** 2);
if (totalAccel > 5) deviceMotion = "active";else if (totalAccel > 2) deviceMotion = "moderate";else if (totalAccel > 0.5) deviceMotion = "gentle";
}
}
return {
accelerometer: this.deviceMotion?.acceleration ? {
x: this.deviceMotion.acceleration.x || 0,
y: this.deviceMotion.acceleration.y || 0,
z: this.deviceMotion.acceleration.z || 9.8
} : {
x: 0,
y: 0,
z: 9.8
},
gyroscope: this.deviceMotion?.rotationRate ? {
alpha: this.deviceMotion.rotationRate.alpha || 0,
beta: this.deviceMotion.rotationRate.beta || 0,
gamma: this.deviceMotion.rotationRate.gamma || 0
} : {
alpha: 0,
beta: 0,
gamma: 0
},
deviceMotion,
batteryLevel: this.battery?.level || 1.0,
networkQuality: this.estimateNetworkQuality(),
screenBrightness: 0.8 // Would require additional APIs
};
}
estimateNetworkQuality() {
// CRITICAL SSR FIX: Skip navigator access on server
if (typeof navigator === 'undefined') {
return "good";
}
const connection = navigator.connection;
if (!connection) return "good";
const effectiveType = connection.effectiveType;
switch (effectiveType) {
case "4g":
return "excellent";
case "3g":
return "good";
case "2g":
return "fair";
case "slow-2g":
return "poor";
default:
return "good";
}
}
async getLocationData() {
return new Promise(resolve => {
if (!this.geolocation) {
resolve({
locationType: "unknown",
activityType: "unknown"
});
return;
}
this.geolocation.getCurrentPosition(position => {
resolve({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
altitude: position.coords.altitude || undefined,
accuracy: position.coords.accuracy,
heading: position.coords.heading || undefined,
speed: position.coords.speed || undefined,
locationType: "unknown",
// Would need additional logic
activityType: this.estimateActivity(position)
});
}, () => {
resolve({
locationType: "unknown",
activityType: "unknown"
});
}, {
enableHighAccuracy: false,
timeout: 5000
});
});
}
estimateActivity(position) {
const speed = position.coords.speed || 0;
if (speed < 0.5) return "stationary";
if (speed < 2) return "walking";
if (speed < 5) return "running";
if (speed < 15) return "cycling";
return "driving";
}
}
// React Context
const ContextualEngineContext = /*#__PURE__*/createContext({
engine: null,
context: {},
adaptations: [],
topAdaptation: null,
provideFeedback: () => {}
});
// Provider component
function GlassContextualEngineProvider({
children,
onContextUpdate,
onAdaptationChange
}) {
useReducedMotion();
const engineRef = useRef();
const [context, setContext] = useState({});
const [adaptations, setAdaptations] = useState([]);
const [topAdaptation, setTopAdaptation] = useState(null);
// Initialize engine
useEffect(() => {
engineRef.current = new GlassContextualEngineCore();
// Update state periodically
const updateInterval = setInterval(() => {
if (engineRef.current) {
const currentContext = engineRef.current.getCurrentContext();
const currentAdaptations = engineRef.current.getCurrentAdaptations();
const currentTopAdaptation = engineRef.current.getTopAdaptation();
setContext(currentContext);
setAdaptations(currentAdaptations);
setTopAdaptation(currentTopAdaptation);
onContextUpdate?.(currentContext);
onAdaptationChange?.(currentTopAdaptation);
}
}, 1000);
return () => clearInterval(updateInterval);
}, [onContextUpdate, onAdaptationChange]);
const provideFeedback = useCallback((adaptationId, satisfaction) => {
engineRef.current?.provideFeedback(adaptationId, satisfaction);
}, []);
const value = {
engine: engineRef.current || null,
context,
adaptations,
topAdaptation,
provideFeedback
};
return jsx(ContextualEngineContext.Provider, {
value: value,
children: children
});
}
// Hook to use contextual engine
function useContextualEngine() {
const context = useContext(ContextualEngineContext);
if (!context) {
throw new Error("useContextualEngine must be used within GlassContextualEngineProvider");
}
return context;
}
// Contextual dashboard component
function GlassContextualDashboard({
className,
showSensors = true
}) {
const prefersReducedMotion = useReducedMotion();
const {
context,
adaptations,
topAdaptation
} = useContextualEngine();
const [showDashboard, setShowDashboard] = useState(false);
return jsxs("div", {
className: cn("fixed top-4 right-4 z-50", className),
children: [jsxs(motion.button, {
className: cn("w-12 h-12 glass-radius-full glass-surface-primary glass-elev-3", "flex items-center justify-center glass-text-primary", "transition-all duration-300 hover:scale-105"),
onClick: () => setShowDashboard(!showDashboard),
whileHover: {
scale: 1.05
},
whileTap: {
scale: 0.95
},
children: ["\uD83C\uDF10", adaptations.length > 0 && jsx(motion.div, {
className: 'absolute glass-top-1 -right-1 w-3 h-3 glass-surface-green glass-radius-full',
initial: {
scale: 0
},
animate: prefersReducedMotion ? {} : {
scale: 1
}
})]
}), jsx(AnimatePresence, {
children: showDashboard && jsxs(motion.div, {
className: cn("absolute top-14 right-0 w-80 max-h-96 overflow-y-auto", "glass-surface-primary glass-elev-4 glass-radius-lg glass-p-4 glass-gap-3"),
initial: {
opacity: 0,
y: -10,
scale: 0.95
},
animate: prefersReducedMotion ? {} : {
opacity: 1,
y: 0,
scale: 1
},
exit: {
opacity: 0,
y: -10,
scale: 0.95
},
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsx("h3", {
className: 'glass-text-sm font-medium text-primary',
children: "Contextual Engine"
}), jsx("button", {
onClick: () => setShowDashboard(false),
className: 'glass-text-xs glass-text-secondary hover:text-primary glass-focus glass-touch-target glass-contrast-guard',
children: "\u2715"
})]
}), jsxs("div", {
className: "glass-gap-2",
children: [jsx("h4", {
className: 'glass-text-xs font-medium glass-text-secondary uppercase tracking-wide',
children: "Current Context"
}), jsxs("div", {
className: "glass-grid glass-grid-cols-2 glass-gap-2 glass-text-xs",
children: [jsxs("div", {
className: "glass-surface-secondary glass-p-2 glass-radius-sm",
children: [jsx("div", {
className: "glass-text-tertiary",
children: "Environment"
}), jsx("div", {
className: 'text-primary',
children: context.environment?.timeOfDay
}), jsxs("div", {
className: "glass-text-secondary",
children: [context.environment?.lightLevel, "lx"]
})]
}), jsxs("div", {
className: "glass-surface-secondary glass-p-2 glass-radius-sm",
children: [jsx("div", {
className: "glass-text-tertiary",
children: "Device"
}), jsx("div", {
className: 'text-primary',
children: context.device?.deviceMotion
}), jsxs("div", {
className: "glass-text-secondary",
children: [((context.device?.batteryLevel || 0) * 100).toFixed(0), "%"]
})]
})]
})]
}), topAdaptation && jsxs("div", {
className: "glass-gap-2",
children: [jsx("h4", {
className: 'glass-text-xs font-medium glass-text-secondary uppercase tracking-wide',
children: "Active Adaptation"
}), jsxs("div", {
className: "glass-p-3 glass-surface-secondary glass-radius-md",
children: [jsx("div", {
className: 'glass-text-sm text-primary font-medium mb-1',
children: topAdaptation.id.split("-")[0].replace(/([A-Z])/g, " $1").toLowerCase()
}), jsxs("div", {
className: "glass-text-xs glass-text-tertiary",
children: ["Confidence: ", (topAdaptation.confidence * 100).toFixed(0), "%"]
})]
})]
})]
})
})]
});
}
// Hook for contextually adaptive components
function useContextualAdaptation() {
const {
topAdaptation
} = useContextualEngine();
const getAdaptiveStyles = useCallback(() => {
if (!topAdaptation) return {};
const {
visual,
animation
} = topAdaptation.adaptations;
return {
filter: `brightness(${1 + visual.brightness}) contrast(${1 + visual.contrast}) saturate(${1 + visual.saturation})`,
animationDuration: `${1 / animation.speed}s`,
opacity: visual.opacity
};
}, [topAdaptation]);
return {
adaptation: topAdaptation,
getAdaptiveStyles,
isAdapting: !!topAdaptation
};
}
// Presets for different contextual scenarios
const contextualEnginePresets = {
office: {
environmentBias: {
lightLevel: 500,
ambientNoise: 45,
temperature: 22
},
adaptationSensitivity: 0.7,
learningRate: 0.1
},
home: {
environmentBias: {
lightLevel: 200,
ambientNoise: 30,
temperature: 24
},
adaptationSensitivity: 0.8,
learningRate: 0.15
},
outdoor: {
environmentBias: {
lightLevel: 20000,
ambientNoise: 60,
temperature: 18
},
adaptationSensitivity: 0.9,
learningRate: 0.05
},
transport: {
environmentBias: {
ambientNoise: 70
},
adaptationSensitivity: 0.6,
learningRate: 0.2
}
};
function ContextualEngineSummary() {
const {
context,
adaptations
} = useContextualEngine();
const {
adaptation,
getAdaptiveStyles,
isAdapting
} = useContextualAdaptation();
const environment = context?.environment;
const device = context?.device;
const safeAdaptations = Array.isArray(adaptations) ? adaptations.slice(0, 3) : [];
return jsxs("div", {
className: cn("glass-surface-primary glass-radius-2xl glass-p-6 glass-space-y-4", "glass-border glass-border-white/10 glass-shadow-soft-lg"),
style: getAdaptiveStyles(),
"data-testid": "glass-contextual-engine-summary",
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsxs("div", {
children: [jsx("p", {
className: "glass-text-xs glass-text-tertiary uppercase tracking-wide",
children: "Contextual Engine"
}), jsx("h2", {
className: "glass-text-xl glass-text-primary font-semibold",
children: isAdapting ? "Adaptive Mode" : "Learning Mode"
})]
}), jsxs("div", {
className: "glass-text-right",
children: [jsx("p", {
className: "glass-text-xs glass-text-tertiary",
children: "Battery"
}), jsx("p", {
className: "glass-text-lg glass-text-primary font-medium",
children: device?.batteryLevel ? `${Math.round(device.batteryLevel * 100)}%` : "—"
})]
})]
}), jsxs("div", {
className: "glass-grid glass-grid-cols-2 glass-gap-3",
children: [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: "Time of day"
}), jsx("p", {
className: "glass-text-lg glass-text-primary font-medium capitalize",
children: environment?.timeOfDay || "detecting"
}), jsxs("p", {
className: "glass-text-xs glass-text-secondary",
children: ["Light ", environment?.lightLevel ? `${environment.lightLevel}lx` : "—"]
})]
}), 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: "Motion"
}), jsx("p", {
className: "glass-text-lg glass-text-primary font-medium capitalize",
children: device?.deviceMotion || "idle"
}), jsx("p", {
className: "glass-text-xs glass-text-secondary",
children: environment?.temperature ? `${environment.temperature.toFixed(1)}°C` : "Analyzing ambient"
})]
})]
}), jsxs("div", {
children: [jsx("p", {
className: "glass-text-xs glass-text-tertiary uppercase tracking-wide mb-2",
children: "Active adaptations"
}), jsxs("div", {
className: "glass-flex glass-flex-wrap glass-gap-2",
children: [safeAdaptations.length === 0 && jsx("span", {
className: "glass-text-sm glass-text-secondary",
children: "Gathering signals\u2026"
}), safeAdaptations.map(item => jsx("span", {
className: "glass-text-xs glass-radius-full glass-px-3 glass-py-1 glass-surface-subtle",
children: item.id.split("-")[0]
}, item.id))]
})]
}), jsxs("div", {
className: "glass-text-xs glass-text-secondary glass-flex glass-items-center glass-justify-between",
children: [jsx("span", {
children: adaptation ? `Confidence ${(adaptation.confidence * 100).toFixed(0)}%` : "Awaiting adaptation event"
}), jsxs("span", {
children: ["Ambient noise:", " ", environment?.ambientNoise ? `${environment.ambientNoise.toFixed(0)} dB` : "—"]
})]
})]
});
}
const GlassContextualEngine = ({
className,
children,
showDashboard = true,
onContextUpdate,
onAdaptationChange,
...rest
}) => {
return jsx(GlassContextualEngineProvider, {
onContextUpdate: onContextUpdate,
onAdaptationChange: onAdaptationChange,
children: jsxs("div", {
className: cn("glass-contextual-engine-demo glass-relative glass-space-y-4", className),
...rest,
children: [children ?? jsx(ContextualEngineSummary, {}), showDashboard && jsx(GlassContextualDashboard, {})]
})
});
};
export { GlassContextualDashboard, GlassContextualEngine, GlassContextualEngineProvider, contextualEnginePresets, GlassContextualEngine as default, useContextualAdaptation, useContextualEngine };
//# sourceMappingURL=GlassContextualEngine.js.map