anycoder-5c0ba8a1 / index.html
drkasi's picture
Upload folder using huggingface_hub
e049f7b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lumina Calc | Glassmorphism Scientific Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@300;400;600&display=swap" rel="stylesheet">
<style>
/* Custom Glassmorphism & Animations */
body {
background: radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%),
radial-gradient(at 50% 0%, hsla(225,39%,30%,1) 0, transparent 50%),
radial-gradient(at 100% 0%, hsla(339,49%,30%,1) 0, transparent 50%);
background-color: #0f172a;
font-family: 'Inter', sans-serif;
overflow: hidden; /* Prevent scroll on body, handle in app */
}
.glass-panel {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
}
.calc-btn {
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.calc-btn::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.3s ease-out, height 0.3s ease-out;
}
.calc-btn:active::after {
width: 200%;
height: 200%;
}
.calc-btn:active {
transform: scale(0.95);
}
.display-font {
font-family: 'JetBrains Mono', monospace;
}
/* Scrollbar for history */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.02);
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.2);
}
/* Floating shapes for background animation */
.blob {
position: absolute;
filter: blur(80px);
z-index: -1;
opacity: 0.6;
animation: float 10s infinite ease-in-out;
}
@keyframes float {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(20px, -20px); }
}
</style>
</head>
<body class="h-screen w-screen flex items-center justify-center text-white selection:bg-pink-500 selection:text-white">
<!-- Background Blobs -->
<div class="blob bg-purple-600 w-96 h-96 rounded-full top-0 left-0 mix-blend-multiply filter blur-3xl opacity-30 animate-blob"></div>
<div class="blob bg-cyan-600 w-96 h-96 rounded-full top-0 right-0 mix-blend-multiply filter blur-3xl opacity-30 animate-blob animation-delay-2000"></div>
<div class="blob bg-pink-600 w-96 h-96 rounded-full -bottom-32 left-20 mix-blend-multiply filter blur-3xl opacity-30 animate-blob animation-delay-4000"></div>
<!-- Main Application Container -->
<main class="relative w-full max-w-5xl h-full max-h-[90vh] flex flex-col md:flex-row gap-6 p-4 md:p-8">
<!-- Header / Branding -->
<div class="absolute top-4 left-6 z-50 flex items-center gap-2 opacity-80 hover:opacity-100 transition-opacity">
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
<span class="ml-2 text-xs font-bold tracking-widest text-gray-400 uppercase">Lumina Calc v1.0</span>
</div>
<div class="absolute top-4 right-6 z-50">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs font-semibold text-cyan-400 hover:text-cyan-300 transition-colors border border-cyan-500/30 px-3 py-1 rounded-full bg-cyan-900/20 backdrop-blur-sm">
Built with anycoder
</a>
</div>
<!-- Calculator Unit -->
<section class="flex-1 glass-panel rounded-3xl flex flex-col p-6 shadow-2xl relative overflow-hidden">
<!-- Display Screen -->
<div class="flex flex-col justify-end items-end h-40 mb-6 px-4 py-2 bg-black/20 rounded-2xl border border-white/5 shadow-inner">
<div id="previous-operand" class="display-font text-gray-400 text-sm h-6 overflow-hidden"></div>
<div id="current-operand" class="display-font text-5xl font-bold tracking-tight break-all text-transparent bg-clip-text bg-gradient-to-r from-white to-gray-300">0</div>
</div>
<!-- Keypad -->
<div class="grid grid-cols-4 gap-3 md:gap-4 flex-1">
<!-- Row 1 -->
<button data-action="clear" class="calc-btn col-span-1 bg-red-500/20 text-red-300 border border-red-500/30 rounded-2xl text-lg font-semibold hover:bg-red-500/30">AC</button>
<button data-action="delete" class="calc-btn col-span-1 bg-white/5 text-white border border-white/10 rounded-2xl text-lg font-semibold hover:bg-white/10">DEL</button>
<button data-action="percent" class="calc-btn bg-white/5 text-cyan-300 border border-white/10 rounded-2xl text-xl font-semibold hover:bg-white/10">%</button>
<button data-operation="÷" class="calc-btn bg-indigo-600/40 text-white border border-indigo-500/30 rounded-2xl text-2xl font-semibold hover:bg-indigo-600/60">÷</button>
<!-- Row 2 -->
<button data-number="7" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">7</button>
<button data-number="8" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">8</button>
<button data-number="9" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">9</button>
<button data-operation="×" class="calc-btn bg-indigo-600/40 text-white border border-indigo-500/30 rounded-2xl text-2xl font-semibold hover:bg-indigo-600/60">×</button>
<!-- Row 3 -->
<button data-number="4" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">4</button>
<button data-number="5" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">5</button>
<button data-number="6" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">6</button>
<button data-operation="-" class="calc-btn bg-indigo-600/40 text-white border border-indigo-500/30 rounded-2xl text-2xl font-semibold hover:bg-indigo-600/60">-</button>
<!-- Row 4 -->
<button data-number="1" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">1</button>
<button data-number="2" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">2</button>
<button data-number="3" class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">3</button>
<button data-operation="+" class="calc-btn bg-indigo-600/40 text-white border border-indigo-500/30 rounded-2xl text-2xl font-semibold hover:bg-indigo-600/60">+</button>
<!-- Row 5 -->
<button data-number="0" class="calc-btn col-span-2 bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">0</button>
<button data-number="." class="calc-btn bg-white/5 text-white border border-white/10 rounded-2xl text-2xl font-medium hover:bg-white/10">.</button>
<button data-action="equals" class="calc-btn bg-gradient-to-br from-cyan-500 to-blue-600 text-white border border-cyan-400/50 rounded-2xl text-2xl font-bold shadow-lg shadow-cyan-500/20 hover:shadow-cyan-500/40 hover:scale-[1.02]">=</button>
</div>
</section>
<!-- History Sidebar (Collapsible on mobile, visible on desktop) -->
<aside class="w-full md:w-80 glass-panel rounded-3xl p-6 flex flex-col hidden md:flex">
<div class="flex justify-between items-center mb-4 border-b border-white/10 pb-4">
<h2 class="text-lg font-semibold text-gray-200 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
History Tape
</h2>
<button id="clear-history" class="text-xs text-red-400 hover:text-red-300 uppercase tracking-wider font-bold">Clear</button>
</div>
<div id="history-list" class="flex-1 overflow-y-auto space-y-3 pr-2">
<!-- History items injected here -->
<div class="text-center text-gray-500 text-sm mt-10 italic">No calculations yet</div>
</div>
</aside>
</main>
<script>
// --- Audio Engine (Tone.js) ---
let synth;
let audioInitialized = false;
async function initAudio() {
if (audioInitialized) return;
await Tone.start();
// Create a simple membrane synth for a pleasant "click" sound
synth = new Tone.MembraneSynth({
pitchDecay: 0.008,
octaves: 2,
oscillator: { type: "sine" },
envelope: {
attack: 0.001,
decay: 0.1,
sustain: 0,
release: 0.1
}
}).toDestination();
// Lower volume
synth.volume.value = -10;
audioInitialized = true;
}
function playClickSound(type) {
if (!audioInitialized) initAudio();
if (!synth) return;
try {
if (type === 'number') synth.triggerAttackRelease("C2", "32n");
else if (type === 'operator') synth.triggerAttackRelease("E2", "32n");
else if (type === 'action') synth.triggerAttackRelease("A1", "16n");
else if (type === 'equals') synth.triggerAttackRelease("C3", "16n");
} catch (e) {
console.log("Audio context not ready yet");
}
}
// --- Calculator Logic ---
class Calculator {
constructor(previousOperandTextElement, currentOperandTextElement, historyListElement) {
this.previousOperandTextElement = previousOperandTextElement;
this.currentOperandTextElement = currentOperandTextElement;
this.historyListElement = historyListElement;
this.clear();
this.history = [];
}
clear() {
this.currentOperand = '0';
this.previousOperand = '';
this.operation = undefined;
this.shouldResetScreen = false;
}
delete() {
if (this.shouldResetScreen) return;
if (this.currentOperand === '0') return;
this.currentOperand = this.currentOperand.toString().slice(0, -1);
if (this.currentOperand === '' || this.currentOperand === '-') {
this.currentOperand = '0';
}
}
appendNumber(number) {
if (this.shouldResetScreen) {
this.currentOperand = '';
this.shouldResetScreen = false;
}
// Prevent multiple decimals
if (number === '.' && this.currentOperand.includes('.')) return;
// Prevent multiple leading zeros
if (number === '0' && this.currentOperand === '0') return;
// Replace initial 0 unless adding decimal
if (this.currentOperand === '0' && number !== '.') {
this.currentOperand = number.toString();
} else {
this.currentOperand = this.currentOperand.toString() + number.toString();
}
}
chooseOperation(operation) {
if (this.currentOperand === '') return;
if (this.previousOperand !== '') {
this.compute();
}
this.operation = operation;
this.previousOperand = this.currentOperand;
this.currentOperand = ''; // Clear current for next input
}
compute() {
let computation;
const prev = parseFloat(this.previousOperand);
const current = parseFloat(this.currentOperand);
if (isNaN(prev) || isNaN(current)) return;
switch (this.operation) {
case '+':
computation = prev + current;
break;
case '-':
computation = prev - current;
break;
case '×':
computation = prev * current;
break;
case '÷':
if (current === 0) {
alert("Cannot divide by zero!");
this.clear();
return;
}
computation = prev / current;
break;
default:
return;
}
// Handle floating point precision issues roughly
computation = Math.round(computation * 100000000) / 100000000;
this.addToHistory(prev, this.operation, current, computation);
this.currentOperand = computation;
this.operation = undefined;
this.previousOperand = '';
this.shouldResetScreen = true;
}
percent() {
const current = parseFloat(this.currentOperand);
if (isNaN(current)) return;
this.currentOperand = current / 100;
}
getDisplayNumber(number) {
const stringNumber = number.toString();
const integerDigits = parseFloat(stringNumber.split('.')[0]);
const decimalDigits = stringNumber.split('.')[1];
let integerDisplay;
if (isNaN(integerDigits)) {
integerDisplay = '';
} else {
integerDisplay = integerDigits.toLocaleString('en', { maximumFractionDigits: 0 });
}
if (decimalDigits != null) {
return `${integerDisplay}.${decimalDigits}`;
} else {
return integerDisplay;
}
}
updateDisplay() {
this.currentOperandTextElement.innerText = this.getDisplayNumber(this.currentOperand);
if (this.operation != null) {
this.previousOperandTextElement.innerText =
`${this.getDisplayNumber(this.previousOperand)} ${this.operation}`;
} else {
this.previousOperandTextElement.innerText = '';
}
}
addToHistory(prev, op, current, result) {
const entry = { prev, op, current, result, timestamp: new Date() };
this.history.unshift(entry);
this.renderHistory();
}
renderHistory() {
if (this.history.length === 0) {
this.historyListElement.innerHTML = '<div class="text-center text-gray-500 text-sm mt-10 italic">No calculations yet</div>';
return;
}
this.historyListElement.innerHTML = this.history.map((item, index) => `
<div class="bg-white/5 p-3 rounded-xl border border-white/5 hover:bg-white/10 transition-colors cursor-pointer group animate-fade-in" onclick="calculator.loadResult(${item.result})">
<div class="text-xs text-gray-400 text-right mb-1 font-mono">${this.getDisplayNumber(item.prev)} ${item.op} ${this.getDisplayNumber(item.current)} =</div>
<div class="text-xl text-cyan-300 text-right font-bold font-mono group-hover:text-cyan-200">${this.getDisplayNumber(item.result)}</div>
</div>
`).join('');
}
loadResult(value) {
this.currentOperand = value;
this.shouldResetScreen = true;
this.updateDisplay();
playClickSound('number');
}
clearHistory() {
this.history = [];
this.renderHistory();
}
}
// --- Initialization & Event Listeners ---
const previousOperandTextElement = document.getElementById('previous-operand');
const currentOperandTextElement = document.getElementById('current-operand');
const historyListElement = document.getElementById('history-list');
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement, historyListElement);
// Button Selection
const numberButtons = document.querySelectorAll('[data-number]');
const operationButtons = document.querySelectorAll('[data-operation]');
const equalsButton = document.querySelector('[data-action="equals"]');
const deleteButton = document.querySelector('[data-action="delete"]');
const allClearButton = document.querySelector('[data-action="clear"]');
const percentButton = document.querySelector('[data-action="percent"]');
const clearHistoryButton = document.getElementById('clear-history');
// Event Handlers
numberButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.appendNumber(button.getAttribute('data-number'));
calculator.updateDisplay();
playClickSound('number');
});
});
operationButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.chooseOperation(button.getAttribute('data-operation'));
calculator.updateDisplay();
playClickSound('operator');
});
});
equalsButton.addEventListener('click', () => {
calculator.compute();
calculator.updateDisplay();
playClickSound('equals');
});
allClearButton.addEventListener('click', () => {
calculator.clear();
calculator.updateDisplay();
playClickSound('action');
});
deleteButton.addEventListener('click', () => {
calculator.delete();
calculator.updateDisplay();
playClickSound('action');
});
percentButton.addEventListener('click', () => {
calculator.percent();
calculator.updateDisplay();
playClickSound('operator');
});
clearHistoryButton.addEventListener('click', () => {
calculator.clearHistory();
playClickSound('action');
});
// Keyboard Support
document.addEventListener('keydown', (e) => {
// Initialize audio on first interaction if not already
if(!audioInitialized) initAudio();
if ((e.key >= 0 && e.key <= 9) || e.key === '.') {
calculator.appendNumber(e.key);
calculator.updateDisplay();
playClickSound('number');
highlightButton(e.key);
}
if (e.key === '+' || e.key === '-') {
calculator.chooseOperation(e.key);
calculator.updateDisplay();
playClickSound('operator');
highlightButton(e.key, 'operation');
}
if (e.key === '*') {
calculator.chooseOperation('×');
calculator.updateDisplay();
playClickSound('operator');
highlightButton('×', 'operation');
}
if (e.key === '/') {
calculator.chooseOperation('÷');
calculator.updateDisplay();
playClickSound('operator');
highlightButton('÷', 'operation');
}
if (e.key === 'Enter' || e.key === '=') {
e.preventDefault(); // Prevent form submission if any
calculator.compute();
calculator.updateDisplay();
playClickSound('equals');
highlightButton('equals', 'action');
}
if (e.key === 'Backspace') {
calculator.delete();
calculator.updateDisplay();
playClickSound('action');
highlightButton('delete', 'action');
}
if (e.key === 'Escape') {
calculator.clear();
calculator.updateDisplay();
playClickSound('action');
highlightButton('clear', 'action');
}
});
// Visual feedback for keyboard presses
function highlightButton(key, type = 'number') {
let selector;
if (type === 'number') selector = `[data-number="${key}"]`;
else if (type === 'operation') selector = `[data-operation="${key}"]`;
else if (key === 'equals') selector = `[data-action="equals"]`;
else if (key === 'delete') selector = `[data-action="delete"]`;
else if (key === 'clear') selector = `[data-action="clear"]`;
const btn = document.querySelector(selector);
if (btn) {
btn.classList.add('scale-95', 'brightness-125');
setTimeout(() => {
btn.classList.remove('scale-95', 'brightness-125');
}, 100);
}
}
// Initial display
calculator.updateDisplay();
</script>
</body>
</html>