- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로 - 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판) - import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/ - 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob - design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄) - 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
89 lines
4.3 KiB
TypeScript
89 lines
4.3 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Structures_Define_Form.ts
|
|
* 손코딩 시설 폼(동작 「계곡통과시설」)에 정의를 붙임(PLAN 48-3 · 48-4) — 숨긴 선택지 · 규칙.
|
|
*
|
|
* · 칸은 `labeled(..., 옵션키)` 가 붙인 `data-option-keys` 표식으로 찾음(키 하나인 칸만) · 찾는 자리 =
|
|
* 폼 본문 전체(그룹 상자로 옮겨 간 칸까지).
|
|
* · 칸 배치 · 이름은 손코딩 그대로(동작이 그림) — 안 씀은 끈 옵션과 같은 길(`_Drainage_Facility_Hidden`).
|
|
* · 선택지 = 정의 · 규칙 선택지 — 새 선택지는 보기를 더하고 밖 보기는 `hidden` 으로만 가림(옛 값은 그대로).
|
|
* 여러 키를 함께 적는 칸(유입구 구조 · 본체 규격)은 키 하나 표식이 아니라 안 건드림.
|
|
* · 규칙이 가린 칸 = `is-rule-hidden`(끈 옵션 표식 `is-option-hidden` 과 따로).
|
|
* ========================================================================== */
|
|
|
|
import type { StructureType } from "./B05_Profile_Api_Structures";
|
|
import { ruleDefaults, ruleStates } from "./logic/B05_Profile_UI_Structures_Define";
|
|
import { isOptionVisible } from "./logic/B05_Profile_UI_Structures_Summary";
|
|
|
|
/** 시설 폼이 가릴 옵션 키 — 「구조물 옵션 보이기」에서 끈 것 + 정의 「안 씀」. */
|
|
export function hiddenOptionKeys(type: StructureType | null): string[] {
|
|
return (type?.options ?? []).filter((o) => !isOptionVisible(o)).map((o) => o.key);
|
|
}
|
|
|
|
export interface FacilityDefinition {
|
|
/** 지금 종류 정의로 칸 모양을 맞춤 — 시설 폼을 채운 뒤마다 부름. */
|
|
apply: (type: StructureType | null) => void;
|
|
}
|
|
|
|
export function createFacilityDefinition(root: HTMLElement): FacilityDefinition {
|
|
let type: StructureType | null = null;
|
|
const wrapOf = (key: string): HTMLElement | null =>
|
|
[...root.querySelectorAll<HTMLElement>("[data-option-keys]")].find(
|
|
(node) => node.dataset.optionKeys === key,
|
|
) ?? null;
|
|
const controlOf = (key: string): HTMLInputElement | HTMLSelectElement | null =>
|
|
wrapOf(key)?.querySelector<HTMLInputElement | HTMLSelectElement>("select, input") ?? null;
|
|
const values = (): Record<string, string> =>
|
|
Object.fromEntries((type?.options ?? []).map((o) => [o.key, controlOf(o.key)?.value ?? ""]));
|
|
|
|
const paint = (): void => {
|
|
if (!type) return;
|
|
const states = ruleStates(type, values());
|
|
for (const option of type.options) {
|
|
const wrap = wrapOf(option.key);
|
|
const state = states.get(option.key);
|
|
if (!wrap || !state) continue;
|
|
wrap.classList.toggle("is-rule-hidden", !state.visible);
|
|
const control = controlOf(option.key);
|
|
if (!(control instanceof HTMLSelectElement)) continue;
|
|
// 정의에 새로 든 선택지는 보기를 더하고, 정의 · 규칙 밖 보기는 가림(빈 보기 · 지금 값은 그대로)
|
|
const have = new Set([...control.options].map((item) => item.value));
|
|
for (const choice of state.choices)
|
|
if (!have.has(choice))
|
|
control.add(new Option(type.spec_names?.[`${option.key}=${choice}`] ?? choice, choice));
|
|
for (const item of control.options) {
|
|
item.hidden =
|
|
!!item.value && !state.choices.includes(item.value) && item.value !== control.value;
|
|
}
|
|
}
|
|
};
|
|
|
|
// 상위 칸이 바뀌면 걸린 규칙의 기본값을 하위 칸에 넣고, 그 칸의 change 로 폼 반영(시설 폼 emit)을 잇는다.
|
|
root.addEventListener("change", (event) => {
|
|
if (!type) return;
|
|
const key = (event.target as HTMLElement).closest<HTMLElement>("[data-option-keys]")?.dataset
|
|
.optionKeys;
|
|
if (key) {
|
|
for (const [child, value] of Object.entries(ruleDefaults(type, key, values()))) {
|
|
const control = controlOf(child);
|
|
if (!control || control.value === String(value)) continue;
|
|
control.value = String(value);
|
|
control.dispatchEvent(new Event("change", { bubbles: true }));
|
|
}
|
|
}
|
|
paint();
|
|
});
|
|
|
|
return {
|
|
apply(next) {
|
|
type = next;
|
|
root
|
|
.querySelectorAll(".is-rule-hidden")
|
|
.forEach((node) => node.classList.remove("is-rule-hidden"));
|
|
root
|
|
.querySelectorAll<HTMLOptionElement>("option[hidden]:not([data-pick-hidden])")
|
|
.forEach((o) => (o.hidden = false));
|
|
paint();
|
|
},
|
|
};
|
|
}
|