fix(B05 노선 편집 상태줄): 종단 판 열림 때 상태 · 범례를 판 위로 올림 (408-2)

- 판이 지도 아래를 덮은 높이 = logic InfoLift infoLiftPx · Chrome 이 판 크기 관찰로 --b05-profile-cover 적음
- 접힘 · 창 분할 = 제자리 · 판을 끝까지 올려도 지도 안 120 px 남김
- 시험 test_408_2_status_lift 새로 · test_345_5c 자리 규칙 고쳐 씀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
2026-10-18 09:23:48 +09:00
co-authored by Claude Opus 5.5
parent e1597084d6
commit c860193090
6 changed files with 122 additions and 4 deletions
@@ -2,6 +2,7 @@ import { createButton } from "@ui/ui_template_elements";
import { createSidePanels, type SidePanels } from "@ui/ui_template_side_panels";
import { bindFootprintToggle } from "./B05_Profile_UI_RouteEdit_Footprint";
import { bindMarkToggle } from "./B05_Profile_UI_RouteEdit_Marks";
import { infoLiftPx } from "./logic/B05_Profile_RouteEdit_InfoLift";
/* =============================================================================
* B05_Profile_UI_RouteEdit_Chrome.ts
@@ -205,6 +206,24 @@ export function createRouteEditChrome(
setInfo(infoCollapsed);
infoToggle.addEventListener("click", () => setInfo(!infoCollapsed));
// 뜬 종단 판(이웃 칸)이 지도 아래를 덮으면 상태 · 범례를 그 위로(408-2) — 판 높이 끌기 · 접기 ·
// 창 분할(판이 다른 창으로 감 = 못 찾음)을 판 크기 관찰로 따라감.
let watchedProfile: Element | null = null;
const liftInfo = (): void => {
if (!overlay.isConnected) return; // 붙기 전 첫 알림 · 걷힌 뒤 — 판 관찰은 판과 함께 사라짐
const profile =
overlay.closest(".design-page__main")?.querySelector(".b05-route-profile") ?? null;
if (profile && profile !== watchedProfile) lift.observe((watchedProfile = profile));
const map = overlay.getBoundingClientRect();
const top = profile?.isConnected ? profile.getBoundingClientRect().top : null;
overlay.style.setProperty(
"--b05-profile-cover",
`${infoLiftPx(map.bottom, map.height, top)}px`,
);
};
const lift = new ResizeObserver(liftInfo);
lift.observe(overlay);
const measureCloseButton = createButton({ label: "✕", variant: "ghost" });
measureCloseButton.classList.add("b05-routeedit__measure-close");
measureCloseButton.setAttribute("aria-label", "닫기");
@@ -88,10 +88,10 @@
display: grid;
}
/* 상태 · 범례 — 지도 왼쪽 아래(사용자 지시 ⑫) · 뜬 종단 판이 덮으면 가려진 채(349-0).
/* 상태 · 범례 — 지도 왼쪽 아래(사용자 지시 ⑫) · 뜬 종단 판이 덮으면 그 위로(408-2 · `_Chrome` 이 적음).
두 줄 안 · 좁은 폭(345-5 덧 3) — 왼쪽 상태 글(두 줄에서 자름) · 가운데 범례 두 줄 · 오른쪽 ▾. */
.b05-routeedit__info {
bottom: var(--spacing-12);
bottom: calc(var(--spacing-12) + var(--b05-profile-cover, 0px));
left: var(--spacing-12);
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
@@ -0,0 +1,19 @@
/* =============================================================================
* B05_Profile/logic/B05_Profile_RouteEdit_InfoLift.ts
* 평면 상태 · 범례 올림(408-2) — 뜬 종단 판이 지도 아래를 덮은 높이만큼 위로.
* 파이썬 짝 아님. 순수 계산 — 화면 · fetch · sessionStorage 없음. 부르는 쪽은 `_UI_RouteEdit_Chrome`.
* ========================================================================== */
/** 상태 글판이 이 높이(px)는 지도 위에 남게 — 판을 끝까지 올려도 지도 밖으로 안 나감. */
const KEEP_PX = 120;
/** 올릴 높이(px) — `profileTop` = 종단 판 윗변(없음 · 접힘 · 창 분할 = null) · 지도 칸 아래 · 높이. */
export function infoLiftPx(
mapBottom: number,
mapHeight: number,
profileTop: number | null,
): number {
if (profileTop === null) return 0;
const cover = Math.max(0, mapBottom - profileTop);
return Math.round(Math.min(cover, Math.max(0, mapHeight - KEEP_PX)));
}