Files
Aislo/A00_Common/spreadsheet/spreadsheet_actions.ts
T
eomsangdonandClaude Opus 5.5 fca4463768 feat(spreadsheet): D 잇기 3 — 칸 넣기 · 이동 · 틀 고정 · 데이터 도구 · 묶기 · 단축키 표 「안됨」 잇기
- spreadsheet_actions(키 · 메뉴 → 이름) + actions_run(몸통 · 늦게): Ctrl+Shift++ · Ctrl+- (행 · 열 통째면 바로) · 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+→/←
- [데이터 ▾] 에 이동 · 틀 고정 ▸ · 칸 넣기/지우기 · 텍스트 나누기 · 중복 제거 · 연속 채우기 · 윤곽 ▸
- 식 편집 중 F4 참조 $ 돌리기(cycleAbs) · 접힌 묶음 행 · 열은 방향키가 건너뜀
- 크기: 수식 분석 · 자동 필터 · 찾기 패널을 처음 쓸 때 불러옴 — 화면 27.0 KB · 합 60.9 KB
- M02 [스프레드시트 시험] ORCA 수치 확인 · D 규칙 시험 9 통과

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

140 lines
4.3 KiB
TypeScript

/* =============================================================================
* 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<string, Act> = {
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<string, Act> = {
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<string, Act>)[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")] },
],
};
}