- D02 걷음 — 길 · 단계(PLAN 단계 둘 = 노선 분석 · 확정) · [>] · 대시보드 단계 점 · 서버 길 · 폴더 만들기 · 캐시 등록 · 글 · 가이드 폴더 - 등록 [등록] · 받은 예정노선 [보기] = D03 으로 곧바로 - D03 지점 = 긋기에 붙는 점 · 목록 칸(여섯 색 · 「지점 N」 · 🗑) · 핀 끌기 = 그 자리 노선 노드 같이 · [저장] 몸에 실음 · [초기화] = 선만 지우고 지점 남김 - 지도 우클릭 메뉴(부품 상자) — 여기서 긋기 시작(빈 땅 = 새 본선) · 갈래 시작 · 이어 긋기 · 지점 놓기 · 지점 지우기 · 긋기 끝 - 받기 — 처음 = 등록 기준점 둘레 ± 1 km(지점 · 선 없을 때) · 지점 · 선 · 지도 보기 가운데가 받은 범위 밖이면 조용히 이어 받음(단추 · 막는 창 걷음 · 실패만 [다시 받기]) - 좌표계 = 파일 머리 · 없으면 기준점 경도 TM 띠 - 시험: 529_3(D02 지점 API) 지움 → 591_2 로 갈음 · 280_2 · 528 · 530_2 · 547_1 · 548 · 553_4 · 556_2 · 560_4 · 401 · 54_2 = D02 단계 · 페이지 걷음에 맞춤 · 590_1 · 530_2_analyze = 사업연도 · 기준점 한 번에 읽음 · 591_1 D04 씨앗 시험 = 590-1 이 씨앗 줄 걷음에 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
/* =============================================================================
|
|
* ui_template_list_row.ts
|
|
* 목록 줄 `list-row`(552-4 틀) — 패널 · 목록 안 고르는 줄 하나 · 왼쪽 글 · 오른쪽 덧붙임.
|
|
* 꼴 = 고르는 줄 · 두 줄(sub) · 끌기 손잡이(grip) · 왼쪽 색 띠(stripe) · 번호 원(no)
|
|
* 크기 = data-size 28 · 32 · 36 (기본 32)
|
|
* 상태 = 마우스 · 눌림 · 고름(`is-active` + aria-selected) · 막힘(disabled)
|
|
* 쓰는 법 = list.append(createListRow({ label: "B1 배수관", active: true, onClick: pick }))
|
|
* 대신하는 옛 변종 = `.ui-sidebar-row`(이 이름도 그대로 냄) · `.ui-tree__row` · `.ui-find__row` ·
|
|
* `b07-plan-manage__row` + `__grip` · `b05-drainage__basin` · `d03-plan__point` · `m02-pick__item` …
|
|
* ========================================================================== */
|
|
|
|
import "./ui_template_list_row.css";
|
|
|
|
export interface ListRowOptions {
|
|
label: string;
|
|
/** 둘째 줄(흐린 글) */
|
|
sub?: string;
|
|
/** 오른쪽 끝 덧붙임(값 · 배지 · 단추) */
|
|
trailing?: HTMLElement | string;
|
|
/** 왼쪽 번호 원 */
|
|
no?: number | string;
|
|
/** 왼쪽 색 띠 — 공통 값 이름(예: "var(--color-success)") */
|
|
stripe?: string;
|
|
/** 끌기 손잡이 — 끌기 동작은 부르는 쪽 몫 */
|
|
grip?: boolean;
|
|
active?: boolean;
|
|
disabled?: boolean;
|
|
size?: 28 | 32 | 36;
|
|
title?: string;
|
|
onClick?: (event: Event) => void;
|
|
}
|
|
|
|
function span(className: string, text?: string): HTMLSpanElement {
|
|
const n = document.createElement("span");
|
|
n.className = className;
|
|
if (text !== undefined) n.textContent = text;
|
|
return n;
|
|
}
|
|
|
|
/** 줄 하나 — onClick 이 있으면 <button> · 없으면 <div> */
|
|
export function createListRow(opts: ListRowOptions): HTMLElement {
|
|
const row = document.createElement(opts.onClick ? "button" : "div");
|
|
if (row instanceof HTMLButtonElement) row.type = "button";
|
|
row.className = "ui-list-row ui-sidebar-row";
|
|
row.dataset.size = String(opts.size ?? 32);
|
|
row.setAttribute("role", "option");
|
|
if (opts.title) row.title = opts.title;
|
|
if (opts.stripe) {
|
|
row.classList.add("ui-list-row--stripe");
|
|
row.style.setProperty("--ui-list-row-stripe", opts.stripe);
|
|
}
|
|
if (opts.grip) row.append(span("ui-list-row__grip"));
|
|
if (opts.no !== undefined) row.append(span("ui-list-row__no", String(opts.no)));
|
|
const text = span("ui-list-row__text");
|
|
text.append(span("ui-list-row__label", opts.label));
|
|
if (opts.sub) text.append(span("ui-list-row__sub", opts.sub));
|
|
row.append(text);
|
|
if (opts.trailing !== undefined) {
|
|
const tail = span("ui-list-row__trailing");
|
|
tail.append(opts.trailing);
|
|
row.append(tail);
|
|
}
|
|
setListRowActive(row, Boolean(opts.active));
|
|
if (opts.disabled) {
|
|
if (row instanceof HTMLButtonElement) row.disabled = true;
|
|
row.setAttribute("aria-disabled", "true");
|
|
}
|
|
if (opts.onClick) row.addEventListener("click", opts.onClick);
|
|
return row;
|
|
}
|
|
|
|
/** 고름 켜고 끄기 — 클래스 · aria 한 번에 */
|
|
export function setListRowActive(row: HTMLElement, active: boolean): void {
|
|
row.classList.toggle("is-active", active);
|
|
row.setAttribute("aria-selected", String(active));
|
|
}
|