feat(B05): 토량분배 시 유토곡선 전체 맞춤 + 상단 여백·테이블 높이 정리

- 토량분배를 켜면 유토곡선이 종단과의 X 맞춤·세로 창을 버리고 스크롤러 안쪽
  폭·전 구간 Y 로 그려 곡선 전체가 한 화면에 들어옴(평형선·운반 블록을 노선
  전체로 읽는 그림이라). 끄면 예전대로 종단과 맞물린 가로 스크롤로 복귀.
- 요약 막대가 상단줄로 올라간 뒤 남던 상단 여백 축소 — 범례 top 34px → 4px,
  차트 padTop 40 → 30(범례 높이 24 + 여유).
- 종단 테이블 오버레이 높이 상한 신설 — 6행 × 행 30px + 24px(=204px).
  12행에서 6행으로 줄인 뒤 같은 높이를 나눠 가지며 행이 부풀던 것을 막음.
  레이아웃 제어(리사이저·패널 비례 연동)는 그대로 두고 상한만 걸음.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-06 17:07:01 +09:00
co-authored by Claude Opus 5
parent 43f6325d30
commit 94266757cd
4 changed files with 38 additions and 17 deletions
@@ -13,6 +13,7 @@
import { readStateRaw, stateKey, writeStateRaw } from "../A00_Common/b_page_state";
import { createWorkflowPanelHandle } from "@ui/ui_template_overlay";
import { createPanelResizer } from "@ui/ui_template_resizer";
import { TABLE_ROW_COUNT } from "./B05_Profile_UI_Profile_Layout";
import { attachWheelHorizontalScroll } from "./B05_Profile_UI_Profile_Wheel";
/* 펼침·높이는 화면 취향(①) — 키는 등록표(`b_page_state`)가 만든다. */
@@ -21,8 +22,16 @@ const OVERLAY_MIN_HEIGHT = 140;
/** 테이블 오버레이 최소 높이 — 메인 패널 하한 계산(Profile_Panel)이 함께 쓴다. */
export const TABLE_OVERLAY_MIN_HEIGHT = OVERLAY_MIN_HEIGHT;
const OVERLAY_MAX_RATIO = 0.75;
/** CSS 기본 높이 — `var(--b05-table-height, 300px)`(_Style_MassHaul.css)와 같아야 한다. */
const OVERLAY_DEFAULT_HEIGHT = 300;
/** 행 하나의 높이 상한(px). 행이 이보다 커지면 글자만 커지고 읽을 내용은 그대로다 —
* 12행에서 6행으로 줄인 뒤 같은 높이를 나눠 가지며 행이 두 배로 부푼 것을 막는다
* (2026-09-06 사용자 지시: 「최대값 제한, 레이아웃 제어는 현재 유지」). */
const MAX_ROW_HEIGHT = 30;
/** 오버레이 높이 상한 = 6행 × 행 상한 + 가로 스크롤바·경계 몫. */
const OVERLAY_MAX_HEIGHT = TABLE_ROW_COUNT * MAX_ROW_HEIGHT + 24;
/** CSS 기본 높이 — `var(--b05-table-height, 204px)`(_Style_MassHaul.css)와 같아야 한다. */
const OVERLAY_DEFAULT_HEIGHT = OVERLAY_MAX_HEIGHT;
/** 어느 경로로 들어온 높이든 상한을 넘지 않게 한다(리사이저·패널 비례 연동 공용). */
const clampHeight = (px: number): number => Math.min(px, OVERLAY_MAX_HEIGHT);
/** 리사이저가 높이를 담는 CSS 변수. */
const HEIGHT_VAR = "--b05-table-height";
@@ -71,7 +80,8 @@ export function createProfileTableOverlay(onChanged: () => void): RouteProfileTa
cssVar: HEIGHT_VAR,
direction: -1,
min: OVERLAY_MIN_HEIGHT,
max: () => (overlay.parentElement?.clientHeight ?? window.innerHeight) * OVERLAY_MAX_RATIO,
max: () =>
clampHeight((overlay.parentElement?.clientHeight ?? window.innerHeight) * OVERLAY_MAX_RATIO),
storageKey: HEIGHT_KEY,
onResize: () => {
syncHandlePosition();
@@ -132,10 +142,10 @@ export function createProfileTableOverlay(onChanged: () => void): RouteProfileTa
isOpen: () => open,
desiredHeight: () => {
const raw = parseFloat(overlay.style.getPropertyValue(HEIGHT_VAR));
return Number.isFinite(raw) && raw > 0 ? raw : OVERLAY_DEFAULT_HEIGHT;
return clampHeight(Number.isFinite(raw) && raw > 0 ? raw : OVERLAY_DEFAULT_HEIGHT);
},
commitHeight: (px) => {
const next = Math.round(px);
const next = Math.round(clampHeight(px));
overlay.style.setProperty(HEIGHT_VAR, `${next}px`);
writeStateRaw("table-height", String(next));
syncHandlePosition();