feat(M02): 도면 칸 위쪽을 줄임 — 자리표 글 줄 뺌 · CAD 제목 줄 숨김 · 작도 영역 한 줄 · headerSlot 옵션
CAD 그림 칸 위쪽 448px 에서 285px 로, 그림 높이 598 에서 760 으로. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PxvYb5ufV1kWdBvZbpDfu6
This commit is contained in:
@@ -55,6 +55,9 @@ button {
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
.cad-host-save {
|
||||
--cad-title-height: 0px;
|
||||
}
|
||||
.controls {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { HtmlEvent } from '../App.types';
|
||||
import { getCommandById } from '../commands/registry';
|
||||
import { runCommand } from '../commands/run-command';
|
||||
import { QUICK_ACCESS_COMMANDS } from '../ribbon/ribbon.config';
|
||||
import { getHostTitle } from '../state';
|
||||
import { getHostTitle, isHostSave } from '../state';
|
||||
|
||||
export const QuickAccessBar: FC = () => {
|
||||
const [hostTitle, setTitle] = useState(getHostTitle());
|
||||
@@ -13,6 +13,8 @@ export const QuickAccessBar: FC = () => {
|
||||
window.addEventListener(HtmlEvent.UPDATE_STATE, refresh);
|
||||
return () => window.removeEventListener(HtmlEvent.UPDATE_STATE, refresh);
|
||||
}, []);
|
||||
// 부모 페이지가 저장·이름을 맡는 M02 에선 제목 줄을 숨겨 그림 칸을 넓힌다.
|
||||
if (isHostSave()) return null;
|
||||
return (
|
||||
<header className="cad-titlebar controls">
|
||||
<div className="cad-brand">
|
||||
|
||||
@@ -503,6 +503,8 @@ export const setDesignMeta = (newMeta: DesignMeta | null) => {
|
||||
export const isHostSave = (): boolean => hostSave;
|
||||
export const setHostSave = (enabled: boolean) => {
|
||||
hostSave = enabled;
|
||||
// 제목 줄이 없어지면 그 높이만큼 위로 당긴다(App.css `.cad-host-save`).
|
||||
document.documentElement.classList.toggle('cad-host-save', enabled);
|
||||
};
|
||||
export const getHostTitle = (): string => hostTitle;
|
||||
export const setHostTitle = (title: string) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* M02 도면 양식 편집 부품 — 위 도구 줄(작도 영역 · 자리표 · 단추) + 아래 웹캐드. */
|
||||
/* M02 도면 양식 편집 부품 — 위 도구 줄 한 줄(작도 영역 · 단추) + 아래 웹캐드. */
|
||||
|
||||
/* 도면 칸이 메인을 꽉 채우고 창 크기를 따른다 — 메인 칸(`ui-workflow-layout__main`)은
|
||||
높이가 정해지지 않아(min-height 만) 100% 가 안 먹으므로 화면 높이로 잡는다.
|
||||
@@ -32,7 +32,7 @@
|
||||
.m02-drawing__toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
gap: var(--spacing-8) var(--spacing-16, 16px);
|
||||
}
|
||||
|
||||
@@ -49,30 +49,31 @@
|
||||
gap: var(--spacing-8);
|
||||
}
|
||||
|
||||
.m02-drawing__area .ui-field {
|
||||
width: 5.5rem;
|
||||
}
|
||||
|
||||
.m02-drawing__fields {
|
||||
display: flex;
|
||||
flex: 1 1 20rem;
|
||||
.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__field {
|
||||
padding: 2px 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 1440px;
|
||||
background-color: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
.m02-drawing__area .ui-field input {
|
||||
width: 4.5rem;
|
||||
padding-block: 2px;
|
||||
}
|
||||
|
||||
.m02-drawing__area .ui-field label {
|
||||
font-size: 0.72rem;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.m02-drawing__field[data-source="도면"] {
|
||||
color: var(--color-text-muted);
|
||||
.m02-drawing__toolbar--slot {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.m02-drawing__actions {
|
||||
|
||||
@@ -36,6 +36,8 @@ export interface DrawingTemplateOptions {
|
||||
projectId?: string | null;
|
||||
/** 저장 안 한 고침이 생기면 true — CAD 편집 · 작도 영역 값 바꿈. */
|
||||
onChanged?: (dirty: boolean) => void;
|
||||
/** 페이지 제목 줄 안의 빈 칸 — 있으면 작도 영역 칸 · 파일 불러오기를 거기 한 줄로 놓는다. */
|
||||
headerSlot?: HTMLElement;
|
||||
}
|
||||
|
||||
const RECOVERY_PREFIX = "OPEN_WEB_CAD__RECOVERY__";
|
||||
@@ -73,19 +75,6 @@ export interface DrawingTemplateHandle {
|
||||
const DEFAULT_AREA: [number, number, number, number] = [42, 47, 812, 567];
|
||||
const AREA_LABELS = ["왼쪽 x", "아래 y", "오른쪽 x", "위 y"];
|
||||
|
||||
interface DrawingField {
|
||||
key: string;
|
||||
source: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
async function fetchDrawingFields(): Promise<DrawingField[]> {
|
||||
const response = await fetch(`${API_BASE_URL}/m02/drawing-fields`, { credentials: "include" });
|
||||
const payload = (await response.json()) as { fields?: DrawingField[]; message?: string };
|
||||
if (!response.ok) throw new Error(payload.message ?? `HTTP ${response.status}`);
|
||||
return payload.fields ?? [];
|
||||
}
|
||||
|
||||
async function importDrawingFile(
|
||||
file: File,
|
||||
): Promise<{ drawing: DrawingTemplateDoc; entity_count: number }> {
|
||||
@@ -126,6 +115,7 @@ export function mountDrawingTemplate(
|
||||
const areaTitle = document.createElement("span");
|
||||
areaTitle.className = "m02-drawing__title";
|
||||
areaTitle.textContent = "작도 영역";
|
||||
areaTitle.title = "도면 내용이 놓이는 칸 — 양식 좌표 mm";
|
||||
const start = doc.drawing_area ?? DEFAULT_AREA;
|
||||
const areaInputs = AREA_LABELS.map((label, index) => {
|
||||
const field = createInputField({ label, type: "number", value: String(start[index]) });
|
||||
@@ -142,34 +132,6 @@ export function mountDrawingTemplate(
|
||||
return valid ? (values as [number, number, number, number]) : null;
|
||||
};
|
||||
|
||||
// 자리표 키 — 누르면 `{{키}}` 를 복사한다. 도각 글자에 붙여 넣으면 그릴 때 값이 채워진다.
|
||||
const fields = document.createElement("div");
|
||||
fields.className = "m02-drawing__fields";
|
||||
const fieldsTitle = document.createElement("span");
|
||||
fieldsTitle.className = "m02-drawing__title";
|
||||
fieldsTitle.textContent = "자리표";
|
||||
fields.append(fieldsTitle);
|
||||
void fetchDrawingFields()
|
||||
.then((list) => {
|
||||
for (const field of list) {
|
||||
const chip = document.createElement("button");
|
||||
chip.type = "button";
|
||||
chip.className = "m02-drawing__field";
|
||||
chip.dataset.source = field.source;
|
||||
chip.textContent = `{{${field.key}}}`;
|
||||
chip.title = `${field.label} (${field.source}) — 눌러 복사`;
|
||||
chip.addEventListener("click", () => {
|
||||
void navigator.clipboard
|
||||
?.writeText(`{{${field.key}}}`)
|
||||
.then(() => showToast(`{{${field.key}}} 를 복사했습니다.`, "success"));
|
||||
});
|
||||
fields.append(chip);
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
showToast(error instanceof Error ? error.message : "자리표 목록을 받지 못했습니다.", "error"),
|
||||
);
|
||||
|
||||
// CAD 안 💾 · Ctrl+S — 양식 파일은 페이지 [저장] 만 쓴다. 저장 중 또 눌러도 한 번만 부른다.
|
||||
let saving = false;
|
||||
const hostSave = (): void => {
|
||||
@@ -242,8 +204,13 @@ export function mountDrawingTemplate(
|
||||
return base;
|
||||
};
|
||||
|
||||
toolbar.append(area, fields, actions);
|
||||
root.append(toolbar, cad.element);
|
||||
// 한 줄 — 페이지가 머리 칸(headerSlot)을 주면 거기, 아니면 그림 칸 위에 작게.
|
||||
toolbar.append(area, actions);
|
||||
if (options.headerSlot) {
|
||||
toolbar.classList.add("m02-drawing__toolbar--slot");
|
||||
options.headerSlot.append(toolbar);
|
||||
root.append(cad.element);
|
||||
} else root.append(toolbar, cad.element);
|
||||
container.append(root);
|
||||
load(doc);
|
||||
|
||||
@@ -251,6 +218,7 @@ export function mountDrawingTemplate(
|
||||
getDoc,
|
||||
destroy: () => {
|
||||
cad.destroy();
|
||||
toolbar.remove();
|
||||
root.remove();
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user