/** * LANE-UI — build bar. One button per machine in GameData.machines, hotkeys 1-9. * Click or hotkey selects for placement; main.ts does the ghost and the actual place. */ import type { GameData } from '../contracts'; import { attrs, cls, el, panel, text } from './dom'; import { machineColor } from './palette'; import type { BuildSelection } from './selection'; import { COPY, DIR_NAME } from './voice'; export interface BuildBar { el: HTMLElement; /** Select the machine in slot `n` (1-based, as printed on the button). */ selectSlot(n: number): void; sync(): void; } export function createBuildBar(data: GameData, sel: BuildSelection): BuildBar { const root = panel(); root.id = 'fk-build'; const row = el('div', 'fk-build-row'); const hint = el('div'); hint.id = 'fk-build-hint'; const buttons: Array<{ def: string; btn: HTMLButtonElement }> = []; data.machines.forEach((m, i) => { const btn = el('button', 'fk-build-btn'); attrs(btn, { type: 'button', title: `${m.name} — ${m.kind}` }); const ico = el('div', 'fk-build-ico'); ico.style.background = machineColor(m); btn.append(ico); // Only the first nine get a printed hotkey; the rest are click-only until the // bar grows tabs/pages (a later round's problem). if (i < 9) { const key = el('span', 'fk-build-key'); key.textContent = String(i + 1); btn.append(key); } btn.append(el('span', 'fk-build-name', [m.name])); btn.addEventListener('click', () => sel.select(m.id)); row.append(btn); buttons.push({ def: m.id, btn }); }); root.append(row, hint); function sync() { const cur = sel.get(); for (const b of buttons) cls(b.btn, 'is-sel', cur?.def === b.def); if (cur) { const def = data.machines.find((m) => m.id === cur.def); text(hint, `${def?.name ?? cur.def} · FACING ${DIR_NAME[cur.dir]} · ${COPY.placingHint}`); } else { text(hint, COPY.idleHint); } cls(hint, 'is-placing', !!cur); } sel.onChange(sync); sync(); return { el: root, selectSlot(n) { const b = buttons[n - 1]; if (b) sel.select(b.def); }, sync, }; }