diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts index dc657656..02d734f3 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Detail.ts @@ -309,19 +309,24 @@ function hoBox(ctx: DetailContext): HTMLElement { } const all = entries(ctx); const calculated = ctx.lines !== null; - const blocks = GROUPS.flatMap((group) => { + const tables = GROUPS.flatMap((group) => { const mine = all.filter((e) => e.group === group); return group === "other" && !mine.length ? [] : groupTable(group, mine, calculated); // 그 밖은 있을 때만 }); const total = all.reduce((s, e) => s + (e.amount ?? 0), 0); - blocks.push( - el("p", { - className: "m01lab__total", - attrs: { "data-sum": calculated ? String(total) : "" }, - text: `${tl("Total")} ${calculated ? formatNumber(total) : "—"}`, - }), - ); - if (isOwnLogic(ctx.row)) blocks.push(ownEditor(ctx)); + const totalLine = el("p", { + className: "m01lab__total", + attrs: { "data-sum": calculated ? String(total) : "" }, + text: `${tl("Total")} ${calculated ? formatNumber(total) : "—"}`, + }); + // 자체 로직 — 고치는 자리는 편집기 하나 · 읽기용 묶음 표는 접어 둠(펼치면 소계가 보임) + const fold = el("details", { + className: "m01lab__fold", + attrs: ctx.ownHost.dataset.fold ? { open: "" } : {}, + children: [el("summary", { text: tl("Ho_Fold") }), ...tables], + }); + fold.addEventListener("toggle", () => (ctx.ownHost.dataset.fold = fold.open ? "1" : "")); + const blocks = isOwnLogic(ctx.row) ? [ownEditor(ctx), fold, totalLine] : [...tables, totalLine]; const hint = calculated ? tl("Click_Hint") : `${tl("Click_Hint")} · ${tl("Calc_First")}`; return section(tl("Ho_Title"), blocks, hint); } @@ -330,10 +335,22 @@ function hoBox(ctx: DetailContext): HTMLElement { export function buildLabDetail(host: HTMLElement, ctx: DetailContext): void { const formula = el("div", { className: "m01lab__formula" }); buildFormula(formula, { text: ctx.text }); + // 다시 그리면 포커스가 빠짐 — 고치던 칸(편집기 · 기본정보)을 기억해 되돌림 + const active = document.activeElement; + const kept = + active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement + ? { node: active, from: active.selectionStart, to: active.selectionEnd } + : null; host.replaceChildren( infoBox(ctx), hoBox(ctx), section(tl("Formula_Title"), [formula]), section(tl("Calc_Title"), [ctx.calcHost]), ); + const own = kept?.node.dataset.own; // 기본정보 칸은 새로 만들어지므로 이름표로 다시 찾음 + const back = own ? host.querySelector(`[data-own="${own}"]`) : kept?.node; + if (kept && back && (own || ctx.ownHost.contains(back))) { + back.focus(); + if (kept.from !== null) back.setSelectionRange(kept.from, kept.to); + } } diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts index dd725120..72b44b35 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Text.ts @@ -19,6 +19,7 @@ const TEXT = { "고치기 (호표 · 중간 값 · 덧줄 · 끝수)", "Edit (lines · middles · extras · rounding)", ], + Ho_Fold: ["묶음 소계 표 (읽기용 — 고치기는 위 편집기)", "Group subtotals (read-only)"], Ho_Title: ["일위대가 호표", "Unit-cost table"], Formula_Title: ["텍스트 수식", "Text formula"], Formula_Slot: ["시험 계산을 누르면 식이 글로 나옴", "Run the trial calc to see the formula"],