Compare commits

..

9 Commits

Author SHA1 Message Date
matmoul 6a37c7c1e8 feat: add pow10 and exp arithmetic operations 2026-05-16 23:15:22 +02:00
matmoul 5f2d18df99 fix(calc-02): constrain keypad area with internal scrolling
Wrap the keypad, function, and trig panels in a dedicated scroll area so the calculator shell can use a fixed grid layout without overflowing the viewport. Also update panel styling to preserve spacing and scrollbar behavior.
2026-05-16 22:40:23 +02:00
matmoul c69380d057 refactor(samples): reorder calculator keypad keys 2026-05-16 21:58:51 +02:00
matmoul c11a75d7f7 fix: bust calc sample stylesheet cache 2026-05-16 21:52:05 +02:00
matmoul 813fae1b61 refactor(calc-02): simplify calculator layout structure
Move the display and button panels into a single wrapper and rely on
viewport-height sizing with hidden page overflow to keep the calculator
contained. Also trim redundant panel-specific layout rules and styling.
2026-05-16 21:41:47 +02:00
matmoul 208db58fe7 fix: make calc-02 panels stretch and scroll within container 2026-05-16 20:24:43 +02:00
matmoul ea6401a006 fix: constrain calculator width on calc-02 sample 2026-05-16 20:17:19 +02:00
matmoul ea61ec17d5 fix: remove portrait class from calc-02 calculator shell 2026-05-16 19:44:09 +02:00
matmoul a4bbffe65b feat: replace calculator enter key label with symbol 2026-05-16 18:41:03 +02:00
4 changed files with 77 additions and 74 deletions
+26 -23
View File
@@ -32,6 +32,7 @@
html, body { html, body {
margin: 0; margin: 0;
min-height: 100%; min-height: 100%;
overflow-y: hidden;
} }
body { body {
@@ -51,25 +52,24 @@ body {
.calculator { .calculator {
width: 100%; width: 100%;
height: auto; max-width: 460px;
display: grid; height: 100vh;
max-height: 100vh;
padding: 8px; padding: 8px;
display: grid;
grid-template-rows: auto auto minmax(0, 1fr);
gap: 8px;
border-radius: 8px; border-radius: 8px;
background: var(--panel); background: var(--panel);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
grid-template-columns: 1fr; justify-content: stretch;
grid-template-rows: auto auto auto auto auto; align-content: start;
row-gap: 6px; overflow: hidden;
grid-template-areas:
"display"
"display-buttons"
"keypad"
"functions"
"trigo";
} }
.display-block, .display-block,
.display-panel, .display-panel,
.display-buttons-panel,
.keypad-panel, .keypad-panel,
.functions-panel, .functions-panel,
.trigo-panel { .trigo-panel {
@@ -79,15 +79,7 @@ body {
box-shadow: none; box-shadow: none;
} }
.display-buttons-panel {
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.06);
background: rgba(6, 10, 16, 0.16);
box-shadow: none;
}
.display-block { .display-block {
grid-area: display;
display: grid; display: grid;
gap: 0; gap: 0;
align-self: start; align-self: start;
@@ -146,10 +138,9 @@ body {
font-size: 20px; font-size: 20px;
} }
.display-buttons-panel { .display-buttons-panel {
grid-area: display-buttons;
padding: 8px; padding: 8px;
align-self: start;
min-height: 0; min-height: 0;
background: rgba(6, 10, 16, 0.16);
} }
.display-buttons-grid { .display-buttons-grid {
@@ -231,10 +222,22 @@ body {
.functions-panel, .functions-panel,
.trigo-panel { .trigo-panel {
padding: 8px; padding: 8px;
align-self: start;
min-height: 0; min-height: 0;
} }
.calculator > .display-block,
.calculator > .display-buttons-panel,
.calculator > .keypad-scroll-area {
justify-self: stretch;
}
.keypad-scroll-area {
min-height: 0;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgba(46, 105, 135, 1);
}
.status-bar { .status-bar {
position: absolute; position: absolute;
top: 0; top: 0;
@@ -291,7 +294,6 @@ button {
border: 1px solid rgba(14, 18, 25, 0.85); border: 1px solid rgba(14, 18, 25, 0.85);
border-radius: 8px; border-radius: 8px;
padding: 8px 8px; padding: 8px 8px;
font: inherit; font: inherit;
font-weight: 700; font-weight: 700;
color: var(--btnText); color: var(--btnText);
@@ -326,6 +328,7 @@ button:active {
opacity: 0.7; opacity: 0.7;
} }
} }
.stack-copy-button { .stack-copy-button {
padding: 4px; padding: 4px;
min-width: 24px; min-width: 24px;
+4 -2
View File
@@ -4,11 +4,11 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>HP48GX RPN Calculator</title> <title>HP48GX RPN Calculator</title>
<link rel="stylesheet" href="./index.css"> <link rel="stylesheet" href="./index.css?ver=1">
</head> </head>
<body> <body>
<main class="app-shell"> <main class="app-shell">
<section class="calculator calculator-portrait" aria-label="HP48GX style RPN calculator"> <section class="calculator" aria-label="HP48GX style RPN calculator">
<div class="display-block"> <div class="display-block">
<div class="display-panel"> <div class="display-panel">
<div class="status-bar" id="statusLine" aria-live="polite"></div> <div class="status-bar" id="statusLine" aria-live="polite"></div>
@@ -36,6 +36,7 @@
</div> </div>
</div> </div>
<div class="keypad-scroll-area">
<div class="keypad-panel"> <div class="keypad-panel">
<div class="keypad-grid" id="keypadGrid"></div> <div class="keypad-grid" id="keypadGrid"></div>
</div> </div>
@@ -47,6 +48,7 @@
<div class="trigo-panel"> <div class="trigo-panel">
<div class="trigo-grid" id="trigoGrid"></div> <div class="trigo-grid" id="trigoGrid"></div>
</div> </div>
</div>
<input id="hiddenInput" class="hidden-input" type="text" autocomplete="off" aria-hidden="true" tabindex="-1"> <input id="hiddenInput" class="hidden-input" type="text" autocomplete="off" aria-hidden="true" tabindex="-1">
</section> </section>
+3 -17
View File
@@ -30,10 +30,10 @@ const calculatorEl = document.querySelector('.calculator');
const statusLine = document.getElementById('statusLine'); const statusLine = document.getElementById('statusLine');
const keypadKeys = [ const keypadKeys = [
{ label: 'ENTER', action: 'enter', className: 'key-enter' },
{ label: '⎋', action: 'escape', className: 'key-escape' },
{ label: 'C', action: 'clear', className: 'key-danger' }, { label: 'C', action: 'clear', className: 'key-danger' },
{ label: '⌫', action: 'backspace', className: 'key-danger' }, { label: '⌫', action: 'backspace', className: 'key-danger' },
{ label: '⎋', action: 'escape', className: 'key-escape' },
{ label: '⏎', action: 'enter', className: 'key-enter' },
{ label: '7', input: '7', className: 'key-default' }, { label: '7', input: '7', className: 'key-default' },
{ label: '8', input: '8', className: 'key-default' }, { label: '8', input: '8', className: 'key-default' },
{ label: '9', input: '9', className: 'key-default' }, { label: '9', input: '9', className: 'key-default' },
@@ -237,22 +237,8 @@ function execute(name) {
if (calc.isEditing) { if (calc.isEditing) {
calc.inputValue = calc.inputValue.startsWith('-') ? calc.inputValue.slice(1) : `-${calc.inputValue}`; calc.inputValue = calc.inputValue.startsWith('-') ? calc.inputValue.slice(1) : `-${calc.inputValue}`;
} else { } else {
calc.push(calc.pop() * -1); calc.command('neg');
} }
} else if (name === 'pow10') {
pushEditingValueIfNeeded();
const exponent = calc.stack[0];
calc.remove(0);
calc.push(10);
calc.push(exponent);
calc.command('pow');
} else if (name === 'exp') {
pushEditingValueIfNeeded();
const exponent = calc.stack[0];
calc.remove(0);
calc.push(Math.E);
calc.push(exponent);
calc.command('pow');
} else { } else {
pushEditingValueIfNeeded(); pushEditingValueIfNeeded();
calc.command(name); calc.command(name);
+13 -1
View File
@@ -49,6 +49,18 @@ class RpnCalculator {
aliases: ['^', 'y^x'], aliases: ['^', 'y^x'],
execute: (calc, a, b) => Math.pow(a, b), execute: (calc, a, b) => Math.pow(a, b),
}, },
pow10: {
category: 'Arithmetic',
argCount: 1,
aliases: ['10^x'],
execute: (calc, a) => Math.pow(10, a),
},
exp: {
category: 'Arithmetic',
argCount: 1,
aliases: ['e^x'],
execute: (calc, a) => Math.exp(a),
},
root: { root: {
category: 'Arithmetic', category: 'Arithmetic',
argCount: 2, argCount: 2,
@@ -195,7 +207,7 @@ class RpnCalculator {
static getOperationsByCategory() { static getOperationsByCategory() {
return { return {
Stack: ['dup', 'drop', 'swap', 'clear', 'enter'], Stack: ['dup', 'drop', 'swap', 'clear', 'enter'],
Arithmetic: ['add', 'sub', 'mul', 'div', 'mod', 'pow', 'root', 'sqr', 'neg', 'sqrt', 'recip', 'log', 'ln'], Arithmetic: ['add', 'sub', 'mul', 'div', 'mod', 'pow', 'pow10', 'exp', 'root', 'sqr', 'neg', 'sqrt', 'recip', 'log', 'ln'],
Trigonometry: ['sin', 'cos', 'tan', 'asin', 'acos', 'atan'], Trigonometry: ['sin', 'cos', 'tan', 'asin', 'acos', 'atan'],
}; };
} }