fix(structure): 정의 그룹 상자 꼴 = 명세 컨테이너 꼴(52-18)

- 잇기 줄 글 「집계 항목」 → 「구조물 조합」 (가드레일 · 맹암거 · 대피로 · 사토장 · 토취장)
- 그룹 숫자 칸 = −/+ 단추 달린 숫자 칸(0.1 · 소수 1자리 · 라벨 대상 = 숫자 칸)
- 상자 = 명세와 같은 조각(group · grid) · 그룹 전용 상자 꼴 CSS 걷음
- 저장 값 · 키 · 잇기 동작 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
2026-10-06 01:09:03 +09:00
co-authored by Claude Opus 5.5
parent fbf87151d7
commit 5a1bcde1df
3 changed files with 22 additions and 25 deletions
+12 -12
View File
@@ -21,7 +21,8 @@ import { hiddenFormKeys } from "./B05_Profile_UI_Drainage_Facility_Merge";
import { buildSummaryRow, type SummaryRow } from "./B05_Profile_UI_Structures_Summary_Row";
import { isOptionVisible } from "./B05_Profile_UI_Structures_Summary";
import { SHAPE_FIELDS, shapeFields, shapeKey } from "./B05_Profile_UI_Structures_Define";
import { field, numberInput } from "./B05_Profile_UI_Structures_Fields";
import { numberInput } from "./B05_Profile_UI_Structures_Fields";
import { grid, group as boxOf, labeled, stepper } from "./B05_Profile_UI_Drainage_Facility_Fields";
import { STRUCTURE_SPECS } from "../A00_Common/design/design_structure_pipe";
import {
GROUP_JOIN,
@@ -126,13 +127,11 @@ export function createGroupBoxes(): GroupBoxes {
);
for (const group of groups) {
const keys = hiddenFormKeys(facility, group.options);
const box = document.createElement("fieldset");
box.className = "b05-structure__group b05-structure__optgroup";
box.dataset.b05Group = group.id;
const legend = document.createElement("legend");
legend.textContent = group.name;
const body = document.createElement("div");
body.className = "b05-structure__grid";
// 상자 꼴 = 명세 컨테이너(`design_structure_form`)와 같은 조각 — 제목 · 몸통 · 격자 · 잇기 줄(52-18)
const box = boxOf(group.name);
box.root.classList.add("b05-structure__optgroup");
box.root.dataset.b05Group = group.id;
const body = grid();
for (const scope of scopes) {
const marked = [...scope.querySelectorAll<HTMLElement>("[data-option-keys]")];
// 지금 숨은 칸(다른 시설 몫 · 안 고른 갈래)은 그 자리에 둠 — 같은 키 칸이 두 벌 옮겨 오지 않게
@@ -180,23 +179,24 @@ export function createGroupBoxes(): GroupBoxes {
handlers?.change?.();
});
shapeInputs.set(key, input);
body.append(field(shape.label, input));
body.append(labeled(shape.label, stepper(input, 0.1)));
}
if (!body.childElementCount) {
const none = document.createElement("p");
none.className = "b05-structure__owner-note";
none.textContent = "옵션 없음 — 집계 항목만 지정";
none.textContent = "옵션 없음 — 구조물 조합만 지정";
body.append(none);
}
const row = buildSummaryRow();
row.root.querySelector(".b05-structure__summary-label")!.textContent = "구조물 조합";
row.set(items[group.id] ?? null);
row.bind({
pick: () => handlers?.pick(group.id),
clear: () => handlers?.clear(group.id),
});
rows.set(group.id, row);
box.append(legend, body, row.root);
boxes.push(box);
box.body.append(body, row.root);
boxes.push(box.root);
bodies.push(body);
}
const stale =
@@ -20,6 +20,7 @@ import {
staleValues,
} from "./B05_Profile_UI_Structures_Define";
import { FORM_OPTION_KEYS } from "./B05_Profile_UI_Drainage_Facility_Merge";
import { stepper } from "./B05_Profile_UI_Drainage_Facility_Fields";
import { STRUCTURE_SPECS } from "../A00_Common/design/design_structure_pipe";
import { paintStructureSpec, specOwnedKeys } from "./B05_Profile_UI_Structures_Spec";
import { solveSplit, specKeys, type SplitRole } from "../A00_Common/design/design_structure_spec";
@@ -97,7 +98,15 @@ export function renderOptionFields(
const name = (c: string): string => type.spec_names?.[`${option.key}=${c}`] ?? c;
const input = optionControl(option, values[option.key], name);
const label = `${option.unit ? `${option.label} (${option.unit})` : option.label}${option.not_in_table ? " · 표에 안 쓰임" : ""}`;
const wrap = field(label, input, option.default_basis);
// 정의 그룹 상자로 옮겨 갈 숫자 칸 = 명세 컨테이너와 같은 [-][숫자][+](52-18)
const grouped =
option.input === "number" && !!type.groups?.some((g) => g.options.includes(option.key));
const wrap = field(
label,
grouped ? stepper(input as HTMLInputElement, 0.1) : input,
option.default_basis,
);
if (grouped) wrap.htmlFor = input.id; // 라벨 대상 = 숫자 칸(첫 버튼으로 새지 않게)
wrap.dataset.optionKeys = option.key; // 옵션 그룹 상자가 이 표식으로 칸을 옮김(PLAN 46-3)
// 배치 격자(48-3) — 정의 `배치` 의 줄 · 칸 · 너비 · 없으면 흐름대로
const place = gridPlace(type.spots?.[option.key], columns);
@@ -499,25 +499,13 @@
}
.b05-structure__optgroup {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0; /* 긴 집계 항목 이름이 상자를 패널 밖으로 밀지 않게(fieldset 최소 폭 · 52-9) */
}
.b05-structure__optgroup > legend {
font-weight: 600;
opacity: 1;
}
.b05-structure__optgroup .is-option-hidden {
display: none;
}
.b05-structure__optgroup > .b05-structure__grid.is-locked {
opacity: 0.5;
}
/* 구조물 정의 규칙(PLAN 48-4)이 가린 칸 — 그룹 상자로 옮겨 가도 같은 표식 */
.b05-structure-section .is-rule-hidden {
display: none;