/* ============================================================================= * ui_template_item_picker_ask.ts * 고르기 모달에서 글을 물을 때 쓰는 작은 입력 창(계획서 26-3b) — [개인에 저장](경로 · 이름) · * 나무 오른쪽 클릭 「새 항목」(이름 · 단위). 확인 = 넣은 글들 · 취소 · 닫기 = null. * ========================================================================== */ import { createButton, createInputField, el } from "./ui_template_elements"; import { openModal } from "./ui_template_modal"; export interface AskField { key: string; label: string; value?: string; placeholder?: string; /** 비우면 확인 안 됨 */ required?: boolean; } export interface AskOptions { title: string; /** 창 위 한 줄 설명 */ note?: string; fields: AskField[]; okLabel: string; cancelLabel: string; closeLabel: string; /** 빈 값 알림 — `{label}` 자리에 칸 이름 */ emptyText: string; } export function askFields(opts: AskOptions): Promise | null> { return new Promise((resolve) => { let done = false; const finish = (value: Record | null): void => { if (done) return; done = true; resolve(value); }; openModal({ title: opts.title, closeLabel: opts.closeLabel, dialogClass: "ui-item-ask", backdropClass: "ui-item-ask__backdrop", beforeClose: () => { finish(null); return true; }, mount: (body, close) => { const inputs = opts.fields.map((field) => ({ field, input: createInputField({ label: field.label, value: field.value ?? "", placeholder: field.placeholder, }), })); const submit = (): void => { let bad = false; for (const { field, input } of inputs) { const empty = field.required && input.input.value.trim() === ""; input.setError(empty ? opts.emptyText.replace("{label}", field.label) : undefined); bad ||= !!empty; } if (bad) return; finish( Object.fromEntries( inputs.map(({ field, input }) => [field.key, input.input.value.trim()]), ), ); close(); }; for (const { input } of inputs) input.input.addEventListener("keydown", (event) => { if (event.key === "Enter") submit(); }); body.append( ...(opts.note ? [el("p", { className: "ui-item-picker__where", text: opts.note })] : []), ...inputs.map(({ input }) => input.root), el("div", { className: "ui-item-picker__actions", children: [ createButton({ label: opts.cancelLabel, variant: "ghost", onClick: () => { finish(null); close(); }, }), createButton({ label: opts.okLabel, variant: "filled", onClick: submit }), ], }), ); }, }); }); }