From 19fed5b90fac37c6beabbb85b273a1dec7574241 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Thu, 1 Oct 2026 16:49:02 +0900 Subject: [PATCH] =?UTF-8?q?feat(M01):=20=EB=8B=A8=EA=B0=80=EC=82=B0?= =?UTF-8?q?=EC=B6=9C=20=EB=A7=89=EB=8C=80=20=EC=8B=9C=ED=97=98=ED=8C=90=20?= =?UTF-8?q?=EB=84=B7=EC=9D=84=20=E3=80=8C=EC=8B=9C=ED=97=98=ED=8C=90=20?= =?UTF-8?q?=E2=96=BE=E3=80=8D=20=EB=AA=A9=EB=A1=9D=20=ED=95=98=EB=82=98?= =?UTF-8?q?=EB=A1=9C=20=EB=AC=B6=EC=9D=8C=20=C2=B7=20CostFlow=20=EC=9B=90?= =?UTF-8?q?=EA=B0=80=20=EC=B9=B8=EC=97=90=20=EC=9E=85=EB=A0=A5=20=EA=B0=92?= =?UTF-8?q?=EB=8F=84=20=EB=84=98=EA=B9=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt --- M01_MasterData/M01_MasterData_UI_LogicLab.ts | 64 +++++++++++++++++--- M02_MasterTemplete/CostFlow/M02_CF_Entry.ts | 10 ++- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab.ts b/M01_MasterData/M01_MasterData_UI_LogicLab.ts index 1daa1b757..b0daf8a6a 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab.ts @@ -7,7 +7,7 @@ * 409 = 그 사이 파일이 바뀜 · 422 = 검사 걸림(아무것도 안 씀) — 까닭은 서버 글 그대로 보임. * ========================================================================== */ -import { t as L } from "@ui/ui_template_locale"; +import { currentLanguageIndex, t as L } from "@ui/ui_template_locale"; import { createButton, el, @@ -75,6 +75,50 @@ interface Opened extends Draft { const cacheKey = "m01_logic_drafts_lab"; const ownHost = (): HTMLElement => el("div", { className: "m01lab__own" }); + +/** 시험판 묶음 — 「시험판 ▾」 단추 하나 · 누르면 시험판 단추들이 목록으로(바깥 · Esc · 고르면 닫힘) */ +function trialMenu(items: HTMLElement[]): HTMLElement { + const list = el("div", { attrs: { role: "menu" }, children: items }); + Object.assign(list.style, { + position: "absolute", + top: "calc(100% + 4px)", + left: "0", + zIndex: "20", + display: "none", + flexDirection: "column", + gap: "var(--spacing-4)", + padding: "var(--spacing-8)", + border: "1px solid var(--color-border)", + borderRadius: "var(--radius-lg)", + background: "var(--color-surface-raised)", + boxShadow: "var(--shadow-lg)", + whiteSpace: "nowrap", + }); + const shut = (): void => { + list.style.display = "none"; + button.setAttribute("aria-expanded", "false"); + document.removeEventListener("click", outside, true); + }; + const outside = (ev: Event): void => { + if (!wrap.contains(ev.target as Node)) shut(); + }; + const button = createButton({ + label: ["시험판 ▾", "Trials ▾"][currentLanguageIndex === 1 ? 1 : 0], + variant: "ghost", + onClick: () => { + if (list.style.display !== "none") return shut(); + list.style.display = "flex"; + button.setAttribute("aria-expanded", "true"); + document.addEventListener("click", outside, true); + }, + }); + button.setAttribute("aria-haspopup", "menu"); + list.addEventListener("click", () => shut()); // 고른 시험판은 제 단추가 엶 + const wrap = el("div", { children: [button, list] }); + Object.assign(wrap.style, { position: "relative", display: "inline-flex" }); + wrap.addEventListener("keydown", (ev) => ev.key === "Escape" && shut()); + return wrap; +} const clone = (v: T): T => JSON.parse(JSON.stringify(v)) as T; function loadDrafts(): Record { @@ -406,14 +450,16 @@ export async function mountM01LogicLab( el("h2", { text: tx("Title") }), pending, createButton({ label: tn("Open"), variant: "filled", onClick: startNew }), - // 쉬운 단가산출 시험 길 — 폴더째 지우면 이 두 줄도 지움 - createEasyCalcButton(), - // 로직 만들기 시험 길 — 폴더째 지우면 이 두 줄도 지움 - createLogicBuilderButton(), - // 시트 로직 시험 길 — 폴더째 지우면 이 두 줄도 지움 - createSheetLogicButton(), - // 단가산출 다이어그램 시험 길 — 폴더째 지우면 이 두 줄도 지움 - createCostFlowButton(), + trialMenu([ + // 쉬운 단가산출 시험 길 — 폴더째 지우면 이 두 줄도 지움 + createEasyCalcButton(), + // 로직 만들기 시험 길 — 폴더째 지우면 이 두 줄도 지움 + createLogicBuilderButton(), + // 시트 로직 시험 길 — 폴더째 지우면 이 두 줄도 지움 + createSheetLogicButton(), + // 단가산출 다이어그램 시험 길 — 폴더째 지우면 이 두 줄도 지움 + createCostFlowButton(), + ]), createButton({ label: tx("Bar_Delete"), variant: "danger", onClick: () => void onDelete() }), discardButton, saveButton, diff --git a/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts b/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts index 8e80d6524..d28a72125 100644 --- a/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts +++ b/M02_MasterTemplete/CostFlow/M02_CF_Entry.ts @@ -447,7 +447,15 @@ function openCostFlow(): void { deleteButton.hidden = !lg.key; M.diagram.renderDiagram(diagramHost, lg, diagramOn, { values: result.ports, selected }); drawPanel(); - M.summary.renderSummary(summaryHost, lg, result, { change: edit }); + // 「고칠 것」 검사가 받은 입력 값으로 하도록 값도 넘김 — Summary 가 opts.values 를 받으면 쓰임 + // ponytail: 지금 Summary 는 checkLogic(lg) 을 값 없이 불러 「값이 아직 없음」 이 남음(sub5 고침 뒤 이 꼴 그대로 둠) + (M.summary.renderSummary as (...args: unknown[]) => void)( + summaryHost, + lg, + result, + { change: edit }, + { values }, + ); note.textContent = [...notes, ...result.errors].slice(0, 4).join("\n"); };