/* ============================================================================= * M02_MasterTemplete_Sangeun_Side.ts * 단가산출(SK) 상세 오른쪽 원문 패널(PLAN 752-1 · 요구 588-3) — 일위대가 상세(47-4 · 85-4)와 같은 부품: * 오른쪽 서랍(`createSidePanels`) + 원문 보기(`createSourceView` · M02 로그인 길 `/m02/logic-lib/source`) * 기초마다 탭 — 바탕 로직 · 둘째 기초(더한줄 로직) 각각의 출처 · 기초가 하나면 탭 없음 · 없으면 안내 * 처음 = 넓은 화면만 열림(좁으면 세로 띠로 접힘) · 열림 · 폭 기억 = `m02-sangeun-side` * 일위대가 줄 모달 안 상세는 안 만듦(부르는 쪽이 `source` 를 안 켬). * ========================================================================== */ import { createSegment } from "@ui/ui_template_segment"; import { el } from "@ui/ui_template_elements"; import { t as L } from "@ui/ui_template_locale"; import { createSidePanels } from "@ui/ui_template_side_panels"; import { createText } from "@ui/ui_template_text"; import { createSourceView } from "../M01_MasterData/M01_MasterData_UI_LogicLab_Source"; import { tc } from "./M02_MasterTemplete_Labor_Text"; export interface SourceTab { label: string; src: string; } /** 기초 로직 → 원문 탭(「원문번호 이름」 · 출처 글) */ export const tabOf = (logic: { 키: string; 원문번호?: string; 이름: string; 출처?: string; }): SourceTab => ({ label: `${logic.원문번호 || logic.키} ${logic.이름}`, src: logic.출처 ?? "", }); /** 이 폭 이상일 때만 처음부터 열림 — 상세 표 여섯 칸이 좁아지지 않게 */ const OPEN_FROM = 1500; export function createSangeunSide(): { wrap: (main: HTMLElement) => HTMLElement; set: (tabs: SourceTab[]) => void; } { const view = createSourceView({ path: "/m02/logic-lib/source", pdf: "/m02/logic-lib/source-pdf", }); const host = el("div", { attrs: { "data-sangeun-source": "" } }); let tabs: SourceTab[] = []; let at = 0; const side = createSidePanels({ prefKey: "m02-sangeun-side", follow: false, // 일위대가와 같음 — 상세 고정 높이 칸을 채움 · 본문과 따로 스크롤 defaultOpen: window.innerWidth >= OPEN_FROM ? "source" : null, panels: [{ id: "source", title: tc("Labor_Source"), body: host }], onChange: () => paint(), }); function paint(): void { if (side.current() !== "source") return; // 접힘 = 찾지 않음 if (!tabs.length) return void host.replaceChildren(createText(L("M02_SangeunSourceNone"), "muted")); at = Math.min(at, tabs.length - 1); view.show(tabs[at].src); const bar = tabs.length > 1 ? [ createSegment({ options: tabs.map((x, i) => ({ value: String(i), label: x.label })), value: String(at), size: 28, ariaLabel: tc("Labor_Source"), onChange: (v) => ((at = Number(v)), paint()), }).root, ] : []; host.replaceChildren(...bar, view.root); } return { wrap: (main) => el("div", { className: "ui-side-panels-row", children: [main, side.root] }), set: (next) => { if (JSON.stringify(next) === JSON.stringify(tabs)) return; tabs = next; paint(); }, }; }