- 줌 [+ − ⤢] = 아이콘 단추 22 · 상세 [칸에 넣기] = 단추 22 · [여럿] = 켜기 칩 22 · 사이 금 지움 - 구조물 조정창 십자 · 9키 · 단 수 [-][+] = 아이콘 단추(선) 22 · ✕ = 고스트 · 옵션 연동 · 경사 = 켜기 칩 24(유입 · 유출 칸 꼴은 그대로) - 카드 머리 단면유형 = 배지(정보) 20 · 구조물 = 배지(강조) 20 - 알림 칩 = 단추(고스트) 20(색만 경고 / 정보) · 측점 목록 날 단추 = 단추(고스트) 20 - 날 details 넷(변수 위치 안내 · 상세값 · 다른 프로젝트 불러오기 · 횡단 조정) = 접이 구역(ui-collapsible) · 가이드 장면 선택자 `details.` 뗌 - 측점 없는 구조물 줄 · 표준 미반영 알림 = 띠 알림(경고) — 날 색 #fff8e6 · #e0b872 · #7a5a12 · #8a6a22 · 폴백 #d98324 지움 - 빈 그림 자리 = 빈 상태 · 선 치수 글 옛 보라 이름 → --color-accent - 흉내 DOM 시험 · 서버 Node 묶음이 끄는 파일이라 부품 함수 대신 클래스 · data-size 계약 + 부품 CSS 직접 실음(묶음 셋 빌드 정상) - 시험 넷 기대 고침 — 108(닫기 클래스) · 179-1(줌 사이 금 규칙 없음) · 196-1(칩 클래스) · 207-1(칩 반경 = 부품) - 그대로 둔 것 — 수량 산출표(b06-detail__qtable · B07 산출서 병합 칸 · 세로선 = 부품 표에 없는 꼴) · 조정창 고르기 · 암 절토 칸(작은 단 없음) · 조정창 · ⋯ · 측점 목록 떠 있는 판 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
110 lines
3.9 KiB
TypeScript
110 lines
3.9 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_UI_Cross_Notice_Chips.ts
|
|
* 횡단 알림 줄 칩 꼴(196-1) — 항목 = 짧은 이름 + 측점 수 칩 한 줄 · 긴 설명 = 공용 호버.
|
|
* 줄 아래 내용 칸 하나를 같이 씀 — 누른 칩의 측점 목록만 · 같은 칩 다시 누르면 닫힘 ·
|
|
* 다른 칩 누르면 바뀜(한 번에 하나). 측점 단추 누름 = `onPick`(그 카드로).
|
|
* ⭐ 207-1 — 내용 칸은 줄 아래 카드 위에 겹쳐 뜸(흐름 밖 · CSS) · 측점 누르면 접힘 ·
|
|
* 열 때 지금 고른 측점(`selected`) 단추 강조.
|
|
* 무엇을 셀지는 부르는 쪽(`_FillSlope_Notice`) — 여기는 그리기만.
|
|
* ========================================================================== */
|
|
|
|
import { attachHoverInfo } from "@ui/ui_template_hover_info";
|
|
|
|
export interface NoticeChipRow {
|
|
stationId: string;
|
|
text: string;
|
|
}
|
|
|
|
export interface NoticeChipItem {
|
|
key: string;
|
|
/** 짧은 이름 — 칩 글 = 이름 + 측점 수 */
|
|
label: string;
|
|
/** 긴 설명 — 호버 */
|
|
hint: string;
|
|
tone: "warn" | "info";
|
|
rows: NoticeChipRow[];
|
|
}
|
|
|
|
export interface NoticeChips {
|
|
root: HTMLElement;
|
|
/** 측점 설계가 바뀔 때마다 — 연 칩은 그대로(측점이 0 이 되면 닫힘) */
|
|
update: (items: NoticeChipItem[]) => void;
|
|
}
|
|
|
|
export function createNoticeChips(
|
|
onPick: (stationId: string) => void,
|
|
selected: () => string | null = () => null,
|
|
): NoticeChips {
|
|
const root = document.createElement("div");
|
|
root.className = "b06-section__notice-blocks";
|
|
const chips = document.createElement("div");
|
|
chips.className = "b06-section__notice-chips";
|
|
const panel = document.createElement("div");
|
|
panel.className = "b06-section__notice-list";
|
|
panel.hidden = true;
|
|
root.append(chips, panel);
|
|
let items: NoticeChipItem[] = [];
|
|
let openKey: string | null = null;
|
|
|
|
const render = (): void => {
|
|
const open = items.find((item) => item.key === openKey);
|
|
if (!open) openKey = null;
|
|
chips.replaceChildren(
|
|
...items.map((item) => {
|
|
const chip = document.createElement("button");
|
|
chip.type = "button";
|
|
// 부품 단추(고스트) 20(553-2) — 클래스 · data-size 계약 · 경고 / 정보 색은 페이지
|
|
chip.className = `ui-btn ui-btn--ghost b06-section__notice-chip b06-section__notice-chip--${item.tone}`;
|
|
chip.setAttribute("data-size", "20");
|
|
chip.dataset.noticeKey = item.key;
|
|
chip.setAttribute("aria-expanded", String(item === open));
|
|
chip.textContent = `${item.label} ${item.rows.length}`;
|
|
return chip;
|
|
}),
|
|
);
|
|
panel.hidden = !open;
|
|
panel.classList.toggle("is-info", open?.tone === "info");
|
|
const picked = open ? selected() : null;
|
|
panel.replaceChildren(
|
|
...(open?.rows ?? []).map((row) => {
|
|
const button = document.createElement("button");
|
|
button.type = "button";
|
|
button.className = "ui-btn ui-btn--ghost"; // 부품 단추(고스트) 20
|
|
button.setAttribute("data-size", "20");
|
|
button.textContent = row.text;
|
|
button.dataset.stationId = row.stationId;
|
|
button.classList.toggle("is-selected", row.stationId === picked);
|
|
return button;
|
|
}),
|
|
);
|
|
};
|
|
|
|
chips.addEventListener("click", (event) => {
|
|
const key = (event.target as HTMLElement).closest<HTMLElement>(".b06-section__notice-chip")
|
|
?.dataset.noticeKey;
|
|
if (!key) return;
|
|
openKey = openKey === key ? null : key;
|
|
render();
|
|
});
|
|
panel.addEventListener("click", (event) => {
|
|
const id = (event.target as HTMLElement).closest("button")?.dataset.stationId;
|
|
if (!id) return;
|
|
openKey = null;
|
|
render();
|
|
onPick(id);
|
|
});
|
|
attachHoverInfo(
|
|
chips,
|
|
(target) => items.find((item) => item.key === target.dataset.noticeKey)?.hint,
|
|
".b06-section__notice-chip",
|
|
);
|
|
|
|
return {
|
|
root,
|
|
update(next) {
|
|
items = next.filter((item) => item.rows.length);
|
|
render();
|
|
},
|
|
};
|
|
}
|