feat(spreadsheet): 우클릭 메뉴 항목 모음 · 공용 메뉴 구분선 · 데이터 창 손잡이(81-3)

- spreadsheet_menu_items.ts 새 파일 — 붙여넣기(보안 문맥만) · 선택하여 붙여넣기 ▸ · 행 · 열 · 셀 삽입/삭제 ▸ · 크기 · 데이터에 맞추기 · 시트 정렬 · 필터 · 고정 ▸ · 그룹 ▸ · 셀 작업 더보기 ▸ · 읽기 전용 복사
- ui_template_context_menu 항목에 구분선 "-" 덧붙임(맨 앞 · 맨 뒤 · 겹침 안 그림)
- ctx.dataMenu — [데이터 ▾] 와 같은 패널 창 · 필터를 우클릭에서 부름

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
This commit is contained in:
2026-10-08 12:31:40 +09:00
co-authored by Claude Opus 5.5
parent b565cdba75
commit 2ebc888f03
5 changed files with 474 additions and 2 deletions
+14 -2
View File
@@ -14,10 +14,12 @@
import "./ui_template_context_menu.css";
/** 평면 항목 = [문구, 동작]. 하위 메뉴 항목 = {label, children} — 누르면 바로 아래로
* 펼쳐지는 아코디언(구조물군 → 종류, 2026-08-18 B05 우클릭 메뉴 일원화). */
* 펼쳐지는 아코디언(구조물군 → 종류, 2026-08-18 B05 우클릭 메뉴 일원화).
* 구분선 = `"-"` — 맨 앞 · 맨 뒤 · 겹친 것은 안 그림. */
export type MapContextMenuItem =
| [label: string, action: () => void]
| { label: string; children: Array<[label: string, action: () => void]> };
| { label: string; children: Array<[label: string, action: () => void]> }
| "-";
export interface MapContextMenu {
/** 뷰포트에 append할 요소. */
@@ -118,6 +120,14 @@ export function createMapContextMenu(blockClass: string): MapContextMenu {
enterMenu(registryEntry);
element.replaceChildren();
items.forEach((item) => {
if (item === "-") {
const last = element.lastElementChild;
if (last && !last.classList.contains("ui-ctx-menu__sep"))
element.append(
Object.assign(document.createElement("div"), { className: "ui-ctx-menu__sep" }),
);
return;
}
if (Array.isArray(item)) {
element.append(buildLeaf(item[0], item[1]));
return;
@@ -145,6 +155,8 @@ export function createMapContextMenu(blockClass: string): MapContextMenu {
});
element.append(head, body);
});
if (element.lastElementChild?.classList.contains("ui-ctx-menu__sep"))
element.lastElementChild.remove();
element.style.left = `${x}px`;
element.style.top = `${y}px`;
element.hidden = false;