/* ============================================================================= * B01_Dashboard_UI_View_Parts.ts * 시스템 관리 · 내 정보 페이지(549-2) 곁부품 — 불러오기 틀 · 거르기 줄 · 묶음 제목. * 공용 조각(`B01_Dashboard_UI_PageKit.ts` · sub4)에 없는 것만 · 모양은 `Style_Pages.css` 아래 「시스템 관리」 쪽. * ========================================================================== */ import { createButton } from "@ui/ui_template_elements"; import { emptyState } from "./B01_Dashboard_UI_PageKit"; export const el = ( tag: K, className = "", text?: string, ): HTMLElementTagNameMap[K] => { const node = document.createElement(tag); if (className) node.className = className; if (text !== undefined) node.textContent = text; return node; }; /** * 자료를 읽는 동안 안내 → 다 읽으면 build 가 stage 에 그린 것으로 바꿈. * 실패하면 까닭 + [다시 시도] · 그 사이 떠났으면(host 떨어짐) 안 그림. */ export function loadPage(host: HTMLElement, build: (stage: HTMLElement) => Promise): void { const run = (): void => { host.replaceChildren(el("p", "b01-sys-loading", "불러오는 중…")); const stage = el("div", "b01-sys-stage"); build(stage).then( () => host.isConnected && host.replaceChildren(...stage.childNodes), (error: unknown) => { if (!host.isConnected) return; const retry = createButton({ label: "다시 시도", variant: "ghost", onClick: run }); const page = el("div", "b01-pg"); page.append( emptyState({ icon: "bell", text: error instanceof Error ? error.message : "불러오지 못했습니다.", action: retry, }), ); host.replaceChildren(page); }, ); }; run(); } /** 거르기 줄 */ export function toolbar(...items: HTMLElement[]): HTMLElement { const bar = el("div", "b01-sys-tool"); bar.append(...items); return bar; } export function searchBox(placeholder: string, onInput: (value: string) => void): HTMLInputElement { const input = el("input", "b01-sys-input"); input.type = "search"; input.placeholder = placeholder; input.ariaLabel = placeholder; input.addEventListener("input", () => onInput(input.value.trim().toLowerCase())); return input; } export function selectBox( label: string, options: [value: string, text: string][], onChange: (value: string) => void, ): HTMLSelectElement { const select = el("select", "b01-sys-input"); select.ariaLabel = label; for (const [value, text] of options) select.append(new Option(text, value)); select.addEventListener("change", () => onChange(select.value)); return select; } /** 묶음 — 제목 + 아래 내용(설정 카드 · 표) */ export function group(title: string, content: Node): HTMLElement { const box = el("section", "b01-sys-group"); box.append(el("h3", "b01-sys-group__title", title), content); return box; }