Files
Aislo/ui_template/ui_template_list_row.ts
T
eomsangdonandClaude Opus 5.5 f941ddc3f5 feat(ui-kit): 틀 부품 여섯 — 작업 화면 틀 겉 · 일반 화면 틀 · 공개 화면 틀 · 단계 줄 · 패널 머리 · 목록 줄 (PLAN 552-4)
- 작업 화면 틀(overlay): 왼쪽 패널 = 흰 판 + 1 px 선 · 그림자 없음 · 덮개 = --color-scrim · 손잡이 강조색 그대로 · 자리 · 폭 그대로
- 일반 화면 틀 createPageFrame(대시보드 세부 꼴) · 공개 화면 틀 createPublicFrame(A01 hero · section 꼴)
- 단계 줄 data-size 28 · 40 · 상태 = 공통 값 · 패널 머리 createPanelHead · 목록 줄 createListRow(옛 .ui-sidebar-row 겉 함께)
- 부품 모음: 떠 있는 판 · 서랍 · 도구줄 · 단계 줄 · 패널 머리 · 목록 줄 여섯 줄을 frame 묶음으로 옮김 · 견본 = ui_template_ui_kit_frames.ts
- 지킴 시험 test_552_4_frames.py · B02~B09 · D · E · M02 전후 자리 수치 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 21:28:17 +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` · `d02-points__row` · `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));
}