aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
474 lines (471 loc) • 19 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { forwardRef, useRef, useState, useEffect, useMemo } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
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 { useMotionPreference } from '../../hooks/useMotionPreference.js';
import { createGlassStyle } from '../../utils/createGlassStyle.js';
const generateWaveFunction = (x, energy, time) => {
const k = Math.sqrt(2 * energy); // Wave number
const frequency = energy / (2 * Math.PI);
return Math.sin(k * x - frequency * time);
};
const calculateTunnelingProbability = (energy, barrierHeight, barrierWidth) => {
if (energy >= barrierHeight) return 1; // Classical behavior
const kappa = Math.sqrt(2 * (barrierHeight - energy));
return Math.exp(-2 * kappa * barrierWidth);
};
const GlassQuantumTunnel = /*#__PURE__*/forwardRef(({
quantumStates,
barriers = [],
showWaveFunction = true,
showTunnelingProbability = true,
showEnergyLevels = true,
showBarriers = true,
animateTransitions = true,
tunnelingSpeed = 1,
waveAmplitude = 20,
coherenceDecay = 0.02,
realTimeMode = false,
onStateTransition,
onTunnelingEvent,
className = "",
...props
}, ref) => {
const prefersReducedMotion = useReducedMotion();
const canvasRef = useRef(null);
const [currentTime, setCurrentTime] = useState(0);
const [activeTransitions, setActiveTransitions] = useState([]);
const [measuredStates, setMeasuredStates] = useState(new Set());
const [quantumParticles, setQuantumParticles] = useState([]);
useA11yId("glass-quantum-tunnel");
const {
shouldAnimate
} = useMotionPreference();
// Initialize quantum particles
useEffect(() => {
const particles = quantumStates.map((state, index) => ({
id: `particle-${state.id}`,
x: state.position.x,
y: state.position.y,
energy: state.energy,
wavePhase: Math.random() * Math.PI * 2,
tunneling: false
}));
setQuantumParticles(particles);
}, [quantumStates]);
// Time evolution
useEffect(() => {
const interval = setInterval(() => {
setCurrentTime(prev => prev + 0.1 * tunnelingSpeed);
}, 16);
return () => clearInterval(interval);
}, [tunnelingSpeed]);
// Quantum tunneling simulation
useEffect(() => {
if (!realTimeMode) return;
const interval = setInterval(() => {
quantumStates.forEach(state => {
if (!state.isActive) return;
state.connections.forEach(connectionId => {
const targetState = quantumStates.find(s => s.id === connectionId);
if (!targetState) return;
const barrier = barriers.find(b => Math.abs(b.position.x - (state.position.x + targetState.position.x) / 2) < b.width / 2);
let tunnelingProb = 1;
if (barrier) {
tunnelingProb = calculateTunnelingProbability(state.energy, barrier.height, barrier.width);
}
// Random tunneling events
if (Math.random() < tunnelingProb * 0.1) {
setActiveTransitions(prev => [...prev, {
from: state.id,
to: connectionId,
progress: 0,
probability: tunnelingProb,
startTime: currentTime
}]);
onTunnelingEvent?.(tunnelingProb);
onStateTransition?.(state.id, connectionId);
}
});
});
}, 2000);
return () => clearInterval(interval);
}, [realTimeMode, quantumStates, barriers, currentTime, onTunnelingEvent, onStateTransition]);
// Update active transitions
useEffect(() => {
setActiveTransitions(prev => prev.map(transition => ({
...transition,
progress: Math.min(1, (currentTime - transition.startTime) / 5)
})).filter(transition => transition.progress < 1));
}, [currentTime]);
// Update quantum particles
useEffect(() => {
setQuantumParticles(prev => prev.map(particle => {
const state = quantumStates.find(s => s.id === particle.id.replace("particle-", ""));
if (!state) return particle;
// Wave function evolution
const newWavePhase = (particle.wavePhase + 0.1) % (2 * Math.PI);
// Check for active transitions
const activeTransition = activeTransitions.find(t => t.from === state.id && t.progress < 1);
if (activeTransition) {
const targetState = quantumStates.find(s => s.id === activeTransition.to);
if (targetState) {
return {
...particle,
x: state.position.x + (targetState.position.x - state.position.x) * activeTransition.progress,
y: state.position.y + (targetState.position.y - state.position.y) * activeTransition.progress,
wavePhase: newWavePhase,
tunneling: true,
targetState: activeTransition.to
};
}
}
return {
...particle,
x: state.position.x,
y: state.position.y,
wavePhase: newWavePhase,
tunneling: false,
targetState: undefined
};
}));
}, [quantumStates, activeTransitions, currentTime]);
// Canvas rendering
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw barriers
if (showBarriers) {
barriers.forEach(barrier => {
ctx.fillStyle = `rgba(255, 100, 100, ${barrier.transparency})`;
ctx.fillRect(barrier.position.x - barrier.width / 2, 50, barrier.width, barrier.height);
// Barrier label
ctx.fillStyle = "rgba(var(--glass-color-white) / var(--glass-opacity-80))";
ctx.font = "12px Arial";
ctx.textAlign = "center";
ctx.fillText(`${barrier.height.toFixed(1)} eV`, barrier.position.x, 45);
});
}
// Draw energy levels
if (showEnergyLevels) {
quantumStates.forEach(state => {
const y = 200 - state.energy * 20;
ctx.strokeStyle = "rgba(100, 200, 255, 0.6)";
ctx.lineWidth = 2;
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.moveTo(state.position.x - 30, y);
ctx.lineTo(state.position.x + 30, y);
ctx.stroke();
ctx.setLineDash([]);
});
}
// Draw wave functions
if (showWaveFunction) {
quantumParticles.forEach(particle => {
const state = quantumStates.find(s => s.id === particle.id.replace("particle-", ""));
if (!state) return;
ctx.strokeStyle = particle.tunneling ? "rgba(255, 100, 255, 0.8)" : "rgba(100, 150, 255, 0.6)";
ctx.lineWidth = 2;
ctx.beginPath();
for (let x = -50; x <= 50; x += 2) {
const waveValue = generateWaveFunction(x / 10, state.energy, currentTime + particle.wavePhase);
const y = state.position.y + waveValue * waveAmplitude;
if (x === -50) {
ctx.moveTo(particle.x + x, y);
} else {
ctx.lineTo(particle.x + x, y);
}
}
ctx.stroke();
// Probability density
ctx.fillStyle = particle.tunneling ? "rgba(255, 100, 255, 0.2)" : "rgba(100, 150, 255, 0.2)";
ctx.beginPath();
ctx.moveTo(particle.x - 50, state.position.y);
for (let x = -50; x <= 50; x += 2) {
const waveValue = generateWaveFunction(x / 10, state.energy, currentTime + particle.wavePhase);
const y = state.position.y + Math.abs(waveValue) * waveAmplitude * 0.5;
ctx.lineTo(particle.x + x, y);
}
ctx.lineTo(particle.x + 50, state.position.y);
ctx.closePath();
ctx.fill();
});
}
// Draw quantum particles
quantumParticles.forEach(particle => {
const radius = particle.tunneling ? 8 : 6;
const alpha = particle.tunneling ? 0.9 : 0.7;
ctx.beginPath();
ctx.arc(particle.x, particle.y, radius, 0, 2 * Math.PI);
const gradient = ctx.createRadialGradient(particle.x, particle.y, 0, particle.x, particle.y, radius);
gradient.addColorStop(0, `rgba(255, 255, 255, ${alpha})`);
gradient.addColorStop(1, `rgba(100, 150, 255, ${alpha * 0.3})`);
ctx.fillStyle = gradient;
ctx.fill();
// Tunneling effect
if (particle.tunneling) {
for (let i = 1; i <= 3; i++) {
ctx.beginPath();
ctx.arc(particle.x, particle.y, radius + i * 4, 0, 2 * Math.PI);
ctx.strokeStyle = `rgba(255, 100, 255, ${0.3 / i})`;
ctx.lineWidth = 2;
ctx.stroke();
}
}
});
// Draw connections
quantumStates.forEach(state => {
state.connections.forEach(connectionId => {
const targetState = quantumStates.find(s => s.id === connectionId);
if (!targetState) return;
ctx.strokeStyle = "var(--glass-bg-hover)";
ctx.lineWidth = 1;
ctx.setLineDash([3, 3]);
ctx.beginPath();
ctx.moveTo(state.position.x, state.position.y);
ctx.lineTo(targetState.position.x, targetState.position.y);
ctx.stroke();
ctx.setLineDash([]);
});
});
}, [quantumStates, quantumParticles, barriers, currentTime, showWaveFunction, showEnergyLevels, showBarriers, waveAmplitude]);
const handleStateClick = stateId => {
setMeasuredStates(prev => new Set(prev).add(stateId));
};
const totalTunnelingProbability = useMemo(() => {
return quantumStates.reduce((sum, state) => sum + state.tunnelingProbability, 0) / quantumStates.length;
}, [quantumStates]);
return jsx(OptimizedGlassCore, {
ref: ref,
variant: "frosted",
className: `relative ${className}`,
...props,
children: jsxs("div", {
className: 'glass-p-6 space-y-4',
children: [jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsxs("div", {
children: [jsx("h2", {
className: 'glass-text-xl font-semibold text-primary/90',
children: "Quantum Tunnel"
}), jsxs("p", {
className: 'glass-text-sm text-primary/60',
children: [quantumStates.length, " quantum states \u2022 ", barriers.length, " ", "barriers"]
})]
}), jsxs("div", {
className: 'glass-flex glass-items-center space-x-4',
children: [jsxs("div", {
className: 'glass-text-sm text-primary/60',
children: ["T: ", (totalTunnelingProbability * 100).toFixed(1), "%"]
}), realTimeMode && jsxs("div", {
className: 'glass-flex glass-items-center space-x-1 text-primary',
children: [jsx("div", {
className: 'w-2 h-2 glass-surface-green glass-radius-full animate-pulse'
}), jsx("span", {
className: "glass-text-xs",
children: "Live"
})]
})]
})]
}), jsxs("div", {
className: 'relative',
children: [jsx("canvas", {
ref: canvasRef,
width: 800,
height: 300,
className: "glass-border glass-border-white/20 glass-radius-lg glass-surface-dark/20"
}), jsx(AnimatePresence, {
children: quantumStates.map(state => jsxs(motion.div, {
className: `
absolute cursor-pointer transform -translate-x-1/2 -translate-y-1/2
${createGlassStyle({
opacity: 0.7
}).background}
border border-white/20 rounded-lg p-2
`,
style: {
left: state.position.x,
top: state.position.y
},
initial: {
opacity: 0,
scale: 0.8
},
animate: prefersReducedMotion ? {} : {
opacity: state.isActive ? 1 : 0.5,
scale: measuredStates.has(state.id) ? 1.2 : 1
},
whileHover: {
scale: 1.1
},
onClick: () => handleStateClick(state.id),
transition: shouldAnimate ? {
duration: 0.3
} : {
duration: 0
},
children: [jsxs("div", {
className: 'glass-flex glass-items-center space-x-2',
children: [state.icon && jsx("span", {
className: "glass-text-lg",
children: state.icon
}), jsxs("div", {
children: [jsx("div", {
className: 'glass-text-sm font-medium text-primary/90',
children: state.label
}), showTunnelingProbability && jsxs("div", {
className: 'glass-text-xs text-primary/60',
children: ["T: ", (state.tunnelingProbability * 100).toFixed(1), "%"]
})]
})]
}), measuredStates.has(state.id) && 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
},
transition: prefersReducedMotion ? {
duration: 0
} : {
duration: 0.2
}
})]
}, state.id))
}), jsx(AnimatePresence, {
children: activeTransitions.map(transition => {
const fromState = quantumStates.find(s => s.id === transition.from);
const toState = quantumStates.find(s => s.id === transition.to);
if (!fromState || !toState) return null;
const x = fromState.position.x + (toState.position.x - fromState.position.x) * transition.progress;
const y = fromState.position.y + (toState.position.y - fromState.position.y) * transition.progress;
return jsxs(motion.div, {
className: 'absolute pointer-events-none',
style: {
left: x,
top: y,
transform: "translate(-50%, -50%)"
},
initial: {
opacity: 0,
scale: 0.5
},
animate: prefersReducedMotion ? {} : {
opacity: 1,
scale: 1
},
exit: {
opacity: 0,
scale: 0.5
},
children: [jsx("div", {
className: 'w-4 h-4 bg-pink-400 glass-radius-full glass-shadow-lg animate-pulse'
}), jsxs("div", {
className: 'absolute -bottom-8 left-1/2 transform -translate-x-1/2 glass-text-xs text-pink-300 whitespace-nowrap',
children: ["Tunneling: ", (transition.probability * 100).toFixed(1), "%"]
})]
}, `${transition.from}-${transition.to}-${transition.startTime}`);
})
})]
}), jsxs("div", {
className: "glass-flex glass-items-center glass-justify-between",
children: [jsx("div", {
className: 'glass-flex glass-items-center space-x-4',
children: jsx("button", {
onClick: () => setMeasuredStates(new Set()),
className: `
px-3 py-1 rounded text-sm font-medium transition-colors duration-200
${createGlassStyle({
opacity: 0.7
}).background}
border border-white/20 text-white/70 hover:text-white
`,
children: "Reset Measurements"
})
}), jsxs("div", {
className: 'glass-flex glass-items-center space-x-6 glass-text-sm text-primary/60',
children: [jsxs("div", {
children: ["Time: ", currentTime.toFixed(1)]
}), jsxs("div", {
children: ["Active: ", activeTransitions.length]
}), jsxs("div", {
children: ["Measured: ", measuredStates.size]
})]
})]
}), jsxs("div", {
className: `
p-4 rounded-lg border border-white/10 space-y-3
${createGlassStyle({
opacity: 0.7
}).background}
`,
children: [jsx("h3", {
className: 'glass-text-sm font-semibold text-primary/90',
children: "Quantum Statistics"
}), jsxs("div", {
className: 'glass-grid glass-grid-cols-2 md:grid-cols-4 glass-gap-4 glass-text-sm',
children: [jsxs("div", {
children: [jsx("span", {
className: 'text-primary/60',
children: "Avg Tunneling:"
}), jsxs("div", {
className: 'text-primary/90 font-medium',
children: [(totalTunnelingProbability * 100).toFixed(1), "%"]
})]
}), jsxs("div", {
children: [jsx("span", {
className: 'text-primary/60',
children: "Wave Coherence:"
}), jsxs("div", {
className: 'text-primary/90 font-medium',
children: [(Math.cos(currentTime * 0.5) * 50 + 50).toFixed(0), "%"]
})]
}), jsxs("div", {
children: [jsx("span", {
className: 'text-primary/60',
children: "Energy Spread:"
}), jsxs("div", {
className: 'text-primary/90 font-medium',
children: [quantumStates.length > 0 ? (Math.max(...quantumStates.map(s => s.energy)) - Math.min(...quantumStates.map(s => s.energy))).toFixed(1) : "0", " ", "eV"]
})]
}), jsxs("div", {
children: [jsx("span", {
className: 'text-primary/60',
children: "Barrier Count:"
}), jsx("div", {
className: 'text-primary/90 font-medium',
children: barriers.length
})]
})]
}), activeTransitions.length > 0 && jsxs("div", {
className: 'space-y-1',
children: [jsx("span", {
className: 'text-primary/60 glass-text-sm',
children: "Active Tunneling:"
}), jsx("div", {
className: "glass-flex glass-flex-wrap glass-gap-1",
children: activeTransitions.slice(-3).map((transition, index) => jsxs("div", {
className: 'glass-px-2 glass-py-1 glass-text-xs bg-pink-500/20 text-pink-300 glass-radius glass-border glass-border-pink-400/20',
children: [transition.from, " \u2192 ", transition.to, " (", (transition.probability * 100).toFixed(0), "%)"]
}, index))
})]
})]
})]
})
});
});
export { GlassQuantumTunnel };
//# sourceMappingURL=GlassQuantumTunnel.js.map