Files
Aislo/common_util/common_util_mass_haul_legend.ts
T

81 lines
3.5 KiB
TypeScript

/* =============================================================================
* common_util_mass_haul_legend.ts
* 유토곡선 곡선 이름 · 범례 줄(`common_util_mass_haul_view` 에서 나눔).
* ========================================================================== */
import type { MassHaulBasis, MassHaulSeries } from "./common_util_mass_haul";
import type { LocaleKey } from "@ui/ui_template_locale";
import { MASS_HAUL_BALANCE_KEY } from "./common_util_mass_haul";
import { L } from "./common_util_svg";
const BASIS_LABEL: Record<MassHaulBasis, LocaleKey> = {
cross: "B06_MassHaul_Basis_Cross",
longitudinal: "B06_MassHaul_Basis_Long",
};
/** 범례·곡선에 함께 쓰는 이름. 색이 곧 산출 기준이다. */
export function massHaulSeriesLabel(series: MassHaulSeries): string {
return L(BASIS_LABEL[series.basis]);
}
export function seriesClass(series: MassHaulSeries, base: string): string {
return `${base} ${base}--${series.basis}`;
}
/**
* 곡선 표시/숨김 버튼 줄.
*
* 그래프 **아래**에 둔다(2026-08-02 사용자 지시). 예전에는 그래프 위에 겹치는 오버레이였는데,
* 가로 스크롤 컨테이너 안에 있으면 컨테이너 폭 계산에 끼어들어 종단면도와 X축이 어긋난다.
* 지금은 스크롤 컨테이너 **밖** 패널 본문에 붙어 곡선 폭에 전혀 관여하지 않는다.
*/
export function createMassHaulLegend(
series: MassHaulSeries[],
visibleKeys: ReadonlySet<string>,
onToggle: (key: string) => void,
onResetBalloons?: () => void,
): HTMLElement {
const legend = document.createElement("div");
legend.className = "b06-masshaul__legend";
legend.setAttribute("role", "group");
legend.setAttribute("aria-label", L("B06_MassHaul_Legend_Title"));
const addItem = (key: string, label: string, variantClass: string): void => {
const shown = visibleKeys.has(key);
const button = document.createElement("button");
button.type = "button";
button.className = variantClass;
button.classList.toggle("is-off", !shown);
button.setAttribute("aria-pressed", String(shown));
button.title = `${label} — ${L(shown ? "B06_MassHaul_Legend_Hide" : "B06_MassHaul_Legend_Show")}`;
const swatch = document.createElement("span");
swatch.className = "b06-masshaul__legend-swatch";
swatch.setAttribute("aria-hidden", "true");
const text = document.createElement("span");
text.textContent = label;
button.append(swatch, text);
button.addEventListener("click", () => onToggle(key));
legend.append(button);
};
for (const entry of series) {
addItem(entry.key, massHaulSeriesLabel(entry), seriesClass(entry, "b06-masshaul__legend-item"));
}
// 토량 분배는 곡선이 아니라 곡선 위에 얹는 레이어라 스와치 모양을 따로 준다.
addItem(
MASS_HAUL_BALANCE_KEY,
L("B06_MassHaul_Balance_Layer"),
"b06-masshaul__legend-item b06-masshaul__legend-item--balance",
);
// 끌어 옮긴 balloon을 한 번에 자동 배치로 되돌린다(프론트 캐시 + 다음 확정 시 영구저장소).
if (onResetBalloons && visibleKeys.has(MASS_HAUL_BALANCE_KEY)) {
const reset = document.createElement("button");
reset.type = "button";
reset.className = "b06-masshaul__legend-item b06-masshaul__legend-item--reset";
reset.textContent = L("B06_MassHaul_Balloon_Reset");
reset.title = L("B06_MassHaul_Balloon_Reset_Tip");
reset.addEventListener("click", onResetBalloons);
// [횡단 기준] 왼쪽(367-1)
legend.prepend(reset);
}
return legend;
}