Files
Aislo/ui_template/ui_template_modal.ts
T
eomsangdonandClaude Opus 5.5 16de9eed8b fix(M02): 16장 점검 — 지운 열 번호 재사용 막음 · 이름 창 커서 · Enter 만들기 · 바인딩 열 손 입력 막음
- 지운 구조물 열의 도번 8자리를 조합 장부 지운번호에 남겨 새 열이 다시 안 받음(다음 저장에서도)
- 공용 창 틀: 몸의 첫 입력 칸에 커서(붙기 전 focus 가 안 먹던 것)
- 좌측 새로 · 본떠 만들기 이름 창에서 Enter = 만들기
- 표: 바인딩 · 계산 열은 손 입력 열 단추 꺼짐(켜도 프로젝트에서 잠김)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011vX53nJGC8ucBRFJns2n7B
2026-09-28 21:56:51 +09:00

48 lines
1.8 KiB
TypeScript

/* =============================================================================
* ui_template_modal.ts
* 공용 모달 겉틀 — 배경 · 제목줄 · 닫기 · Esc · 포커스. 몸은 `mount` 가 채움.
* M01 · M02 가 함께 씀 — `dialogClass` · `backdropClass` 로 화면별 겉모양을 덧붙임.
* ========================================================================== */
import "./ui_template_modal.css";
import { createButton, el } from "./ui_template_elements";
export interface ModalOptions {
title: string;
closeLabel: string;
mount: (body: HTMLElement, close: () => void) => void;
dialogClass?: string;
backdropClass?: string;
}
export function openModal(opts: ModalOptions): { close: () => void } {
const body = el("div", { className: "ui-modal__body" });
const close = (): void => backdrop.remove();
const dialog = el("div", {
className: `ui-modal ${opts.dialogClass ?? ""}`.trim(),
attrs: { role: "dialog", "aria-label": opts.title },
children: [
el("div", {
className: "ui-modal__top",
children: [
el("h3", { text: opts.title }),
createButton({ label: opts.closeLabel, variant: "ghost", onClick: close }),
],
}),
body,
],
});
const backdrop = el("div", {
className: `ui-modal__backdrop ${opts.backdropClass ?? ""}`.trim(),
children: [dialog],
});
backdrop.addEventListener("click", (ev) => ev.target === backdrop && close());
backdrop.addEventListener("keydown", (ev) => ev.key === "Escape" && close());
opts.mount(body, close);
document.body.append(backdrop);
dialog.tabIndex = -1;
// 몸의 첫 입력 칸에 커서 — mount 안의 focus() 는 붙기 전이라 안 먹음
(body.querySelector<HTMLElement>("input, textarea, select") ?? dialog).focus();
return { close };
}