Files
battery-builder/src/ui.js
Maxim ea030930cc Initial commit: cell holder generator + busbar builder
- 3D printable cell holder with STEP export (grid/honeycomb/vertical layouts)
- Configurable BMS holes (half circles, full circles, edge tabs)
- Busbar builder: click cells to define busbars, auto-routed with bend fallback
- Compound STEP export bundles holder + busbars
- OpenCascade.js (wasm) vendored for 3D modeling
2026-04-22 16:16:46 +02:00

95 lines
3.7 KiB
JavaScript

export function showStatus(message, type = 'success') {
const status = document.getElementById('previewStats');
if (!status) return;
status.textContent = message;
if (type === 'error') {
status.style.color = '#ef4444';
} else if (type === 'success') {
status.style.color = '#10b981';
} else {
status.style.color = '#94a3b8';
}
}
export function showLoading(show, text = 'Generating 3D Model', subtext = 'Please be patient...') {
const overlay = document.getElementById('loadingOverlay');
if (!overlay) return;
const loadingText = document.getElementById('loadingText');
const loadingSubtext = document.getElementById('loadingSubtext');
if (loadingText) loadingText.textContent = text;
if (loadingSubtext) loadingSubtext.textContent = subtext;
if (show) {
overlay.classList.add('active');
overlay.style.display = 'flex';
} else {
overlay.classList.remove('active');
overlay.style.display = 'none';
}
}
export function toggleBmsDiameter() {
const bmsType = document.getElementById('bmsHolesType').value;
const diameterGroup = document.getElementById('bmsHoleDiameterGroup');
const tabDimsGroup = document.getElementById('tabDimensionsGroup');
diameterGroup.style.display =
(bmsType === 'halfcircles' || bmsType === 'fullcircles') ? 'block' : 'none';
tabDimsGroup.style.display = (bmsType === 'tabs') ? 'grid' : 'none';
}
export function initCustomSelects() {
const selects = document.querySelectorAll('select');
selects.forEach(select => {
const wrapper = document.createElement('div');
wrapper.className = 'custom-select';
select.parentNode.insertBefore(wrapper, select);
wrapper.appendChild(select);
const selected = document.createElement('div');
selected.className = 'select-selected';
selected.textContent = select.options[select.selectedIndex].text;
wrapper.appendChild(selected);
const itemsContainer = document.createElement('div');
itemsContainer.className = 'select-items';
Array.from(select.options).forEach((option, index) => {
const item = document.createElement('div');
item.textContent = option.text;
item.dataset.value = option.value;
if (index === select.selectedIndex) item.className = 'same-as-selected';
item.addEventListener('click', function (e) {
e.stopPropagation();
select.selectedIndex = index;
selected.textContent = this.textContent;
const prevSelected = itemsContainer.querySelector('.same-as-selected');
if (prevSelected) prevSelected.classList.remove('same-as-selected');
this.classList.add('same-as-selected');
selected.click();
select.dispatchEvent(new Event('change'));
});
itemsContainer.appendChild(item);
});
wrapper.appendChild(itemsContainer);
selected.addEventListener('click', function (e) {
e.stopPropagation();
closeAllSelect(this);
itemsContainer.classList.toggle('show');
this.classList.toggle('select-arrow-active');
});
});
document.addEventListener('click', closeAllSelect);
}
function closeAllSelect(element) {
const items = document.querySelectorAll('.select-items');
const selected = document.querySelectorAll('.select-selected');
items.forEach((item, index) => {
if (element !== selected[index]) {
item.classList.remove('show');
selected[index].classList.remove('select-arrow-active');
}
});
}