From ef6390486689392b18acb8dc939828ff95537c37 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 25 Sep 2026 18:04:27 +0900 Subject: [PATCH] =?UTF-8?q?fix(M02):=20=EC=9E=91=EB=8F=84=20=EC=98=81?= =?UTF-8?q?=EC=97=AD=EC=9D=84=20=EA=B0=92=EC=9D=B4=20=EB=8B=A4=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=EB=8B=A8=EC=B6=94=20=ED=95=98=EB=82=98?= =?UTF-8?q?=EB=A1=9C=20=E2=80=94=20=EB=88=84=EB=A5=B4=EB=A9=B4=20=EC=B9=B8?= =?UTF-8?q?=20=EB=84=B7=EC=9D=B4=20=EC=9E=91=EC=9D=80=20=EC=B0=BD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=8E=BC=EC=B3=90=EC=A7=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01PxvYb5ufV1kWdBvZbpDfu6 --- .../M02_MasterTemplete_Drawing.css | 41 +++++++---------- .../M02_MasterTemplete_Drawing.ts | 44 +++++++++++++++---- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/M02_MasterTemplete/M02_MasterTemplete_Drawing.css b/M02_MasterTemplete/M02_MasterTemplete_Drawing.css index 24892a35c..982029d01 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Drawing.css +++ b/M02_MasterTemplete/M02_MasterTemplete_Drawing.css @@ -43,35 +43,24 @@ color: var(--color-text); } -.m02-drawing__area { - display: flex; - align-items: flex-end; - gap: var(--spacing-4, 4px); -} - -.m02-drawing__area { - flex-wrap: wrap; - align-items: center; -} - -/* 칸 이름과 입력을 한 줄로 — 세로로 쌓지 않는다. */ -.m02-drawing__area .ui-field { - flex-direction: row; - align-items: center; - gap: var(--spacing-4, 4px); - width: auto; -} - -.m02-drawing__area .ui-field input { - width: 3rem; - padding-block: 2px; -} - -.m02-drawing__area .ui-field label { - font-size: 0.72rem; +.m02-drawing__areabtn { + font-variant-numeric: tabular-nums; white-space: nowrap; } +.m02-drawing__areabtn.is-invalid { + border-color: var(--color-danger); + color: var(--color-danger); +} + +/* 작은 창 안 칸 넷 — 이름이 다 보이는 넉넉한 폭 */ +.m02-drawing__areaform { + display: grid; + grid-template-columns: repeat(2, minmax(9rem, 1fr)); + gap: var(--spacing-12); + min-width: min(22rem, 80vw); +} + .m02-drawing__toolbar--slot { flex: 1 1 0; min-width: 0; diff --git a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts index e0dd3c685..c56f8da6c 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts @@ -14,6 +14,7 @@ import "./M02_MasterTemplete_Drawing.css"; import { API_BASE_URL } from "@config/config_frontend"; import { createCadHost, type CadHostDrawing } from "@ui/cad_host/cad_host"; import { createButton, createInputField, showToast } from "@ui/ui_template_elements"; +import { openModal } from "@ui/ui_template_modal"; /** 도면 양식 문서 — 작도 영역은 [x0, y0, x1, y1] (양식 좌표 mm). */ export interface DrawingTemplateDoc extends CadHostDrawing { @@ -73,7 +74,7 @@ export interface DrawingTemplateHandle { /** 작도 영역 칸이 없는 양식이 쓰는 값 — 서버 `Engine_Template._A1_INNER` 와 같다. */ const DEFAULT_AREA: [number, number, number, number] = [42, 47, 812, 567]; -const AREA_LABELS = ["왼x", "아래y", "오른x", "위y"]; +const AREA_LABELS = ["왼쪽 x", "아래 y", "오른쪽 x", "위 y"]; async function importDrawingFile( file: File, @@ -109,25 +110,49 @@ export function mountDrawingTemplate( const toolbar = document.createElement("div"); toolbar.className = "m02-drawing__toolbar"; - // 작도 영역 — 도면 내용이 이 칸 한가운데에 놓인다. - const area = document.createElement("div"); - area.className = "m02-drawing__area"; + // 작도 영역 — 도면 내용이 이 칸 한가운데에 놓인다. 제목 줄에는 값이 다 보이는 단추 하나, + // 누르면 칸 넷이 작은 창으로 펼쳐진다(칸은 창을 닫아도 그대로 살아 있음). + const areaForm = document.createElement("div"); + areaForm.className = "m02-drawing__areaform"; const start = doc.drawing_area ?? DEFAULT_AREA; const areaInputs = AREA_LABELS.map((label, index) => { const field = createInputField({ label, type: "number", value: String(start[index]) }); field.input.disabled = readOnly; - field.input.addEventListener("input", () => options.onChanged?.(true)); + field.input.addEventListener("input", () => { + options.onChanged?.(true); + readArea(); + }); return field; }); - area.title = "작도 영역 — 도면 내용이 놓이는 칸(양식 좌표 mm)"; - area.append(...areaInputs.map((field) => field.root)); + areaForm.append(...areaInputs.map((field) => field.root)); + + const areaButton = createButton({ label: "", variant: "ghost" }); + areaButton.classList.add("m02-drawing__areabtn"); + areaButton.title = "작도 영역 — 도면 내용이 놓이는 칸(양식 좌표 mm) · 눌러서 고침"; + let areaModal: { close: () => void } | null = null; const readArea = (): [number, number, number, number] | null => { const values = areaInputs.map((field) => Number(field.input.value)); - const valid = values.every(Number.isFinite) && values[0] < values[2] && values[1] < values[3]; + const valid = + areaInputs.every((field) => field.input.value.trim() !== "") && + values.every(Number.isFinite) && + values[0] < values[2] && + values[1] < values[3]; areaInputs.forEach((field) => field.setError(valid ? undefined : "왼쪽<오른쪽 · 아래<위")); + areaButton.textContent = `작도 영역 ${areaInputs.map((f) => f.input.value.trim() || "?").join(" · ")}`; + areaButton.classList.toggle("is-invalid", !valid); return valid ? (values as [number, number, number, number]) : null; }; + readArea(); + areaButton.addEventListener("click", () => { + areaModal?.close(); + areaModal = openModal({ + title: "작도 영역", + closeLabel: "닫기", + dialogClass: "m02-modal", + mount: (body) => body.append(areaForm), + }); + }); // CAD 안 💾 · Ctrl+S — 양식 파일은 페이지 [저장] 만 쓴다. 저장 중 또 눌러도 한 번만 부른다. let saving = false; @@ -203,7 +228,7 @@ export function mountDrawingTemplate( }; // 한 줄 — 페이지가 머리 칸(headerSlot)을 주면 거기, 아니면 그림 칸 위에 작게. - toolbar.append(area, actions); + toolbar.append(areaButton, actions); if (options.headerSlot) { toolbar.classList.add("m02-drawing__toolbar--slot"); options.headerSlot.append(toolbar); @@ -215,6 +240,7 @@ export function mountDrawingTemplate( return { getDoc, destroy: () => { + areaModal?.close(); cad.destroy(); toolbar.remove(); root.remove();