feat: functional gridfinity calculator app

This commit is contained in:
w33ble
2026-01-11 19:38:34 -07:00
commit 7c512f5adb
19 changed files with 3561 additions and 0 deletions

90
src/main.ts Normal file
View File

@@ -0,0 +1,90 @@
import { calculateGridfinity, GridfinitySpec } from './calculator';
// DOM Elements
const inputWidth = document.getElementById('input-width') as HTMLInputElement;
const inputLength = document.getElementById('input-length') as HTMLInputElement;
const inputHeight = document.getElementById('input-height') as HTMLInputElement;
const unitMmBtn = document.getElementById('unit-mm') as HTMLButtonElement;
const unitInBtn = document.getElementById('unit-in') as HTMLButtonElement;
const specGridSize = document.getElementById('spec-grid-size') as HTMLInputElement;
const specHeightUnit = document.getElementById('spec-height-unit') as HTMLInputElement;
const specBaseThickness = document.getElementById('spec-base-thickness') as HTMLInputElement;
const resultsSection = document.getElementById('results') as HTMLElement;
const resultGridCount = document.getElementById('result-grid-count') as HTMLElement;
const resultGridFractional = document.getElementById('result-grid-fractional') as HTMLElement;
const resultBinHeight = document.getElementById('result-bin-height') as HTMLElement;
const gapWidth = document.getElementById('gap-width') as HTMLElement;
const gapLength = document.getElementById('gap-length') as HTMLElement;
const gapHeight = document.getElementById('gap-height') as HTMLElement;
// State
let currentUnit: 'mm' | 'in' = 'mm';
function updateResults() {
const width = parseFloat(inputWidth.value) || 0;
const length = parseFloat(inputLength.value) || 0;
const height = parseFloat(inputHeight.value) || 0;
const spec: GridfinitySpec = {
gridSize: parseFloat(specGridSize.value) || 42,
heightUnit: parseFloat(specHeightUnit.value) || 7,
baseThickness: parseFloat(specBaseThickness.value) || 4.8,
};
if (width > 0 && length > 0 && height > 0) {
const results = calculateGridfinity({
width,
length,
height,
unit: currentUnit,
spec,
});
resultsSection.classList.remove('hidden');
resultGridCount.textContent = `${results.fullGridsX} x ${results.fullGridsY}`;
resultGridFractional.textContent = `${results.widthGrids.toFixed(2)} x ${results.lengthGrids.toFixed(2)} grids`;
resultBinHeight.textContent = `${results.maxBinUnits}U`;
const unitLabel = currentUnit === 'in' ? 'in' : 'mm';
const displayGapWidth = currentUnit === 'in' ? results.remainingWidth / 25.4 : results.remainingWidth;
const displayGapLength = currentUnit === 'in' ? results.remainingLength / 25.4 : results.remainingLength;
const displayGapHeight = currentUnit === 'in' ? results.remainingHeight / 25.4 : results.remainingHeight;
gapWidth.textContent = `${displayGapWidth.toFixed(1)} ${unitLabel}`;
gapLength.textContent = `${displayGapLength.toFixed(1)} ${unitLabel}`;
gapHeight.textContent = `${displayGapHeight.toFixed(1)} ${unitLabel}`;
} else {
resultsSection.classList.add('hidden');
}
}
// Event Listeners
[inputWidth, inputLength, inputHeight, specGridSize, specHeightUnit, specBaseThickness].forEach(el => {
el.addEventListener('input', updateResults);
});
unitMmBtn.addEventListener('click', () => {
currentUnit = 'mm';
unitMmBtn.classList.add('bg-white', 'shadow-sm');
unitMmBtn.classList.remove('text-slate-600');
unitInBtn.classList.remove('bg-white', 'shadow-sm');
unitInBtn.classList.add('text-slate-600');
updateResults();
});
unitInBtn.addEventListener('click', () => {
currentUnit = 'in';
unitInBtn.classList.add('bg-white', 'shadow-sm');
unitInBtn.classList.remove('text-slate-600');
unitMmBtn.classList.remove('bg-white', 'shadow-sm');
unitMmBtn.classList.add('text-slate-600');
updateResults();
});
// Initial call
updateResults();