Merge remote-tracking branches 'origin/main_laptop_1' and 'origin/sub_laptop_7' into sub_laptop_2

This commit is contained in:
2026-10-10 13:23:40 +09:00
3 changed files with 320 additions and 7 deletions
@@ -119,17 +119,38 @@ export function wireStructureSelection(
revealed = field;
reveal?.(chainageM);
};
panel.root.addEventListener("focusin", (event) => {
if (fieldOf(event.target as HTMLElement) !== revealed) revealed = null;
});
panel.root.addEventListener("change", ({ target: el }) => {
const box = (el as HTMLElement).closest<HTMLElement>("fieldset[data-spec-container]");
const pickAt = (el: HTMLElement): void => {
const box = el.closest<HTMLElement>("fieldset[data-spec-container]");
const chainageM = panel.currentChainage();
if (!box || chainageM === null) return;
revealAt(chainageM, fieldOf(el as HTMLElement));
revealAt(chainageM, fieldOf(el));
// 단 수 칸은 고른 단을 지킴(단 수 바꿈 뒤 강조 유지) — 새 단은 다시 그린 뒤 아래에서 고름
if (!(el as HTMLElement).closest('[data-spec-item="outlet.tiers"]')) pickBox(box);
if (!el.closest('[data-spec-item="outlet.tiers"]')) pickBox(box);
};
// 값을 안 바꾸고 상자를 누르거나 칸에 초점만 줘도 같은 고름(191-1) — 칸 제 동작(누름 · 값 반영) 뒤에
// 돌림 · 고름이 폼을 다시 그려 초점 칸이 사라지면 같은 이름 새 칸에 초점을 되살림
const pressAt = (el: HTMLElement): void => {
setTimeout(() => {
const focused = document.activeElement as HTMLElement | null;
const named = focused?.closest("[data-spec-item]") && panel.root.contains(focused);
const field = named ? fieldOf(focused!) : null;
pickAt(el);
if (!field || focused!.isConnected) return;
// ponytail: 같은 칸 이름 · 같은 태그 첫 칸 — 한 칸에 같은 태그가 여럿이면 그 차례까지 맞출 것
[...panel.root.querySelectorAll<HTMLElement>(focused!.tagName)]
.find((next) => fieldOf(next) === field)
?.focus();
}, 0);
};
let pointing = false; // 누름이 준 초점은 click 이 맡음 — 초점 고름은 키보드(Tab) 몫
panel.root.addEventListener("pointerdown", () => (pointing = true));
panel.root.addEventListener("keydown", () => (pointing = false));
panel.root.addEventListener("click", ({ target: el }) => pressAt(el as HTMLElement));
panel.root.addEventListener("focusin", (event) => {
if (fieldOf(event.target as HTMLElement) !== revealed) revealed = null;
if (!pointing) pressAt(event.target as HTMLElement);
});
panel.root.addEventListener("change", ({ target: el }) => pickAt(el as HTMLElement));
// 상자가 새로 서면(단 늘림 · [추가]) 그 상자를 고름 — 같은 시설을 다시 그린 때만
let painted: { chainageM: number | null; keys: Set<string> } | null = null;
panel.root.addEventListener("specpaint", () => {