- 탭 줄을 안 그림 · Ctrl+PageDown/PageUp · Shift+F11 을 받지 않음(브라우저 몫) · [데이터 ▾] 의 시트 숨기기 · 탭 색 빠짐 - 산출근거(시트 하나)용 · 크기 화면 28,199 B(예산 28,672) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L6KXAabDTenEU7hrDQmCKY
144 lines
4.6 KiB
TypeScript
144 lines
4.6 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",
|
|
};
|
|
|
|
const SHEET_ACTS = new Set<Act>(["next", "prev", "newSheet"]);
|
|
|
|
/** 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 || (SHEET_ACTS.has(act) && ctx.root.classList.contains("ss--notabs"))) return false;
|
|
go(act);
|
|
return true;
|
|
},
|
|
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")] },
|
|
],
|
|
};
|
|
}
|