UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

925 lines (922 loc) 32.7 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { useRef, useState, useEffect, useCallback, useContext, forwardRef, createContext } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { cn } from '../../lib/utilsComprehensive.js'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import '../../primitives/motion/MotionFramer.js'; import { useA11yId } from '../../utils/a11y.js'; import { useMotionPreferenceContext } from '../../contexts/MotionPreferenceContext.js'; const IS_TEST_ENV = typeof process !== "undefined" && process.env?.JEST_WORKER_ID !== undefined; // Biometric sensor integration class BiometricSensorManager { constructor() { this.heartRateSensor = null; this.accelerometer = null; this.gyroscope = null; this.ambientLightSensor = null; this.isSupported = false; this.readings = []; this.listeners = []; this.behavioralCleanupCallbacks = []; } async initialize() { // CRITICAL SSR FIX: Skip all sensor initialization on server if (typeof window === "undefined") { console.warn("BiometricSensorManager: Skipping initialization on server"); return false; } this.cleanupBehavioralAnalysis(); try { // Check for Generic Sensor API support if ("Accelerometer" in window) { this.accelerometer = new window.Accelerometer({ frequency: 10 }); this.accelerometer.addEventListener("reading", this.handleAccelerometer.bind(this)); this.accelerometer.start?.(); } if ("Gyroscope" in window) { this.gyroscope = new window.Gyroscope({ frequency: 10 }); this.gyroscope.addEventListener("reading", this.handleGyroscope.bind(this)); this.gyroscope.start?.(); } if ("AmbientLightSensor" in window) { this.ambientLightSensor = new window.AmbientLightSensor({ frequency: 2 }); this.ambientLightSensor.addEventListener("reading", this.handleAmbientLight.bind(this)); this.ambientLightSensor.start?.(); } // Check for Web Bluetooth (for heart rate monitors) if ("bluetooth" in navigator) { this.isSupported = true; } } catch (error) { console.warn("Biometric sensors not available, using behavioral analysis:", error); } // Always fall back to behavioral analysis so component still works this.setupBehavioralAnalysis(); return true; } setupBehavioralAnalysis() { // CRITICAL SSR FIX: Skip document access on server if (typeof document === "undefined" || typeof window === "undefined") { return; } this.cleanupBehavioralAnalysis(); // Track mouse/touch patterns for stress indicators let lastClickTime = 0; let clickCount = 0; let mouseMovements = []; let errorCount = 0; const handleClick = () => { const now = Date.now(); if (now - lastClickTime < 500) { clickCount++; } else { clickCount = 0; } lastClickTime = now; if (clickCount > 5) { this.reportStressIndicator("rapidClicking", 0.8); } }; document.addEventListener("click", handleClick); this.behavioralCleanupCallbacks.push(() => document.removeEventListener("click", handleClick)); const handleMouseMove = e => { mouseMovements.push({ x: e.clientX, y: e.clientY, timestamp: Date.now() }); // Keep only recent movements if (mouseMovements.length > 10) { mouseMovements = mouseMovements.slice(-5); } // Analyze movement patterns if (mouseMovements.length > 3) { const movements = mouseMovements.slice(-3); const distances = movements.map((point, i) => { if (i === 0) return 0; const prev = movements[i - 1]; return Math.sqrt(Math.pow(point.x - prev.x, 2) + Math.pow(point.y - prev.y, 2)); }); const avgDistance = distances.reduce((sum, d) => sum + d, 0) / distances.length; const timeDiff = movements[movements.length - 1].timestamp - movements[0].timestamp; const speed = timeDiff === 0 ? 0 : avgDistance / timeDiff; // Irregular, jittery movement indicates stress if (speed > 2 && avgDistance < 50) { this.reportStressIndicator("irregularMovement", 0.6); } } }; document.addEventListener("mousemove", handleMouseMove); this.behavioralCleanupCallbacks.push(() => document.removeEventListener("mousemove", handleMouseMove)); const handleWindowError = () => { errorCount++; this.reportStressIndicator("errorFrequency", Math.min(1, errorCount * 0.2)); }; window.addEventListener("error", handleWindowError); this.behavioralCleanupCallbacks.push(() => window.removeEventListener("error", handleWindowError)); const intervalId = window.setInterval(() => this.analyzeBehavioralPatterns(), 5000); this.behavioralCleanupCallbacks.push(() => window.clearInterval(intervalId)); } cleanupBehavioralAnalysis() { if (!this.behavioralCleanupCallbacks.length) { return; } this.behavioralCleanupCallbacks.forEach(cleanup => { try { cleanup(); } catch (error) { console.warn("Failed to cleanup behavioral analysis handler:", error); } }); this.behavioralCleanupCallbacks = []; } handleAccelerometer() { if (!this.accelerometer) return; const { x, y, z } = this.accelerometer; const acceleration = Math.sqrt(x * x + y * y + z * z); // High acceleration might indicate stress/agitation if (acceleration > 15) { this.reportBiometricReading({ stressLevel: Math.min(1, acceleration / 30), timestamp: Date.now(), confidence: 0.6 }); } } handleGyroscope() { if (!this.gyroscope) return; const { x, y, z } = this.gyroscope; const rotation = Math.sqrt(x * x + y * y + z * z); // Rapid device rotation might indicate stress if (rotation > 5) { this.reportStressIndicator("deviceMovement", Math.min(1, rotation / 10)); } } handleAmbientLight() { if (!this.ambientLightSensor) return; const { illuminance } = this.ambientLightSensor; // Very low light might indicate late hours / stress if (illuminance < 10) { this.reportStressIndicator("lowLight", 0.3); } } reportStressIndicator(type, level) { this.reportBiometricReading({ stressLevel: level, timestamp: Date.now(), confidence: 0.5 }); } analyzeBehavioralPatterns() { const now = Date.now(); const recentReadings = this.readings.filter(r => now - r.timestamp < 30000); // Last 30 seconds if (recentReadings.length === 0) return; // Calculate average stress level const avgStress = recentReadings.reduce((sum, r) => sum + (r.stressLevel || 0), 0) / recentReadings.length; // Generate composite reading this.reportBiometricReading({ stressLevel: avgStress, heartRate: this.estimateHeartRateFromBehavior(avgStress), timestamp: now, confidence: 0.7 }); } estimateHeartRateFromBehavior(stressLevel) { // Rough estimation: normal resting HR + stress factor const baselineHR = 70; return Math.round(baselineHR + stressLevel * 30); } reportBiometricReading(reading) { this.readings.push(reading); // Keep only recent readings if (this.readings.length > 100) { this.readings = this.readings.slice(-50); } // Notify listeners this.listeners.forEach(listener => listener(reading)); } async connectHeartRateMonitor() { // CRITICAL SSR FIX: Skip bluetooth access on server if (typeof navigator === 'undefined') { console.warn('BiometricSensorManager: Bluetooth not available on server'); return false; } try { if (!("bluetooth" in navigator)) { throw new Error("Web Bluetooth not supported"); } const device = await navigator.bluetooth.requestDevice({ filters: [{ services: ["heart_rate"] }], optionalServices: ["heart_rate"] }); const server = await device.gatt.connect(); const service = await server.getPrimaryService("heart_rate"); const characteristic = await service.getCharacteristic("heart_rate_measurement"); await characteristic.startNotifications(); characteristic.addEventListener("characteristicvaluechanged", event => { const value = event.target.value; const heartRate = value.getUint16(1, true); this.reportBiometricReading({ heartRate, timestamp: Date.now(), confidence: 0.9 }); }); return true; } catch (error) { console.warn("Failed to connect heart rate monitor:", error); return false; } } addListener(listener) { this.listeners.push(listener); return () => { const index = this.listeners.indexOf(listener); if (index > -1) { this.listeners.splice(index, 1); } }; } getLatestReading() { return this.readings.length > 0 ? this.readings[this.readings.length - 1] : null; } getReadingHistory(duration = 300000) { const cutoff = Date.now() - duration; return this.readings.filter(r => r.timestamp > cutoff); } cleanup() { if (this.accelerometer) { this.accelerometer.stop(); } if (this.gyroscope) { this.gyroscope.stop(); } if (this.ambientLightSensor) { this.ambientLightSensor.stop(); } this.listeners = []; this.readings = []; this.cleanupBehavioralAnalysis(); } } // Adaptive UI engine class BiometricAdaptationEngine { constructor(settings = {}) { this.adaptationCallbacks = new Map(); this.currentAdaptations = new Map(); this.sensorManager = new BiometricSensorManager(); this.settings = { sensitivity: 0.7, responseSpeed: 1000, enableColorAdaptation: true, enableMotionAdaptation: true, enableLayoutAdaptation: true, enableAudioAdaptation: true, stressThreshold: 0.7, calmingThreshold: 0.3, ...settings }; this.profile = { userId: "default", baselineHeartRate: 70, stressPatterns: [], preferences: { calmingColors: ["var(--glass-color-primary)", "#06b6d4", "var(--glass-color-success)", "#8b5cf6"], stressColors: ["var(--glass-color-danger)", "var(--glass-color-warning)", "#ec4899"], calmingAnimations: ["gentle", "slow", "smooth"], stressAnimations: ["fast", "sharp", "intense"] }, history: [] }; } async initialize() { const success = await this.sensorManager.initialize(); if (success) { this.sensorManager.addListener(this.handleBiometricReading.bind(this)); this.loadProfile(); } return success; } handleBiometricReading(reading) { this.profile.history.push(reading); // Keep history manageable if (this.profile.history.length > 1000) { this.profile.history = this.profile.history.slice(-500); } // Determine adaptation needed const adaptations = this.determineAdaptations(reading); // Apply adaptations with debouncing this.debounceAdaptations(adaptations); } determineAdaptations(reading) { const adaptations = new Map(); const stressLevel = reading.stressLevel || 0; // Color adaptations if (this.settings.enableColorAdaptation) { if (stressLevel > this.settings.stressThreshold) { adaptations.set("color", { type: "calming", intensity: stressLevel, colors: this.profile.preferences.calmingColors }); } else if (stressLevel < this.settings.calmingThreshold) { adaptations.set("color", { type: "energizing", intensity: 1 - stressLevel, colors: this.profile.preferences.stressColors }); } } // Motion adaptations if (this.settings.enableMotionAdaptation) { if (stressLevel > this.settings.stressThreshold) { adaptations.set("motion", { type: "calming", speed: Math.max(0.5, 1 - stressLevel), amplitude: Math.max(0.3, 1 - stressLevel) }); } else { adaptations.set("motion", { type: "normal", speed: 1, amplitude: 1 }); } } // Layout adaptations if (this.settings.enableLayoutAdaptation && stressLevel > this.settings.stressThreshold) { adaptations.set("layout", { type: "simplified", density: Math.max(0.5, 1 - stressLevel), spacing: Math.min(2, 1 + stressLevel) }); } // Audio adaptations if (this.settings.enableAudioAdaptation) { if (stressLevel > this.settings.stressThreshold) { adaptations.set("audio", { type: "calming", volume: Math.max(0.1, 0.5 - stressLevel * 0.3), frequency: "low" }); } } return adaptations; } debounceAdaptations(adaptations) { adaptations.forEach((adaptation, type) => { const existingTimeout = this.currentAdaptations.get(`${type}_timeout`); if (existingTimeout) { clearTimeout(existingTimeout); } const timeout = setTimeout(() => { this.applyAdaptation(type, adaptation); this.currentAdaptations.delete(`${type}_timeout`); }, this.settings.responseSpeed); this.currentAdaptations.set(`${type}_timeout`, timeout); }); } applyAdaptation(type, adaptation) { this.currentAdaptations.set(type, adaptation); const callback = this.adaptationCallbacks.get(type); if (callback) { callback(adaptation); } } registerAdaptationCallback(type, callback) { this.adaptationCallbacks.set(type, callback); } unregisterAdaptationCallback(type) { this.adaptationCallbacks.delete(type); } getCurrentAdaptation(type) { return this.currentAdaptations.get(type); } async connectHeartRateMonitor() { return this.sensorManager.connectHeartRateMonitor(); } getLatestReading() { return this.sensorManager.getLatestReading(); } getProfile() { return { ...this.profile }; } updateSettings(settings) { this.settings = { ...this.settings, ...settings }; } loadProfile() { // CRITICAL SSR FIX: Skip localStorage access on server if (typeof localStorage === 'undefined') { return; } try { const stored = localStorage.getItem("auraglass-biometric-profile"); if (stored) { const data = JSON.parse(stored); this.profile = { ...this.profile, ...data }; } } catch (error) { console.warn("Failed to load biometric profile:", error); } } saveProfile() { // CRITICAL SSR FIX: Skip localStorage access on server if (typeof localStorage === 'undefined') { return; } try { localStorage.setItem("auraglass-biometric-profile", JSON.stringify(this.profile)); } catch (error) { console.warn("Failed to save biometric profile:", error); } } cleanup() { this.sensorManager.cleanup(); this.adaptationCallbacks.clear(); this.currentAdaptations.clear(); this.saveProfile(); } } // React context const BiometricAdaptationContext = /*#__PURE__*/createContext({ engine: null, isInitialized: false, latestReading: null, currentStressLevel: 0, connectHeartRateMonitor: async () => false }); // Provider component function GlassBiometricAdaptationProvider({ children, settings, autoInitialize = true }) { const engineRef = useRef(); const [isInitialized, setIsInitialized] = useState(false); const [latestReading, setLatestReading] = useState(null); const [currentStressLevel, setCurrentStressLevel] = useState(0); useEffect(() => { const engine = new BiometricAdaptationEngine(settings); engineRef.current = engine; let isMounted = true; let interval; const finalizeInitialization = success => { if (isMounted) { setIsInitialized(success); } }; if (autoInitialize) { if (IS_TEST_ENV) { finalizeInitialization(true); } else { engine.initialize().then(finalizeInitialization).catch(() => finalizeInitialization(false)); } } if (!IS_TEST_ENV) { interval = setInterval(() => { if (!engineRef.current || !isMounted) { return; } const reading = engineRef.current.getLatestReading(); if (reading) { setLatestReading(reading); setCurrentStressLevel(reading.stressLevel || 0); } }, 1000); } return () => { isMounted = false; if (interval) { clearInterval(interval); } if (engineRef.current === engine) { engineRef.current.cleanup(); engineRef.current = undefined; } else { engine.cleanup(); } }; }, [autoInitialize, settings]); const connectHeartRateMonitor = useCallback(async () => { if (!engineRef.current) return false; return engineRef.current.connectHeartRateMonitor(); }, []); const value = { engine: engineRef.current || null, isInitialized, latestReading, currentStressLevel, connectHeartRateMonitor }; return jsx(BiometricAdaptationContext.Provider, { value: value, children: children }); } // Hook to use biometric adaptation function useBiometricAdaptation() { const context = useContext(BiometricAdaptationContext); if (!context) { throw new Error("useBiometricAdaptation must be used within GlassBiometricAdaptationProvider"); } return context; } class BiometricStressDetector extends BiometricAdaptationEngine { getStressLevel() { return this.getLatestReading()?.stressLevel ?? 0; } getConfidence() { return this.getLatestReading()?.confidence ?? 0; } } // Stress-responsive glass component const GlassStressResponsive = /*#__PURE__*/forwardRef(function GlassStressResponsive({ children, className, adaptationType = "all", respectMotionPreference = true, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role, ...restProps }, ref) { const { engine, currentStressLevel, latestReading } = useBiometricAdaptation(); const [adaptations, setAdaptations] = useState({}); const { prefersReducedMotion } = useMotionPreferenceContext(); const stressId = useA11yId("stress-responsive"); const descriptionId = useA11yId("stress-description"); useEffect(() => { if (!engine) return; const handleColorAdaptation = adaptation => { if (adaptationType === "color" || adaptationType === "all") { setAdaptations(prev => ({ ...prev, color: adaptation })); } }; const handleMotionAdaptation = adaptation => { if (adaptationType === "motion" || adaptationType === "all") { setAdaptations(prev => ({ ...prev, motion: adaptation })); } }; const handleLayoutAdaptation = adaptation => { if (adaptationType === "layout" || adaptationType === "all") { setAdaptations(prev => ({ ...prev, layout: adaptation })); } }; engine.registerAdaptationCallback("color", handleColorAdaptation); engine.registerAdaptationCallback("motion", handleMotionAdaptation); engine.registerAdaptationCallback("layout", handleLayoutAdaptation); return () => { engine.unregisterAdaptationCallback("color"); engine.unregisterAdaptationCallback("motion"); engine.unregisterAdaptationCallback("layout"); }; }, [engine, adaptationType]); // Calculate adaptive styles const colorAdaptation = adaptations.color; const motionAdaptation = adaptations.motion; const layoutAdaptation = adaptations.layout; const adaptiveStyles = {}; if (colorAdaptation) { if (colorAdaptation.type === "calming") { const calmColor = colorAdaptation.colors[0] || "var(--glass-color-primary)"; adaptiveStyles.backgroundColor = `${calmColor}20`; adaptiveStyles.borderColor = `${calmColor}40`; } } const motionSpeed = motionAdaptation?.speed || 1; const layoutSpacing = layoutAdaptation?.spacing || 1; const shouldAnimate = respectMotionPreference ? !prefersReducedMotion : true; return jsx(motion.div, { ref: ref, style: adaptiveStyles, animate: shouldAnimate ? { scale: 1 + (currentStressLevel > 0.7 ? -0.02 : 0.01) * currentStressLevel, padding: `${8 * layoutSpacing}px` } : {}, transition: shouldAnimate ? { duration: 2 / motionSpeed, ease: currentStressLevel > 0.7 ? "easeOut" : "easeInOut" } : {}, id: stressId, role: role || "region", "aria-label": ariaLabel || `Stress-responsive interface (${Math.round(currentStressLevel * 100)}% stress level)`, "aria-describedby": ariaDescribedBy || descriptionId, "aria-live": "polite", className: cn("glass-surface glass-border glass-radius-md glass-glass-backdrop-blur-md glass-contrast-guard transition-all duration-1000", currentStressLevel > 0.7 ? "glass-surface-subtle glass-border-subtle" : "glass-surface-medium glass-border-medium", currentStressLevel > 0.7 && "calming-mode", className), ...restProps, children: jsxs(OptimizedGlassCore, { children: [jsxs("span", { id: descriptionId, className: 'sr-only', children: ["Biometric adaptation interface responding to stress level", " ", Math.round(currentStressLevel * 100), "%.", adaptationType !== "all" ? ` Adaptation type: ${adaptationType}` : " All adaptations active."] }), children, jsx("div", { className: "glass-absolute glass-top-2 glass-right-2 glass-opacity-30", children: jsx("div", { className: cn("glass-w-2 glass-h-2 glass-radius-full glass-transition", currentStressLevel > 0.7 ? "glass-surface-danger" : currentStressLevel > 0.4 ? "glass-surface-warning" : "glass-surface-success"), "aria-hidden": true }) })] }) }); }); // Biometric dashboard const GlassBiometricDashboard = /*#__PURE__*/forwardRef(function GlassBiometricDashboard({ className, show = true, "aria-label": ariaLabel, role, ...restProps }, ref) { const { latestReading, currentStressLevel, connectHeartRateMonitor, engine } = useBiometricAdaptation(); const [history, setHistory] = useState([]); const [showDetails, setShowDetails] = useState(false); const dashboardId = useA11yId("biometric-dashboard"); useEffect(() => { if (!engine) return; const interval = setInterval(() => { const readings = engine.getLatestReading(); if (readings) { setHistory(prev => [...prev.slice(-19), readings]); // Keep last 20 readings } }, 2000); return () => clearInterval(interval); }, [engine]); if (!show) return null; return jsxs(OptimizedGlassCore, { ref: ref, intensity: "subtle", glassBlur: "strong", className: cn("fixed top-4 left-4 glass-p-4 glass-radius-lg", className), id: dashboardId, role: role || "region", "aria-label": ariaLabel || "Biometric monitoring dashboard", ...restProps, children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between glass-mb-3", children: [jsx("h3", { className: 'glass-text-sm font-medium glass-text-secondary dark:glass-text-secondary', children: "Biometrics" }), jsx("button", { onClick: () => setShowDetails(!showDetails), className: 'glass-text-xs glass-text-secondary hover:glass-text-secondary glass-focus glass-touch-target glass-contrast-guard', "aria-expanded": showDetails, "aria-controls": `${dashboardId}-details`, children: showDetails ? "−" : "+" })] }), jsxs("div", { className: "glass-gap-2", children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsx("span", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: "Stress Level" }), jsxs("div", { className: "glass-flex glass-items-center glass-gap-2", children: [jsx("div", { className: "glass-w-16 glass-h-2 glass-surface-subtle glass-radius-full glass-overflow-hidden", children: jsx(motion.div, { className: cn("glass-h-full glass-radius-full glass-transition", currentStressLevel > 0.7 ? "glass-surface-danger" : currentStressLevel > 0.4 ? "glass-surface-warning" : "glass-surface-success"), animate: { width: `${currentStressLevel * 100}%` }, transition: { duration: 0.5 } }) }), jsxs("span", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: [(currentStressLevel * 100).toFixed(0), "%"] })] })] }), latestReading?.heartRate && jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsx("span", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: "Heart Rate" }), jsxs("span", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: [latestReading.heartRate, " bpm"] })] })] }), jsx(AnimatePresence, { children: showDetails && jsxs(motion.div, { id: `${dashboardId}-details`, className: 'glass-mt-4 pt-4 glass-border-t glass-border-white/10 glass-gap-3', initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.3 }, children: [jsxs("div", { children: [jsx("div", { className: "glass-text-xs glass-text-secondary glass-mb-2", children: "Stress History" }), jsx("div", { className: "glass-relative glass-h-12 glass-surface-primary/50 glass-radius-md", children: history.map((reading, index) => jsx("div", { ref: el => { if (!el) return; el.style.left = `${index / (history.length - 1) * 100}%`; el.style.height = `${(reading.stressLevel || 0) * 100}%`; el.style.backgroundColor = (reading.stressLevel || 0) > 0.7 ? "var(--glass-color-danger)" : (reading.stressLevel || 0) > 0.4 ? "var(--glass-color-warning)" : "var(--glass-color-success)"; }, className: "glass-absolute glass-bottom-0 glass-w-1 glass-radius-md" }, index)) })] }), jsx("div", { children: jsx("button", { onClick: connectHeartRateMonitor, className: cn("glass-w-full glass-px-3 glass-py-2 glass-text-xs glass-surface-subtle glass-radius-md glass-focus glass-touch-target glass-contrast-guard", "glass-text-secondary hover:glass-surface-subtle glass-transition"), children: "Connect Heart Rate Monitor" }) }), engine && jsxs("div", { children: [jsx("div", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary mb-2', children: "Active Adaptations" }), jsx("div", { className: "glass-gap-1", children: ["color", "motion", "layout", "audio"].map(type => { const adaptation = engine.getCurrentAdaptation(type); return adaptation ? jsxs("div", { className: "glass-flex glass-items-center glass-justify-between glass-text-xs", children: [jsx("span", { className: 'glass-text-secondary dark:glass-text-secondary capitalize', children: type }), jsx("span", { className: 'glass-text-secondary dark:glass-text-secondary capitalize', children: adaptation.type })] }, type) : null; }) })] }), latestReading && jsxs("div", { children: [jsx("div", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary mb-1', children: "Last Reading" }), jsx("div", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: new Date(latestReading.timestamp).toLocaleTimeString() }), jsxs("div", { className: 'glass-text-xs glass-text-secondary dark:glass-text-secondary', children: ["Confidence: ", (latestReading.confidence * 100).toFixed(0), "%"] })] })] }) })] }); }); // Presets for different adaptation modes const biometricAdaptationPresets = { subtle: { sensitivity: 0.3, responseSpeed: 2000, stressThreshold: 0.8, calmingThreshold: 0.2 }, standard: { sensitivity: 0.7, responseSpeed: 1000, stressThreshold: 0.7, calmingThreshold: 0.3 }, sensitive: { sensitivity: 0.9, responseSpeed: 500, stressThreshold: 0.5, calmingThreshold: 0.4 }, accessibility: { sensitivity: 0.8, responseSpeed: 1500, enableColorAdaptation: true, enableMotionAdaptation: true, enableLayoutAdaptation: true, stressThreshold: 0.6 } }; function BiometricSummaryCard() { const { latestReading, currentStressLevel, isInitialized } = useBiometricAdaptation(); 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"), "data-testid": "glass-biometric-summary", children: [jsxs("div", { children: [jsx("p", { className: "glass-text-xs glass-text-tertiary uppercase tracking-wide", children: "Biometric adaptation" }), jsx("h2", { className: "glass-text-2xl glass-text-primary font-semibold", children: isInitialized ? "Monitoring" : "Initializing" }), jsxs("p", { className: "glass-text-sm glass-text-secondary", children: ["Stress level ", (currentStressLevel * 100).toFixed(0), "%"] })] }), 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: "Heart rate" }), jsx("p", { className: "glass-text-lg glass-text-primary font-semibold", children: latestReading?.heartRate ? `${latestReading.heartRate.toFixed(0)} bpm` : "—" })] }), 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: "Respiratory" }), jsx("p", { className: "glass-text-lg glass-text-primary font-semibold", children: latestReading?.respiratoryRate ? `${latestReading.respiratoryRate.toFixed(0)} rpm` : "—" })] })] }), jsxs("div", { className: "glass-text-xs glass-text-secondary", children: ["Confidence", " ", latestReading ? `${Math.round((latestReading.confidence || 0) * 100)}%` : "Collecting signals"] })] }); } const GlassBiometricAdaptation = ({ settings, autoInitialize = true, showDashboard = true, className, children, ...rest }) => jsx(GlassBiometricAdaptationProvider, { settings: settings, autoInitialize: autoInitialize, children: jsxs("div", { className: cn("glass-biometric-adaptation glass-relative glass-space-y-4", className), ...rest, children: [children ?? jsx(BiometricSummaryCard, {}), showDashboard && jsx(GlassBiometricDashboard, {})] }) }); export { BiometricAdaptationEngine, BiometricStressDetector, GlassBiometricAdaptation, GlassBiometricAdaptationProvider, GlassBiometricDashboard, GlassStressResponsive, biometricAdaptationPresets, GlassBiometricAdaptation as default, useBiometricAdaptation }; //# sourceMappingURL=GlassBiometricAdaptation.js.map