diff --git a/B06_Section/B06_Section_UI_Adjust_Dock.ts b/B06_Section/B06_Section_UI_Adjust_Dock.ts index 52ddbb81..18a83ce5 100644 --- a/B06_Section/B06_Section_UI_Adjust_Dock.ts +++ b/B06_Section/B06_Section_UI_Adjust_Dock.ts @@ -30,13 +30,12 @@ export function setAdjustSideSlots(next: SideSlots): void { sideSlots = next; } -/** 다단 벽에서 옮겨 오는 행 — 폼에 자기 칸이 없어 형태·높이·구간값까지 전부 온다. */ +/** 다단 벽에서 옮겨 오는 행 — 폼에 자기 칸이 없어 형태·높이·구간값이 온다. + * 단 수·옵션은 부모 벽의 값이라 여기 오지 않고 부모 칸에 남는다(2026-08-30 사용자). */ const EXTRA_ROWS = [ ".b06-structure-panel__struct--form", ".b06-structure-panel__struct--height", ".b06-structure-panel__struct--span", - ".b06-structure-panel__struct--tier", - ".b06-structure-panel__struct--options", ].join(", "); /** 유입구·유출구는 폼이 이미 가진 항목 말고 단 수·옵션만 받는다. */ @@ -97,6 +96,18 @@ function clearSideSlots(): void { } } +/** 행 DOM을 제자리 표식과 함께 옮긴다 — 숨은 행은 그대로 둔다. */ +function moveRows(panelRoot: HTMLElement, selector: string, target: HTMLElement): void { + panelRoot.querySelectorAll(selector).forEach((row) => { + if (row.classList.contains("is-hidden")) return; + // 제자리에 표식을 남기고 옮긴다 — 선택이 바뀌면 이 자리로 되돌린다. + const anchor = document.createComment("adjust-row"); + row.parentNode?.insertBefore(anchor, row); + movedRows.push({ row, anchor }); + target.append(row); + }); +} + /** * 조정창 사본의 단 수·옵션 행을 고른 벽 쪽(유입/유출) 그룹으로 옮긴다. 행 DOM을 * 그대로 옮기므로 배선·값 동기는 손대지 않는다. 자리가 없으면 사본에 그대로 둔다. @@ -111,21 +122,18 @@ function relocateSideRows(panelRoot: HTMLElement): void { if (side === "extra") { const group = target.closest("fieldset"); if (!group) return; - const owner = slotOf(panelRoot.dataset.extraSide === "inlet" ? "inlet" : "outlet").closest( - "fieldset", - ); + const ownerSlot = slotOf(panelRoot.dataset.extraSide === "inlet" ? "inlet" : "outlet"); + const owner = ownerSlot.closest("fieldset"); if (owner && owner !== group) owner.after(group); group.hidden = false; - } else if (!slotUsable(target)) return; - const rows = panelRoot.querySelectorAll(side === "extra" ? EXTRA_ROWS : SIDE_ROWS); - rows.forEach((row) => { - if (row.classList.contains("is-hidden")) return; - // 제자리에 표식을 남기고 옮긴다 — 선택이 바뀌면 이 자리로 되돌린다. - const anchor = document.createComment("adjust-row"); - row.parentNode?.insertBefore(anchor, row); - movedRows.push({ row, anchor }); - target.append(row); - }); + moveRows(panelRoot, EXTRA_ROWS, target); + // 단 수·옵션은 그 단이 딸린 부모 벽의 값이라 부모 칸에 그대로 세운다 — 다단을 + // 고를 때 그 두 행이 사라지던 것을 막는다(2026-08-30 사용자). + if (slotUsable(ownerSlot)) moveRows(panelRoot, SIDE_ROWS, ownerSlot); + } else { + if (!slotUsable(target)) return; + moveRows(panelRoot, SIDE_ROWS, target); + } // 고른 구조물이 어느 쪽인지 그룹 테두리로 알린다(2026-08-29 사용자 지시 3). const group = target.closest("fieldset"); if (!group) return; diff --git a/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts b/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts index 3349554f..b360e64d 100644 --- a/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts +++ b/B06_Section/B06_Section_UI_Cross_Structure_Panel.ts @@ -569,7 +569,15 @@ export function buildStructurePanel( // 유출 벽과 독립 기슭막이 유입 벽에서는 **항상** 보인다(2026-08-22 사용자 ⑤ — // 상태 따라 나타났다 사라지면 레이아웃이 널뛴다). 집수정 계류측은 둘 자리가 // 있을 때만 뜬다(배관 유입 기슭막이는 다단 채널 자체가 없다). - tierChannel = key === "outlet" ? "outlet" : key === "inlet" ? "basin" : null; + // 다단 벽을 고른 동안에도 단 수는 **그 단이 딸린 부모 벽**의 값이다 — 채널을 + // 부모 쪽으로 열어 두고 행은 부모 칸에 남긴다(2026-08-30 사용자: 추가 기슭막이를 + // 고르면 단 수·옵션이 사라지던 것). + tierChannel = + key === "outlet" || key.startsWith("extra") + ? "outlet" + : key === "inlet" || key.startsWith("bextra") + ? "basin" + : null; // 좌측 [횡단 조정] 사본의 단 수·옵션 행이 어느 그룹(유입구·유출구)으로 옮겨 // 붙을지 알린다(2026-08-29 지시 4). 다단 벽은 자기 채널 쪽으로 간다. // 다단(추가) 벽은 유입·유출 어느 칸에도 자기 자리가 없다 — 유입구·유출구 아래 @@ -596,7 +604,8 @@ export function buildStructurePanel( // 기슭막이 기준벽(배관 유입·유출, 독립 좌·우)에서는 **항상** 보인다(2026-08-30 // 사용자). 링크 카드에서 만져도 제어기가 소유 측점 값을 고치므로 안전하다. // 집수정 유입은 계류측 단이 설 자리가 있을 때만 — 벽이 아니라 구체다. - const revetWall = (key === "inlet" || key === "outlet") && !isBasin; + // 다단 벽도 포함한다 — 행은 부모 칸에 서 있고, 그 값(부모 단 수·옵션)을 그대로 쓴다. + const revetWall = ((key === "inlet" || key === "outlet") && !isBasin) || isExtra; extraRow.classList.toggle( "is-hidden", !revetWall && !(isBasin && tierChannel === "basin" && (tiers.canAdd || tiers.count > 0)),