From c6e826fe1f4c75b75f800ae43bfd8e6e606dbde5 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 27 Sep 2026 21:23:54 +0900 Subject: [PATCH] =?UTF-8?q?perf(spreadsheet):=20D=20=E2=80=94=20=EB=88=84?= =?UTF-8?q?=EB=A5=BC=20=EB=95=8C=EB=A7=8C=20=EC=93=B0=EB=8A=94=20=EC=B0=BD?= =?UTF-8?q?=EC=9D=84=20=EB=8A=A6=EA=B2=8C=20=EB=B6=88=EB=9F=AC=EC=98=B4(?= =?UTF-8?q?=ED=81=AC=EA=B8=B0=20=EC=98=88=EC=82=B0=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?28=20KB=20=EC=95=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - spreadsheet_data_menu.ts — 정렬(↑ ↓ · 정렬…) · 조건부 서식 · 시트 숨김/탭 색 창은 import() - spreadsheet_extras.ts — 셀 서식 창(Ctrl+1 · [서식…]) import() - 크기 시험: 엔진 31.4 · 화면 27.2 · css 3.9 · 합 62.6 KB Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01L6KXAabDTenEU7hrDQmCKY --- .../spreadsheet/spreadsheet_data_menu.ts | 53 ++++++++++++++----- A00_Common/spreadsheet/spreadsheet_extras.ts | 9 ++-- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/A00_Common/spreadsheet/spreadsheet_data_menu.ts b/A00_Common/spreadsheet/spreadsheet_data_menu.ts index 63721d63..431cd309 100644 --- a/A00_Common/spreadsheet/spreadsheet_data_menu.ts +++ b/A00_Common/spreadsheet/spreadsheet_data_menu.ts @@ -5,6 +5,7 @@ * 조건부 서식 · 데이터 유효성 · 이름 관리 · 시트 숨김/탭 색(sub4 패널 — 부품 오른위 창에 띄움) · 눈금선 · * 수식 분석(sub3 — 선행 · 종속 추적 화살표 · 화살표 지우기 · 수식 계산 · 오류 ⚠ 풍선) · 자동 합계(Σ · Alt+=). * 유효성 목록 칸은 고르면 칸 옆 ▼ · Alt+↓ 로 값 목록(필터 머리 칸이면 필터 목록이 먼저). + * 누를 때만 쓰는 창(정렬 · 조건부 서식 · 시트)은 `import()` 로 늦게 — 크기 예산(열 때 받는 조각). * ========================================================================== */ import "./spreadsheet_stage3.css"; // sub4 패널 스타일(잇는 쪽이 붙임) @@ -12,13 +13,10 @@ import { createMapContextMenu, type MapContextMenuItem } from "@ui/ui_template_c import { el, showToast } from "@ui/ui_template_elements"; import { parseRange, rangeToA1, toA1 } from "./spreadsheet_address"; import { autoSumRange } from "./spreadsheet_autosum"; -import { createCondFmtPanel } from "./spreadsheet_condfmt"; import { attachErrorTip } from "./spreadsheet_errcheck"; import { openEvalSteps } from "./spreadsheet_eval_steps"; import { attachFilter, toggleFilter } from "./spreadsheet_filter"; import { createNameManagerPanel } from "./spreadsheet_names"; -import { createSheetExtraPanel } from "./spreadsheet_sheet_extra"; -import { openSortDialog, sortSelection } from "./spreadsheet_sort_dialog"; import { attachTrace } from "./spreadsheet_trace"; import { createValidationDropdown, @@ -108,7 +106,11 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe closePanel(); back(); }); - function openPanel(name: string, make: (c: SpreadsheetContext) => PartHandle): void { + async function openPanel( + name: string, + load: () => Promise<(c: SpreadsheetContext) => PartHandle>, + ): Promise { + const make = await load(); closePanel(); panel = make(ctx); title.textContent = name.replace("…", ""); @@ -116,15 +118,42 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe dialog.removeAttribute("hidden"); } + const sorting = () => import("./spreadsheet_sort_dialog"); + async function sortQuick(desc: boolean): Promise { + (await sorting()).sortSelection(ctx, desc); + back(); + } + async function sortDialog(): Promise { + const m = await sorting(); + closeSort?.(); + closeSort = m.openSortDialog(ctx); + } + function evalSteps(): void { + closeSteps?.(); + closeSteps = openEvalSteps(ctx); + } + function openMenu(anchor: HTMLElement): void { const r = anchor.getBoundingClientRect(); const items: MapContextMenuItem[] = [ - [TEXT.sort, () => ((closeSort = openSortDialog(ctx)), undefined)], + [TEXT.sort, () => void sortDialog()], [TEXT.filterItem, () => (toggleFilter(ctx), back())], - [TEXT.condfmt, () => openPanel(TEXT.condfmt, createCondFmtPanel)], - [TEXT.validation, () => openPanel(TEXT.validation, createValidationPanel)], - [TEXT.names, () => openPanel(TEXT.names, createNameManagerPanel)], - [TEXT.sheets, () => openPanel(TEXT.sheets, createSheetExtraPanel)], + [ + TEXT.condfmt, + () => + void openPanel(TEXT.condfmt, () => + import("./spreadsheet_condfmt").then((m) => m.createCondFmtPanel), + ), + ], + [TEXT.validation, () => void openPanel(TEXT.validation, async () => createValidationPanel)], + [TEXT.names, () => void openPanel(TEXT.names, async () => createNameManagerPanel)], + [ + TEXT.sheets, + () => + void openPanel(TEXT.sheets, () => + import("./spreadsheet_sheet_extra").then((m) => m.createSheetExtraPanel), + ), + ], [TEXT.grid, () => (toggleGridlines(), back())], { label: TEXT.audit, @@ -132,7 +161,7 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe [TEXT.prec, () => traced(trace.precedents())], [TEXT.dep, () => traced(trace.dependents())], [TEXT.clear, () => (trace.clear(), back())], - [TEXT.steps, () => (closeSteps?.(), (closeSteps = openEvalSteps(ctx)))], + [TEXT.steps, evalSteps], ], }, ]; @@ -201,8 +230,8 @@ export function mountDataMenu(ctx: SpreadsheetContext, back: () => void): DataMe const buttons = ctx.readOnly ? [] : [ - button("↑", TEXT.asc, () => sortSelection(ctx, false)), - button("↓", TEXT.desc, () => sortSelection(ctx, true)), + button("↑", TEXT.asc, () => void sortQuick(false), true), + button("↓", TEXT.desc, () => void sortQuick(true), true), button("필터", TEXT.filter, () => toggleFilter(ctx)), button("Σ", TEXT.sum, autosum, true), button(TEXT.menu, TEXT.menu, openMenu, true), diff --git a/A00_Common/spreadsheet/spreadsheet_extras.ts b/A00_Common/spreadsheet/spreadsheet_extras.ts index 863a8d27..2c78275d 100644 --- a/A00_Common/spreadsheet/spreadsheet_extras.ts +++ b/A00_Common/spreadsheet/spreadsheet_extras.ts @@ -12,7 +12,6 @@ import { attachComments, getComment, setComment } from "./spreadsheet_comments"; import { mountDataMenu } from "./spreadsheet_data_menu"; import type { Editor } from "./spreadsheet_editor"; import { mountFindPanel } from "./spreadsheet_find_panel"; -import { openFormatDialog } from "./spreadsheet_format_dialog"; import { createFormatPainter } from "./spreadsheet_format_painter"; import type { KeyHooks } from "./spreadsheet_keys"; import type { MouseHooks } from "./spreadsheet_mouse"; @@ -116,9 +115,9 @@ export function attachExtras( attrs: { type: "button", title: TEXT.format }, }); /** 창이 닫히면(확인 · 취소) 초점을 격자로 */ - function openFormat(): void { + async function openFormat(): Promise { if (ctx.readOnly) return; - openFormatDialog(ctx); + (await import("./spreadsheet_format_dialog")).openFormatDialog(ctx); // 늦게 — 크기 예산 const watch = new MutationObserver(() => { if (document.querySelector(".ss-fmtdlg")) return; watch.disconnect(); @@ -126,7 +125,7 @@ export function attachExtras( }); watch.observe(document.body, { childList: true }); } - fmt.addEventListener("click", openFormat); + fmt.addEventListener("click", () => void openFormat()); if (!ctx.readOnly) ed.bar.prepend(fmt, brush); // ── 데이터 단추 · 메뉴(정렬 · 필터 · 조건부 서식 · 유효성 · 이름 · 눈금선) ───────── @@ -207,7 +206,7 @@ export function attachExtras( find: (replace) => find.open(replace), pasteSpecial: () => (armed = true), comment: editMemo, - formatDialog: openFormat, + formatDialog: () => void openFormat(), ...data.keys, escape() { painter.clear();