Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
70 lines
3.7 KiB
TypeScript
70 lines
3.7 KiB
TypeScript
/* =============================================================================
|
|
* design_profile_overlays.ts
|
|
* 종단도 바닥 오버레이 서브패널 — 유토곡선 · 테이블 · 유토 총괄 배지(213-3 · 700줄 한계로 뗌).
|
|
* 만들어 `bodyWrap` 에 붙이고 종단 스크롤과 잇는 데까지 — 그리기 · 높이는 종단도 몫.
|
|
* ========================================================================== */
|
|
|
|
import { attachMassHaulBadgeDrag, createMassHaulBadge } from "@util/common_util_mass_haul_badge";
|
|
import { readStateRaw, writeStateRaw } from "../b_page_state";
|
|
import { createHaulPlanPrefetch } from "../../B05_Profile/B05_Profile_Api_HaulPlan";
|
|
import { createProfileTableOverlay } from "../../B05_Profile/B05_Profile_UI_Profile_TableOverlay";
|
|
import {
|
|
createRouteMassHaulPanel,
|
|
type MassHaulSummaryValues,
|
|
} from "../../B05_Profile/B05_Profile_UI_Profile_MassHaul";
|
|
|
|
export interface ProfileOverlaysDeps {
|
|
projectId: string;
|
|
routeId: () => number | null;
|
|
/** 종단 열(요약 줄 · 본문 · 서클을 담은 칸) — 오버레이가 그 위를 덮는다. */
|
|
bodyWrap: HTMLElement;
|
|
/** 종단 스크롤러 — 오버레이 가로 스크롤을 이것과 맞춘다. */
|
|
body: HTMLElement;
|
|
/** 서브패널이 바뀜(펼침 · 범례 · 리사이저 · 유토 배분 도착). */
|
|
onChange: () => void;
|
|
}
|
|
|
|
export function createProfileOverlays(deps: ProfileOverlaysDeps) {
|
|
const { bodyWrap, body, onChange } = deps;
|
|
/** 유토곡선 총괄값 — **그래프 좌측 상단 배지**가 보인다(2026-09-06 사용자 지시).
|
|
* 유토곡선을 접어도 이 값은 남아야 한다. */
|
|
const massBadge = createMassHaulBadge();
|
|
// 그래프 위 도구줄 · 측점 ▲ 줄(바닥 47px) 아래로 내려 겹치지 않게 한다(289).
|
|
massBadge.root.style.setProperty("--mass-haul-badge-top", "52px");
|
|
bodyWrap.append(massBadge.root);
|
|
// 그래프 안 끌어 옮김(309-2) — 자리는 화면 설정 한 칸(B05 · B06 같은 값)
|
|
attachMassHaulBadgeDrag(massBadge.root, body, {
|
|
read: () => readStateRaw("mass-haul-badge-pos"),
|
|
write: (value) => writeStateRaw("mass-haul-badge-pos", value),
|
|
});
|
|
let massHaulSummary: MassHaulSummaryValues | null = null;
|
|
// 유토 배분은 **서버가 만든다**(2026-09-06) — 편집이 멈추면 뒤에서 받아 두고, 도착하면
|
|
// 곡선을 다시 그린다. 그 산식이 브라우저 번들에 안 실리는 것이 이 구조의 목적이다.
|
|
const haulPrefetch = createHaulPlanPrefetch(
|
|
deps.projectId,
|
|
() => deps.routeId() ?? undefined,
|
|
onChange,
|
|
);
|
|
const massHaul = createRouteMassHaulPanel(
|
|
onChange,
|
|
(summary) => {
|
|
const before = massHaulSummary;
|
|
massHaulSummary = summary;
|
|
if (before?.finalM3 !== summary?.finalM3) massBadge.set(summary);
|
|
},
|
|
haulPrefetch,
|
|
);
|
|
bodyWrap.append(massHaul.overlay, massHaul.handle);
|
|
// 오버레이의 가로 스크롤을 종단 스크롤러와 양방향 동기화 — 측점 세로선 정렬 유지.
|
|
massHaul.attachScrollSync(body);
|
|
// 테이블도 유토곡선과 같은 오버레이 서브패널 — 유토곡선 위에 쌓인다(2026-08-05 사용자 지시).
|
|
const tableOverlay = createProfileTableOverlay(onChange);
|
|
bodyWrap.append(tableOverlay.overlay, tableOverlay.handle);
|
|
tableOverlay.attachScrollSync(body);
|
|
// 유토곡선·테이블 영역에서 브라우저 기본 우클릭 메뉴를 막는다(2026-08-05 사용자 지시).
|
|
// 종단 그래프의 구조물 메뉴는 chartWrap에서 이미 preventDefault 후 자체 메뉴를 띄운다.
|
|
body.addEventListener("contextmenu", (event) => event.preventDefault());
|
|
massHaul.overlay.addEventListener("contextmenu", (event) => event.preventDefault());
|
|
return { massHaul, tableOverlay };
|
|
}
|