/* ============================================================================= * spreadsheet_memo.ts (주인 D) * 메모 편집(Shift+F2) — 칸 옆 글상자 · Ctrl+Enter 또는 밖을 누르면 적용 · Esc 취소. * 처음 쓸 때 `spreadsheet_extras.ts` 가 불러옴(크기 예산). * ========================================================================== */ import { el } from "@ui/ui_template_elements"; import type { getComment, setComment } from "./spreadsheet_comments"; import type { SpreadsheetContext } from "./spreadsheet_view_types"; const TITLE = "메모 — Ctrl+Enter 또는 밖을 누르면 적용 · Esc 취소"; export interface Memo { /** (r, c) 메모를 열고 `place` 로 칸 옆에 둠 */ open(r: number, c: number, place: (node: HTMLElement) => void): void; /** 편집 중인가 — 풍선을 띄우지 않음 */ busy(): boolean; destroy(): void; } /** 메모 읽기 · 쓰기는 부른 쪽이 넘김 — 여기서 끌어오면 메모 조각이 따로 쪼개져 크기가 늘어남 */ export function createMemo( ctx: SpreadsheetContext, back: () => void, io: { get: typeof getComment; set: typeof setComment }, ): Memo { const memo = el("textarea", { className: "ss-memo", attrs: { hidden: "", title: TITLE } }); ctx.root.append(memo); let memoAt: { r: number; c: number } | null = null; const close = (save: boolean): void => { if (!memoAt) return; const at = memoAt; memoAt = null; memo.setAttribute("hidden", ""); if (save && memo.value !== (io.get(ctx.sheet(), at.r, at.c) ?? "")) io.set(ctx, at.r, at.c, memo.value.trim()); back(); }; memo.addEventListener("keydown", (e) => { if (e.key === "Escape" || (e.key === "Enter" && e.ctrlKey)) { e.preventDefault(); e.stopPropagation(); close(e.key === "Enter"); } }); memo.addEventListener("blur", () => close(true)); return { open(r, c, place) { memoAt = { r, c }; memo.value = io.get(ctx.sheet(), r, c) ?? ""; memo.removeAttribute("hidden"); place(memo); memo.focus(); }, busy: () => !!memoAt, destroy: () => memo.remove(), }; }