Files
Aislo/ui_template/ui_template_list_row.ts
T
eomsangdonandClaude Opus 5.5 29512c001b feat(D 예정노선): D02 기준 지정 걷음 · 지점 마킹 = D03 노선분석 · 기준점 둘레 1 km 처음 받기 · 조용히 이어 받기 (PLAN 591-2 · 요구 452 · 453)
- 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>
2026-10-30 10:19:34 +09:00

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));
}