refactor(B05 평면 · 지도 공용): RouteEdit 마우스 배선 · 재기 한 벌 떼어냄 · 긋기 방식 칸 공용 자리로 (PLAN 626-3 · 요구 530 · 531)

- B05_Profile_UI_RouteEdit.ts 684 → 655 줄 — 두 번 클릭 삽입 · 오른쪽 클릭 삭제 · 지도 이동 · 휠 = 새 `_RouteEdit_Mouse.ts` · 재기 도구 + 단추 한 벌 = `_Measure.ts` `createRouteMeasure` (동작 그대로)
- 긋기 방식 칸(`createDrawKindFields` · 기본값 · 이름) = 새 `A00_Common/map/map_draw_kind.ts` · `.css` — D03 DrawPanel 은 다시 내보냄(D03 화면 · 동작 같음 · 칸 꼴 선택자만 공용 이름)
- D03 `paintPreview` · `planLabel` 받는 지도 꼴을 쓰는 칸만(Pick)으로 — B05 평면이 그대로 부름
- 시험 test_553_4 — 방식 칸 대조를 공용 파일로 옮김(낡은 자리 대조)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 21:51:58 +09:00
co-authored by Claude Opus 5.5
parent 63ea2c181d
commit 62a8ee362e
9 changed files with 300 additions and 214 deletions
+28
View File
@@ -0,0 +1,28 @@
/* 공용 긋기 방식 칸(626-3 · `map_draw_kind.ts`) — 고름 아래 길이 · 기울기 두 열 */
.map-draw-kind {
display: flex;
flex-direction: column;
gap: 6px;
}
.map-draw-kind__fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--spacing-8);
align-items: start;
}
.map-draw-kind__fields[hidden] {
display: none;
}
.map-draw-kind__fields .ui-field {
margin: 0;
min-width: 0;
}
.map-draw-kind__fields .ui-input-unit,
.map-draw-kind__fields .ui-input {
width: 100%;
min-width: 0;
}
+146
View File
@@ -0,0 +1,146 @@
/* =============================================================================
* map_draw_kind.ts
* 공용 긋기 방식 칸(PLAN 626-3 · 599-1 · 625-1) — 예정노선(D03) 그리기 칸 · 노드 판 · B05 평면 예정노선 그리기가 같이 씀.
* 꼴 = 마디 고름 2 × 2(자유지정 · 길이·기울기 고정 / 길이 고정 · 기울기 고정) + 길이 · 기울기 두 열(기울기 아래 ≈ °) ·
* 방식에 안 쓰는 칸은 숨김(막힘 = 권한 없음만) · 설명 글 없음(요구 463-6).
* 쓰는 법 = `createDrawKindFields({ value, onChange })` → { root, get, set, setDisabled }.
* ========================================================================== */
import type { UiSize } from "@ui/ui_template_button";
import { createInputField } from "@ui/ui_template_input";
import { createSegment } from "@ui/ui_template_segment";
import { createText } from "@ui/ui_template_text";
import "./map_draw_kind.css";
/** 기울기 % → 각(°) 한 자리 글. */
const slopeDegText1 = (pct: number): string => ((Math.atan(pct / 100) * 180) / Math.PI).toFixed(1);
/** 제약 칸 처음 값 — 길이 = 측점 간격(지식DB 설계제원_총괄) · 기울기 = 간선 20 km/h 일반지형 상한(종단선형). */
export const DRAW_DEFAULT_LENGTH_M = 20;
export const DRAW_DEFAULT_SLOPE_PCT = 9;
export type DrawConstraint = "free" | "length" | "slope" | "both";
export interface DrawKindValue {
kind: DrawConstraint;
lengthM: number;
slopePct: number;
}
export const DRAW_KIND_LABELS: Record<DrawConstraint, string> = {
free: "자유지정",
both: "길이·기울기 고정",
length: "길이 고정",
slope: "기울기 고정",
};
export interface DrawKindFields {
root: HTMLElement;
get: () => DrawKindValue;
/** 값을 바꿈(onChange 는 안 부름). */
set: (value: Partial<DrawKindValue>) => void;
setDisabled: (disabled: boolean) => void;
}
/** 긋기 방식 칸 — 고름 · 길이 · 기울기가 바뀔 때마다 `onChange(지금 값)`(빈 · 틀린 수는 칸 오류만). */
export function createDrawKindFields(opts: {
value: DrawKindValue;
onChange: (value: DrawKindValue) => void;
size?: UiSize;
}): DrawKindFields {
const size = opts.size ?? 24;
let value = { ...opts.value };
let disabled = false;
const changed = (): void => opts.onChange({ ...value });
const segment = createSegment({
options: (Object.keys(DRAW_KIND_LABELS) as DrawConstraint[]).map((kind) => ({
value: kind,
label: DRAW_KIND_LABELS[kind],
})),
value: value.kind,
size,
columns: 2,
ariaLabel: "긋기 방식",
onChange: (next) => {
value.kind = next as DrawConstraint;
fieldsState();
changed();
},
});
segment.root.dataset.role = "draw-constraint";
const lengthField = createInputField({
label: "길이",
type: "number",
value: String(value.lengthM),
min: 1,
unit: "m",
size,
onInput: (text) => {
const next = Number(text);
lengthField.setError(next > 0 ? undefined : "0 보다 큰 수");
if (!(next > 0)) return;
value.lengthM = next;
changed();
},
});
lengthField.input.dataset.role = "draw-length";
const slopeField = createInputField({
label: "기울기",
type: "number",
value: String(value.slopePct),
unit: "%",
size,
onInput: (text) => {
const next = Number(text);
const ok = text.trim() !== "" && Number.isFinite(next);
slopeField.setError(ok ? undefined : "숫자");
if (!ok) return;
value.slopePct = next;
degText();
changed();
},
});
slopeField.input.dataset.role = "draw-slope";
const slopeDegText = createText("", "muted");
slopeDegText.dataset.role = "draw-slope-deg";
const degText = (): void => {
slopeDegText.textContent = `≈ ${slopeDegText1(Math.abs(value.slopePct))}°`;
};
const slopeColumn = document.createElement("div");
slopeColumn.append(slopeField.root, slopeDegText);
const fields = document.createElement("div");
fields.className = "map-draw-kind__fields";
fields.append(lengthField.root, slopeColumn);
const root = document.createElement("div");
root.className = "map-draw-kind";
root.append(segment.root, fields);
function fieldsState(): void {
for (const button of segment.root.querySelectorAll("button")) button.disabled = disabled;
lengthField.input.disabled = slopeField.input.disabled = disabled;
fields.hidden = value.kind === "free";
lengthField.root.hidden = value.kind === "slope";
slopeColumn.hidden = value.kind === "length";
}
degText();
fieldsState();
return {
root,
get: () => ({ ...value }),
set(next) {
value = { ...value, ...next };
segment.set(value.kind);
lengthField.input.value = String(value.lengthM);
slopeField.input.value = String(value.slopePct);
lengthField.setError(undefined);
slopeField.setError(undefined);
degText();
fieldsState();
},
setDisabled(next) {
disabled = next;
fieldsState();
},
};
}
+13 -42
View File
@@ -22,7 +22,6 @@ import {
type ViewState,
} from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import { showToast } from "@ui/ui_template_elements";
import {
bindMinorContourToggle,
createSheetFollow,
@@ -41,12 +40,12 @@ import {
import { bindRouteApply } from "./B05_Profile_UI_RouteEdit_Apply";
import type { EditedCurve, EditedNode } from "./logic/B05_Profile_UI_RouteEdit_Curve";
import { drawRouteEditScene, routeHeadText, watchTheme } from "./B05_Profile_UI_RouteEdit_Render";
import { bindNodeSplice, bindRouteEditNavigation } from "./B05_Profile_UI_RouteEdit_Input";
import { bindRouteEditMouse } from "./B05_Profile_UI_RouteEdit_Mouse";
import { bindRouteEditPointer } from "./B05_Profile_UI_RouteEdit_Pointer";
import { createCrossPreview } from "./B05_Profile_UI_RouteEdit_Cross";
import { createMapRotation } from "./B05_Profile_UI_RouteEdit_Rotate";
import { createRouteEditChrome } from "./B05_Profile_UI_RouteEdit_Chrome";
import { bindMeasureControls, createMeasureTool } from "./B05_Profile_UI_RouteEdit_Measure";
import { createRouteMeasure } from "./B05_Profile_UI_RouteEdit_Measure";
import { createSlopeLabels } from "./B05_Profile_UI_RouteEdit_Slope";
import {
captureView,
@@ -191,22 +190,13 @@ export async function mountRouteEditor(
// 횡단이 뜨면 그 측점 반폭 선을 그린다 — 새로 고침 뒤 고른 측점은 만드는 도중 불려 아래 선언이 아직이라 한 박자 뒤에(505-4).
onShown: () => queueMicrotask(draw),
});
/** 구간 재기 — 계획·예상 노선 위 두 점. 셈·서버 묻기는 `_Measure` 몫(계획서 0-9 ⑤). */
const measure = createMeasureTool({
/** 구간 재기 — 계획·예상 노선 위 두 점 · 재기 단추·작은 창. 셈·서버 묻기 · 배선은 `_Measure` 몫(계획서 0-9 ⑤). */
const { measure, measureControls } = createRouteMeasure({
projectId,
stationIntervalM,
lines: () => ({ planned: plannedLine.length ? plannedLine : planned, expected }),
toScreen: (vertex) => toScreen(vertex),
isClosed: () => closed,
onChange: () => {
measureControls.sync();
draw();
},
onHint: () => measureControls.sync(),
});
/** 재기 단추·작은 창 — 배선은 `_Measure` 몫. */
const measureControls = bindMeasureControls({
measure,
box: measureBox,
text: measureText,
button: measureButton,
@@ -547,37 +537,18 @@ export async function mountRouteEditor(
offStation,
});
bindNodeSplice({
canvas,
unrotate: rotation.unrotate,
segmentAt: pointer.segmentAt,
nodeAt: pointer.nodeAt,
insert: (segment, px, py) => {
edits.spliceNode(snapshotNow(), segment + 1, toMetric(px, py)); // 편집값도 같은 자리에 끼운다.
picked = segment + 1;
applyEdit("새 노드를 넣었습니다(직선 추가).");
},
remove: (index) => {
if (planned.length <= 2) return showToast("노선은 노드가 2개 이상이어야 합니다.", "error");
if (apexLock[index])
return showToast("고정한 점은 못 지웁니다 — 고정을 먼저 푸세요.", "error");
edits.spliceNode(snapshotNow(), index);
picked = -1;
applyEdit("노드를 지웠습니다(직선 삭제).");
},
});
bindRouteEditNavigation({
// 두 번 클릭 삽입 · 오른쪽 클릭 삭제 · 지도 이동 · 확대 · 돌리기 — 배선은 `_Mouse` 몫.
bindRouteEditMouse({
canvas,
rotation,
pointer,
toMetric,
getView: () => view,
setView: (next) => {
view = next;
},
setView: (next) => (view = next),
getMeta: () => meta,
// 돌린 지도에서는 손이 민 방향과 그림이 움직일 방향이 다르다 — 거꾸로 돌려 넘긴다.
unrotateDelta: rotation.unrotateDelta,
rotateWheel: rotation.wheel, // Ctrl+휠 = 5° 돌리기(390-3)
claimed: pointer.claimed, // 왼쪽 옮기기 = 노드 · 손잡이 · 마커 · 재기 아닌 누름만(588-4)
snapshot: snapshotNow,
setPicked: (index) => (picked = index),
applyEdit: (message) => applyEdit(message),
draw,
});
@@ -183,6 +183,22 @@ export function bindMeasureControls(params: MeasureControlsParams): {
return { sync, mode: () => mode };
}
/** 재기 도구 + 단추 · 작은 창 한 벌(626-3 · `_RouteEdit` 에서 뗌) — 상태 바뀜 = 창 맞춤 · 다시 그림 · 미리보기 = 창 글만. */
export function createRouteMeasure(
params: Omit<MeasureToolParams, "onChange" | "onHint"> & Omit<MeasureControlsParams, "measure">,
): { measure: MeasureTool; measureControls: ReturnType<typeof bindMeasureControls> } {
const measure = createMeasureTool({
...params,
onChange: () => {
measureControls.sync();
params.redraw();
},
onHint: () => measureControls.sync(),
});
const measureControls = bindMeasureControls({ ...params, measure });
return { measure, measureControls };
}
export function createMeasureTool(params: MeasureToolParams): MeasureTool {
/** 찍은 두 점. 셋째를 찍으면 새 구간의 시작이 된다. */
let picked: MeasurePoint[] = [];
@@ -0,0 +1,72 @@
/* =============================================================================
* B05_Profile_UI_RouteEdit_Mouse.ts
* 계획노선 편집(평면) 마우스 배선 — 선 두 번 클릭 = 노드 넣기 · 노드 오른쪽 클릭 = 지움 · 가운데(휠) 버튼 끌기 =
* 지도 이동 · 휠 = 확대 · Ctrl+휠 = 돌리기. `B05_Profile_UI_RouteEdit.ts` 에서 뗌(626-3 · 동작 그대로).
* 노드 끌기 · 집기는 `_Pointer` 몫 · 집기 셈 · 듣기는 `_Input` 몫.
* ========================================================================== */
import type { ViewState } from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import { showToast } from "@ui/ui_template_elements";
import { bindNodeSplice, bindRouteEditNavigation } from "./B05_Profile_UI_RouteEdit_Input";
import type { RouteEditSnapshot } from "./B05_Profile_UI_RouteEdit_History";
import type { MapRotation } from "./B05_Profile_UI_RouteEdit_Rotate";
import * as edits from "./logic/B05_Profile_UI_RouteEdit_Edits";
type Vertex = [number, number];
export interface RouteEditMouseParams {
canvas: HTMLCanvasElement;
rotation: Pick<MapRotation, "unrotate" | "unrotateDelta" | "wheel">;
pointer: {
segmentAt: (px: number, py: number) => number;
nodeAt: (px: number, py: number) => number;
claimed: () => boolean;
};
toMetric: (px: number, py: number) => Vertex;
getView: () => ViewState;
setView: (next: ViewState) => void;
getMeta: () => VWorldMeta | null;
/** 지금 편집값(같은 배열 — 넣고 빼면 그대로 바뀜). */
snapshot: () => RouteEditSnapshot;
setPicked: (index: number) => void;
applyEdit: (message: string) => void;
draw: () => void;
}
export function bindRouteEditMouse(params: RouteEditMouseParams): void {
const { canvas, rotation, pointer } = params;
bindNodeSplice({
canvas,
unrotate: rotation.unrotate,
segmentAt: pointer.segmentAt,
nodeAt: pointer.nodeAt,
insert: (segment, px, py) => {
edits.spliceNode(params.snapshot(), segment + 1, params.toMetric(px, py)); // 편집값도 같은 자리에 끼운다.
params.setPicked(segment + 1);
params.applyEdit("새 노드를 넣었습니다(직선 추가).");
},
remove: (index) => {
const snapshot = params.snapshot();
if (snapshot.planned.length <= 2)
return showToast("노선은 노드가 2개 이상이어야 합니다.", "error");
if (snapshot.apexLock[index])
return showToast("고정한 점은 못 지웁니다 — 고정을 먼저 푸세요.", "error");
edits.spliceNode(snapshot, index);
params.setPicked(-1);
params.applyEdit("노드를 지웠습니다(직선 삭제).");
},
});
bindRouteEditNavigation({
canvas,
getView: params.getView,
setView: params.setView,
getMeta: params.getMeta,
// 돌린 지도에서는 손이 민 방향과 그림이 움직일 방향이 다르다 — 거꾸로 돌려 넘긴다.
unrotateDelta: rotation.unrotateDelta,
rotateWheel: rotation.wheel, // Ctrl+휠 = 5° 돌리기(390-3)
claimed: pointer.claimed, // 왼쪽 옮기기 = 노드 · 손잡이 · 마커 · 재기 아닌 누름만(588-4)
draw: params.draw,
});
}
@@ -5,7 +5,7 @@
* 미리보기(거리 · 가상 종단 기울기 % · °) · 집기 = 화면 px 둘레 선 위 자리.
* 길이·기울기 고정 부채꼴(625-2) — 정방향 = 채움 · 역방향 = 테두리 · 노드 · 놓인 꺾임점 · 미리보기 고리 =
* 기울기 부호 색(+ 오르막 `--draw-map-slope-up` 따뜻한 색 · − 내리막 `--draw-map-slope-down` 찬 색 · 막힘 = 경고 빨강).
* `paintFan` = ScreenMap 의 `toScreen` 만 씀 — B05 평면(626-3)이 그대로 씀.
* `paintFan` · `paintPreview` = ScreenMap 의 `toScreen` · `pxPerMeter` · `upright` 만 씀 — B05 평면(626-3)이 그대로 씀.
* 지점 핀(585-1) = 따로 겹(`pointLayer` · 겹 목록 맨 끝 = 늘 맨 위) · 색 = 목록 줄과 같은 `pointColor(i)` · 끌기 · 메뉴 = `D03_PlanAnalysis_UI_Points`.
* ========================================================================== */
@@ -330,7 +330,7 @@ export function paintMark(
* 고리 = 고른 점 기울기 부호 색(놓인 뒤 꺾임점과 같은 색). */
export function paintPreview(
context: CanvasRenderingContext2D,
map: ScreenMap,
map: Pick<ScreenMap, "toScreen" | "pxPerMeter" | "upright">,
from: Vertex,
preview: DrawPreview,
compass: { lengthM: number; fan: Fan } | null,
@@ -368,7 +368,7 @@ export function paintPreview(
export function planLabel(
context: CanvasRenderingContext2D,
map: ScreenMap,
map: Pick<ScreenMap, "upright">,
x: number,
y: number,
text: string,
+13 -137
View File
@@ -2,150 +2,26 @@
* D03_PlanAnalysis_UI_DrawPanel.ts
* D03 좌측 「그리기」 칸 몸(PLAN 599-1 · 599-4 · 요구 463-10 · 22) — [긋기] · 연도 구역 마커 · 긋기 방식 칸.
*
* 방식 칸 `createDrawKindFields` = 마디 고름 2 × 2(자유지정 · 길이·기울기 고정 / 길이 고정 · 기울기 고정 ·
* 625-1) + 길이 · 기울기 두 열(기울기 아래 ≈ °) — 방식에 안 쓰는 칸은 숨김(막힘 = 권한 없음만) ·
* 그리기 칸 · 노드 판(598-4)이 같은 부품을 씀.
* 방식 칸 `createDrawKindFields` = 공용 `A00_Common/map/map_draw_kind`(626-3) — 그리기 칸 · 노드 판(598-4) ·
* B05 평면 예정노선 그리기가 같은 부품을 씀(여기서 다시 내보냄).
* 연도 구역 마커 = 끌어 선 위에 놓기(`YEAR_MARK_DRAG` · 받음 = `D03_PlanAnalysis_UI_Edit` drop).
* 설명 글 없음(요구 463-6) — 칸 오류 · ≈ ° 값만.
* ========================================================================== */
import type { UiSize } from "@ui/ui_template_button";
import { createButton } from "@ui/ui_template_elements";
import { createInputField } from "@ui/ui_template_input";
import { createSegment } from "@ui/ui_template_segment";
import { createText } from "@ui/ui_template_text";
import { fmt, slopeDeg } from "./D03_PlanAnalysis_UI_DrawPaint";
import { YEAR_MARK_DRAG } from "./D03_PlanAnalysis_UI_Map";
import type { DrawKindFields } from "../A00_Common/map/map_draw_kind";
/** 제약 칸 처음 값 — 길이 = 측점 간격(지식DB 설계제원_총괄) · 기울기 = 간선 20 km/h 일반지형 상한(종단선형). */
export const DRAW_DEFAULT_LENGTH_M = 20;
export const DRAW_DEFAULT_SLOPE_PCT = 9;
export type DrawConstraint = "free" | "length" | "slope" | "both";
export interface DrawKindValue {
kind: DrawConstraint;
lengthM: number;
slopePct: number;
}
export const DRAW_KIND_LABELS: Record<DrawConstraint, string> = {
free: "자유지정",
both: "길이·기울기 고정",
length: "길이 고정",
slope: "기울기 고정",
};
export interface DrawKindFields {
root: HTMLElement;
get: () => DrawKindValue;
/** 값을 바꿈(onChange 는 안 부름). */
set: (value: Partial<DrawKindValue>) => void;
setDisabled: (disabled: boolean) => void;
}
/** 긋기 방식 칸 — 고름 · 길이 · 기울기가 바뀔 때마다 `onChange(지금 값)`(빈 · 틀린 수는 칸 오류만). */
export function createDrawKindFields(opts: {
value: DrawKindValue;
onChange: (value: DrawKindValue) => void;
size?: UiSize;
}): DrawKindFields {
const size = opts.size ?? 24;
let value = { ...opts.value };
let disabled = false;
const changed = (): void => opts.onChange({ ...value });
const segment = createSegment({
options: (Object.keys(DRAW_KIND_LABELS) as DrawConstraint[]).map((kind) => ({
value: kind,
label: DRAW_KIND_LABELS[kind],
})),
value: value.kind,
size,
columns: 2,
ariaLabel: "긋기 방식",
onChange: (next) => {
value.kind = next as DrawConstraint;
fieldsState();
changed();
},
});
segment.root.dataset.role = "draw-constraint";
const lengthField = createInputField({
label: "길이",
type: "number",
value: String(value.lengthM),
min: 1,
unit: "m",
size,
onInput: (text) => {
const next = Number(text);
lengthField.setError(next > 0 ? undefined : "0 보다 큰 수");
if (!(next > 0)) return;
value.lengthM = next;
changed();
},
});
lengthField.input.dataset.role = "draw-length";
const slopeField = createInputField({
label: "기울기",
type: "number",
value: String(value.slopePct),
unit: "%",
size,
onInput: (text) => {
const next = Number(text);
const ok = text.trim() !== "" && Number.isFinite(next);
slopeField.setError(ok ? undefined : "숫자");
if (!ok) return;
value.slopePct = next;
degText();
changed();
},
});
slopeField.input.dataset.role = "draw-slope";
const slopeDegText = createText("", "muted");
slopeDegText.dataset.role = "draw-slope-deg";
const degText = (): void => {
slopeDegText.textContent = `≈ ${fmt(slopeDeg(Math.abs(value.slopePct)))}°`;
};
const slopeColumn = document.createElement("div");
slopeColumn.append(slopeField.root, slopeDegText);
const fields = document.createElement("div");
fields.className = "d03-plan__draw-fields";
fields.append(lengthField.root, slopeColumn);
const root = document.createElement("div");
root.className = "d03-plan__draw-kind";
root.append(segment.root, fields);
function fieldsState(): void {
for (const button of segment.root.querySelectorAll("button")) button.disabled = disabled;
lengthField.input.disabled = slopeField.input.disabled = disabled;
fields.hidden = value.kind === "free";
lengthField.root.hidden = value.kind === "slope";
slopeColumn.hidden = value.kind === "length";
}
degText();
fieldsState();
return {
root,
get: () => ({ ...value }),
set(next) {
value = { ...value, ...next };
segment.set(value.kind);
lengthField.input.value = String(value.lengthM);
slopeField.input.value = String(value.slopePct);
lengthField.setError(undefined);
slopeField.setError(undefined);
degText();
fieldsState();
},
setDisabled(next) {
disabled = next;
fieldsState();
},
};
}
// 방식 칸 = 공용(`A00_Common/map/map_draw_kind` · 626-3 · B05 평면 예정노선 그리기도 씀)
export {
createDrawKindFields,
DRAW_DEFAULT_LENGTH_M,
DRAW_DEFAULT_SLOPE_PCT,
DRAW_KIND_LABELS,
type DrawConstraint,
type DrawKindFields,
type DrawKindValue,
} from "../A00_Common/map/map_draw_kind";
export interface DrawPanel {
root: HTMLElement;
+1 -28
View File
@@ -185,34 +185,7 @@
margin: 0;
}
/* 599 그리기 칸 — 방식 칸(마디 고름 2 × 2 · 길이 · 기울기 두 열) */
.d03-plan__draw-kind {
display: flex;
flex-direction: column;
gap: 6px;
}
.d03-plan__draw-fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--spacing-8);
align-items: start;
}
.d03-plan__draw-fields[hidden] {
display: none;
}
.d03-plan__draw-fields .ui-field {
margin: 0;
min-width: 0;
}
.d03-plan__draw-fields .ui-input-unit,
.d03-plan__draw-fields .ui-input {
width: 100%;
min-width: 0;
}
/* 599 그리기 칸 방식 칸 = 공용 `A00_Common/map/map_draw_kind.css`(626-3) */
/* 597 구역 · 연도 목록 — 구역 줄(이름 칸 · 연도 고름 · 지움) · 구간 줄(측점 글 작게) */
.d03-plan__line-tail {
+8 -4
View File
@@ -98,10 +98,14 @@ def test_d03_parts():
], keys
assert ".d03-plan__layers" in css and ".d03-plan__legend" in css
# 599-1 — 방식 칸 = 마디 고름 2 × 2 · 길이 · 기울기 두 열 · 노드 판(598-4)과 같은 함수
assert "createSegment({" in draw_panel and draw_panel.count("createInputField(") == 2
assert "columns: 2" in draw_panel and "export function createDrawKindFields(" in draw_panel
assert ".d03-plan__draw-fields" in css and "createDrawKindFields(" in draw
assert '"길이·기울기 고정"' in draw_panel and '"둘 다"' not in draw_panel
# 626-3 — 방식 칸은 공용 `A00_Common/map/map_draw_kind`(B05 평면도 씀) · D03 칸은 다시 내보냄
kind = _src("A00_Common/map/map_draw_kind.ts")
kind_css = _src("A00_Common/map/map_draw_kind.css")
assert "createSegment({" in kind and kind.count("createInputField(") == 2
assert "columns: 2" in kind and "export function createDrawKindFields(" in kind
assert "createDrawKindFields," in draw_panel and 'from "../A00_Common/map/map_draw_kind"' in draw_panel
assert ".map-draw-kind__fields" in kind_css and "createDrawKindFields(" in draw
assert '"길이·기울기 고정"' in kind and '"둘 다"' not in kind
assert "d03-plan__hint" not in draw # 칸 설명 글 걷음(요구 463-6)
# 599-4 — 연도 구역 마커 = 그리기 칸 단추(끌어 놓기) · 지도 도구줄에서 뺌
assert "YEAR_MARK_DRAG" in draw_panel and '"year-mark"' not in tools