/* ============================================================================= * line_stack_sourced.ts * 가져온 식 옵션 가로 칸(PLAN 810-3 · 요구 705 · 703) — 줄 쌓기 위 옵션 가로(`formula_doc_options.ts`) 뒤에 붙음 * 값 칸 = 경쟁사 파일에 값으로 드러난 수(q · K · E · Cm · Q …) · 꼬리표 「원파일」 · 「엑셀」(`sourceOf`) · * 고침 = 그 숫자 연결 값(부른 쪽 `set` · 캐시 → [저장]) * 규격 칸 = 원파일 블록 규격(읽기만) · 추정 칸 = 값 없이 이름만 적힌 품셈 조건 글(문서 `가져온.추정` · 읽기만 · * M01 기초에 묶지 않음 · 703) * ========================================================================== */ import { createBadge } from "@ui/ui_template_badge"; import { el } from "@ui/ui_template_elements"; import { createInputField } from "@ui/ui_template_input"; import { varId, type DocVar, type FormulaDoc } from "../common_util/common_util_formula_doc"; import { sourceOf } from "../common_util/common_util_line_stack"; import { lt } from "./line_stack_text"; interface Head { 원파일?: boolean; 규격?: string; 추정?: { 행?: number; 글?: string }[]; } const cell = (field: HTMLElement, tag: string, tone: "info" | "warning", hint: string) => el("div", { className: "lstk-src", attrs: { title: hint }, children: [field, createBadge(tag, tone)], }); export function buildSourced( doc: FormulaDoc | null, lock: boolean, set: (key: string, v: DocVar, value: unknown) => void, ): HTMLElement[] { const head = (doc as { 가져온?: Head } | null)?.가져온; if (!doc || !head) return []; const out: HTMLElement[] = []; for (const v of doc.변수 ?? []) { const tag = sourceOf(doc, v); if (!tag) continue; const id = varId(v); const f = createInputField({ label: v.이름 || id, value: String(v.연결?.값 ?? ""), compact: true, size: 28, unit: v.단위 || undefined, }); f.input.disabled = lock; f.input.addEventListener("change", () => { const n = Number(f.input.value.trim().replace(/,/g, "")); if (f.input.value.trim() === "" || !Number.isFinite(n)) return void (f.input.value = String(v.연결?.값 ?? "")); // 수만 — 빈 값 · 글 = 그대로 set(id, v, n); // 수 그대로(글 「0.7」 = 셈 「—」 · 공식 묶음 값 칸 `setRow` 와 같은 꼴 · 812-3) }); f.root.dataset.option = id; const tagText = tag === "원파일" ? lt("Src_Native") : tag === "엑셀" ? lt("Src_Excel") : tag; out.push(cell(f.root, tagText, "info", lt("Src_Hint"))); } const ro = (label: string, value: string, mark: string, guess: boolean) => { const f = createInputField({ label, value, compact: true, size: 28 }); f.input.readOnly = true; f.input.title = value; // 긴 조건 글 = 칸 위에 올리면 다 보임 if (guess) f.root.dataset.guess = mark; return guess ? cell(f.root, lt("Guess"), "warning", lt("Guess_Hint")) : cell(f.root, lt(head.원파일 ? "Src_Native" : "Src_Excel"), "info", lt("Src_Hint")); // 812-1 엑셀 읽기기 = 「엑셀」 }; if (head.규격) out.push(ro(lt("Spec"), head.규격, "", false)); for (const g of head.추정 ?? []) out.push( ro( `${lt("Guess_Label")}${g.행 !== undefined ? ` · ${g.행}행` : ""}`, String(g.글 ?? "").replace(/^※\s*/, ""), String(g.행 ?? ""), true, ), ); return out; }