Files
Aislo/B09_Estimation/B09_Estimation_UI_TabBar.ts
T
eomsangdonandClaude Sonnet 5.5 361ce51659 refactor(B08·B09): 자체 변종 → 부품 상자 — 탭 줄 · 분할 고르기 · 배지 칩 · 도구줄 · 떠 있는 판 · 보조 글 (PLAN 553-3)
- 위 · 보조 탭 줄 = 부품 탭(fillTabs · 밑줄 · 알약) · B09 좌측 스위치 = 분할 고르기
- 연결 칩 · 검사 탭 이름 · 끌기 태그 = 배지 · 이정표 도구 · 머리 줄 · 저장 줄 = 도구줄 · 구간 고침 · 행 고름 창 = 떠 있는 판
- 안내 · 빈 줄 · 상태 글 = 보조 글 · 운반 칸 = 카드 · 인쇄 미리보기 좌측 줄 = B09 dock 한 벌 · 쪽 체크 = 라디오 · 체크 부품
- 시험 흉내 틀 · 문구 맞춤

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 22:33:35 +09:00

71 lines
3.1 KiB
TypeScript

/* =============================================================================
* B09_Estimation_UI_TabBar.ts
* B09 탭 줄 두 층(PLAN 181-1) — 위 탭(밑줄 · 32) · 아래 탭(보조 알약) · B08 수량산출 페이지 꼴(부품 「탭」).
*
* 위 탭 = `TAB_GROUPS`(`…_UI_Tabs`) · 아래 탭 하나뿐인 위 탭 = 보이지 않는 보조 탭 한 칸(높이만 채움)
* 위 탭 누름 = 그 묶음에서 마지막으로 본 아래 탭(이 화면 안 Map · 저장 안 함) · 없으면 첫 아래 탭
* 탭 이동은 `draw(탭)` — 이동이 묶음을 넘어도 위 탭이 따라 켜짐
* 보기 단추 · 가로 열 수(202-1) = 아래 줄 오른쪽 맞춤 자리(`setTools`) · 빈 줄에서도 보임
* ========================================================================== */
import { createToolbar } from "@ui/ui_template_toolbar";
import { fillTabs } from "../A00_Common/b_page_tabs";
import { groupOf, tabName, TAB_GROUPS, type TabId } from "./B09_Estimation_UI_Tabs";
export interface TabBars {
top: HTMLElement;
sub: HTMLElement;
/** 이 탭이 켜진 꼴로 두 줄을 다시 그림 */
draw: (tab: TabId) => void;
/** 아래 줄 오른쪽 도구(박스보기 · 가로 열 수) — 빈 목록 = 비움 */
setTools: (tools: HTMLElement[]) => void;
}
export function createTabBars(onPick: (tab: TabId) => void): TabBars {
const top = document.createElement("div");
top.className = "b09-estimation__tabs";
const sub = document.createElement("div");
sub.className = "b09-estimation__tabs";
const tools = createToolbar({ items: [], size: 24 });
tools.classList.add("b09-estimation__tools", "ui-subtabs__tools");
const lastSeen = new Map<TabId, TabId>();
const draw = (tab: TabId): void => {
const [, picked] = groupOf(tab);
lastSeen.set(picked[0], tab);
const groupTab = new Map(TAB_GROUPS.map(([, tabs]) => [tabs[0], tabs]));
fillTabs(top, {
tabs: TAB_GROUPS.map(([label, tabs]) => ({ key: tabs[0], label })),
value: picked[0],
kind: "line",
size: 32,
data: "b09Group",
onChange: (key) => onPick(lastSeen.get(key as TabId) ?? (key as TabId)),
}).forEach((button) => {
const tabs = groupTab.get(button.dataset.tab as TabId);
if (tabs?.length === 1) button.dataset.b09Tab = tabs[0];
});
const single = picked.length === 1;
sub.classList.toggle("b09-estimation__tabs--blank", single);
const buttons = fillTabs(sub, {
tabs: single
? [{ key: picked[0], label: tabName(picked[0]) }]
: picked.map((id) => ({ key: id, label: tabName(id) })),
value: single ? picked[0] : tab,
kind: "pill",
data: "b09Tab",
onChange: (id) => onPick(id as TabId),
});
sub.setAttribute("role", single ? "presentation" : "tablist");
if (single)
for (const button of buttons) {
button.tabIndex = -1;
button.setAttribute("aria-hidden", "true"); // 도구는 보이는 줄이라 줄 전체를 숨기지 않음
delete button.dataset.b09Tab;
}
sub.append(tools);
};
const setTools = (items: HTMLElement[]): void => tools.replaceChildren(...items);
return { top, sub, draw, setTools };
}