/* ============================================================================= * spreadsheet_actions.ts (주인 D) * 단축키 표(sub1 `spreadsheet_shortcuts.ts`) 「안됨」 잇기 + 3차 부품 메뉴 자리([데이터 ▾] 에 붙임). * Ctrl+Shift++ · Ctrl+- 칸 넣기 · 지우기(행 · 열 통째면 바로 · 아니면 sub1 창) · F5 · Ctrl+G 이동 · * Ctrl+9/0 숨김 · Ctrl+Shift+9/0 풀기 · Ctrl+B/I/U/5 글꼴 뒤집기 · Ctrl+Shift+& 바깥 테두리 · * Ctrl+Shift+_ 테두리 없앰 · Ctrl+; 오늘 날짜 · Ctrl+PageDown/PageUp 시트 · Shift+F11 새 시트 · * Shift+Alt+→/← 행 · 열 묶기 · 풀기(C 윤곽 +/- 가 접음). * 여기는 키 · 메뉴 → 이름만 · 몸통은 `spreadsheet_actions_run.ts`(늦게 — 크기 예산). * ========================================================================== */ import type { MapContextMenuItem } from "@ui/ui_template_context_menu"; import type { SpreadsheetContext } from "./spreadsheet_view_types"; const TEXT = { goTo: "이동…(F5)", freeze: "틀 고정", freezeRow: "첫 행 고정", freezeCol: "첫 열 고정", freezeAt: "지금 칸 기준 고정", unfreeze: "틀 고정 풀기", insert: "칸 넣기…(Ctrl+Shift++)", remove: "칸 지우기…(Ctrl+-)", split: "텍스트 나누기…", dedupe: "중복된 항목 제거…", series: "연속 데이터 채우기…", group: "묶기(Shift+Alt+→)", ungroup: "묶음 풀기(Shift+Alt+←)", outline: "윤곽", }; export type Act = | "goTo" | "insert" | "remove" | "hideRows" | "hideCols" | "showRows" | "showCols" | "group" | "ungroup" | "outline" | "clearBorders" | "today" | "next" | "prev" | "newSheet" | "freezeRow" | "freezeCol" | "freezeAt" | "unfreeze" | "split" | "dedupe" | "series" | `flip:${"굵게" | "기울임" | "밑줄" | "취소선"}`; /** Ctrl+글자(e.code) → 이름 */ const CTRL: Record = { KeyB: "flip:굵게", KeyI: "flip:기울임", KeyU: "flip:밑줄", Digit5: "flip:취소선", KeyG: "goTo", Minus: "remove", NumpadSubtract: "remove", NumpadAdd: "insert", Digit9: "hideRows", Digit0: "hideCols", Semicolon: "today", // ponytail: 시각(Ctrl+Shift+;)은 numfmt 시간 형식이 오면 PageDown: "next", PageUp: "prev", }; /** Ctrl+Shift+글자 → 이름 */ const CTRL_SHIFT: Record = { Equal: "insert", NumpadAdd: "insert", Minus: "clearBorders", Digit9: "showRows", Digit0: "showCols", Digit7: "outline", PageDown: "next", PageUp: "prev", }; /** body 에 뜬 창(.ui-confirm)이 다 닫히면 초점을 격자로 — 창을 연 바로 뒤에 부름 */ export function watchClose(back: () => void): void { const w = new MutationObserver(() => { if (document.querySelector("body > .ui-confirm, body > .ui-confirm__panel")) return; w.disconnect(); back(); }); w.observe(document.body, { childList: true }); } function pick(e: KeyboardEvent): Act | undefined { const ctrl = e.ctrlKey || e.metaKey; if (e.altKey) return e.shiftKey && !ctrl ? ({ ArrowRight: "group", ArrowLeft: "ungroup" } as Record)[e.key] : undefined; if (ctrl) return (e.shiftKey ? CTRL_SHIFT : CTRL)[e.code]; if (e.key === "F5" && !e.shiftKey) return "goTo"; if (e.key === "F11" && e.shiftKey) return "newSheet"; } export interface Actions { key(e: KeyboardEvent): boolean; items: MapContextMenuItem[]; } export function mountActions(ctx: SpreadsheetContext, back: () => void): Actions { const go = (act: Act): void => void import("./spreadsheet_actions_run").then((m) => m.run(ctx, back, act)); const item = (label: string, act: Act): [string, () => void] => [label, () => go(act)]; return { key(e) { const act = pick(e); if (act) go(act); return !!act; }, items: [ item(TEXT.goTo, "goTo"), { label: TEXT.freeze, children: [ item(TEXT.freezeRow, "freezeRow"), item(TEXT.freezeCol, "freezeCol"), item(TEXT.freezeAt, "freezeAt"), item(TEXT.unfreeze, "unfreeze"), ], }, item(TEXT.insert, "insert"), item(TEXT.remove, "remove"), item(TEXT.split, "split"), item(TEXT.dedupe, "dedupe"), item(TEXT.series, "series"), { label: TEXT.outline, children: [item(TEXT.group, "group"), item(TEXT.ungroup, "ungroup")] }, ], }; }